home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s1.arc / KBDINTP.MOD < prev    next >
Text File  |  1988-02-08  |  32KB  |  473 lines

  1. (*----------------------------------------------------------------------*)
  2. (*  Keyboard_Interrupt_Handler --- Replaces int 9 keyboard handler      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Keyboard_Interrupt_Handler(
  6.           Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : WORD );
  7. (*   Interrupt; *)
  8.  
  9. (*----------------------------------------------------------------------*)
  10. (*                                                                      *)
  11. (*     Procedure:  Keyboard_Interrupt_Handler                           *)
  12. (*                                                                      *)
  13. (*     Purpose:    Replaces standard interrupt 9 keyboard driver        *)
  14. (*                                                                      *)
  15. (*     Calling Sequence:                                                *)
  16. (*                                                                      *)
  17. (*                 -- Called by system only!                            *)
  18. (*     Remarks:                                                         *)
  19. (*                                                                      *)
  20. (*        This routine replaces the standard interrupt 9 keyboard       *)
  21. (*        driver so that the extended key combinations will work        *)
  22. (*        properly.                                                     *)
  23. (*                                                                      *)
  24. (*        This handler is a slight modification of one by               *)
  25. (*        Neil J. Rubenking.                                            *)
  26. (*                                                                      *)
  27. (*----------------------------------------------------------------------*)
  28.  
  29. (* STRUCTURED *) CONST
  30.    Ctrl_Keys : ARRAY[0..12] OF BYTE =
  31.                ( 119, 160, 132, 161, 115, 162, 116,
  32.                  163, 117, 164, 118, 165, 166 );
  33.  
  34. BEGIN (* Keyboard_Interrupt_Handler *)
  35.  
  36. INLINE(
  37.                               {;}
  38.   $E4/$60/                    {           IN    AL,$60                 ;Read the keyboard port}
  39.   $88/$C1/                    {           MOV   CL,AL                  ;Save the key in CL}
  40.                               {;}
  41.   $3C/$E0/                    {           CMP   AL,224                 ;Check for scan code of 224}
  42.   $75/$09/                    {           JNE   ChkRel                 ;No -- may be release}
  43.   $A2/>KBD_SAVE_SCAN/         {           MOV   BYTE [>Kbd_Save_Scan],AL}
  44.   $E8/$B2/$00/                {           CALL  ReadPort}
  45.   $E9/$8E/$00/                {           JMP   SendEOI}
  46.                               {;}
  47.   $3C/$80/                    {ChkRel:    CMP   AL,$80                 ;Is is a RELEASE? If so,}
  48.   $72/$08/                    {           JB    ChkPrt                 ;}
  49.   $C6/$06/>KBD_SAVE_SCAN/$00/ {           MOV   BYTE [>Kbd_Save_Scan],0;clear scan code flag, and}
  50.   $E9/$89/$00/                {           JMP   NormalKey              ;treat as Normal}
  51.                               {;}
  52.   $3C/$37/                    {ChkPrt:    CMP   AL,55                  ;Check for PrtSc or kpd * key}
  53.   $75/$03/                    {           JNE   ChkEnt                 ;No -- may be Enter or keypad}
  54.   $E9/$E0/$00/                {           JMP   ChkPrtSc               ;Yes -- process PrtSc/kpd * key}
  55.                               {;}
  56.   $3C/$1C/                    {ChkEnt:    CMP   AL,28                  ;Check for ENTER key}
  57.   $75/$03/                    {           JNE   ChkBS                  ;No -- may be backspace}
  58.   $E9/$A4/$00/                {           JMP   ChkEnter               ;Yes -- process enter key}
  59.                               {;}
  60.   $3C/$0E/                    {ChkBS:     CMP   AL,14                  ;Check for backspace key}
  61.   $75/$03/                    {           JNE   ChkSls                 ;No -- may be slash}
  62.   $E9/$0A/$01/                {           JMP   ChkBackSp              ;Yes -- process backspace key}
  63.                               {;}
  64.   $3C/$35/                    {ChkSls:    CMP   AL,53                  ;Check for forward slash}
  65.   $75/$0A/                    {           JNE   ChkKeyPad              ;No -- may be keypad key}
  66.   $80/$3E/>KBD_SAVE_SCAN/$E0/ {           CMP   BYTE [>Kbd_Save_Scan],224  ;Yes -- Check for 224 as scan code}
  67.   $75/$69/                    {           JNE   NormalKey              ;No -- ordinary slash, process as normal}
  68.   $E9/$1B/$01/                {           JMP   ChkSlash               ;Yes -- process keypad slash}
  69.                               {;}
  70.   $3C/$47/                    {ChkKeyPad: CMP   AL,71                  ;71 = value for HOME key}
  71.   $72/$62/                    {           JB    NormalKey              ;Below Home is normal}
  72.   $3C/$53/                    {           CMP   AL,83                  ;83 = value for DEL key}
  73.   $7F/$5E/                    {           JG    NormalKey              ;Above Del is normal}
  74.                               {;}
  75.   $B8/>KBD_ROM_DATA/          {           MOV   AX,>Kbd_ROM_Data}
  76.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  77.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  78.                               {;}
  79.   $A8/$F3/                    {           TEST  AL,$F3                 ;Check if shifts other than alt, ctrl}
  80.   $75/$51/                    {           JNZ   NormalKey              ;If so, normal}
  81.                               {;}
  82.   $88/$C3/                    {           MOV   BL,AL                  ;Copy shift state}
  83.   $80/$E3/$0C/                {           AND   BL,$0C                 ;Remove all but Ctrl + Alt}
  84.   $80/$FB/$0C/                {           CMP   BL,$0C                 ;We only want one shift --}
  85.   $74/$47/                    {           JE    NormalKey              ;If Ctrl + Alt, pass key on.}
  86.                               {;}
  87.                               {;   If we got here w/o a jump, it's one of our}
  88.                               {;   special keystrokes.}
  89.                               {;}
  90.   $E8/$5E/$00/                {Special:   CALL  ReadPort               ;Read the keyboard port.}
  91.                               {;}
  92.                               {;   Figure out TURBO code for key based upon scan code.}
  93.                               {;   For normal keys, add nothing.  For ALT keys, add 103.}
  94.                               {;   For control keys, special mapping is required.}
  95.                               {;}
  96.   $A8/$08/                    {           TEST  AL,8                   ;Check for ALT}
  97.   $74/$06/                    {           JZ    TestCtrl}
  98.                               {;}
  99.   $80/$C1/$67/                {           ADD   CL,103                 ;+103 converts to TURBO code for ALT}
  100.   $E9/$11/$00/                {           JMP   InsCode}
  101.                               {;}
  102.   $A8/$04/                    {TestCtrl:  TEST  AL,4                   ;Check for CTRL}
  103.   $74/$0D/                    {           JZ    InsCode                ;otherwise it is unshifted}
  104.                               {;}
  105.   $8D/$1E/>CTRL_KEYS/         {           LEA   BX,[>Ctrl_Keys]        ;Get address of ctrl key table}
  106.   $80/$E9/$47/                {           SUB   CL,71                  ;Zero origin for key}
  107.   $30/$ED/                    {           XOR   CH,CH}
  108.   $01/$CB/                    {           ADD   BX,CX                  ;Get offset of new key value}
  109.   $8A/$0F/                    {           MOV   CL,[BX]                ;Pick up TURBO value from table}
  110.                               {;}
  111.   $8A/$26/>KBD_SAVE_SCAN/     {InsCode:   MOV   AH,[>Kbd_Save_Scan]    ;Get back saved scan code header}
  112.   $88/$C8/                    {           MOV   AL,CL                  ;Get the key back from CL}
  113.   $86/$C4/                    {           XCHG  AH,AL}
  114.   $26/$8B/$1E/>KBD_TAIL/      {       ES: MOV   BX,[>Kbd_Tail]         ;Get tail of keyboard buffer}
  115.   $26/$89/$07/                {       ES: MOV   [BX],AX                ;Put the key in the buffer}
  116.                               {;}
  117.   $81/$C3/$02/$00/            {           ADD   BX,2                   ;Advance the tail pointer}
  118.   $81/$FB/>KBD_BUFFER_END/    {           CMP   BX,>Kbd_Buffer_End     ;If at end of buffer...}
  119.   $7C/$03/                    {           JL    BufOK}
  120.                               {;}
  121.   $BB/>KBD_BUFFER/            {           MOV   BX,>Kbd_Buffer         ;...set back to beginning.}
  122.   $26/$89/$1E/>KBD_TAIL/      {BufOK: ES: MOV   [>Kbd_Tail],BX}
  123.                               {;}
  124.   $B0/$20/                    {SendEOI:   MOV   AL,$20                 ;Send the EOI to the}
  125.   $E6/$20/                    {           OUT   $20,AL                 ;...interrupt controller}
  126.                               {;}
  127.   $E9/$D9/$00/                {           JMP   Exit                   ;and return}
  128.                               {;}
  129.                               {;          NormalKey}
  130.                               {;                                       ;Chain to old keyboard ISR}
  131.                               {;}
  132.   $FF/$36/>KBD_SAVE_IADDR+2/  {NormalKey: PUSH   [>Kbd_Save_IAddr+2]   ;Push address of old ISR onto stack}
  133.   $FF/$36/>KBD_SAVE_IADDR/    {           PUSH   [>Kbd_Save_IAddr]     ;Need to do this before DS restored!}
  134.   $5B/                        {           POP    BX                    ;BX = OFS(Old_Keyboard_Interrupt)}
  135.   $58/                        {           POP    AX                    ;AX = SEG(Old_Keyboard_Interrupt)}
  136.   $87/$5E/$0E/                {           XCHG   BX,[BP+14]            ;Swap old BX and Ofs(Old_Key...)}
  137.   $87/$46/$10/                {           XCHG   AX,[BP+16]            ;Swap old AX and Seg(Old_Key...)}
  138.   $89/$EC/                    {           MOV    SP,BP                 ;Restore other registers}
  139.   $5D/                        {           POP    BP}
  140.   $07/                        {           POP    ES}
  141.   $1F/                        {           POP    DS}
  142.   $5F/                        {           POP    DI}
  143.   $5E/                        {           POP    SI}
  144.   $5A/                        {           POP    DX}
  145.   $59/                        {           POP    CX}
  146.                               {;                                       ;BX and AX restored earlier.}
  147.                               {;                                       ;Their places on stack now have}
  148.                               {;                                       ;old keyboard interrupt address,}
  149.                               {;                                       ;which is where return will go.}
  150.                               {;}
  151.   $CB/                        {           RETF                         ;Chain to Old_Keyboard_Interrupt}
  152.                               {;}
  153.                               {;          Read keyboard control port.}
  154.                               {;}
  155.   $50/                        {ReadPort:  PUSH  AX}
  156.   $E4/$61/                    {           IN    AL,$61                 ;Read keyboard control port}
  157.   $88/$C4/                    {           MOV   AH,AL}
  158.   $0C/$80/                    {           OR    AL,$80                 ;Set the "reset" bit and}
  159.   $E6/$61/                    {           OUT   $61,AL                 ;   send it back to control}
  160.   $86/$C4/                    {           XCHG  AH,AL                  ;Get back the control value}
  161.   $E6/$61/                    {           OUT   $61,AL                 ;Send it out also}
  162.   $58/                        {           POP   AX}
  163.   $C3/                        {           RET}
  164.                               {;}
  165.                               {;          Handle Enter key.  We're only interested in Alt-Enter,}
  166.                               {;          which we want to return as Esc + CHR( 28 ).}
  167.                               {;}
  168.   $B8/>KBD_ROM_DATA/          {ChkEnter:  MOV   AX,>Kbd_ROM_Data}
  169.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  170.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  171.                               {;}
  172.   $80/$3E/>KBD_SAVE_SCAN/$E0/ {           CMP   BYTE [>Kbd_Save_Scan],224 ;Distinguish Enter from Keypad Enter}
  173.   $74/$0E/                    {           JE    ChkKEnt                   ;No difference on some keyboards}
  174.                               {;}
  175.   $A8/$F7/                    {           TEST  AL,$F7                 ;Test for shifts other than ALT}
  176.   $75/$C3/                    {           JNZ   NormalKey              ;If so, treat as normal key.}
  177.                               {;}
  178.   $A8/$08/                    {           TEST  AL,8                   ;Check for ALT}
  179.   $74/$BF/                    {           JZ    NormalKey              ;Process as normal key if not ALT}
  180.                               {;}
  181.   $80/$E9/$67/                {           SUB   CL,103                 ;Bias for ALT key code above}
  182.   $E9/$72/$FF/                {           JMP   Special                ;Go insert ESC 28.}
  183.                               {;}
  184.   $A8/$F3/                    {ChkKEnt:   TEST  AL,$F3                 ;Test for shifts other than CTRL, ALT}
  185.   $74/$02/                    {           JZ    ChkKEnt1}
  186.   $EB/$B3/                    {           JMP   NormalKey              ;If so, treat as normal key.}
  187.                               {;}
  188.   $B1/$08/                    {ChkKEnt1:  MOV   CL,8}
  189.   $A8/$08/                    {           TEST  AL,8                   ;Check for ALT}
  190.   $75/$2D/                    {           JNZ   ChkPrtSc2              ;}
  191.                               {;}
  192.   $B1/$09/                    {           MOV   CL,9}
  193.   $A8/$04/                    {           TEST  AL,4                   ;Check for CTRL}
  194.   $75/$27/                    {           JNZ   ChkPrtSc2              ;}
  195.                               {;}
  196.   $B1/$07/                    {           MOV   CL,7                   ;Unshifted}
  197.   $E9/$22/$00/                {           JMP   ChkPrtSc2              ;Go insert ESC + Code.}
  198.                               {;}
  199.                               {;          Handle PrtSc or Keypad * key.}
  200.                               {;}
  201.   $B8/>KBD_ROM_DATA/          {ChkPrtSc:  MOV   AX,>Kbd_ROM_Data}
  202.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  203.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  204.                               {;}
  205.   $A8/$F3/                    {           TEST  AL,$F3                 ;Test for shifts other than CTRL, ALT}
  206.   $75/$95/                    {           JNZ   NormalKey              ;If so, treat as normal key.}
  207.                               {;}
  208.   $80/$3E/>KBD_SAVE_SCAN/$E0/ {           CMP   BYTE [>Kbd_Save_Scan],224 ;Distinguish PrtSc from Keypad *}
  209.   $75/$14/                    {           JNE   ChkStar                   ;No difference on some keyboards}
  210.                               {;}
  211.   $B1/$0B/                    {           MOV   CL,11}
  212.   $A8/$08/                    {           TEST  AL,8                   ;Check for ALT}
  213.   $75/$08/                    {           JNZ   ChkPrtSc2              ;}
  214.                               {;}
  215.   $B1/$0C/                    {           MOV   CL,12}
  216.   $A8/$04/                    {           TEST  AL,4                   ;Check for CTRL}
  217.   $75/$02/                    {           JNZ   ChkPrtSc2              ;}
  218.                               {;}
  219.   $B1/$0A/                    {           MOV   CL,10                  ;Unshifted}
  220.                               {;}
  221.   $E8/$97/$FF/                {ChkPrtSc2: CALL  ReadPort               ;Read keyboard port.}
  222.   $E9/$51/$FF/                {           JMP   InsCode                ;Go insert ESC + Code.}
  223.                               {;}
  224.   $B1/$02/                    {ChkStar:   MOV   CL,2                   ;Code for Alt}
  225.   $A8/$08/                    {           TEST  AL,8                   ;Check for Alt}
  226.   $75/$F4/                    {           JNZ   ChkPrtSc2}
  227.                               {;}
  228.   $B1/$03/                    {           MOV   CL,3                   ;Code for Ctrl}
  229.   $A8/$04/                    {           TEST  AL,4                   ;Check for Ctrl}
  230.   $75/$EE/                    {           JNZ   ChkPrtSc2}
  231.                               {;}
  232.   $B1/$01/                    {           MOV   CL,1                   ;Code for unshifted}
  233.   $EB/$EA/                    {           JMP   ChkprtSc2}
  234.                               {;}
  235.                               {;          Handle backspace key.  We're only interested in Alt-backspace,}
  236.                               {;          which we want to return as Esc + CHR( 171 ).}
  237.                               {;}
  238.   $B8/>KBD_ROM_DATA/          {ChkBackSp: MOV   AX,>Kbd_ROM_Data}
  239.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  240.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  241.                               {;}
  242.   $A8/$F7/                    {           TEST  AL,$F7                 ;Test for shifts other than ALT}
  243.   $74/$03/                    {           JZ    ChkBacSp1              ;If so, treat as normal key.}
  244.   $E9/$5A/$FF/                {           JMP   NormalKey}
  245.                               {;}
  246.   $A8/$08/                    {ChkBacSp1 :TEST  AL,8                   ;Check for ALT}
  247.   $75/$03/                    {           JNZ   ChkBacSp2}
  248.   $E9/$53/$FF/                {           JMP   NormalKey              ;Process as normal key if not ALT}
  249.                               {;}
  250.   $B1/$AB/                    {ChkbacSp2: MOV   CL,171                 ;Alt-backspace code}
  251.   $E8/$68/$FF/                {           CALL  ReadPort               ;Read keyboard port}
  252.   $E9/$22/$FF/                {           JMP   InsCode                ;Go insert ESC 171.}
  253.                               {;}
  254.                               {;          Handle / key.  We're only interested in the keypad /,}
  255.                               {;          so the scan code flag must be 224 to process this.}
  256.                               {;}
  257.   $B8/>KBD_ROM_DATA/          {ChkSlash:  MOV   AX,>Kbd_ROM_Data}
  258.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  259.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  260.                               {;}
  261.   $A8/$F3/                    {           TEST  AL,$F3                 ;Test for shifts other than Ctrl, Alt.}
  262.   $74/$03/                    {           JZ    ChkSlash1              ;No -- handle it here.}
  263.   $E9/$3B/$FF/                {           JMP   NormalKey              ;Else treat as normal key.}
  264.                               {;}
  265.   $B1/$05/                    {ChkSlash1: MOV   CL,5                   ;Scan code if ALT flag.}
  266.   $A8/$08/                    {           TEST  AL,8                   ;Check for Alt}
  267.   $75/$08/                    {           JNZ   ChkSlash2}
  268.                               {;}
  269.   $B1/$06/                    {           MOV   CL,6                   ;Scan code if CTRL flag.}
  270.   $A8/$04/                    {           TEST  AL,4                   ;Check for CTRL}
  271.   $75/$02/                    {           JNZ   ChkSlash2}
  272.                               {;}
  273.   $B1/$04/                    {           MOV   CL,4                   ;Scan code with no shifts}
  274.                               {;}
  275.   $E8/$44/$FF/                {ChkSlash2: CALL  ReadPort               ;Read keyboard port.}
  276.   $E9/$FE/$FE);               {           JMP   InsCode                ;Go insert ESC + Code.}
  277.                               {;}
  278.                               {Exit:}
  279.  
  280. END   (* Keyboard_Interrupt_Handler *);
  281.  
  282. (*----------------------------------------------------------------------*)
  283. (* Ext_Keyboard_Interrupt_Handler --- Replaces int 9 keyboard handler   *)
  284. (*----------------------------------------------------------------------*)
  285.  
  286. PROCEDURE Ext_Keyboard_Interrupt_Handler(
  287.           Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : WORD );
  288. (*   Interrupt; *)
  289.  
  290. (*----------------------------------------------------------------------*)
  291. (*                                                                      *)
  292. (*     Procedure:  Ext_Keyboard_Interrupt_Handler                       *)
  293. (*                                                                      *)
  294. (*     Purpose:    Replaces standard interrupt 9 keyboard driver for    *)
  295. (*                 extended 101-key keyboards.                          *)
  296. (*                                                                      *)
  297. (*     Calling Sequence:                                                *)
  298. (*                                                                      *)
  299. (*                 -- Called by system only!                            *)
  300. (*     Remarks:                                                         *)
  301. (*                                                                      *)
  302. (*        This routine replaces the standard interrupt 9 keyboard       *)
  303. (*        driver so that the extended key combinations will work        *)
  304. (*        properly.  This version for the 101-key keyboard is much      *)
  305. (*        simpler than for the 83/84-key keyboards since only the       *)
  306. (*        keyboard <ALT>key combinations need to be handled.            *)
  307. (*                                                                      *)
  308. (*----------------------------------------------------------------------*)
  309.  
  310. BEGIN (* Ext_Keyboard_Interrupt_Handler *)
  311.  
  312. INLINE(
  313.                               {;}
  314.   $E4/$60/                    {           IN    AL,$60                 ;Read the keyboard port}
  315.   $88/$C1/                    {           MOV   CL,AL                  ;Save the key in CL}
  316.                               {;}
  317.   $3C/$E0/                    {           CMP   AL,$E0                 ;Check for scan code of 224}
  318.   $75/$06/                    {           JNE   ChkRel                 ;No -- may be release}
  319.   $A2/>KBD_SAVE_SCAN/         {           MOV   BYTE [>Kbd_Save_Scan],AL}
  320.   $E9/$63/$00/                {           JMP   NormalKey}
  321.                               {;}
  322.   $3C/$80/                    {ChkRel:    CMP   AL,$80                 ;Is is a RELEASE? If so,}
  323.   $72/$08/                    {           JB    Chk224                 ;}
  324.   $C6/$06/>KBD_SAVE_SCAN/$00/ {           MOV   BYTE [>Kbd_Save_Scan],0;clear scan code flag, and}
  325.   $E9/$57/$00/                {           JMP   NormalKey              ;treat as Normal}
  326.                               {;}
  327.   $80/$3E/>KBD_SAVE_SCAN/$00/ {Chk224:    CMP   BYTE [>Kbd_Save_Scan],0;Check for extended scan code}
  328.   $74/$08/                    {           JE    ChkKeyPad              ;No -- go check keypad}
  329.                               {;}
  330.   $C6/$06/>KBD_SAVE_SCAN/$00/ {           MOV   BYTE [>Kbd_Save_Scan],0;Yes -- clear scan code flag,}
  331.   $E9/$48/$00/                {           JMP   NormalKey              ;and treat as Normal}
  332.                               {;}
  333.   $3C/$47/                    {ChkKeyPad: CMP   AL,71                  ;71 = value for HOME key}
  334.   $72/$44/                    {           JB    NormalKey              ;Below Home is normal}
  335.   $3C/$53/                    {           CMP   AL,83                  ;83 = value for DEL key}
  336.   $7F/$40/                    {           JG    NormalKey              ;Above Del is normal}
  337.                               {;}
  338.   $B8/>KBD_ROM_DATA/          {           MOV   AX,>Kbd_ROM_Data}
  339.   $8E/$C0/                    {           MOV   ES,AX                  ;Point ES at the ROM DATA}
  340.   $26/$A0/>KBD_FLAG/          {       ES: MOV   AL,[>Kbd_Flag]         ;Pick up shift key flags}
  341.                               {;}
  342.   $A8/$F7/                    {           TEST  AL,$F7                 ;Check if shifts other than alt}
  343.   $75/$33/                    {           JNZ   NormalKey              ;If so, normal}
  344.                               {;}
  345.                               {;   If we got here w/o a jump, it's one of our}
  346.                               {;   special keystrokes.}
  347.                               {;}
  348.   $E8/$4A/$00/                {Special:   CALL  ReadPort               ;Read the keyboard port.}
  349.                               {;}
  350.                               {;   Figure out TURBO code for key based upon scan code.}
  351.                               {;   For normal keys, add nothing.  For ALT keys, add 103.}
  352.                               {;   For control keys, special mapping is required.}
  353.                               {;}
  354.   $A8/$08/                    {           TEST  AL,8                   ;See if ALT turned on}
  355.   $74/$2C/                    {           JZ    NormalKey              ;No -- treat as normal key.}
  356.                               {;}
  357.   $80/$C1/$67/                {           ADD   CL,103                 ;+103 converts to TURBO code for ALT}
  358.                               {;}
  359.   $8A/$26/>KBD_SAVE_SCAN/     {InsCode:   MOV   AH,[>Kbd_Save_Scan]    ;Get back saved scan code header}
  360.   $88/$C8/                    {           MOV   AL,CL                  ;Get the key back from CL}
  361.   $86/$C4/                    {           XCHG  AH,AL}
  362.   $26/$8B/$1E/>KBD_TAIL/      {       ES: MOV   BX,[>Kbd_Tail]         ;Get tail of keyboard buffer}
  363.   $26/$89/$07/                {       ES: MOV   [BX],AX                ;Put the key in the buffer}
  364.                               {;}
  365.   $81/$C3/$02/$00/            {           ADD   BX,2                   ;Advance the tail pointer}
  366.   $81/$FB/>KBD_BUFFER_END/    {           CMP   BX,>Kbd_Buffer_End     ;If at end of buffer...}
  367.   $7C/$03/                    {           JL    BufOK}
  368.                               {;}
  369.   $BB/>KBD_BUFFER/            {           MOV   BX,>Kbd_Buffer         ;...set back to beginning.}
  370.   $26/$89/$1E/>KBD_TAIL/      {BufOK: ES: MOV   [>Kbd_Tail],BX}
  371.                               {;}
  372.   $B0/$20/                    {SendEOI:   MOV   AL,$20                 ;Send the EOI to the}
  373.   $E6/$20/                    {           OUT   $20,AL                 ;...interrupt controller}
  374.                               {;}
  375.   $E9/$29/$00/                {           JMP   Exit                   ;and return}
  376.                               {;}
  377.                               {;          NormalKey}
  378.                               {;                                       ;Chain to old keyboard ISR}
  379.                               {;}
  380.   $FF/$36/>KBD_SAVE_IADDR+2/  {NormalKey: PUSH   [>Kbd_Save_IAddr+2]   ;Push address of old ISR onto stack}
  381.   $FF/$36/>KBD_SAVE_IADDR/    {           PUSH   [>Kbd_Save_IAddr]     ;Need to do this before DS restored!}
  382.   $5B/                        {           POP    BX                    ;BX = OFS(Old_Keyboard_Interrupt)}
  383.   $58/                        {           POP    AX                    ;AX = SEG(Old_Keyboard_Interrupt)}
  384.   $87/$5E/$0E/                {           XCHG   BX,[BP+14]            ;Swap old BX and Ofs(Old_Key...)}
  385.   $87/$46/$10/                {           XCHG   AX,[BP+16]            ;Swap old AX and Seg(Old_Key...)}
  386.   $89/$EC/                    {           MOV    SP,BP                 ;Restore other registers}
  387.   $5D/                        {           POP    BP}
  388.   $07/                        {           POP    ES}
  389.   $1F/                        {           POP    DS}
  390.   $5F/                        {           POP    DI}
  391.   $5E/                        {           POP    SI}
  392.   $5A/                        {           POP    DX}
  393.   $59/                        {           POP    CX}
  394.                               {;                                       ;BX and AX restored earlier.}
  395.                               {;                                       ;Their places on stack now have}
  396.                               {;                                       ;old keyboard interrupt address,}
  397.                               {;                                       ;which is where return will go.}
  398.                               {;}
  399.   $CB/                        {           RETF                         ;Chain to Old_Keyboard_Interrupt}
  400.                               {;}
  401.                               {;          Read keyboard control port.}
  402.                               {;}
  403.   $50/                        {ReadPort:  PUSH  AX}
  404.   $E4/$61/                    {           IN    AL,$61                 ;Read keyboard control port}
  405.   $88/$C4/                    {           MOV   AH,AL}
  406.   $0C/$80/                    {           OR    AL,$80                 ;Set the "reset" bit and}
  407.   $E6/$61/                    {           OUT   $61,AL                 ;   send it back to control}
  408.   $86/$C4/                    {           XCHG  AH,AL                  ;Get back the control value}
  409.   $E6/$61/                    {           OUT   $61,AL                 ;Send it out also}
  410.   $58/                        {           POP   AX}
  411.   $C3);                       {           RET}
  412.                               {;}
  413.                               {Exit:}
  414.  
  415. END   (* Ext_Keyboard_Interrupt_Handler *);
  416.  
  417. (*----------------------------------------------------------------------*)
  418. (* Install_Keyboard_Handler --- Installs new interrupt 9 keyboard driver*)
  419. (*----------------------------------------------------------------------*)
  420.  
  421. PROCEDURE Install_Keyboard_Handler;
  422.  
  423. (*----------------------------------------------------------------------*)
  424. (*                                                                      *)
  425. (*     Procedure:  Install_Keyboard_Handler                             *)
  426. (*                                                                      *)
  427. (*     Purpose:    Replaces standard interrupt 9 keyboard driver        *)
  428. (*                                                                      *)
  429. (*     Calling Sequence:                                                *)
  430. (*                                                                      *)
  431. (*        Install_Keyboard_Handler;                                     *)
  432. (*                                                                      *)
  433. (*----------------------------------------------------------------------*)
  434.  
  435. BEGIN (* Install_Keyboard_Handler *)
  436.  
  437.                                    (* Make sure keyboard scan is zero *)
  438.    Kbd_Save_Scan := 0;
  439.                                    (* Set interrupt routine address *)
  440.  
  441.    IF ( ( Mem[$40:$96] AND $10 ) <> 0 ) THEN
  442.       SetIntVec( Kbd_Interrupt , @Ext_Keyboard_Interrupt_Handler )
  443.    ELSE
  444.       SetIntVec( Kbd_Interrupt , @Keyboard_Interrupt_Handler );
  445.  
  446. END   (* Install_Keyboard_Handler *);
  447.  
  448. (*----------------------------------------------------------------------*)
  449. (*  Remove_Keyboard_Handler --- Removes installed interrupt 9 driver    *)
  450. (*----------------------------------------------------------------------*)
  451.  
  452. PROCEDURE Remove_Keyboard_Handler;
  453.  
  454. (*----------------------------------------------------------------------*)
  455. (*                                                                      *)
  456. (*     Procedure:  Remove_Keyboard_Handler                              *)
  457. (*                                                                      *)
  458. (*     Purpose:    Restores standard interrupt 9 keyboard driver        *)
  459. (*                                                                      *)
  460. (*     Calling Sequence:                                                *)
  461. (*                                                                      *)
  462. (*        Remove_Keyboard_Handler;                                      *)
  463. (*                                                                      *)
  464. (*----------------------------------------------------------------------*)
  465.  
  466. BEGIN (* Remove_Keyboard_Handler *)
  467.  
  468.                      (* Restore the previous interrupt pointers *)
  469.  
  470.    SetIntVec( Kbd_Interrupt , Kbd_Save_Iaddr );
  471.  
  472. END   (* Remove_Keyboard_Handler *);
  473.