home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / keyboard / enhanced / enhkbd.asm next >
Assembly Source File  |  1990-11-16  |  16KB  |  416 lines

  1. ;--------------------------------ENHKBD.ASM -------------------------------
  2.  
  3. ;Assembly language file for ENHKBD unit
  4. ;Written by Kim Kokkonen, TurboPower Software
  5.  
  6. ;Version 1.0, 1/3/88
  7. ;  initial release
  8.  
  9. ;Version 1.1, 1/29/88
  10. ;  support the NumLock key!
  11.  
  12. ;Version 1.2, 2/23/88, with help from Brian Foley
  13. ;  don't let NumLock key affect dedicated cursor pad on enhanced keyboard
  14. ;  minimize conflict with QuickKeys and other int 9 handlers
  15. ;  allow Ctrl-Alt-Del with int 9 installed
  16. ;  add method to disable handlers temporarily
  17. ;  use safer test for enhanced keyboard
  18. ;  support alt-keypad keys with Alt-LeftShift combination
  19. ;  add RestoreKbdVectors routine for use by TSR's
  20.  
  21. ;Released to the public domain
  22.  
  23. DATA    SEGMENT BYTE PUBLIC
  24.         EXTRN   HasEnhancedKbd : BYTE
  25.         EXTRN   EnableEnhanced : BYTE
  26. DATA    ENDS
  27.  
  28. CODE    SEGMENT BYTE PUBLIC
  29.  
  30.         ASSUME  CS:CODE, DS:DATA
  31.  
  32.         PUBLIC  GetIntVec, SetIntVec
  33.         PUBLIC  InitVectors
  34.         PUBLIC  EnhancedKbd
  35.         PUBLIC  NewInt09, NewInt16
  36.  
  37. ;CS-relative variables, easily accessible to interrupt handlers
  38. PrevInt09       LABEL DWORD
  39. PrevInt09Ofs    DW ?
  40. PrevInt09Seg    DW ?
  41. PrevInt16       LABEL DWORD
  42. PrevInt16Ofs    DW ?
  43. PrevInt16Seg    DW ?
  44.  
  45. ;*********************************************************** GetIntVec
  46. ;Return an interrupt vector
  47. ;procedure GetIntVec(IntNo : Byte; var Vector : pointer);
  48.  
  49. GetIntVec PROC NEAR
  50.         PUSH    BP
  51.         MOV     BP,SP
  52.         MOV     AL,[BP+8]               ;Get interrupt number
  53.         MOV     AH,35h
  54.         INT     21h
  55.         MOV     AX,ES                   ;Save interrupt segment
  56.         LES     DI,[BP+4]               ;ES:DI => result
  57.         MOV     ES:[DI],BX              ;Offset
  58.         MOV     ES:[DI+2],AX            ;Segment
  59.         MOV     SP,BP
  60.         POP     BP
  61.         RET     6
  62. GetIntVec ENDP
  63.  
  64. ;*********************************************************** SetIntVec
  65. ;Set an interrupt vector
  66. ;procedure SetIntVec(IntNo : Byte; Vector : Pointer);
  67.  
  68. SetIntVec PROC NEAR
  69.         MOV     BX,SP                   ;Set up stack frame
  70.         PUSH    DS
  71.         LDS     DX,SS:[BX+2]            ;Get interrupt address
  72.         MOV     AL,SS:[BX+6]            ;Get interrupt number
  73.         MOV     AH,25h
  74.         INT     21h
  75.         POP     DS
  76.         RET     6
  77. SetIntVec ENDP
  78.  
  79. ;*********************************************************** EnhancedKbd
  80. ;See if enhanced keyboard BIOS installed
  81. ;function EnhancedKbd : Boolean;
  82.  
  83. EnhancedKbd PROC NEAR
  84.         MOV     AH,05                   ;Stuff buffer function
  85.         MOV     CX,0FFFFh               ;Stuff FFFF
  86.         INT     16h
  87.         MOV     AH,11h                  ;Read enhanced function
  88.         INT     16h
  89.         CMP     AX,0FFFFh               ;Did we read the FFFF?
  90.         MOV     AX,0                    ;Prepare for False
  91.         JNZ     EnhDone
  92.         MOV     AH,10h                  ;Get the key out of the buffer
  93.         INT     16h
  94.         MOV     AX,1                    ;Set to true
  95. EnhDone:
  96.         RET
  97. EnhancedKbd ENDP
  98.  
  99. ;*********************************************************** NewInt09
  100. ;Handle hardware keyboard interrupts
  101.  
  102. IndexTable        LABEL BYTE            ;Table of indexes into WordTable
  103.         DB       0FFh   ;00h
  104.         DB        00    ;01h - Esc
  105.         DB       0FFh   ;02h
  106.         DB       0FFh   ;03h
  107.         DB       0FFh   ;04h
  108.         DB       0FFh   ;05h
  109.         DB       0FFh   ;06h
  110.         DB       0FFh   ;07h
  111.         DB       0FFh   ;08h
  112.         DB       0FFh   ;09h
  113.         DB       0FFh   ;0Ah
  114.         DB       0FFh   ;0Bh
  115.         DB       0FFh   ;0Ch
  116.         DB       0FFh   ;0Dh
  117.         DB        01    ;0Eh - Backspace
  118.         DB        02    ;0Fh - Tab
  119.         DB       0FFh   ;10h
  120.         DB       0FFh   ;11h
  121.         DB       0FFh   ;12h
  122.         DB       0FFh   ;13h
  123.         DB       0FFh   ;14h
  124.         DB       0FFh   ;15h
  125.         DB       0FFh   ;16h
  126.         DB       0FFh   ;17h
  127.         DB       0FFh   ;18h
  128.         DB       0FFh   ;19h
  129.         DB        03    ;1Ah - Left Brack
  130.         DB        04    ;1Bh - Right Brack
  131.         DB        05    ;1Ch - Enter
  132.         DB       0FFh   ;1Dh
  133.         DB       0FFh   ;1Eh
  134.         DB       0FFh   ;1Fh
  135.         DB       0FFh   ;20h
  136.         DB       0FFh   ;21h
  137.         DB       0FFh   ;22h
  138.         DB       0FFh   ;23h
  139.         DB       0FFh   ;24h
  140.         DB       0FFh   ;25h
  141.         DB       0FFh   ;26h
  142.         DB        06    ;27h - Semicolon
  143.         DB        07    ;28h - Quote
  144.         DB        08    ;29h - Backquote
  145.         DB       0FFh   ;2Ah
  146.         DB        09    ;2Bh - Backslash
  147.         DB       0FFh   ;2Ch
  148.         DB       0FFh   ;2Dh
  149.         DB       0FFh   ;2Eh
  150.         DB       0FFh   ;2Fh
  151.         DB       0FFh   ;30h
  152.         DB       0FFh   ;31h
  153.         DB       0FFh   ;32h
  154.         DB        10    ;33h - Comma
  155.         DB        11    ;34h - Period
  156.         DB        12    ;35h - Slash
  157.         DB       0FFh   ;36h
  158.         DB        13    ;37h - Pad-Asterisk
  159.         DB       0FFh   ;38h
  160.         DB       0FFh   ;39h
  161.         DB       0FFh   ;3Ah
  162.         DB       0FFh   ;3Bh
  163.         DB       0FFh   ;3Ch
  164.         DB       0FFh   ;3Dh
  165.         DB       0FFh   ;3Eh
  166.         DB       0FFh   ;3Fh
  167.         DB       0FFh   ;40h
  168.         DB       0FFh   ;41h
  169.         DB       0FFh   ;42h
  170.         DB       0FFh   ;43h
  171.         DB       0FFh   ;44h
  172.         DB       0FFh   ;45h
  173.         DB       0FFh   ;46h
  174.         DB        14    ;47h - Home
  175.         DB        15    ;48h - Up
  176.         DB        16    ;49h - PgUp
  177.         DB        17    ;4Ah - Pad-Minus
  178.         DB        18    ;4Bh - Left
  179.         DB        19    ;4Ch - Pad-5
  180.         DB        20    ;4Dh - Right
  181.         DB        21    ;4Eh - Pad-Plus
  182.         DB        22    ;4Fh - End
  183.         DB        23    ;50h - Down
  184.         DB        24    ;51h - PgDn
  185.         DB        25    ;52h - Insert
  186.         DB        26    ;53h - Del
  187.  
  188. WordTable         LABEL WORD            ;Table of Scan words to return
  189.         ;         Control   Alt
  190.         DW       0FFFFh,    0100h  ;Esc
  191.         DW       0FFFFh,    0E00h  ;Backspace
  192.         DW        9400h,   0A500h  ;Tab
  193.         DW       0FFFFh,    1A00h  ;Left Brack
  194.         DW       0FFFFh,    1B00h  ;Right Brack
  195.         DW       0FFFFh,    1C00h  ;Enter
  196.         DW       0FFFFh,    2700h  ;Semicolon
  197.         DW       0FFFFh,    2800h  ;Quote
  198.         DW       0FFFFh,    2900h  ;Backquote
  199.         DW       0FFFFh,    2B00h  ;Backslash
  200.         DW       0FFFFh,    3300h  ;Comma
  201.         DW       0FFFFh,    3400h  ;Period
  202.         DW       0FFFFh,    3500h  ;Slash
  203.         DW       0FFFFh,    3700h  ;Pad-Asterisk
  204.         DW       0FFFFh,    9700h  ;Home
  205.         DW        8D00h,    9800h  ;Up
  206.         DW       0FFFFh,    9900h  ;PgUp
  207.         DW        8E00h,    4A00h  ;Pad-minus
  208.         DW       0FFFFh,    9B00h  ;Left
  209.         DW        8F00h,    9C00h  ;Pad-5
  210.         DW       0FFFFh,    9D00h  ;Right
  211.         DW        9000h,    4E00h  ;Pad-Plus
  212.         DW       0FFFFh,    9F00h  ;End
  213.         DW        9100h,   0A000h  ;Down
  214.         DW       0FFFFh,   0A100h  ;PgDn
  215.         DW        9200h,   0A200h  ;Insert
  216.         DW        9300h,   0A300h  ;Del
  217.  
  218.         BiosShiftFlags  EQU BYTE PTR 17h  ;Addresses in BIOS data area
  219.         BufferHead      EQU WORD PTR 1Ah
  220.         BufferTail      EQU WORD PTR 1Ch
  221.         BufferStart     EQU WORD PTR 80h
  222.         BufferEnd       EQU WORD PTR 82h
  223.  
  224. NewInt09 PROC FAR
  225.         STI                             ;Interrupts on
  226.         PUSH    AX                      ;Save registers we use
  227.         PUSH    BX
  228.         PUSH    CX
  229.         PUSH    DS
  230.  
  231.         MOV     AX,SEG DATA
  232.         MOV     DS,AX                   ;Point to Turbo data area
  233.         CMP     EnableEnhanced,0        ;Enhanced functions enabled?
  234.         JZ      Int09Orig               ;No, get out
  235.  
  236.         MOV     AX,0040h
  237.         MOV     DS,AX                   ;Point to BIOS data area
  238.  
  239.         MOV     AL,DS:BiosShiftFlags    ;Shift status in AL
  240.         MOV     CL,AL                   ;Save shift state in CL
  241.         TEST    AL,00001100b            ;Either Control or Alt depressed?
  242.         JZ      TestPad5                ;No, check special case of Pad-5
  243.  
  244.         AND     AL,00001100b            ;Just Ctrl-Alt bits
  245.         CMP     AL,00001100b            ;Both Ctrl and Alt depressed?
  246.         JE      Int09Orig               ;Get out in case of Ctrl-Alt-Del
  247.  
  248.         MOV     AL,CL                   ;Restore shift state
  249.         AND     AL,00001111b            ;All shift bits
  250.         CMP     AL,00001010b            ;Just Alt-LeftShift?
  251.         JE      Int09Orig               ;Get out so Alt-Keypad works
  252.  
  253.         IN      AL,60h                  ;Read scan code
  254.         CMP     AL,53h                  ;Is it in range 0..53h?
  255.         JA      Int09Orig               ;If not, pass on to BIOS int 09 handler
  256.  
  257.         MOV     BX,offset IndexTable    ;Point to index table
  258.         XLAT    BYTE PTR CS:[0]         ;Get index
  259.         CMP     AL,0FFh                 ;AL = FFh?
  260.         JNZ     MatchedScan             ;Special case if AL <> FFh
  261.  
  262. Int09Orig:                              ;Let BIOS int 09 handler take care of it
  263.         POP     DS                      ;Restore registers
  264.         POP     CX
  265.         POP     BX
  266.         POP     AX
  267.         JMP     PrevInt09               ;Transfer to previous interrupt 09
  268.  
  269. TestPad5:
  270.         IN      AL,60h                  ;Read scan code
  271.         CMP     AL,4Ch                  ;Pad-5 key?
  272.         JNZ     Int09Orig               ;No, get out
  273.         MOV     AX,4C00h                ;Set up scan code to return
  274.         TEST    CL,00100000b            ;Is NumLock set?
  275.         JZ      NoNumLock               ;No, it's not
  276. NumLockSet:
  277.         TEST    CL,00000011b            ;Is a shift key depressed?
  278.         JNZ     StoreScanWord           ;Yes, we want to store 4C00 in buffer
  279.         JMP SHORT Int09Orig             ;No, let original int 9 do it
  280. NoNumLock:
  281.         TEST    CL,00000011b            ;Is a shift key depressed?
  282.         JZ      StoreScanWord           ;No, store scan word
  283.         JMP SHORT Int09Orig             ;Yes, let original int 9 do it
  284.  
  285. MatchedScan:
  286.         SHL     AX,1                    ;Multiply scan index by 2
  287.         SHL     AX,1                    ;Multiply by 2 again
  288.         MOV     BX,AX                   ;BX = Index * 4
  289.         TEST    CL,00001000b            ;Alt depressed?
  290.         JZ      NoAltKey                ;No, use first column of table
  291.         ADD     BX,2                    ;Yes, use second column of table
  292. NoAltKey:
  293.         MOV     AX,CS:WordTable[BX]     ;Get the scan word
  294.         CMP     AX,0FFFFh               ;Case handled by BIOS?
  295.         JZ      Int09Orig               ;Yes, get out of here
  296.  
  297. StoreScanWord:
  298.         MOV     CX,AX                   ;Save scan word in CX
  299.         IN      AL,61h                  ;Read control port value
  300.         MOV     AH,AL                   ;Save in AH
  301.         OR      AL,80h                  ;Set high bit
  302.         OUT     61h,AL                  ;Reset keyboard
  303.         MOV     AL,AH                   ;Retrieve original value
  304.         OUT     61h,AL                  ;Enable keyboard
  305.         CLI                             ;Stop CPU interrupts
  306.         MOV     AL,20h                  ;End of interrupt
  307.         OUT     20h,AL                  ;To the interrupt controller
  308.  
  309.         MOV     BX,DS:BufferTail        ;Point to end of keyboard buffer
  310.         MOV     AX,BX                   ;Transfer to AX
  311.         ADD     AX,0002                 ;Advance to next position
  312.         CMP     AX,DS:BufferEnd         ;Wrap around if needed
  313.         JNE     CheckFull               ;No need to wrap
  314.         MOV     AX,DS:BufferStart       ;Else to beginning of buffer
  315. CheckFull:
  316.         CMP     AX,DS:BufferHead        ;Bumping in to start?
  317.         JE      NewInt09Done            ;Exit if full
  318.         MOV     [BX],CX                 ;Store keystroke
  319.         MOV     DS:BufferTail,AX        ;Advance tail
  320. NewInt09Done:
  321.         STI                             ;Interrupts on
  322.         POP     DS                      ;Restore registers
  323.         POP     CX
  324.         POP     BX
  325.         POP     AX
  326.         IRET                            ;Return to caller
  327. NewInt09 ENDP
  328.  
  329. ;*********************************************************** NewInt16
  330. ;Handle software keyboard interrupts
  331. NewInt16 PROC FAR
  332.         PUSH    DX                      ;Save registers we use
  333.         PUSH    DS
  334.         PUSHF                           ;Save flags
  335.         STI                             ;Allow interrupts
  336.  
  337.         MOV     DX,SEG DATA
  338.         MOV     DS,DX                   ;Assure DS points to Turbo data
  339.         CMP     EnableEnhanced,0        ;Enhanced functions enabled?
  340.         JZ      Int16Orig               ;No, pass to previous int 16
  341.         CMP     HasEnhancedKbd,0        ;Is enhanced keyboard installed?
  342.         JZ      Int16Orig               ;No, leave call alone
  343.  
  344.         OR      AH,AH                   ;AH=0?
  345.         JNZ     TryAH1                  ;No, try AH=1
  346. AH0:
  347.         OR      AH,10h                  ;Use enhanced BIOS call instead
  348.         CALL    PrevInt16               ;Call previous int 16 (pops flags)
  349.         OR      AH,AH                   ;AH=0?
  350.         JZ      AH0Done                 ;Yes, done
  351.         CMP     AL,0E0h                 ;AL=E0h?
  352.         JNZ     AH0Done                 ;No, leave it alone
  353.         XOR     AL,AL                   ;Clear low byte of scan word
  354. AH0Done:
  355.         POP     DS                      ;Restore registers
  356.         POP     DX
  357.         IRET                            ;Return to caller
  358.  
  359. TryAH1:
  360.         CMP     AH,1                    ;AH=1?
  361.         JNZ     Int16Orig               ;No, let original int 16 do it
  362. AH1:
  363.         OR      AH,10h                  ;Use enhanced BIOS call instead
  364.         CALL    PrevInt16               ;Call previous int 16 (pops flags)
  365.         PUSHF                           ;Save result flags
  366.         JZ      AH1Done                 ;Just return if no key available
  367.         OR      AH,AH                   ;AH=0?
  368.         JZ      AH1Done                 ;Yes, done
  369.         CMP     AL,0E0h                 ;AL=E0h?
  370.         JNZ     AH1Done                 ;Yes, clear it
  371.         XOR     AL,AL                   ;Clear low byte of scan word
  372. AH1Done:
  373.         POPF                            ;Restore result flags
  374.         POP     DS                      ;Restore registers
  375.         POP     DX
  376.         RET     2                       ;Return with flags intact
  377.  
  378. Int16Orig:
  379.         POPF                            ;Restore flags
  380.         POP     DS
  381.         POP     DX
  382.         JMP     PrevInt16               ;Let old int16 handle the rest
  383. NewInt16 ENDP
  384.  
  385. ;*********************************************************** InitVectors
  386. ;Save and setup interrupt vectors
  387. InitVectors PROC NEAR
  388.         MOV     AX,3509h                ;Get current int 9
  389.         INT     21h
  390.         MOV     PrevInt09Ofs,BX         ;Save it in CS-relative variables
  391.         MOV     PrevInt09Seg,ES
  392.         PUSH    DS
  393.         PUSH    CS
  394.         POP     DS
  395.         MOV     DX,offset NewInt09
  396.         MOV     AX,2509h                ;Install new int 9
  397.         INT     21h
  398.         POP     DS
  399.         MOV     AX,3516h                ;Get current int 16
  400.         INT     21h
  401.         MOV     PrevInt16Ofs,BX         ;Save it in CS-relative variables
  402.         MOV     PrevInt16Seg,ES
  403.         PUSH    DS
  404.         PUSH    CS
  405.         POP     DS
  406.         MOV     DX,offset NewInt16
  407.         MOV     AX,2516h                ;Install new int 16
  408.         INT     21h
  409.         POP     DS
  410.         RET
  411. InitVectors ENDP
  412.  
  413. CODE    ENDS
  414.         END
  415.  
  416.