From: Guillermo J. Rozas Date: Thu, 3 Sep 1992 07:30:46 +0000 (+0000) Subject: Change DOS timer interrupt behavior: X-Git-Tag: 20090517-FFI~9006 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=10bc6c38923fe6fb787da0463a8c3deb08661946;p=mit-scheme.git Change DOS timer interrupt behavior: - Low level timer interrupt sets the "Global GC" interrupt but. - The Global GC interrupt handler (a primitive) tracks user timer requests and sets the timer interrupt bit when appropriate. It also invokes consume_typeahead to look for keyboard interrupt characters. Keyboard interrupt behavior changes: - The interactive handler is invoked from the consume_typeahead routine, not when Scheme is trying to map the interrupt character. In this way, its range of actions is greater. - Add reset option and hard attention keys. Keyboard interrupt handler: - Implement X32 version (does not work under DPMI). - Rewrite DPMI handler to use masm-assembled code instead of hand-assembled code. This makes it considerably easier to modify. --- diff --git a/v7/src/microcode/dosconio.c b/v7/src/microcode/dosconio.c index 73a98effe..806891729 100644 --- a/v7/src/microcode/dosconio.c +++ b/v7/src/microcode/dosconio.c @@ -1,6 +1,6 @@ /* -*-C-*- -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosconio.c,v 1.1 1992/05/05 06:55:13 jinx Exp $ +$Id: dosconio.c,v 1.2 1992/09/03 07:29:51 jinx Exp $ Copyright (c) 1992 Massachusetts Institute of Technology @@ -41,7 +41,7 @@ MIT in each case. */ #include "dosscan.h" #include "dossys.h" #include "intrpt.h" - + /* This is really not set up to include Scheme level headers, so we fake them here. */ extern long @@ -52,7 +52,6 @@ extern long #define fileno(fp) ((fp)->_file) #endif - #define CONIO_BUFFER_SIZE (1024) #define TYPEAHEAD_BUFFER_SIZE (1024) @@ -83,7 +82,6 @@ typedef struct typeahead_buffer_struct static conio_buffer_t line_buffer, key_buffer; static typeahead_buffer_t typeahead_buffer; - static int max_scancode_conversion_length = 0; static unsigned char * keyboard_scancode_table[] = DEFAULT_SCANCODE_CONVERSIONS; @@ -124,7 +122,8 @@ static unsigned long scancode_malloced_table[MALLOCED_TABLE_SIZE] = {0,}; static void DEFUN (map_keyboard_scancode, (scancode), unsigned char scancode) -{ extern int signal_keyboard_character_interrupt(unsigned char); +{ + extern int signal_keyboard_character_interrupt (int); if (scancode < KEYBOARD_SCANCODE_TABLE_SIZE) { @@ -132,15 +131,27 @@ DEFUN (map_keyboard_scancode, (scancode), unsigned char scancode) unsigned char * conversion = keyboard_scancode_table[scancode]; if (conversion == NO_CONVERSION) return; + else if (conversion == SOFT_ATTN) + { + signal_keyboard_character_interrupt (-1); + return; + } + else if (conversion == HARD_ATTN) + { + signal_keyboard_character_interrupt (-2); + return; + } - len = ((conversion == CTRL_AT) ? 1 : strlen (conversion)); + len = ((conversion == CTRL_AT) ? 1 : (strlen (conversion))); if (len <= (Typeahead_Buffer_Remaining ())) - { /* Copy conversion string into typeahead buffer, worrying about - interrupt characters along the way. */ + { + /* Copy conversion string into typeahead buffer, worrying about + interrupt characters along the way. + */ while (--len >= 0) { - if ((signal_keyboard_character_interrupt (*conversion)) == 0) + if ((signal_keyboard_character_interrupt ((int) (*conversion))) == 0) typeahead_buffer.buffer[typeahead_buffer.length++] = *conversion++; } } @@ -162,7 +173,7 @@ DEFUN_VOID (recompute_max_scancode_conversion_length) else if (conversion == CTRL_AT) length = 1; else - length = strlen (conversion); + length = (strlen (conversion)); max_scancode_conversion_length = Max (length, max_scancode_conversion_length); } @@ -202,8 +213,8 @@ DEFINE_PRIMITIVE ("KEYBOARD-SET-CONVERSION!", Prim_keyboard_set_conversion, { PRIMITIVE_HEADER (2); { - int scancode = arg_integer (1); - SCHEME_OBJECT scheme_conversion = ARG_REF (2); + int scancode = (arg_integer (1)); + SCHEME_OBJECT scheme_conversion = (ARG_REF (2)); if ((scancode < 0) || (scancode >= KEYBOARD_SCANCODE_TABLE_SIZE)) error_bad_range_arg(1); @@ -259,18 +270,18 @@ DEFINE_PRIMITIVE ("KEYBOARD-SET-CONVERSION!", Prim_keyboard_set_conversion, static void DEFUN_VOID (consume_typeahead) { - extern int signal_keyboard_character_interrupt(unsigned char); + extern int signal_keyboard_character_interrupt (int); unsigned char character; - while ( (Typeahead_Buffer_Available_p()) && - (dos_poll_keyboard_character(&character)) ) + while ((Typeahead_Buffer_Available_p ()) && + (dos_poll_keyboard_character (&character))) { if (character == '\0') /* Extended scancode */ { - dos_poll_keyboard_character(&character); - map_keyboard_scancode(character); + dos_poll_keyboard_character (&character); + map_keyboard_scancode (character); } - else if (signal_keyboard_character_interrupt(character) == 0) + else if ((signal_keyboard_character_interrupt ((int) character)) == 0) typeahead_buffer.buffer[typeahead_buffer.length++] = character; else break; @@ -281,35 +292,47 @@ DEFUN_VOID (consume_typeahead) static int DEFUN_VOID (typeahead_available_p) { - consume_typeahead(); - return !(typeahead_buffer.length == 0); + consume_typeahead (); + return (!(typeahead_buffer.length == 0)); } static unsigned char DEFUN_VOID (get_typeahead_character) -{ unsigned char result; - +{ if (typeahead_buffer.length == 0) return '\0'; else - { int i; + { + int i; + unsigned char result; + result = typeahead_buffer.buffer[0]; for (i = 1; i < typeahead_buffer.length; i++) typeahead_buffer.buffer[i - 1] = typeahead_buffer.buffer[i]; typeahead_buffer.length--; - return result; + return (result); } } DEFINE_PRIMITIVE ("CONSUME-TYPEAHEAD", Prim_consume_typeahead, 0, 0, - "Suck up DOS typeahead.") + "Suck up DOS typeahead.") { - + /* Obsolete -- done by microcode directly. */ PRIMITIVE_HEADER(0); - consume_typeahead(); PRIMITIVE_RETURN (UNSPECIFIC); } +DEFINE_PRIMITIVE ("DOS-HIGH-PRIORITY-TIMER-INTERRUPT", Prim_dos_high_priority_timer, 2, 2, + "High-priority timer interrupt handler.") +{ + extern void EXFUN (dos_process_timer_interrupt, (void)); + PRIMITIVE_HEADER (2); + + consume_typeahead (); + dos_process_timer_interrupt (); + CLEAR_INTERRUPT (INT_Global_GC); + PRIMITIVE_RETURN (UNSPECIFIC); +} static void DEFUN (key_buffer_insert_self, (c), unsigned char c) @@ -319,12 +342,13 @@ DEFUN (key_buffer_insert_self, (c), unsigned char c) if (key_buffer.length != CONIO_BUFFER_SIZE) { key_buffer.buffer[key_buffer.length++] = c; - ( (c == LINEFEED) - ? dos_console_write(crlf, sizeof(crlf)) - : dos_console_write(&c, 1) ); + if (c == LINEFEED) + dos_console_write (crlf, (sizeof (crlf))); + else + dos_console_write (&c, 1); } return; -} +} static void DEFUN_VOID (key_buffer_erase_character) @@ -334,27 +358,26 @@ DEFUN_VOID (key_buffer_erase_character) if (key_buffer.length != 0) { key_buffer.length -= 1; - dos_console_write(erase, sizeof(erase)); + dos_console_write (erase, (sizeof (erase))); } return; } static void DEFUN_VOID(key_buffer_to_line_buffer) -{ register size_t i = 0; +{ + register size_t i = 0; register size_t j = 0; - while ((i < key_buffer.length)&&(line_buffer.length != CONIO_BUFFER_SIZE)) + while ((i < key_buffer.length) + && (line_buffer.length != CONIO_BUFFER_SIZE)) line_buffer.buffer[line_buffer.length++] = key_buffer.buffer[i++]; while (i < key_buffer.length) key_buffer.buffer[j++] = key_buffer.buffer[i++]; key_buffer.length = j; - return; } - - void DEFUN_VOID (flush_conio_buffers) { @@ -366,19 +389,34 @@ DEFUN_VOID (flush_conio_buffers) void DEFUN_VOID (DOS_initialize_conio) -{ void initialize_keyboard_interrupt_table(void); - - flush_conio_buffers(); - initialize_keyboard_interrupt_table(); - initialize_scancode_table(); +{ + void initialize_keyboard_interrupt_table (void); + flush_conio_buffers (); + initialize_keyboard_interrupt_table (); + initialize_scancode_table (); return; } +extern void EXFUN (DOS_initialize_fov, (SCHEME_OBJECT)); + +void +DEFUN (DOS_initialize_fov, (fov), SCHEME_OBJECT fov) +{ + extern SCHEME_OBJECT EXFUN (make_primitive, (unsigned char *)); + SCHEME_OBJECT iv, prim; + + prim = (make_primitive ("DOS-HIGH-PRIORITY-TIMER-INTERRUPT")); + iv = (FAST_VECTOR_REF (fov, System_Interrupt_Vector)); + VECTOR_SET (iv, Global_GC_Level, prim); + + return; +} static int -DEFUN(empty_line_buffer, (buffer, nbytes), char * buffer AND size_t nbytes) -{ register size_t i, j; +DEFUN (empty_line_buffer, (buffer, nbytes), char * buffer AND size_t nbytes) +{ + register size_t i, j; for (i = 0; ((i < line_buffer.length)&&(i < nbytes)); i++) *buffer++ = line_buffer.buffer[i]; @@ -386,9 +424,8 @@ DEFUN(empty_line_buffer, (buffer, nbytes), char * buffer AND size_t nbytes) for (j = 0; i < line_buffer.length; i++, j++) line_buffer.buffer[j] = line_buffer.buffer[i]; line_buffer.length -= nbytes; - return nbytes; + return (nbytes); } - static void DEFUN (buffered_key_command, (c), unsigned char c) @@ -432,34 +469,35 @@ DEFUN(console_read, (buffer, nbytes, buffered_p, blocking_p), System_Error_Reset(); do { /* Get all pending characters into the buffer */ - while (typeahead_available_p()) + while (typeahead_available_p ()) { if (buffered_p) - buffered_key_command(get_typeahead_character()); - else /* Non buffered channel, in CScheme, also no echo. */ - non_buffered_key_command(get_typeahead_character()); + buffered_key_command (get_typeahead_character ()); + else + /* Non buffered channel, in CScheme, also no echo. */ + non_buffered_key_command (get_typeahead_character ()); } /* End WHILE */ /* Test for pending interrupts here: */ - if (pending_interrupts_p()) - { if (INTERRUPT_QUEUED_P(INT_Character)) - flush_conio_buffers(); - System_Error_Return(EINTR); + if (pending_interrupts_p ()) + { + if (INTERRUPT_QUEUED_P (INT_Character)) + flush_conio_buffers (); + System_Error_Return (EINTR); } /* Return if we buffered up a line, or channel is not buffered */ if (line_buffer.length != 0) - return empty_line_buffer(buffer, nbytes); + return (empty_line_buffer (buffer, nbytes)); } while (blocking_p); /* Keep reading for blocking channel. */ /* This means there is nothing available, don't block */ - System_Error_Return(ERRNO_NONBLOCK); + System_Error_Return (ERRNO_NONBLOCK); } - - + extern int EXFUN (text_write, (int fd AND CONST unsigned char * buffer AND size_t nbytes)); void DEFUN (console_write_string, (string), void * string) { - text_write(fileno(stdout), string, strlen((char *) string)); + text_write ((fileno(stdout)), string, strlen((char *) string)); return; } diff --git a/v7/src/microcode/doskbd.c b/v7/src/microcode/doskbd.c index 8b2786012..2f026bd68 100644 --- a/v7/src/microcode/doskbd.c +++ b/v7/src/microcode/doskbd.c @@ -1,6 +1,5 @@ /* -*-C-*- - -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/doskbd.c,v 1.7 1992/06/04 12:40:40 jinx Exp $ +$Id: doskbd.c,v 1.8 1992/09/03 07:30:46 jinx Exp $ Copyright (c) 1992 Massachusetts Institute of Technology @@ -53,6 +52,10 @@ MIT in each case. */ #undef getDS #endif +#ifdef getCS +#undef getCS +#endif + #include "dossys.h" #include "dosinsn.h" #include "doskbd.h" @@ -64,12 +67,20 @@ MIT in each case. */ #ifndef EFAULT # define EFAULT 2001 #endif + +/* These depend on the C compiler (Zortech) allocating them contiguosly. */ + +extern unsigned char scan_code_tables_start[]; +extern unsigned char scan_code_tables_end[]; /* Tables mapping scan codes to ASCII characters. Entries with NULL (\0) should not be mapped by the Scheme keyboard ISR. Let the default handler map them. */ +unsigned char +scan_code_tables_start[] = "foo"; + static unsigned char shifted_scan_code_to_ascii[] = { @@ -132,7 +143,7 @@ shifted_scan_code_to_ascii[] = '\0', /* 56 */ ' ' /* 57 */ }; - + static unsigned char unshifted_scan_code_to_ascii[] = { @@ -197,6 +208,9 @@ unshifted_scan_code_to_ascii[] = }; static unsigned char modifier_mask = 0x4f; + +unsigned char +scan_code_tables_end[] = "bar"; union RM_address { @@ -229,16 +243,6 @@ under_QEMM_386_p (void) return (dos_false); } -dos_boolean -under_DPMI_p (void) -{ - union REGS regs; - - regs.e.eax = 0x1686; - int86 (0x2f, ®s, ®s); - return (regs.x.ax == 0); -} - static void normalize_RM_address (union RM_address * addr) { @@ -298,7 +302,7 @@ install_kbd_hook_p (char * var_name) #define DOS_KBD_FUNC_RECORD_KEYSTROKE 0x5 int -bios_keyboard_handler(struct INT_DATA *pd) +bios_keyboard_handler (struct INT_DATA *pd) { unsigned char scan_code, chord, ascii; union REGS regs; @@ -783,129 +787,80 @@ DPMI_restore_kbd_hook (void) #if defined(DPMI_RM_HANDLER_REAL) || defined(DOSX_RM_HANDLER_REAL) -unsigned char RM_handler_pattern[] = -{ - /* chain: */ -0x9d, /* 0 popf */ -0xea,0,0,0,0, /* 1 jmpf next_in_chain */ - /* kbd_isr: */ -0x9c, /* 6 pushf */ -0x80,0xfc,0x4f, /* 7 cmp ah,4fh */ -0x75,0xf4, /* a jne chain */ -0x3c,0x39, /* c cmp al,39h */ -0x77,0xf0, /* e ja chain */ -0x53, /* 10 push bx ; Preserve bx */ -0x50, /* 11 push ax ; Preserve scan code */ -0xb4,2, /* 12 mov ah,2h */ -0xcd,0x16, /* 14 int 16h ; Get modifier bits */ -0x2e,0x22,6,0xf4,0, /* 16 and al,cs:modifier mask */ -0x5b, /* 1b pop bx ; Get scan code */ -0x53, /* 1c push bx */ -0x81,0xe3,0x3f,0, /* 1d and bx,3fh ; Drop fncn */ -0x3c,8, /* 21 cmp al,8h ; Only meta bit set? */ -0x74,0xb, /* 23 je do_unshifted */ -0x3c,0, /* 25 cmp al,0 ; No modifier bits set? */ -0x74,7, /* 27 je do_unshifted */ - /* do_shifted: */ -0x2e,0x8a,0x9f,0x80,0, /* 29 mov bl,cs:shifted_table[bx] */ -0xeb,5, /* 2e jmp merge */ - /* do_unshifted: */ -0x2e,0x8a,0x9f,0xba,0, /* 30 mov bl,cs:unshifted_table[bx] */ - /* merge: */ -0x80,0xfb,0, /* 35 cmp bl,0 ; No translation? */ -0x74,0x37, /* 38 je abort_translation */ -0x0f,0xba,0xe0,2, /* 3a bt al,2h ; Control set? */ -0x73,3, /* 3e jnc after_ctrl */ -0x80,0xe3,0x9f, /* 40 and bl,09fh ; controlify */ - /* after_ctrl: */ -0x0f,0xba,0xe0,3, /* 43 bt al,3h ; Alt set? */ -0x73,3, /* 47 jnc after_meta */ -0x80,0xcb,0x80, /* 49 or bl,080h ; metify */ - /* after_meta: */ -0x80,0xfb,0xf0, /* 4c cmp bl,0f0h ; M-p ? */ -0x74,0x20, /* 4f je abort_translation */ -0x58, /* 51 pop ax */ -0x51, /* 52 push cx ; Preserve cx */ -0x50, /* 53 push ax */ -0x8a,0xe8, /* 54 mov ch,al ; Scan code */ -0x80,0xfb,0, /* 56 cmp bl,0 ; C-Space? */ -0x75,2, /* 59 jne after_ctrl_space */ -0xb5,3, /* 5b mov ch,3 ; Fudge scan code */ - /* after_ctrl_space: */ -0x8a,0xcb, /* 5d mov cl,bl ; ASCII value */ -0xb4,5, /* 5f mov ah,05h ; fcn. number */ -0xcd,0x16, /* 61 int 16h ; Record keystroke */ -0x58, /* 63 pop ax ; Restore registers */ -0x59, /* 64 pop cx */ -0x5b, /* 65 pop bx */ -0x55, /* 66 push bp */ -0x8b,0xec, /* 67 mov bp,sp */ -0x80,0x66,8,0xfe, /* 69 and 8[bp],0feh ; clc iret's flags */ -0x5d, /* 6d pop bp */ -0x9d, /* 6e popf */ -0xf8, /* 6f clc */ -0xcf, /* 70 iret */ - /* abort_translation: */ -0x58, /* 71 pop ax */ -0x5b, /* 72 pop bx */ -0xeb,0x8b /* 73 jmp chain */ - /* 75 PAD */ -}; - -#define PATTERN_SIZE 0x75 -#define PADDED_PATTERN_SIZE 0x80 -#define PATTERN_CHAIN_OFFSET 2 -#define PATTERN_START_OFFSET 6 -#define RM_ISR_TABLE_SIZE 0x3a -#define RM_ISR_TOTAL_SIZE \ - (PADDED_PATTERN_SIZE + (2 * RM_ISR_TABLE_SIZE) + 1) -#define RM_ISR_MASK_OFFSET (RM_ISR_TOTAL_SIZE - 1) +static unsigned shifted_table_offset = 0; +static unsigned unshifted_table_offset = 0; +#define PATTERN_MODIFIER_OFFSET 0 +#define PATTERN_SHIFTED_PTR_OFFSET 2 +#define PATTERN_UNSHIFTED_PTR_OFFSET 4 +#define PATTERN_CHAIN_OFFSET 8 +#define PATTERN_START_OFFSET 12 + +#define RM_ISR_MASK_OFFSET PATTERN_MODIFIER_OFFSET + static void * -make_RM_handler (void) +make_RM_handler (unsigned * size, unsigned * offset, unsigned * delta) { - unsigned char * copy; + extern void RM_keyboard_pattern_start (void); + extern void RM_keyboard_pattern_end (void); + unsigned long pattern_start, start_offset; + unsigned long pattern_size, total_size; unsigned short * wordptr; + unsigned char * copy; + union REGS regs; - if (((sizeof (RM_handler_pattern)) != PATTERN_SIZE) - || ((sizeof (shifted_scan_code_to_ascii)) != RM_ISR_TABLE_SIZE) - || ((sizeof (unshifted_scan_code_to_ascii)) != RM_ISR_TABLE_SIZE) - || (RM_ISR_MASK_OFFSET != 0xf4)) - { - fprintf (stderr, "make_RM_handler: Inconsistent sizes!\n"); - fprintf (stderr, " PATTERN_SIZE = %d\n", PATTERN_SIZE); - fprintf (stderr, "and (sizeof (RM_handler_pattern)) = %d\n", - (sizeof (RM_handler_pattern))); - fprintf (stderr, " RM_ISR_TABLE_SIZE = %d\n", - RM_ISR_TABLE_SIZE); - - fprintf (stderr, "and (sizeof (shifted_scan_code_to_ascii)) = %d\n", - (sizeof (shifted_scan_code_to_ascii))); - fprintf (stderr, "and (sizeof (unshifted_scan_code_to_ascii)) = %d\n", - (sizeof (unshifted_scan_code_to_ascii))); - fprintf (stderr, " RM_ISR_MASK_OFFSET = 0x%x <> 0xf4", - RM_ISR_MASK_OFFSET); - errno = EFAULT; - return ((void *) NULL); - } + regs.x.ax = 0x2509; + int86 (0x21, ®s, ®s); + start_offset = ((unsigned long) RM_keyboard_pattern_start); + pattern_start = ((((unsigned long) regs.x.bx) << 4) + start_offset); - copy = ((unsigned char *) (malloc (RM_ISR_TOTAL_SIZE))); + pattern_size = (((unsigned long) RM_keyboard_pattern_end) - start_offset); + total_size = (pattern_size + + (sizeof (shifted_scan_code_to_ascii)) + + (sizeof (unshifted_scan_code_to_ascii))); + + copy = ((unsigned char *) (malloc (total_size))); if (copy == ((unsigned char *) NULL)) return ((void *) NULL); - memcpy (copy, RM_handler_pattern, (sizeof (RM_handler_pattern))); - memcpy ((copy + PADDED_PATTERN_SIZE), + farcpy (((unsigned) copy), (getDS ()), + ((unsigned) pattern_start), (regs.e.edx >> 16), + pattern_size); + + if (copy[PATTERN_START_OFFSET] != ((unsigned char) 0x9c)) + { + fprintf (stderr, "make_RM_handler: Bad pattern!\n"); + fprintf (stderr, "\tpattern_start = 0x%lx, pattern_size = %d.\n", + pattern_start, pattern_size); + fprintf (stderr, "\tselector = 0x%x; segment = 0x%x; start_offset = 0x%x.\n", + (regs.e.edx >> 16), regs.x.bx, start_offset); + free (copy); + return ((void *) NULL); + } + + memcpy ((copy + pattern_size), shifted_scan_code_to_ascii, - RM_ISR_TABLE_SIZE); - memcpy ((copy + PADDED_PATTERN_SIZE + RM_ISR_TABLE_SIZE), - unshifted_scan_code_to_ascii, - RM_ISR_TABLE_SIZE); + (sizeof (shifted_scan_code_to_ascii))); + memcpy ((copy + (pattern_size + (sizeof (shifted_scan_code_to_ascii)))), + unshifted_scan_code_to_ascii, + (sizeof (unshifted_scan_code_to_ascii))); + + copy[PATTERN_MODIFIER_OFFSET] = modifier_mask; + wordptr = ((unsigned short *) (copy + PATTERN_SHIFTED_PTR_OFFSET)); + * wordptr = (pattern_size + start_offset); + wordptr = ((unsigned short *) (copy + PATTERN_UNSHIFTED_PTR_OFFSET)); + * wordptr = ((pattern_size + (sizeof (shifted_scan_code_to_ascii))) + + start_offset); wordptr = ((unsigned short *) (copy + PATTERN_CHAIN_OFFSET)); * wordptr++ = old_RM_vector.x.off; * wordptr = old_RM_vector.x.seg; - * (copy + RM_ISR_MASK_OFFSET) = modifier_mask; + * delta = start_offset; + * size = total_size; + * offset = PATTERN_START_OFFSET; + shifted_table_offset = pattern_size; + unshifted_table_offset = (pattern_size + (sizeof (shifted_scan_code_to_ascii))); return ((void *) copy); } @@ -1011,10 +966,12 @@ DPMI_install_kbd_hook (void) { void * RM_handler; - unsigned short real_mode_segment; + unsigned handler_size, entry_offset, relocation; unsigned short prot_mode_selector; + unsigned short real_mode_segment; + unsigned long base_addr; - RM_handler = (make_RM_handler ()); + RM_handler = (make_RM_handler (& handler_size, & entry_offset, & relocation)); if (RM_handler == ((void *) NULL)) { int saved_errno = errno; @@ -1024,7 +981,7 @@ DPMI_install_kbd_hook (void) return (DOS_FAILURE); } - if ((DPMI_allocate_DOS_block (RM_ISR_TOTAL_SIZE, + if ((DPMI_allocate_DOS_block (handler_size, & real_mode_segment, & prot_mode_selector)) != DOS_SUCCESS) @@ -1037,11 +994,13 @@ DPMI_install_kbd_hook (void) farcpy (0, prot_mode_selector, ((unsigned) RM_handler), (getDS ()), - RM_ISR_TOTAL_SIZE); + handler_size); + + base_addr = ((((unsigned long) real_mode_segment) << 4) - relocation); if ((DPMI_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES, - PATTERN_START_OFFSET, - real_mode_segment)) + (entry_offset + relocation), + (base_addr >> 4))) != DOS_SUCCESS) { DPMI_free_DOS_block (prot_mode_selector); @@ -1060,6 +1019,51 @@ DPMI_install_kbd_hook (void) return (DOS_SUCCESS); } +static void +DPMI_set_modifier_mask (unsigned char new_mask) +{ +#ifdef DPMI_RM_HANDLER_REAL + + if (DPMI_RM_selector != 0) + farcpy (RM_ISR_MASK_OFFSET, DPMI_RM_selector, + ((unsigned) (& new_mask)), (getDS ()), + 1); + +#endif /* DPMI_RM_HANDLER_REAL */ + return; +} + +static void +DPMI_set_kbd_translation (unsigned shift_p, + unsigned scan_code, + unsigned char new) +{ +#ifdef DPMI_RM_HANDLER_REAL + + if (DPMI_RM_selector != 0) + farcpy ((scan_code + ((shift_p != 0) + ? shifted_table_offset + : unshifted_table_offset)), + DPMI_RM_selector, + ((unsigned) (& new)), + (getDS ()), + 1); + +#endif /* DPMI_RM_HANDLER_REAL */ + + return; +} + +dos_boolean +under_DPMI_p (void) +{ + union REGS regs; + + regs.e.eax = 0x1686; + int86 (0x2f, ®s, ®s); + return (regs.x.ax == 0); +} + #ifdef DOSX_RM_HANDLER_REAL static unsigned short DOSX_RM_segment = 0; #endif /* DOSX_RM_HANDLER_REAL */ @@ -1111,18 +1115,20 @@ DOSX_install_kbd_hook (void) { void * RM_handler; union RM_address new_handler; + unsigned handler_size, entry_offset, relocation; + unsigned long base_addr; DOSX_RM_getvector (DOS_INTVECT_SYSTEM_SERVICES, ((unsigned *) & old_RM_vector)); - RM_handler = (make_RM_handler ()); + RM_handler = (make_RM_handler (& handler_size, & entry_offset, & relocation)); if (RM_handler == ((void *) NULL)) return (DOS_FAILURE); #if 0 if ((DOSX_convert_PM_to_RM_address ((getDS ()), ((unsigned) RM_handler), - RM_ISR_TOTAL_SIZE, + handler_size, ((unsigned *) & new_handler))) != DOS_SUCCESS) { @@ -1142,7 +1148,11 @@ DOSX_install_kbd_hook (void) return (DOS_FAILURE); } - normalize_RM_address (& new_handler); + base_addr = (((new_handler.x.seg << 4) + (new_handler.x.off)) + - relocation); + new_handler.x.seg = (base_addr >> 4); + new_handler.x.off = (base_addr & 0xf); + new_handler.x.off += (relocation + entry_offset); if ((DOSX_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES, ((unsigned) new_handler))) @@ -1156,7 +1166,7 @@ DOSX_install_kbd_hook (void) #else /* not 0 */ - if ((DOSX_allocate_DOS_block (RM_ISR_TOTAL_SIZE, &new_handler.x.seg)) + if ((DOSX_allocate_DOS_block (handler_size, &new_handler.x.seg)) != DOS_SUCCESS) { int saved_errno = errno; @@ -1165,7 +1175,6 @@ DOSX_install_kbd_hook (void) errno = saved_errno; return (DOS_FAILURE); } - new_handler.x.off = 0; /* This assumes that the bottom 1 Mb of memory is mapped to the DOS memory, so it can be accessed directly. @@ -1173,18 +1182,25 @@ DOSX_install_kbd_hook (void) memcpy (((void *) ((unsigned long) new_handler.x.seg << 4)), RM_handler, - RM_ISR_TOTAL_SIZE); + handler_size); + + DOSX_RM_segment = new_handler.x.seg; + + base_addr = ((new_handler.x.seg << 4) - relocation) + new_handler.x.seg = (base_addr >> 4); + new_handler.x.off = (base_addr & 0xf); + new_handler.x.off += (relocation + entry_offset); if ((DOSX_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES, new_handler.fp)) != DOS_SUCCESS) { - DOSX_free_DOS_block (new_handler.x.seg); + DOSX_free_DOS_block (DOSX_RM_segment); + DOSX_RM_segment = 0; fflush (stdout); free (RM_handler); errno = EFAULT; return (DOS_FAILURE); } - DOSX_RM_segment = new_handler.x.seg; #endif /* 0 */ @@ -1243,45 +1259,165 @@ DOSX_restore_kbd_hook (void) return (DOS_SUCCESS); } -int -dos_install_kbd_hook (void) +static void +DOSX_set_modifier_mask (unsigned char new_mask) { - if (scheme_PM_vector != ((void *) NULL)) - { - errno = ELOOP; +#ifdef DOSX_RM_HANDLER_REAL + + if (DOSX_RM_segment != 0) + (* ((unsigned char *) + ((((unsigned long) DOSX_RM_segment) << 4) + RM_ISR_MASK_OFFSET))) + = new_mask; + +#endif /* DOSX_RM_HANDLER_REAL */ + return; +} + +static void +DOSX_set_kbd_translation (unsigned shift_p, + unsigned scan_code, + unsigned char new) +{ +#ifdef DOSX_RM_HANDLER_REAL + + if (DOSX_RM_segment != 0) + (* ((unsigned char *) + ((((unsigned long) DOSX_RM_segment) << 4) + + (scan_code + ((shift_p != 0) + ? shifted_table_offset + : unshifted_table_offset))))) + = new; + +#endif /* DOSX_RM_HANDLER_REAL */ + return; +} + +static dos_boolean +under_DOSX_p (void) +{ + return (dos_true); +} + +/* Zortech's int_intercept does not work consistently with X32. + Here is alternative lower-level code. + */ + +extern dos_boolean EXFUN (under_X32_p, (void)); + +static int +X32_install_kbd_hook (void) +{ + extern int EXFUN (X32_int_intercept, (unsigned, void (*) (void), PTR)); + extern void EXFUN (X32_keyboard_interrupt, (void)); + extern PTR X32_kbd_interrupt_pointers[]; + extern int X32_kbd_interrupt_previous; + + X32_kbd_interrupt_pointers[0] = ((PTR) &modifier_mask); + X32_kbd_interrupt_pointers[1] = ((PTR) &unshifted_scan_code_to_ascii[0]); + X32_kbd_interrupt_pointers[2] = ((PTR) &shifted_scan_code_to_ascii[0]); + + if ((X32_int_intercept (DOS_INTVECT_SYSTEM_SERVICES, + X32_keyboard_interrupt, + ((PTR) &X32_kbd_interrupt_previous))) + != 0) return (DOS_FAILURE); - } - if (under_DPMI_p ()) - return (DPMI_install_kbd_hook ()); - else - return (DOSX_install_kbd_hook ()); + return (DOS_SUCCESS); } -int -dos_restore_kbd_hook (void) +static int +X32_restore_kbd_hook (void) { - if ((scheme_PM_vector == ((void *) NULL)) - && (scheme_RM_vector == ((void *) NULL))) - return (DOS_SUCCESS); - else if (!under_DPMI_p ()) - { - if ((DOSX_restore_kbd_hook ()) != DOS_SUCCESS) - return (DOS_FAILURE); - } - else if ((DPMI_restore_kbd_hook ()) != DOS_SUCCESS) + extern int EXFUN (X32_interrupt_restore, (unsigned)); + + if ((X32_interrupt_restore (DOS_INTVECT_SYSTEM_SERVICES)) != 0) return (DOS_FAILURE); + return (DOS_SUCCESS); +} - if (scheme_PM_vector != ((void *) NULL)) +static void +X32_set_modifier_mask (unsigned char new_mask) +{ + return; +} + +static void +X32_set_kbd_translation (unsigned shift_p, + unsigned scan_code, + unsigned char new) +{ + return; +} + +struct keyboard_method_s +{ + dos_boolean (* present) (void); + int (* install) (void); + int (* restore) (void); + void (* set_modifier_mask) (unsigned char); + void (* set_kbd_translation) (unsigned, unsigned, unsigned char); +}; + +static struct keyboard_method_s keyboard_methods[] = +{ { - free (scheme_PM_vector); - scheme_PM_vector = ((void *) NULL); + under_DPMI_p, + DPMI_install_kbd_hook, + DPMI_restore_kbd_hook, + DPMI_set_modifier_mask, + DPMI_set_kbd_translation + }, + { + under_X32_p, + X32_install_kbd_hook, + X32_restore_kbd_hook, + X32_set_modifier_mask, + X32_set_kbd_translation + }, + { + under_DOSX_p, + DOSX_install_kbd_hook, + DOSX_restore_kbd_hook, + DOSX_set_modifier_mask, + DOSX_set_kbd_translation } - if (scheme_RM_vector != ((void *) NULL)) +}; + +struct keyboard_method_s * + installed_keyboard_method = ((struct keyboard_method_s *) NULL); + +#define N_KEYBOARD_METHODS \ + ((sizeof (keyboard_methods)) / (sizeof (struct keyboard_method_s))) + +int +dos_install_kbd_hook (void) +{ + int i, result; + + for (i = 0; i < N_KEYBOARD_METHODS; i++) { - free (scheme_RM_vector); - scheme_RM_vector = ((void *) NULL); + if ((* (keyboard_methods[i].present)) ()) + { + result = ((* (keyboard_methods[i].install)) ()); + if (result == DOS_SUCCESS) + installed_keyboard_method = &keyboard_methods[i]; + return (result); + } } - return (DOS_SUCCESS); + return (DOS_FAILURE); +} + +int +dos_restore_kbd_hook (void) +{ + int result; + + if (installed_keyboard_method == ((struct keyboard_method_s *) NULL)) + return (DOS_SUCCESS); + + result = (* (installed_keyboard_method->restore)) (); + if (result == DOS_SUCCESS) + installed_keyboard_method = ((struct keyboard_method_s *) NULL); + return (result); } unsigned char @@ -1291,38 +1427,15 @@ dos_set_kbd_modifier_mask (unsigned char new_mask) modifier_mask = new_mask; -#ifdef DPMI_RM_HANDLER_REAL - - if (DPMI_RM_selector != 0) - farcpy (RM_ISR_MASK_OFFSET, DPMI_RM_selector, - ((unsigned) (& modifier_mask)), (getDS ()), - 1); - -#endif /* DPMI_RM_HANDLER_REAL */ - -#ifdef DOSX_RM_HANDLER_REAL - - if (DOSX_RM_segment != 0) - (* ((unsigned char *) - ((((unsigned long) DOSX_RM_segment) << 4) + RM_ISR_MASK_OFFSET))) - = modifier_mask; - -#endif /* DOSX_RM_HANDLER_REAL */ + if (installed_keyboard_method != ((struct keyboard_method_s *) NULL)) + (* (installed_keyboard_method->set_modifier_mask)) (modifier_mask); return (old_mask); } - + extern int EXFUN (dos_set_kbd_translation, (unsigned, unsigned, unsigned char)); -#ifndef PADDED_PATTERN_SIZE -# define PADDED_PATTERN_SIZE 0 -#endif - -#ifndef RM_ISR_TABLE_SIZE -# define RM_ISR_TABLE_SIZE 0 -#endif - int dos_set_kbd_translation (unsigned shift_p, unsigned scan_code, @@ -1330,44 +1443,20 @@ dos_set_kbd_translation (unsigned shift_p, { unsigned char old; unsigned char * table; - unsigned offset; if (scan_code >= (sizeof (shifted_scan_code_to_ascii))) return (-1); if (shift_p != 0) - { table = &shifted_scan_code_to_ascii[0]; - offset = PADDED_PATTERN_SIZE; - } else - { table = &unshifted_scan_code_to_ascii[0]; - offset = (PADDED_PATTERN_SIZE + RM_ISR_TABLE_SIZE); - } + old = table[scan_code]; table[scan_code] = new; - -#ifdef DPMI_RM_HANDLER_REAL - - if (DPMI_RM_selector != 0) - farcpy ((offset + scan_code), - DPMI_RM_selector, - ((unsigned) (& table[scan_code])), - (getDS ()), - 1); - -#endif /* DPMI_RM_HANDLER_REAL */ - -#ifdef DOSX_RM_HANDLER_REAL - - if (DOSX_RM_segment != 0) - (* ((unsigned char *) - ((((unsigned long) DOSX_RM_segment) << 4) + offset))) - = new; - -#endif /* DOSX_RM_HANDLER_REAL */ + if (installed_keyboard_method != ((struct keyboard_method_s *) NULL)) + (* (installed_keyboard_method->set_kbd_translation)) (shift_p, scan_code, new); - return (old); + return ((int) old); } diff --git a/v7/src/microcode/doskbutl.asm b/v7/src/microcode/doskbutl.asm index 2147b9daf..57de4b2e8 100644 --- a/v7/src/microcode/doskbutl.asm +++ b/v7/src/microcode/doskbutl.asm @@ -1,6 +1,6 @@ ;;; -*-Midas-*- ;;; -;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/doskbutl.asm,v 1.3 1992/07/28 14:30:04 jinx Exp $ +;;; $Id: doskbutl.asm,v 1.4 1992/09/03 07:30:20 jinx Exp $ ;;; ;;; Copyright (c) 1992 Massachusetts Institute of Technology ;;; @@ -53,8 +53,9 @@ ;;4 offset for shifted table ;;0 DS for scan_code to ascii tables - public _DOSX_scheme_system_isr - public _DPMI_PM_scheme_system_isr + extrn scheme_system_isr:near + public _DOSX_scheme_system_isr + public _DPMI_PM_scheme_system_isr _DOSX_scheme_system_isr: _DPMI_PM_scheme_system_isr: @@ -119,111 +120,110 @@ DPMI_scheme_system_dismiss: lea esp,24[esp] ; pop args iret ; tell DPMI we're done -;; Stack on entry to scheme_system_isr -;; -;;24 address of modifier mask -;;20 offset for unshifted table -;;16 offset for shifted table -;;12 DS for scan_code to ascii tables -;;8 Flags to restore/modify -;;4 EIP for low-level hook (DPMI or DOSX) -;;0 Old ebp [pushed on entry] -;; -;; Arguments: -;; AL = scan code -;; AH = 4fh -;; CF set -;; -;; Return: -;; AL = scan code -;; CF clear if scan code should be ignored (interrupt dismissed). - -chain_to_next_handler: - stc ; set the carry flag - ret - -scheme_system_isr: +;; These macros taken from x32's mac32.asm + +;Macro for start of a real mode code segment +start16code macro +__X386_CODESEG_16 segment para use16 public 'CODE' +assume cs:__X386_CODESEG_16,ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing +endm + +;Macro for end of real mode code segment +end16code macro +__X386_CODESEG_16 ends +endm + +start16code + public _RM_keyboard_pattern_start +_RM_keyboard_pattern_start: + +modifier_mask: + db 2 dup (0) +shifted_table_offset: + db 2 dup (0) +unshifted_table_offset: + db 2 dup (0) + +chain: + popf + db 0eah ; jmpf next_in_chain + db 4 dup (0) + +kbd_isr: + pushf cmp ah,4fh - jne chain_to_next_handler + jne chain cmp al,39h - ja chain_to_next_handler - -;; process a keystroke - - push ebp - mov ebp,esp - push eax ; Preserve accross interrupt - - mov ah,2h ; Get shift bits - int 16h ; Return in AL - - push ecx - push edx ; Preserve regs - push es - - mov edx,12[ebp] ; Segment selector - push edx - pop es - - mov edx,24[ebp] ; Modifier mask address - and al,es:[edx] ; Ignore modifiers - push eax ; Save result - - mov ecx,-4[ebp] ; Scan code + function number - and ecx,3fh ; Only scan code - mov edx,20[ebp] ; Unshifted table offset - and eax,47h ; Shift, ctrl, and CAPS-LOCK mask - cmp al,0 - je index_into_table - mov edx,16[ebp] ; Shifted table offset - -index_into_table: - mov al,es:[edx] [ecx] ; Get ASCII value - pop edx ; Masked modifier bits - cmp al,0 ; Null entries mean chain - je abort_translation - - bt edx,2 ; Control set? - jnc after_control - and al,09fh ; Clear bits 6 and 5 - -after_control: - bt edx,3 ; Alt set? - jnc after_meta - or al,080h ; Set bit 8 - + ja chain + push bx ; Preserve bx + push ax ; Preserve scan code + mov ah,2h + int 16h ; Get modifier bits + and al,byte ptr cs:modifier_mask + pop bx ; Get scan code + push bx + and bx,3fh ; Drop fncn + cmp al,8h ; Only meta bit set? + je do_unshifted + cmp al,0 ; No modifier bits set? + je do_unshifted +do_shifted: + push si + mov si,word ptr cs:shifted_table_offset + mov bl,byte ptr cs:[bx+si] + pop si + jmp merge +do_unshifted: + push si + mov si,word ptr cs:unshifted_table_offset + mov bl,byte ptr cs:[bx+si] + pop si +merge: + cmp bl,0 ; No translation? + je abort_translation + ; bt al,2h ; Control set? + db 0fh,0bah,0e0h,2 ; bt al,2h + jnc after_ctrl + and bl,09fh ; controlify +after_ctrl: + ; bt al,3h ; Alt set? + db 0fh,0bah,0e0h,3 + jnc after_meta + or bl,080h ; metify after_meta: - cmp al,0f0h ; M-p ? + cmp bl,0f0h ; M-p ? je abort_translation - mov ecx,-4[ebp] ; Get scan code - - cmp al,0 ; C-Space ? + pop ax + push cx ; Preserve cx + push ax + mov ch,al ; Scan code + cmp bl,0 ; C-Space? jne after_ctrl_space - mov cl,3 ; Fudge scan code - + mov ch,3 ; Fudge scan code after_ctrl_space: - mov ch,cl - mov cl,al ; Transfer ASCII value - - mov ah,5h ; Insert keystroke - int 16h ; CH = scan code, CL = ASCII - ; returns AL = 0h if win, 1h if buffer full - - and byte ptr 8[ebp],0feh ; clear interrupt carry flag - pop es - pop edx - pop ecx - pop eax - pop ebp - clc ; clear our carry flag - ret + mov cl,bl ; ASCII value + mov ah,05h ; fcn. number + int 16h ; Record keystroke + pop ax ; Restore registers + pop cx + pop bx + push bp + mov bp,sp + and 8[bp],0feh ; clc iret's flags + pop bp + popf + clc + iret abort_translation: - pop es - pop edx - pop ecx - pop eax - pop ebp - stc ; set carry flag - ret + pop ax + pop bx + jmp chain + + public _RM_keyboard_pattern_end +_RM_keyboard_pattern_end: + nop + +end16code + end diff --git a/v7/src/microcode/dosscan.h b/v7/src/microcode/dosscan.h index 0332640db..b71f62c97 100644 --- a/v7/src/microcode/dosscan.h +++ b/v7/src/microcode/dosscan.h @@ -1,6 +1,6 @@ /* -*-C-*- -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosscan.h,v 1.1 1992/05/05 06:55:13 jinx Exp $ +$Id: dosscan.h,v 1.2 1992/09/03 07:29:58 jinx Exp $ Copyright (c) 1992 Massachusetts Institute of Technology @@ -44,6 +44,8 @@ MIT in each case. */ #define NO_CONVERSION ((unsigned char *) ((void *) 0)) unsigned char CTRL_AT[] = { '\0' }; +unsigned char HARD_ATTN[] = "This is hard attention"; +unsigned char SOFT_ATTN[] = "This is soft attention"; unsigned char META_a[] = {Metafy('a'), '\0'}; unsigned char META_b[] = {Metafy('b'), '\0'}; unsigned char META_c[] = {Metafy('c'), '\0'}; @@ -235,9 +237,9 @@ unsigned char META_PLUS[] = {Metafy('+'), '\0'}; /* 135 */ NO_CONVERSION, \ /* 136 */ NO_CONVERSION, \ /* 137 */ NO_CONVERSION, \ -/* 138 */ NO_CONVERSION, \ +/* 138 */ HARD_ATTN, /* Ctrl-F12 */ \ /* 139 */ NO_CONVERSION, \ -/* 140 */ NO_CONVERSION, \ +/* 140 */ SOFT_ATTN, /* Alt-F12 */ \ /* 141 */ NO_CONVERSION, \ /* 142 */ NO_CONVERSION, \ /* 143 */ NO_CONVERSION, \ diff --git a/v7/src/microcode/dossig.c b/v7/src/microcode/dossig.c index 2e5e5fe8d..2d57858d8 100644 --- a/v7/src/microcode/dossig.c +++ b/v7/src/microcode/dossig.c @@ -1,6 +1,6 @@ /* -*-C-*- -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dossig.c,v 1.4 1992/07/28 14:40:43 jinx Exp $ +$Id: dossig.c,v 1.5 1992/09/03 07:29:39 jinx Exp $ Copyright (c) 1992 Massachusetts Institute of Technology @@ -44,6 +44,8 @@ MIT in each case. */ #include "dossys.h" #include "dosexcp.h" #include "doskbd.h" + +cc_t EXFUN (DOS_interactive_interrupt_handler, (void)); /* Signal Manipulation */ @@ -232,12 +234,13 @@ DEFUN (ta_abort_handler, (ap), PTR ap) (((struct handler_record *) ap) -> handler)); } -#define CONTROL_B_INTERRUPT_CHAR 'B' -#define CONTROL_G_INTERRUPT_CHAR 'G' -#define CONTROL_U_INTERRUPT_CHAR 'U' -#define CONTROL_X_INTERRUPT_CHAR 'X' -#define GENERAL_INTERRUPT_CHAR '!' -#define NO_INTERRUPT_CHAR '0' +#define CONTROL_B_INTERRUPT_CHAR 'B' +#define CONTROL_G_INTERRUPT_CHAR 'G' +#define CONTROL_U_INTERRUPT_CHAR 'U' +#define CONTROL_X_INTERRUPT_CHAR 'X' +#define INTERACTIVE_INTERRUPT_CHAR '!' +#define TERMINATE_INTERRUPT_CHAR '@' +#define NO_INTERRUPT_CHAR '0' static void DEFUN (echo_keyboard_interrupt, (c, dc), cc_t c AND cc_t dc) @@ -264,12 +267,17 @@ DEFUN_STD_HANDLER (sighnd_control_g, DEFUN_STD_HANDLER (sighnd_control_c, { - tty_set_next_interrupt_char (GENERAL_INTERRUPT_CHAR); + cc_t int_char; + + int_char = (DOS_interactive_interrupt_handler ()); + if (int_char != ((cc_t) 0)) + tty_set_next_interrupt_char (int_char); }) /* Keyboard interrupt */ #define KB_INT_TABLE_SIZE ((256) + 1) +#define CONTROL_BREAK '\0' /* A lie. */ #define CONTROL_B '\002' #define CONTROL_C '\003' #define CONTROL_G '\007' @@ -280,7 +288,8 @@ DEFUN_STD_HANDLER (sighnd_control_c, #define CONTROL_G_ENABLE (0x2) #define CONTROL_U_ENABLE (0x4) #define CONTROL_X_ENABLE (0x8) -#define GENERAL_INTERRUPT_ENABLE (0x10) +#define INTERACTIVE_INTERRUPT_ENABLE (0x10) +#define TERMINATE_INTERRUPT_ENABLE (0x20) /* This is a table and also a null terminated string. */ unsigned char keyboard_interrupt_table[KB_INT_TABLE_SIZE]; @@ -289,20 +298,22 @@ static unsigned char keyboard_interrupt_enables; void DEFUN (OS_ctty_get_interrupt_enables, (mask), Tinterrupt_enables * mask) { - *mask = (Tinterrupt_enables) keyboard_interrupt_enables; + *mask = ((Tinterrupt_enables) keyboard_interrupt_enables); return; } void DEFUN (OS_ctty_set_interrupt_enables, (mask), Tinterrupt_enables * mask) { - keyboard_interrupt_enables = *mask; + /* Kludge: ctl-break always enabled. */ + keyboard_interrupt_enables = (((unsigned char) (*mask)) + | TERMINATE_INTERRUPT_ENABLE); return; } /* This is a temporary kludge. */ -#define NUM_INT_CHANNELS 5 +#define NUM_INT_CHANNELS 6 static cc_t int_chars[NUM_INT_CHANNELS]; static cc_t int_handlers[NUM_INT_CHANNELS]; @@ -337,7 +348,11 @@ DEFUN_VOID (update_interrupt_characters) break; case interrupt_handler_interactive: - handler = GENERAL_INTERRUPT_CHAR; + handler = INTERACTIVE_INTERRUPT_CHAR; + break; + + case interrupt_handler_terminate: + handler = TERMINATE_INTERRUPT_CHAR; break; default: @@ -404,71 +419,138 @@ DEFUN_VOID (initialize_keyboard_interrupt_table) int_handlers[3] = ((unsigned char) interrupt_handler_control_x); int_chars[4] = CONTROL_C; int_handlers[4] = ((unsigned char) interrupt_handler_interactive); + int_chars[5] = CONTROL_BREAK; + int_handlers[5] = ((unsigned char) interrupt_handler_terminate); update_interrupt_characters (); keyboard_interrupt_enables = - (CONTROL_B_ENABLE | CONTROL_G_ENABLE | CONTROL_U_ENABLE | - CONTROL_X_ENABLE | GENERAL_INTERRUPT_ENABLE); + (CONTROL_B_ENABLE | CONTROL_G_ENABLE + | CONTROL_U_ENABLE | CONTROL_X_ENABLE + | INTERACTIVE_INTERRUPT_ENABLE + | TERMINATE_INTERRUPT_ENABLE); + return; +} + +static int hard_attn_limit = 2; +static int hard_attn_counter = 0; + +cc_t +DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char) +{ + /* Scheme got a keyboard interrupt, reset the hard attention counter. */ + hard_attn_counter = 0; + return (int_char); +} + +static void +DEFUN_VOID (print_interrupt_help) +{ + console_write_string ("\nInterrupt Choices are:\n"); + console_write_string ("C-G interrupt: G, g, ^G (abort to top level)\n"); + console_write_string ("C-X interrupt: X, x, ^x (abort)\n"); + console_write_string ("C-B interrupt: B, b, ^B (break)\n"); + console_write_string ("C-U interrupt: U, u, ^U (up)\n"); + console_write_string ("Ignore interrupt: I, i (dismiss)\n"); + console_write_string ("Reset scheme: R, r (hard reset)\n"); + console_write_string ("Quit scheme: Q, q (exit)\n"); + console_write_string ("Print help: ?"); return; } +#define REQUEST_INTERRUPT_IF_ENABLED(mask) do \ +{ \ + if (keyboard_interrupt_enables & (mask)) \ + { \ + tty_set_next_interrupt_char (interrupt_char); \ + interrupt_p = 1; \ + } \ + else \ + interrupt_p = 0; \ +} while (0) + +int EXFUN (signal_keyboard_character_interrupt, (int)); + int -DEFUN (signal_keyboard_character_interrupt, (c), unsigned char c) +DEFUN (signal_keyboard_character_interrupt, (c), int c) { - if ((c >= 0) && (c < KB_INT_TABLE_SIZE)) - { int interrupt_char = keyboard_interrupt_table[c]; - int interrupt_p; + if (c == -1) + { + if (keyboard_interrupt_enables & TERMINATE_INTERRUPT_ENABLE) + goto interactive_interrupt; + else + return (0); + } + if (c == -2) + { + /* Special kludge for hard attn. */ + if (keyboard_interrupt_enables & TERMINATE_INTERRUPT_ENABLE) + { + hard_attn_counter += 1; + if (hard_attn_counter >= hard_attn_limit) + { + console_write_string ("\nTerminating scheme!"); + termination_normal (0); + } + goto interactive_interrupt; + } + return (0); + } + else if ((c >= 0) && (c < KB_INT_TABLE_SIZE)) + { + int interrupt_p, interrupt_char; + + interrupt_char = keyboard_interrupt_table[c]; -#define Request_Interrupt_If_Enabled(mask) \ - ( interrupt_p = \ - ( (keyboard_interrupt_enables&(mask)) \ - ? tty_set_next_interrupt_char (interrupt_char), 1 : 0 )) - switch (interrupt_char) { case CONTROL_B_INTERRUPT_CHAR: - Request_Interrupt_If_Enabled(CONTROL_B_ENABLE); break; + REQUEST_INTERRUPT_IF_ENABLED (CONTROL_B_ENABLE); + break; + case CONTROL_G_INTERRUPT_CHAR: - Request_Interrupt_If_Enabled(CONTROL_G_ENABLE); break; + REQUEST_INTERRUPT_IF_ENABLED (CONTROL_G_ENABLE); + break; + case CONTROL_U_INTERRUPT_CHAR: - Request_Interrupt_If_Enabled(CONTROL_U_ENABLE); break; + REQUEST_INTERRUPT_IF_ENABLED (CONTROL_U_ENABLE); + break; + case CONTROL_X_INTERRUPT_CHAR: - Request_Interrupt_If_Enabled(CONTROL_X_ENABLE); break; - case GENERAL_INTERRUPT_CHAR: - Request_Interrupt_If_Enabled(GENERAL_INTERRUPT_ENABLE); break; + REQUEST_INTERRUPT_IF_ENABLED (CONTROL_X_ENABLE); + break; + + case INTERACTIVE_INTERRUPT_CHAR: + if (! (keyboard_interrupt_enables & INTERACTIVE_INTERRUPT_ENABLE)) + { + interrupt_p = 0; + break; + } +interactive_interrupt: + { + cc_t int_char; + + int_char = (DOS_interactive_interrupt_handler ()); + if (int_char != ((cc_t) 0)) + { + tty_set_next_interrupt_char ((int) int_char); + interrupt_p = 1; + } + } + break; + default: interrupt_p = 0; } - return interrupt_p; + return (interrupt_p); } - return 0; -} - - -static void -DEFUN_VOID (print_interrupt_help) -{ - console_write_string("\nInterrupt Choices are:\n"); - console_write_string("C-G interrupt: G, g, ^G (abort to top level)\n"); - console_write_string("C-X interrupt: X, x, ^x (abort)\n"); - console_write_string("C-B interrupt: B, b, ^B (break)\n"); - console_write_string("C-U interrupt: U, u, ^U (up)\n"); - console_write_string("Quit scheme: Q, q\n"); - console_write_string("Print help: ?"); - - return; + return (0); } - + cc_t -DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char) -{ - if ((int_char == CONTROL_B_INTERRUPT_CHAR) || - (int_char == CONTROL_G_INTERRUPT_CHAR) || - (int_char == CONTROL_X_INTERRUPT_CHAR) || - (int_char == CONTROL_U_INTERRUPT_CHAR) ) - return int_char; - +DEFUN_VOID (DOS_interactive_interrupt_handler) +{ while (1) - { unsigned char response; + { + unsigned char response; console_write_string ("\nKeyboard interrupt, type character (? for help): "); @@ -488,6 +570,18 @@ DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char) case CONTROL_G: return CONTROL_G_INTERRUPT_CHAR; + case 'i': + case 'I': + return ((cc_t) 0); + + case 'R': + case 'r': + { + extern void EXFUN (soft_reset, (void)); + soft_reset (); + /*NOTREACHED*/ + } + case 'q': case 'Q': { @@ -526,8 +620,8 @@ DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char) print_interrupt_help (); break; } - } /* End CASE */ - } /* End WHILE */ + } + } } void @@ -548,7 +642,6 @@ DEFUN_VOID (OS_restartable_exit) stop_signal_default (SIGTSTP); } - #ifdef HAVE_ITIMER DEFUN_STD_HANDLER (sighnd_timer, @@ -625,6 +718,7 @@ DEFUN_STD_HANDLER (sighnd_dead_subprocess, /* PC specific low-level interrupt hooks */ /* Control-Break Interrupt */ + int DEFUN (control_break_handler, (pd), struct INT_DATA *pd) { @@ -635,23 +729,45 @@ DEFUN (control_break_handler, (pd), struct INT_DATA *pd) /* Interval timer */ /* Scheme timer emulation; DOS does not have an ITIMER like unix. */ -/* Zero means timer is not set. */ +/* Zero means timer is not set or has expired. */ -extern volatile unsigned long scm_itimer_counter; -extern volatile unsigned long scm_itimer_reload; -extern int EXFUN (bios_timer_handler, (struct INT_DATA *)); +extern unsigned long scm_itimer_counter; +extern unsigned long scm_itimer_reload; -int -DEFUN (bios_timer_handler, (pd), struct INT_DATA *pd) +unsigned long scm_itimer_counter = 0; +unsigned long scm_itimer_reload = 0; + +extern void EXFUN (dos_process_timer_interrupt, (void)); + +void +DEFUN_VOID (dos_process_timer_interrupt) { - if (scm_itimer_reload != 0) + if (scm_itimer_counter != 0) { if (--scm_itimer_counter == 0) { scm_itimer_counter = scm_itimer_reload; - request_timer_interrupt(); + request_timer_interrupt (); } } + return; +} + +extern int EXFUN (bios_timer_handler, (struct INT_DATA *)); + +int +DEFUN (bios_timer_handler, (pd), struct INT_DATA *pd) +{ +#if 0 + dos_process_timer_interrupt (); +#else + /* This is a kludge for DOS. + Reuse INT_Global_GC as a high-priority interrupt from + which the keyboard interrupt and real timer interrupt are + derived. + */ + REQUEST_INTERRUPT (INT_Global_GC); +#endif return (INTERRUPT_CHAIN_NEXT); } @@ -867,12 +983,13 @@ DEFUN_VOID (DOS_install_interrupts) extern int X32_timer_interrupt_previous; X32_asm_initialize (); + if ((X32_lock_scheme_microcode ()) != 0) { fprintf (stderr, "\n;; DOS_install_interrupts (X32): Unable to lock memory."); fprintf (stderr, - "\n;; Timer interrupt not available!\n"); + "\n;; Interrupt and exceptions handlers not available!\n"); fflush (stderr); return; } @@ -887,43 +1004,39 @@ DEFUN_VOID (DOS_install_interrupts) fprintf (stderr, "\n;; Timer interrupt not available!\n"); fflush (stderr); - return; } else dos_record_interrupt_interception (DOS_INTVECT_USER_TIMER_TICK, X32_interrupt_restore); - if ((dos_install_kbd_hook ()) == DOS_SUCCESS) - { - dos_record_interrupt_interception (DOS_INTVECT_SYSTEM_SERVICES, - DOS_restore_keyboard); - DOS_keyboard_intercepted_p = true; - } + install_exception_handlers (X32_get_exception_vector, X32_set_exception_handler, X32_restore_handler); } + else { scm_int_intercept (DOS_INTVECT_USER_TIMER_TICK, bios_timer_handler, 256); - if ((dos_install_kbd_hook ()) == DOS_SUCCESS) - { - dos_record_interrupt_interception (DOS_INTVECT_SYSTEM_SERVICES, - DOS_restore_keyboard); - DOS_keyboard_intercepted_p = true; - } - if (!under_DPMI_p ()) scm_int_intercept (DOS_INTVECT_KB_CTRL_BREAK, control_break_handler, 256); + else if (enable_DPMI_exceptions_p ()) install_exception_handlers (DPMI_get_exception_vector, DPMI_set_exception_handler, DPMI_restore_handler); } + + if ((dos_install_kbd_hook ()) == DOS_SUCCESS) + { + dos_record_interrupt_interception (DOS_INTVECT_SYSTEM_SERVICES, + DOS_restore_keyboard); + DOS_keyboard_intercepted_p = true; + } return; } diff --git a/v7/src/microcode/dosx32.c b/v7/src/microcode/dosx32.c index f9cdd0ccd..5c42ce2b1 100644 --- a/v7/src/microcode/dosx32.c +++ b/v7/src/microcode/dosx32.c @@ -1,6 +1,6 @@ /* -*-C-*- -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosx32.c,v 1.1 1992/07/28 17:55:42 jinx Exp $ +$Id: dosx32.c,v 1.2 1992/09/03 07:30:13 jinx Exp $ Copyright (c) 1992 Massachusetts Institute of Technology @@ -42,31 +42,25 @@ extern int EXFUN (X32_lock_scheme_microcode, (void)); extern int EXFUN (under_X32_p, (void)); -#ifdef USE_LOCKED_INT_INTERCEPT - -extern int EXFUN (locked_int_intercept, - (unsigned, - int (_cdecl * funcptr) (struct INT_DATA *), - unsigned)); - -extern void EXFUN (locked_int_restore, (unsigned)); - -/* Imports */ - -extern void EXFUN (int_service, (void)); - -#else /* not USE_LOCKED_INT_INTERCEPT */ - extern int EXFUN (X32_interrupt_restore, (unsigned)); extern int EXFUN (X32_int_intercept, (unsigned, void (*) (void), PTR)); -#endif /* USE_LOCKED_INT_INTERCEPT */ - extern unsigned short EXFUN (getCS, (void)); extern unsigned short EXFUN (getDS, (void)); +int +DEFUN_VOID (under_X32_p) +{ + union REGS regs; + + regs.x.bx = (getDS ()); + regs.x.ax = 0x3504; + int86 (0x21, ®s, ®s); + return ((regs.e.flags & 1) == 0); +} + #define I486_PAGE_SIZE 4096 #define OPERATION_LOCK 0 @@ -105,7 +99,7 @@ DEFUN (lock_unlock, (operation, segment, offset, size), return (((regs.e.flags & 1) != 0) ? -1 : 0); } -int +static int DEFUN (lock_region, (segment, offset, size), unsigned short segment AND PTR offset @@ -114,7 +108,7 @@ DEFUN (lock_region, (segment, offset, size), return (lock_unlock (OPERATION_LOCK, segment, offset, size)); } -int +static int DEFUN (unlock_region, (segment, offset, size), unsigned short segment AND PTR offset @@ -122,263 +116,79 @@ DEFUN (unlock_region, (segment, offset, size), { return (lock_unlock (OPERATION_UNLOCK, segment, offset, size)); } - -#ifdef USE_LOCKED_INT_INTERCEPT - -extern PTR EXFUN (malloc, (unsigned long)); -extern int EXFUN (free, (PTR)); - -PTR -DEFUN (locked_malloc, (size), unsigned long size) -{ - PTR block; - - block = (malloc (size)); - if (block == ((PTR) NULL)) - return (block); - if ((lock_region ((getDS ()), block, size)) != 0) - { - free (block); - return ((PTR) NULL); - } - return (block); -} - -void -DEFUN (locked_free, (block, size), - PTR block AND unsigned long size) -{ - if ((unlock_region ((getDS ()), block, size)) != 0) - return; - free (block); - return; -} -#pragma ZTC align 1 /* no alignment for DOS structs */ +#define ES 0 +#define CS 1 +#define SS 2 +#define DS 3 -struct trampoline +struct wired_area_s { - unsigned char callf; /* CALLF opcode */ - PTR off; /* CALLF offset */ - unsigned short seg; /* CALLF segment */ - struct INT_DATA closure; - unsigned short datasel; + int seg; + PTR start; + PTR end; }; - -#pragma ZTC align - - -#define MIN_STACK_SIZE 128 - - -void -DEFUN (locked_int_restore, (vectornumber), - unsigned vectornumber) -{ - union REGS regs; - struct SREGS sregs; - struct trampoline * tramp; - struct INT_DATA * clos; - /* Get protected mode interrupt vector. */ - - { - regs.x.ax = 0x2502; - regs.h.cl = vectornumber; - segread (&sregs); - int86x (0x21, ®s, ®s, &sregs); - if ((regs.e.flags & 1) != 0) - return; - tramp = ((struct trampoline *) regs.e.ebx); - } - - clos = &tramp->closure; - - /* Restore previous vectors */ - { - regs.x.ax = 0x2507; - regs.h.cl = vectornumber; - segread (&sregs); - sregs.ds = clos->prevvec_seg; - regs.e.edx = clos->prevvec_off; - regs.e.ebx = (* ((unsigned long *) &clos->prevvecr_off)); - int86x (0x21, ®s, ®s, &sregs); - if ((regs.e.flags & 1) != 0) - return; - } - - if (clos->stacksize != 0) - locked_free (((PTR) (((char *) clos->newstack_off) - clos->stacksize)), - clos->stacksize); - - locked_free (((PTR) tramp), (sizeof (struct trampoline))); - return; -} - -int -DEFUN (locked_int_intercept, (vectornumber, handler, stacksize), - unsigned vectornumber - AND int EXFUN ((_cdecl * handler), (struct INT_DATA *)) - AND unsigned stacksize) +extern unsigned X32_locked_data_start; +extern unsigned X32_locked_data_end; +extern void EXFUN (X32_locked_code_start, (void)); +extern void EXFUN (X32_locked_code_end, (void)); +extern unsigned char scan_code_tables_start[]; +extern unsigned char scan_code_tables_end[]; + +static struct wired_area_s wired_areas[] = { - extern void EXFUN (int_setvector, (unsigned, unsigned, unsigned)); - union REGS regs; - struct SREGS sregs; - struct trampoline * tramp; - struct INT_DATA * clos; - - tramp = ((struct trampoline *) - (locked_malloc (sizeof (struct trampoline)))); - if (tramp == ((struct trampoline *) NULL)) - return (-1); - - tramp->callf = 0x9a; - tramp->off = ((PTR) int_service); - tramp->seg = (getCS ()); - - clos = &tramp->closure; - - if (stacksize == 0) { - clos->stacksize = 0; - clos->newstack_off = 0; - clos->newstack_seg = 0; - } - else + DS, + ((PTR) &X32_locked_data_start), + ((PTR) &X32_locked_data_end) + }, { - PTR stack; - - if (stacksize < MIN_STACK_SIZE) - stacksize = MIN_STACK_SIZE; - - stack = (locked_malloc (stacksize)); - if (stack == ((PTR) NULL)) - { - locked_free (((PTR) tramp), (sizeof (struct trampoline))); - return (-1); - } - - clos->stacksize = stacksize; - clos->newstack_off = ((unsigned) (((char *) stack) + stacksize)); - clos->newstack_seg = (getDS ()); - } - clos->funcptr = handler; - - /* Preserve previous real mode interrupt handler */ - + CS, + ((PTR) X32_locked_code_start), + ((PTR) X32_locked_code_end) + }, { - regs.x.ax = 0x2503; - regs.h.cl = vectornumber; - int86 (0x21, ®s, ®s); - if ((regs.e.flags & 1) != 0) - { -error_getting_old_handlers: - if (clos->stacksize != 0) - locked_free (((PTR) (((char *) clos->newstack_off) - clos->stacksize)), - clos->stacksize); - locked_free (((PTR) tramp), (sizeof (struct trampoline))); - return (-1); - } - * ((unsigned *) &clos->prevvecr_off) = regs.e.ebx; + DS, + ((PTR) &scan_code_tables_start[0]), + ((PTR) &scan_code_tables_end[0]) } +}; - /* Preserve previous protected mode interrupt handler. */ - - { - regs.x.ax = 0x2502; - regs.h.cl = vectornumber; - segread (&sregs); - int86x (0x21, ®s, ®s, &sregs); - if ((regs.e.flags & 1) != 0) - goto error_getting_old_handlers; - - clos->prevvec_off = regs.e.ebx; - clos->prevvec_seg = sregs.es; - } - tramp->datasel = (getDS ()); +#define N_WIRED_AREAS ((sizeof (wired_areas)) / (sizeof (struct wired_area_s))) - int_setvector (vectornumber, ((unsigned) tramp), (getCS ())); - return (0); -} -#endif /* USE_LOCKED_INT_INTERCEPT */ - int DEFUN_VOID (X32_lock_scheme_microcode) { - extern unsigned X32_locked_data_start; - extern unsigned X32_locked_data_end; -#ifdef USE_LOCKED_INT_INTERCEPT - extern int EXFUN (bios_timer_handler, (struct INT_DATA *)); - extern void EXFUN (bios_timer_handler_end, (void)); -#else - extern void EXFUN (X32_locked_code_start, (void)); - extern void EXFUN (X32_locked_code_end, (void)); -#endif - unsigned short cs, ds; + int i, j; + unsigned short cs, ds, sel; ds = (getDS ()); cs = (getCS ()); - if ((lock_region (ds, ((PTR) &X32_locked_data_start), - (((unsigned long) &X32_locked_data_end) - - ((unsigned long) &X32_locked_data_start)))) - != 0) - return (-1); - -#ifdef USE_LOCKED_INT_INTERCEPT - if ((lock_region (cs, ((PTR) bios_timer_handler), - (((unsigned long) bios_timer_handler_end) - - ((unsigned long) bios_timer_handler)))) - != 0) - { - unlock_region (ds, ((PTR) &X32_locked_data_start), - (((unsigned long) &X32_locked_data_end) - - ((unsigned long) &X32_locked_data_start))); - return (-1); - } - if ((lock_region (cs, ((PTR) int_service), - (((unsigned long) int_intercept) - - ((unsigned long) int_service)))) - != 0) - { - unlock_region (ds, ((PTR) &X32_locked_data_start), - (((unsigned long) &X32_locked_data_end) - - ((unsigned long) &X32_locked_data_start))); - unlock_region (cs, ((PTR) bios_timer_handler), - (((unsigned long) bios_timer_handler_end) - - ((unsigned long) bios_timer_handler))); - return (-1); - } -#else /* not USE_LOCKED_INT_INTERCEPT */ - - if ((lock_region (cs, ((PTR) X32_locked_code_start), - (((unsigned long) X32_locked_code_end) - - ((unsigned long) X32_locked_code_start)))) - != 0) + for (i = 0; i < N_WIRED_AREAS; i++) { - unlock_region (ds, ((PTR) &X32_locked_data_start), - (((unsigned long) &X32_locked_data_end) - - ((unsigned long) &X32_locked_data_start))); - return (-1); + sel = ((wired_areas[i].seg == CS) ? cs : ds); + if ((lock_region (sel, + wired_areas[i].start, + (((unsigned long) wired_areas[i].end) + - ((unsigned long) wired_areas[i].start)))) + != 0) + { + while (--i >= 0) + { + sel = ((wired_areas[i].seg == CS) ? cs : ds); + (void) unlock_region (sel, + wired_areas[i].start, + (((unsigned long) wired_areas[i].end) + - ((unsigned long) wired_areas[i].start))); + } + return (-1); + } } - -#endif /* USE_LOCKED_INT_INTERCEPT */ return (0); } - -int -DEFUN_VOID (under_X32_p) -{ - union REGS regs; - - regs.x.bx = (getDS ()); - regs.x.ax = 0x3504; - int86 (0x21, ®s, ®s); - return ((regs.e.flags & 1) == 0); -} -#ifndef USE_LOCKED_INT_INTERCEPT - struct save_area { unsigned protected_offset; @@ -436,7 +246,7 @@ DEFUN (X32_interrupt_restore, (iv), unsigned iv) } return (-1); } - + int DEFUN (X32_remember_interrupt, (iv, area), unsigned iv @@ -508,5 +318,3 @@ DEFUN (X32_int_intercept, (iv, handler, ptr), } return (0); } - -#endif /* USE_LOCKED_INT_INTERCEPT */ diff --git a/v7/src/microcode/dosxcutl.asm b/v7/src/microcode/dosxcutl.asm index 368384c77..684b6c380 100644 --- a/v7/src/microcode/dosxcutl.asm +++ b/v7/src/microcode/dosxcutl.asm @@ -1,6 +1,6 @@ ;;; -*-Midas-*- ;;; -;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosxcutl.asm,v 1.2 1992/07/28 14:26:03 jinx Exp $ +;;; $Id: dosxcutl.asm,v 1.3 1992/09/03 07:30:06 jinx Exp $ ;;; ;;; Copyright (c) 1992 Massachusetts Institute of Technology ;;; @@ -378,24 +378,31 @@ common_different_stacks: ;; it cannot process a page fault. .data + public _X32_locked_data_start -_X32_locked_data_start dd 0 +_X32_locked_data_start dd 0 -X32_excp_buffer db 64 dup(0) +X32_excp_buffer db 64 dup(0) public _X32_excp_handlers -_X32_excp_handlers db 32*20 dup (0) +_X32_excp_handlers db 32*20 dup (0) public _X32_ds_val -_X32_ds_val dd 06765h +_X32_ds_val dd 06765h + public _X32_timer_interrupt_previous -_X32_timer_interrupt_previous dd 0 - dd 0 - dd 0 +_X32_timer_interrupt_previous dd 0 + dd 0 + dd 0 - public _scm_itimer_counter -_scm_itimer_counter dd 0 - public _scm_itimer_reload -_scm_itimer_reload dd 0 + public _X32_kbd_interrupt_previous +_X32_kbd_interrupt_previous dd 0 + dd 0 + dd 0 + + public _X32_kbd_interrupt_pointers +_X32_kbd_interrupt_pointers dd 0 + dd 0 + dd 0 public _IntCode ; These are usually declared in C, _IntCode dd 0 ; but they need to be locked since @@ -548,23 +555,22 @@ X32_set_up_trap_sp_merge: ;; executing as a normal program again), so it should be able to ;; page it in if necessary. -;; X32 timer interrupt. -;; Must be locked in memory (and all the data it accesses. +;;;; X32 interrupt handlers: +;; Must be locked in memory (and all the data they access). + +;; X32 timer interrupt handler. +;; This signals Scheme's "global GC interrupt", a high-priority +;; timer interrupt from which the keyboard and real timer +;; interrupts are derived. -INT_Timer equ 64 ; This must agree with intrpt.h +INT_Timer equ 2 ; This must agree with intrpt.h +;; INT_Timer equ 64 public _X32_timer_interrupt _X32_timer_interrupt: push ds mov ds,cs:_X32_ds_val - cmp dword ptr _scm_itimer_reload,0 - je x32_timer_return - dec dword ptr _scm_itimer_counter - cmp dword ptr _scm_itimer_counter,0 - jne x32_timer_return push eax - mov eax,dword ptr _scm_itimer_reload - mov dword ptr _scm_itimer_counter,eax or _IntCode,INT_Timer mov eax,_IntCode and eax,_IntEnb @@ -579,10 +585,151 @@ x32_timer_return: pop ds jmp fword ptr cs:_X32_timer_interrupt_previous +;; X32 keyboard interrupt handler +;; This performs scan-code to ASCII translation in order +;; not to drop the bucky bits. +;; + + public _X32_keyboard_interrupt +_X32_keyboard_interrupt: + push dword ptr cs:_X32_kbd_interrupt_pointers[0] + push dword ptr cs:_X32_kbd_interrupt_pointers[4] + push dword ptr cs:_X32_kbd_interrupt_pointers[8] + push dword ptr cs:_X32_ds_val[0] + pushfd + call scheme_system_isr + jnc x32_keyboard_interrupt_dismiss + + popfd ; original flags + lea esp,16[esp] + jmp fword ptr cs:_X32_kbd_interrupt_previous + +x32_keyboard_interrupt_dismiss: + push ebx ; preserve ebx + push ecx ; preserve ecx + mov ebx,8[esp] ; updated flags + mov 36[esp],ebx ; store eflags to location 1 + mov ecx,40[esp] ; pointer to interrupt structure + mov ss:[ecx],eax ; store new eax + mov ss:24[ecx],ebx ; store eflags to location 2 + pop ecx + pop ebx + popfd ; updated flags + lea esp,16[esp] ; pop args + iretd + +;; Stack on entry to scheme_system_isr +;; +;;24 address of modifier mask +;;20 offset for unshifted table +;;16 offset for shifted table +;;12 DS for scan_code to ascii tables +;;8 Flags to restore/modify +;;4 EIP for low-level hook (DPMI or DOSX) +;;0 Old ebp [pushed on entry] +;; +;; Arguments: +;; AL = scan code +;; AH = 4fh +;; CF set +;; +;; Return: +;; AL = scan code +;; CF clear if scan code should be ignored (interrupt dismissed). + +chain_to_next_handler: + stc ; set the carry flag + ret + + public scheme_system_isr +scheme_system_isr: + cmp ah,4fh + jne chain_to_next_handler + cmp al,39h + ja chain_to_next_handler + +;; process a keystroke + + push ebp + mov ebp,esp + push eax ; Preserve accross interrupt + + mov ah,2h ; Get shift bits + int 16h ; Return in AL + + push ecx + push edx ; Preserve regs + push es + + mov edx,12[ebp] ; Segment selector + push edx + pop es + + mov edx,24[ebp] ; Modifier mask address + and al,es:[edx] ; Ignore modifiers + push eax ; Save result + + mov ecx,-4[ebp] ; Scan code + function number + and ecx,3fh ; Only scan code + mov edx,20[ebp] ; Unshifted table offset + and eax,47h ; Shift, ctrl, and CAPS-LOCK mask + cmp al,0 + je index_into_table + mov edx,16[ebp] ; Shifted table offset + +index_into_table: + mov al,es:[edx] [ecx] ; Get ASCII value + pop edx ; Masked modifier bits + cmp al,0 ; Null entries mean chain + je abort_translation + + bt edx,2 ; Control set? + jnc after_control + and al,09fh ; Clear bits 6 and 5 + +after_control: + bt edx,3 ; Alt set? + jnc after_meta + or al,080h ; Set bit 8 + +after_meta: + cmp al,0f0h ; M-p ? + je abort_translation + mov ecx,-4[ebp] ; Get scan code + + cmp al,0 ; C-Space ? + jne after_ctrl_space + mov cl,3 ; Fudge scan code + +after_ctrl_space: + mov ch,cl + mov cl,al ; Transfer ASCII value + + mov ah,5h ; Insert keystroke + int 16h ; CH = scan code, CL = ASCII + ; returns AL = 0h if win, 1h if buffer full + + and byte ptr 8[ebp],0feh ; clear interrupt carry flag + pop es + pop edx + pop ecx + pop eax + pop ebp + clc ; clear our carry flag + ret + +abort_translation: + pop es + pop edx + pop ecx + pop eax + pop ebp + stc ; set carry flag + ret + public _X32_locked_code_end _X32_locked_code_end: - X32_set_up_trap_stack: push 4[edx] ; Trapped SS push 0[edx] ; Trapped ESP