home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
msker301.zip
/
LK250.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-01-18
|
11KB
|
264 lines
Name MSLK250
; MSLK250.ASM - A simple driver program for the DEC LK250 keyboard on IBM AT's
; Author: Terry Kennedy, St. Peter's College, Terry@spcvxa.Bitnet.
;
; Edit history
; Last edit 17 Oct 1989
; 17 Oct 1989 Add test for pre-80286 cpu and jmp $+2 breathers. [jrd]
; 16 Oct 1989 Sync USU, SPC versions; add initialization tests. [tmk]
; 9 Oct 1989 Add building instructions etc. [jrd]
;
; Purpose: Allow access to LK250 features without requiring the user to have
; any DEC drivers loaded.
;
; Method: Intercept INT 15 subfunction 4F (SysReq) and 50 (Control). If en-
; tered via 4F, place substitute scan code in buffer if the keypress
; was for a key we're remapping *and* we are active. If entered via
; 50, perform control function as follows:
;
; AL=00 - Disable substitution (keyboard "Special" [IBM] mode)
; AL=01 - Enable sunstitution (keyboard DEC mode)
; AL=02 - Send the byte in BL to the keyboard (caution: sending
; "random" bytes with this function can lock the key-
; board, necessitating a reboot.
;
; Construct final file MSLK250.COM by
; masm mslk250; reads file mslk250.asm, writes file mslk250.obj
; link mslk250; expect and ignore statement about no stack segment
; exe2bin mslk250 produces file mslk250.bin from mslk250.exe
; ren mslk250.bin mslk250.com rename the result to our runnable filename
; del mslk250.exe delete non-runnable intermediate files .exe & .obj
; del mslk250.obj
;
; mslk250 run mslk250.com to install the driver
;
;
; Date: 20-Aug-1989, X0.0-00 - Original version
; 26-Aug-1989, X0.0-01 - Pass Shift-PrtSc through even in DEC mode
; 16-Oct-1989, X0.0-02 - Add initialization tests suggested by jrd
; 17-Oct-1989, X0.0-03 - Add cpu test, add time between tests. jrd
;
main group code
;
data segment at 40h
;
db 23 dup (?)
shift db ?
db 2 dup (?)
head dw ?
tail dw ?
buff dw 16 dup (?)
db 66 dup (?)
bstart dw ?
bend dw ?
db 19 dup (?)
kbflg2 db ?
;
data ends
;
code segment public para 'code'
assume cs:main,ds:nothing
;
org 100h ; making a.COM file
;
begin: jmp start ; program starts here
;
saved15 dd ? ; previous int 15 vector
active db 0 ; are we translating?
;
; This is the new interrupt 15 routine.
;
newi15 proc far
assume ds:data
cmp ah,50h ; control function?
je ctlfnc ; if so...
cmp ah,4fh ; keyboard intercept?
jne bail ; nope, time to leave...
cmp active,1 ; are we active?
jne bail ; no, just exit...
cmp al,01h ; Esc/PF1?
je kpf1 ; if so
cmp al,45h ; Num Lk/PF2?
je kpf2 ; if so
cmp al,46h ; Scrl Lk/PF3?
je kpf3 ; if so
cmp al,37h ; PrtSc / PF4?
je kpf4 ; if so
cmp al,54h ; is it a scan we handle?
jl bail ; nope, bail out...
cmp al,69h
jg bail ; likewise...
jmp putkey ; otherwise go save the key...
;
kpf1: mov al,6ah ; make PF1 scan 6ah
jmp putkey
;
kpf2: mov al,6bh ; make PF2 scan 6bh
jmp putkey
;
kpf3: mov al,6ch ; make PF3 scan 6ch
jmp putkey
;
kpf4: push ds ; save user's [DS]
mov ax,40h
push ax
pop ds
mov al,shift ; get shift states
pop ds ; restore user's [DS]
and al,3 ; either shift state set?
jz kpf4a ; nope, this key gets translated
mov al,37h ; yes, we didn't want to translate it
jmp bail ; oh, this is a bad pun...
;
kpf4a: mov al,6dh ; make PF4 scan 6dh
jmp putkey
;
; stuff a scancode into the keyboard buffer
;
putkey: mov ah,al ; copy scan to someplace useful
mov al,0
push ds ; save user's [DS]
mov bx,40h ; point to system space
push bx
pop ds
mov bx,tail ; offset of buffer tail
mov si,bx
inc bx
inc bx ; point to next free
cmp bx,bend ; at end?
jne nowrap ; if not...
mov bx,bstart ; else wrap buffer
nowrap: cmp bx,head ; buffer full?
je bufull ; if so...
mov [si],ax ; else store character
mov tail,bx ; and update pointer
bufull: pop ds ; restore [DS]
clc ; say we did something...
iret ; and exit
;
bail: jmp [saved15]
;
; control functions: enable / disable translation, set LED's, set click
; volume, set auto-repeat rate
;
ctlfnc: cmp al,0 ; disable translation?
jne tst1 ; no
mov active,al ; else do it
mov al,0adh ; set keyboard mode
call kbsend
jmp exit ; and exit
;
tst1: cmp al,1 ; enable translation?
jne tst2 ; no
mov active,al ; else do it
mov al,0ach ; set keyboard mode
call kbsend
jmp exit ; and exit
;
tst2: cmp al,2 ; send to keyboard?
jne error ; nope, must be an error
mov al,bl ; byte to [AL] for send
call kbsend ; yes, send the byte out
jmp exit ; and exit
;
error: mov ax,0 ; say bad function
iret ; and exit
;
exit: mov ax,1234h ; say we did it
iret ; and exit
;
newi15 endp
;
; send a byte to the keyboard controller
;
kbsend proc near
push ax ; save some regs
push bx
push cx
push ds ; save user's [DS]
mov bx,40h ; point to system space
push bx
pop ds
mov bh,al ; copy data byte for retry
mov bl,3 ; set retry count
sd0: cli
and kbflg2,0cfh ; turn off ack, re-send bits
sub cx,cx ; a nice big loop
sd1: in al,64h
jmp $+2 ; reduce looping rate
test al,2
loopnz sd1 ; if not ready
mov al,bh
out 60h,al ; send the command
sti
mov cx,2800h ; wait a bit
sd3: test kbflg2,30h ; anything happen?
jnz sd7 ; seems so, go handle
jmp $+2 ; reduce looping rate
loop sd3 ; else wait
sd5: dec bl ; call it a retry if timed out
jnz sd0 ; if we have another chance
or kbflg2,80h ; otherwise fail it
jmp sd9 ; and exit
;
sd7: test kbflg2,10h ; got a proper ack?
jz sd5 ; nope, re-send it
sd9: pop ds
pop cx
pop bx
pop ax
ret
;
kbsend endp
;
endres label byte ; end of resident code
;
; Code after here will not remain resident
; Cpu test uses DOS's stack [jrd]
start: ; begin with cpu test [jrd]
push sp ; push DOS's SP, 8088's push old SP-2
pop ax ; 286's and higher push old SP
mov dx,offset main:cpumsg ; prepare bad news message
cmp ax,sp ; pre versus post push SP's
jne start0 ; ne = an 8088, sorry 'bout that [jrd]
mov ax,5000h ; see if we are already loaded
int 15h ; look for DOS->DEC mode driver
cmp ax,1234h ; find marker 1234h
jne start1 ; ne = marker not present, no driver
mov dx,offset main:errmsg ; say we're already loaded
start0: mov ah,9
int 21h
int 20h ; and bail out
;
start1: mov ax,3515h ; get existing INT 15 vector
int 21h
mov word ptr [saved15],bx ; save it
mov word ptr [saved15+2],es
mov dx,offset main:newi15 ; set new INT 15 vector
mov ax,2515h
int 21h ; set new vector from DS:DX
;
mov dx,offset main:lodmsg ; say we're loaded
mov ah,9
int 21h
;
mov ax,ds:[2ch] ; de-allocate the environment
mov es,ax ; load envirnoment segment into es
mov ah,49h ; DOS function number
int 21h ; free the environment memory
;
mov dx,offset main:endres ; point to end of resident code
add dx,0fh ; round up
mov cl,4
shr dx,cl ; convert to paragraphs (divide by 16)
mov ax,3100h ; DOS function 31h, error code=0
int 21h ; terminate and remain resident
;
errmsg: db 0dh,0ah,'MSLK250 is already loaded',0dh,0ah,07h,'$'
lodmsg: db 0dh,0ah,'MSLK250 X0.0-03 loaded',0dh,0ah,'$'
cpumsg: db 0dh,0ah,'MSLK250 requires a 286 (AT) machine or higher'
db 0dh,0ah,'$' ; wrong cpu type msg [jrd]
;
code ends
end begin ; start execution at BEGIN