home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msulk2.asm < prev    next >
Assembly Source File  |  2020-01-01  |  11KB  |  275 lines

  1.         Name MSLK250
  2. ; MSLK250.ASM - A simple driver program for the DEC LK250 keyboard on IBM AT's
  3. ; Author:  Terry Kennedy, St. Peter's College, Terry@spcvxa.Bitnet.
  4. ;
  5. ; Edit history
  6. ; Last edit Sat Apr  6 18:02:34 1991
  7. ;  6 Apr 1991 Change internal references to this file to have right name [fdc]
  8. ; 17 Oct 1989 Add test for pre-80286 cpu and jmp $+2 breathers. [jrd]
  9. ; 16 Oct 1989 Sync USU, SPC versions; add initialization tests. [tmk] 
  10. ;  9 Oct 1989 Add building instructions etc. [jrd]
  11. ;
  12. ; Purpose: Allow access to LK250 features without requiring the user to have
  13. ;          any DEC drivers loaded.
  14. ;
  15. ; Method:  Intercept INT 15 subfunction 4F (SysReq) and 50 (Control). If en-
  16. ;          tered via 4F, place substitute scan code in buffer if the keypress
  17. ;          was for a key we're remapping *and* we are active. If entered via
  18. ;          50, perform control function as follows:
  19. ;
  20. ;               AL=00 - Disable substitution (keyboard "Special" [IBM] mode)
  21. ;               AL=01 - Enable substitution (keyboard DEC mode)
  22. ;               AL=02 - Send the byte in BL to the keyboard (caution: sending
  23. ;            "random" bytes with this function can lock the key-
  24. ;            board, necessitating a reboot.
  25. ;
  26. ; Construct final file MSLK250.COM by
  27. ;  masm msulk2;        reads file msulk2.asm, writes file msulk2.obj
  28. ;  link msulk2;        expect and ignore statement about no stack segment
  29. ;  exe2bin msulk2      produces file msulk2.bin from msulk2.exe
  30. ;  ren msulk2.bin msulk2.com    rename the result to our runnable filename
  31. ;  del msulk2.exe      delete non-runnable intermediate files .exe & .obj
  32. ;  del msulk2.obj
  33. ;
  34. ;  msulk2              run msulk2.com to install the driver
  35. ;
  36. ;
  37. ; Date:    20-Aug-1989, X0.0-00 - Original version
  38. ;       26-Aug-1989, X0.0-01 - Pass Shift-PrtSc through even in DEC mode
  39. ;       16-Oct-1989, X0.0-02 - Add initialization tests suggested by jrd
  40. ;       17-Oct-1989, X0.0-03 - Add cpu test, add time between tests. jrd
  41. ;       28-Nov-1990  X0.0-04 - Fix problem on PS/2's where special keys
  42. ;                  were followed by a spurious divide symbol.
  43. ;       29-Nov-1990  X0.0-05 - More PS/2 fixes.
  44. ;
  45. main    group   code
  46. ;
  47. data    segment at 40h
  48. ;
  49.         db      23 dup (?)
  50. shift    db    ?
  51.     db    2 dup (?)
  52. head    dw      ?
  53. tail    dw      ?
  54. buff    dw      16 dup (?)
  55.         db      66 dup (?)
  56. bstart  dw      ?
  57. bend    dw      ?
  58.         db      19 dup (?)
  59. kbflg2  db      ?
  60. ;
  61. data    ends
  62. ;
  63. code    segment public para 'code'
  64. assume  cs:main,ds:nothing
  65. ;
  66.         org     100h                    ; making a.COM file
  67. ;
  68. begin:  jmp     start                   ; program starts here
  69. ;
  70. saved15 dd      ?                       ; previous int 15 vector
  71. active  db      0                       ; are we translating?
  72. ;
  73. bail:   jmp     [saved15]
  74. ;
  75. ; This is the new interrupt 15 routine.
  76. ;
  77. newi15  proc    far
  78.         assume  ds:data
  79.         cmp     ah,50h                  ; control function?
  80.         jne     noctl
  81.     jmp    ctlfnc                  ; if so...
  82. noctl:  cmp     ah,4fh                  ; keyboard intercept?
  83.         jne     bail                    ; nope, time to leave...
  84.         cmp     active,1                ; are we active?
  85.         jne     bail                    ; no, just exit...
  86.         cmp     al,01h                  ; Esc/PF1?
  87.         je      kpf1                    ; if so
  88.         cmp     al,45h                  ; Num Lk/PF2?
  89.         je      kpf2                    ; if so
  90.         cmp     al,46h                  ; Scrl Lk/PF3?
  91.         je      kpf3                    ; if so
  92.         cmp     al,37h                  ; PrtSc / PF4?
  93.         je      kpf4                    ; if so
  94.         cmp     al,54h                  ; is it a scan we handle?
  95.         jl      bail                    ; nope, bail out...
  96.         cmp     al,69h
  97.         jg      bail                    ; likewise...
  98.         jmp     putkey                  ; otherwise go save the key...
  99. ;
  100. kpf1:   mov     al,6ah                  ; make PF1 scan 6ah
  101.         jmp     putkey
  102. ;
  103. kpf2:   mov     al,6bh                  ; make PF2 scan 6bh
  104.         jmp     putkey
  105. ;
  106. kpf3:   mov     al,6ch                  ; make PF3 scan 6ch
  107.         jmp     putkey
  108. ;
  109. kpf4:    push    ds            ; save user's [DS]
  110.     mov    ax,40h
  111.     push    ax
  112.     pop    ds
  113.     mov    al,shift        ; get shift states
  114.     pop    ds            ; restore user's [DS]
  115.     and    al,3            ; either shift state set?
  116.     jz    kpf4a            ; nope, this key gets translated
  117.     mov    al,37h            ; yes, we didn't want to translate it
  118.     jmp    bail            ; oh, this is a bad pun...
  119. ;
  120. kpf4a:    mov     al,6dh                  ; make PF4 scan 6dh
  121.         jmp     putkey
  122. ;
  123. ; stuff a scancode into the keyboard buffer
  124. ;
  125. putkey: push    ax            ; edit 04 - save registers for PS/2
  126.     push    bx            ; "
  127.     push    si            ; "
  128.     mov     ah,al                   ; copy scan to someplace useful
  129.         mov     al,0
  130.         push    ds                      ; save user's [DS]
  131.         mov     bx,40h                  ; point to system space
  132.         push    bx
  133.         pop     ds
  134.         mov     bx,tail                 ; offset of buffer tail
  135.         mov     si,bx
  136.         inc     bx
  137.         inc     bx                      ; point to next free
  138.         cmp     bx,bend                 ; at end?
  139.         jne     nowrap                  ; if not...
  140.         mov     bx,bstart               ; else wrap buffer
  141. nowrap: cmp     bx,head                 ; buffer full?
  142.         je      bufull                  ; if so...
  143.         mov     [si],ax                 ; else store character
  144.         mov     tail,bx                 ; and update pointer
  145. bufull: pop     ds                      ; restore [DS]
  146.     pop    si            ; edit 04 - restore registers for PS/2
  147.     pop    bx            ; "
  148.     pop    ax            ; "
  149.         clc                             ; say we did something...
  150.     retf    2            ; edit 05 - preserve flags
  151. ;
  152. ; control functions: enable / disable translation, set LED's, set click
  153. ; volume, set auto-repeat rate
  154. ;
  155. ctlfnc: cmp     al,0                    ; disable translation?
  156.         jne     tst1                    ; no
  157.         mov     active,al               ; else do it
  158.         mov     al,0adh                 ; set keyboard mode
  159.         call    kbsend
  160.         jmp     exit                    ; and exit
  161. ;
  162. tst1:   cmp     al,1                    ; enable translation?
  163.         jne     tst2                    ; no
  164.         mov     active,al               ; else do it
  165.         mov     al,0ach                 ; set keyboard mode
  166.         call    kbsend
  167.         jmp     exit                    ; and exit
  168. ;
  169. tst2:   cmp     al,2                    ; send to keyboard?
  170.         jne     error                   ; nope, must be an error
  171.         mov     al,bl                   ; byte to [AL] for send
  172.         call    kbsend                  ; yes, send the byte out
  173.         jmp     exit                    ; and exit
  174. ;
  175. error:  mov     ax,0                    ; say bad function
  176.         iret                            ; and exit
  177. ;
  178. exit:   mov     ax,1234h                ; say we did it
  179.         iret                            ; and exit
  180. ;
  181. newi15  endp
  182. ;
  183. ; send a byte to the keyboard controller
  184. ;
  185. kbsend  proc    near
  186.         push    ax                      ; save some regs
  187.         push    bx
  188.         push    cx
  189.         push    ds                      ; save user's [DS]
  190.         mov     bx,40h                  ; point to system space
  191.         push    bx
  192.         pop     ds
  193.         mov     bh,al                   ; copy data byte for retry
  194.         mov     bl,3                    ; set retry count
  195. sd0:    cli
  196.         and     kbflg2,0cfh             ; turn off ack, re-send bits
  197.         sub     cx,cx                   ; a nice big loop
  198. sd1:    in      al,64h
  199.     jmp    $+2            ; reduce looping rate
  200.         test    al,2
  201.         loopnz  sd1                     ; if not ready
  202.         mov     al,bh
  203.         out     60h,al                  ; send the command
  204.         sti
  205.         mov     cx,2800h                ; wait a bit
  206. sd3:    test    kbflg2,30h              ; anything happen?
  207.         jnz     sd7                     ; seems so, go handle
  208.     jmp    $+2            ; reduce looping rate
  209.         loop    sd3                     ; else wait
  210. sd5:    dec     bl                      ; call it a retry if timed out
  211.         jnz     sd0                     ; if we have another chance
  212.         or      kbflg2,80h              ; otherwise fail it
  213.         jmp     sd9                     ; and exit
  214. ;
  215. sd7:    test    kbflg2,10h              ; got a proper ack?
  216.         jz      sd5                     ; nope, re-send it
  217. sd9:    pop     ds
  218.         pop     cx
  219.         pop     bx
  220.         pop     ax
  221.         ret
  222. ;
  223. kbsend  endp
  224. ;
  225. endres  label   byte                    ; end of resident code
  226. ;
  227. ; Code after here will not remain resident
  228. ;  Cpu test uses DOS's stack [jrd]
  229. start:                    ; begin with cpu test [jrd]
  230.     push    sp            ; push DOS's SP, 8088's push old SP-2
  231.     pop    ax            ; 286's and higher push old SP
  232.     mov    dx,offset main:cpumsg    ; prepare bad news message
  233.     cmp    ax,sp            ; pre versus post push SP's
  234.     jne    start0            ; ne = an 8088, sorry 'bout that [jrd]
  235.     mov     ax,5000h                ; see if we are already loaded
  236.         int     15h                     ; look for DOS->DEC mode driver
  237.         cmp     ax,1234h                ; find marker 1234h
  238.         jne     start1                  ; ne = marker not present, no driver
  239.         mov     dx,offset main:errmsg   ; say we're already loaded
  240. start0: mov     ah,9
  241.         int     21h
  242.     int    20h            ; and bail out
  243. ;
  244. start1: mov     ax,3515h                ; get existing INT 15 vector
  245.         int     21h
  246.         mov     word ptr [saved15],bx   ; save it
  247.         mov     word ptr [saved15+2],es
  248.         mov     dx,offset main:newi15   ; set new INT 15 vector
  249.         mov     ax,2515h
  250.         int     21h                     ; set new vector from DS:DX
  251. ;
  252.         mov     dx,offset main:lodmsg   ; say we're loaded
  253.         mov     ah,9
  254.         int     21h
  255. ;
  256.         mov     ax,ds:[2ch]             ; de-allocate the environment
  257.         mov     es,ax                   ; load envirnoment segment into es
  258.         mov     ah,49h                  ; DOS function number
  259.         int     21h                     ; free the environment memory
  260. ;
  261.         mov     dx,offset main:endres   ; point to end of resident code
  262.         add     dx,0fh                  ; round up
  263.         mov     cl,4
  264.         shr     dx,cl                   ; convert to paragraphs (divide by 16)
  265.         mov     ax,3100h                ; DOS function 31h, error code=0
  266.         int     21h                     ; terminate and remain resident
  267. ;
  268. errmsg:    db    0dh,0ah,'MSULK2 is already loaded',0dh,0ah,07h,'$'
  269. lodmsg: db      0dh,0ah,'MSULK2 X0.0-05 loaded',0dh,0ah,'$'
  270. cpumsg:    db    0dh,0ah,'MSULK2 requires a 286 (AT) machine or higher'
  271.     db    0dh,0ah,'$'        ; wrong cpu type msg  [jrd]
  272. ;
  273. code    ends
  274.         end     begin                   ; start execution at BEGIN
  275.