Files
wbios/KBD.8
T

999 lines
21 KiB
Plaintext

;
; Keyboard BIOS
;
; (C)1997-2003 Pascal Dornier / PC Engines; All rights reserved.
; This file is licensed pursuant to the COMMON PUBLIC LICENSE 0.5.
;
; pd 030219 add explicit wait for acknowledge, option STPC_KBD -
; required for funky KBC in STPC Atlas and Industrial.
;
; Limitations:
;
; - Doesn't call INT15 on key wait, system request key
; - Screen dump is called, but not implemented by BIOS. This function
; considered risky for embedded systems, and is also highly
; printer specific. Recommend implementation as TSR if required.
; - We currently don't detect whether the keyboard is enhanced
; (101 key) or not. Most keyboards are, so we set the status bit
; kb_fkbx.
; - XT keyboard support is not tested !
;
; Note:
;
; - If interrupt latency is critical, recommend disabling keyboard
; LED updates -> comment out option LED_UPDATE.
;
;
; Flag bit definitions
;
; m_kbf bits
kb_frsh equ 01h ;right shift pressed
kb_flsh equ 02h ;left shift pressed
kb_fcsh equ 04h ;control pressed
kb_fash equ 08h ;alt pressed
kb_fscrs equ 10h ;scroll lock active
kb_fnums equ 20h ;num lock active
kb_fcaps equ 40h ;caps lock active
kb_finss equ 80h ;ins active
; m_kbf1 bits
kb_flct equ 01h ;left control pressed
kb_flal equ 02h ;left alt pressed
kb_fsys equ 04h ;system key pressed
kb_fhld equ 08h ;hold active
kb_fscr equ 10h ;scroll lock pressed
kb_fnum equ 20h ;num lock pressed
kb_fcap equ 40h ;caps lock pressed
kb_fins equ 80h ;ins key pressed
; m_kbf2 bits
kb_fled equ 07h ;led mask
kb_fscrl equ 01h ;scroll lock led
kb_fnuml equ 02h ;num lock led
kb_fcapl equ 04h ;caps lock led
kb_fack equ 10h ;kbd ACK received
kb_fres equ 20h ;kbd RESEND received
kb_fcled equ 40h ;led update
kb_ferr equ 80h ;kbd transmit error
; m_kbf3 bits
kb_fe1 equ 01h ;e1 prefix was last
kb_fe0 equ 02h ;e0 prefix was last
kb_frct equ 04h ;right control pressed
kb_fral equ 08h ;right alt pressed
kb_fkbx equ 10h ;enhanced kbd installed
kb_fnumf equ 20h ;force num lock if kbx
kb_fab equ 40h ;ab read ID was last
kb_fid equ 80h ;doing a read ID
;
; put keystroke in buffer
;
putbuf: mov si,[m_kbtail]
mov di,si
inc si
inc si
cmp si,[m_kbend] ;end of buffer ?
jnz pb1 ;:no
mov si,[m_kbstart] ;:restart at beg
pb1: cmp si,[m_kbhead] ;buffer full ?
jz pbovr ;:overrun;:yes
mov [di.bofs],ax ;store keystroke
mov [m_kbtail],si
clc ;ok
ret
pbovr: stc ;overrun: return error
ret
;
; wait for AT kbd
;
waitkbd: push cx
xor cx,cx ;timeout
wk1: out iowait,ax
in al,kb_stat ;read status port
test al,2 ;output buffer full ?
loopnz wk1 ;:yes
pop cx
ret
;
; disable AT kbd
;
disakbd: cli
call waitkbd
mov al,0adh ;disable
out kb_stat,al
sti
ret
;
; send command to AT kbd
;
kb_send: push ax ;save
push cx
mov ah,3 ;3 retries
sk1: cli
and byte [m_kbf2],kb_fled+kb_fcled+8 ;clear error bits
push ax
call waitkbd
pop ax
out kb_dat,al ;store command
sti
mov cx,2000h ;wait
sk2: test byte [m_kbf2],kb_fack+kb_fres
jnz sk4 ;:response
out iowait,ax
loop sk2 ;wait
sk3: dec ah
jnz sk1 ;:another retry
or byte [m_kbf2],kb_ferr ;set error bit
jmp short sk9 ;done
sk4: test byte [m_kbf2],kb_fres ;resend flag ?
jnz sk3 ;:retry
sk9: cli
pop cx
pop ax
ret
;
; read char from kbd
;
readchar:
#if ! def XTKBD
call disakbd
cli
call waitkbd
in al,kb_dat ;read scan code
sti
cmp al,0feh ;resend ?
jz rch3 ;:yes
cmp al,0fah ;ack ?
jnz setled ;:no
mov al,kb_fack
jmp short rch4
rch3: mov al,kb_fres
rch4: cli
or byte [m_kbf2],al
pop bx
jmp done
setled:
#if def LED_UPDATE
cli
push dx
mov dx,pic0
call setleds ;set mode LEDs
pop dx
#endif
sti
ret
#else ;XT keyboard
in al,kb_dat ;read char
xchg bx,ax
in al,port61 ;restore kbd
mov ah,al
or al,80h
out port61,al
mov al,ah
out port61,al
xchg bx,ax ;scan code -> AL
ret
#endif
#if def LED_UPDATE
;
; update LEDs
;
setleds: push ax
push cx
mov ah,[m_kbf] ;current mode flags
rol ah,4 ;-> low bits
mov al,[m_kbf2] ;current LED status
and ax,0707h ;LED bits only
cmp ah,al ;same ?
jz setled9 ;:done
test byte [m_kbf2],kb_fcled ;led update pending ?
jnz setled9 ;:yes, don't reenter
or byte [m_kbf2],kb_fcled ;set update flag
mov al,eoi ;reset interrupt controller
out dx,al ;(or iowait, depending on DX)
mov al,0edh ;set mode indicators
call kb_send ;send kbd command
#if def STPC_KBD ;funky KBC - insist on acknowledge
xor cx,cx
setled2: mov al,[m_kbf2]
test al,kb_ferr ;transmit error ?
jnz setled8
test al,kb_fack ;acknowledge ?
jnz setled3 ;:yes
dec cx
jnz setled2 ;keep waiting
jmp setled8 ;bail out
setled3: and byte [m_kbf2],!kb_fack ;clear acknowledge flag
#else
test byte [m_kbf2],kb_ferr ;transmit error ?
jnz setled8 ;:yes
#endif
mov al,ah ;send mode
call kb_send
test byte [m_kbf2],kb_ferr ;transmit error ?
jnz setled8 ;:yes
and byte [m_kbf2],255-kb_fled ;set new state
or [m_kbf2],ah
setled8: and byte [m_kbf2],3fh ;reset update flag
setled9: pop cx
pop ax
ret
#endif
;
; invalid key: ignore
;
kinval: ret
;
; left shift
;
kshlt: mov al,kb_flsh
kshlt1: test byte [m_kbf3],kb_fe0 ;did we get E0 prefix ?
jnz kshlt2 ;yes: ignore (extended key)
or [m_kbf],al ;set flag
and cl,cl ;break ?
jns kshlt2
xor [m_kbf],al ;:clear flag
kshlt2: ret
;
; right shift
;
kshrt: mov al,kb_frsh
jmp kshlt1
;
; left control
;
kctlt: or byte [m_kbf1],kb_flct ;set flag
and cl,cl ;break ?
jns kctlt1
xor byte [m_kbf1],kb_flct ;:clear flag
kctlt1: or byte [m_kbf],kb_fcsh ;set left & right flag
test byte [m_kbf1],kb_flct
jnz kctlt2 ;:ok
test byte [m_kbf3],kb_frct
jnz kctlt2 ;:ok
xor byte [m_kbf],kb_fcsh ;clear control flag
ret
kctlt2: pop ax ;don't clear hold flag
jmp i12
;
; right control
;
kctrt: test byte [m_kbf3],kb_fe0+kb_fe1 ;no E0/E1: caps lock
jz kcaps
kctrt1: or byte [m_kbf3],kb_frct ;set flag
and cl,cl ;break ?
jns kctlt1
xor byte [m_kbf3],kb_frct ;:clear flag
jmp kctlt1
;
; left alt
;
kallt: test byte [m_kbf3],kb_fe0 ;E0: right alt
jnz kalrt
or byte [m_kbf1],kb_flal ;set flag
and cl,cl ;break ?
jns kallt1
xor byte [m_kbf1],kb_flal ;:clear flag
kallt1: or byte [m_kbf],kb_fash ;set left & right flag
test byte [m_kbf1],kb_flal
jnz kallt2 ;:ok
test byte [m_kbf3],kb_fral
jnz kallt2 ;:ok
xor byte [m_kbf],kb_fash ;clear alt flag
xor ax,ax ;any char entered via alt ?
xchg al,[m_kbnum]
and al,al
jz kallt2 ;:no
call putbuf ;put it in buffer
kallt2: ret
;
; right alt
;
kalrt: or byte [m_kbf3],kb_fral ;set flag
and cl,cl ;break ?
jns kallt1
xor byte [m_kbf3],kb_fral ;:clear flag
jmp kallt1
;
; handle toggle keys &pd fixed autorepeat 980115
;
kcaps: mov ch,kb_fcaps ;caps lock
jmp short ktog
kscrl: mov ch,kb_fscrs ;scroll lock
jmp short ktog
knums: mov ch,kb_fnums
ktog: and cl,cl ;break ?
jns knums2 ;:no
not ch ;clear key pressed flag
and [m_kbf1],ch
knums1: ret
knums2: test [m_kbf1],ch ;already pressed ?
jnz knums3 ;:don't toggle again
xor [m_kbf],ch ;toggle numlock flag
knums3: or [m_kbf1],ch ;set pressed flag
ret
;
; pause
;
kpaus: and cl,cl ;break ?
js knums1 ;:ignore
test byte [m_kbf1],kb_fhld ;in hold mode ?
jnz knums1 ;:yes -> ret
or byte [m_kbf1],kb_fhld ;set hold flag
mov al,eoi ;reset interrupt controller
out pic0,al
call enakbd ;enable keyboard
kpaus1: sti ;wait for next event
hlt
test byte [m_kbf1],kb_fhld ;still on ?
jnz kpaus1 ;yes: hold
pop ax ;remove return address
jmp done2 ;exit
;
; print screen
;
kprts: and cl,cl
js knums1 ;:ignore break
cli
mov al,eoi ;reset interrupt controller
out pic0,al
int 5 ;do screen dump
pop ax ;remove return address
jmp done2 ;return
;
; reboot system
;
kboot: mov word [m_rstflg],1234h ;set cookie
jmp far 0f000h:0fff0h ;reset jump
;
; system request
;
ksysr: mov al,eoi ;reset interrupt controller
out pic0,al
mov ax,8500h
and cl,cl
jns ksysr1 ;:make
inc ax ;break code
ksysr1: int 15h ;sys req interrupt
pop ax ;remove return address
jmp done2 ;exit
;
; break
;
kbrk: and cl,cl ;ignore key release
js knums1
or byte [m_brkflg],128 ;set break flag
mov ax,[m_kbstart] ;clear kbd buffer
mov [m_kbhead],ax
mov [m_kbtail],ax
int 1bh ;break interrupt
xor ax,ax
jmp putbuf ;put break char
;
; alt + digit
;
kdigtab: db 7,8,9,0,4,5,6,0,1,2,3,0
kdig: and cl,cl ;ignore break
js kdig1
test byte [m_kbf3],kb_fe0 ;E0 prefix ?
jnz kdig2 ;yes: cursor keys, not Alt-number
mov al,cl
mov bx,offset kdigtab-47h
cs: xlat
mov ch,al
mov al,[m_kbnum] ;old value * 10
mov ah,10
mul ah
add al,ch ;add digit
mov [m_kbnum],al
kdig1: ret
kdig2: mov ah,cl ;handle Alt-cursor keys
add ah,50h
mov al,0
jmp putbuf
;
; action vector table
;
vectab: dw kinval ;FFFF = ignore key
dw kshlt ;FFFE = left shift
dw kshrt ;FFFD = right shift
dw kctlt ;FFFC = left control
dw kctrt ;FFFB = right control
dw kallt ;FFFA = left alt
dw kalrt ;FFF9 = right alt
dw kcaps ;FFF8 = caps lock
dw knums ;FFF7 = num lock
dw kscrl ;FFF6 = scroll lock
dw kpaus ;FFF5 = pause
dw kprts ;FFF4 = print screen
dw kboot ;FFF3 = reboot system
dw ksysr ;FFF2 = system request
dw kbrk ;FFF1 = break
dw kctrt1 ;FFF0 = right control
dw kdig ;FFEF = alt + digit
;
; shift offset table
;
shftab: db 1,3,3,3,5,5,5,5,7,7,7,7,9,9,9,9
;
; kbd interrupt routine
;
irq1: sti ;enable interrupt
push ax ;save registers
push bx
push cx
push dx
push si
push di
push ds
push es
cld ;forward direction
xor ax,ax ;BIOS segment
mov ds,ax
call readchar
stc ;give TSRs an opportunity to grap
mov ah,4fh ;this key: call Int15 AH=4F
int 15h
jb irq1a ;:not taken
jmp i11 ;skip this key
irq1a: mov cl,al ;copy scan code
cmp al,0e0h ;prefix code ?
jnz i1
or byte [m_kbf3],kb_fe0 ;set prefix flag
jmp done
i1: cmp al,0e1h ;prefix code ?
jnz i2
or byte [m_kbf3],kb_fe1 ;set prefix flag
jmp done
i2: cmp al,0ffh ;overrun ?
jnz i2a ;:no
#if def STPC_KBD
jmp done
#else
jmp overrun
#endif
i2a: test byte [m_kbf1],kb_fhld ;hold mode ?
jz i3 ;:no
and cl,cl ;make code ?
js i3 ;no - break
xor byte [m_kbf1],kb_fhld ;clear hold mode
i3: and al,127 ;make = break
jz overrun1 ;zero: ignore
cmp al,maxscan ;too high ?
ja overrun1 ;yes: ignore char
mov ah,11 ;11 bytes per key entry
mul ah
add ax,offset kb_tab-11 ;add offset of key table
mov si,ax
mov ah,[cs:si] ;get control byte
mov al,[m_kbf] ;get shift flag
test al,kb_flsh+kb_frsh ;shift set ?
jz i4 ;:no
or al,kb_flsh+kb_frsh ;set both bits
i4: shr ah,1 ;caps lock ?
jnb i5 ;:no
test al,kb_fcaps
jnz i6 ;:set
i5: shr ah,1 ;num lock ?
jnb i7 ;:no
test byte [m_kbf3],kb_fe0 ;E0 prefix ?
jz i5a ;:no
and al,255-kb_flsh-kb_frsh ;extended key - force unshifted scan
jmp short i7
i5a: test al,kb_fnums
jz i7 ;:not set
i6: xor al,kb_flsh+kb_frsh ;toggle shift
i7: and ax,15
mov bx,offset shftab ;shift state
cs: xlat
xchg bx,ax ;-> entry offset
mov ax,[cs:bx+si] ;get scan/action code
cmp ax,vecmin
jb ikey ;:scan code
not ax ;action key: convert to jump vector
shl ax,1
xchg bx,ax
; Dispatch special keys.
mov bx,[cs:bx+vectab] ;get vector of special key handler
call bx ;call special key handler
iact2: jmp short i11 ;done
overrun1: jmp short overrun
ikey: and cl,cl ;is it break ?
js i11 ;yes: ignore
test byte [m_kbf3],kb_fe0 ;E0 prefix ?
jz ikey9 ;:no
test al,al
jnz ikey4
cmp ah,96h ;Ctrl * -> Ctrl PrtSc
jnz ikey1
mov ah,72h
jmp short ikey9
ikey1: cmp ah,1ch ;Alt keypad enter -> A600
jnz ikey2
mov ah,0a6h
ikey2: cmp ah,35h ;Alt keypad -> A400
jnz ikey3
mov ah,0a4h
ikey3: cmp ah,84h ;high extended keys -> no change
jae ikey9
mov al,0e0h ;remember this was a extended key
jmp short ikey9
ikey4: cmp ah,1ch ;keypad enter ?
jz ikey8
cmp ah,35h ;keypad / ?
jnz ikey9
ikey8: mov ah,0e0h ;extended key, translated back by
;kb_xlat
ikey9: call putbuf ;put scan code in buffer
jnb i11 ;:ok
overrun: cli
mov al,eoi ;reset interrupt controller
out pic0,al
call beep
jmp short done2
i11:
i12: and byte [m_kbf3],255-kb_fe0-kb_fe1 ;reset prefix flag
#if ! def XTKBD ;if AT
cli
mov al,eoi ;reset interrupt controller
out pic0,al
call enakbd
jmp short done3
#endif
done: cli
mov al,eoi ;reset interrupt controller
out pic0,al
done2 :
#if ! def XTKBD
call enakbd
#endif
done3: pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
;
; INT 16 entry
;
int16: sti ;enable interrupts
push bx
push cx
push dx
push ds
xor dx,dx ;access BIOS segment
mov ds,dx
add dl,ah ;command code
jz kb_get ;AH=00: get key
dec dx
jz kb_check ;AH=01: check if key available
dec dx
jz kb_shift ;AH=02: return shift status
dec dx
jz kb_rate ;AH=03: set repetition rate
dec dx
dec dx
#if def STPC_KBD
jnz int16b
jmp kb_write ;AH=05: place scan code in buffer
int16b:
#else
jz kb_write ;AH=05: place scan code in buffer
#endif
sub dl,11
jz kb_extrd ;AH=10: extended read
dec dx
jz kb_extst ;AH=11: extended status
dec dx
jz kb_extsh ;AH=12: extended shift status
kb_exit: pop ds
pop dx
pop cx
pop bx
iret
;
; AH=00: get key from buffer
;
kb_get: call kb_getch ;get character from buffer
call kb_xlat ;translate extended characters
jb kb_get ;:extended character, try again
jmp kb_exit
;
; AH=01: check if key available
;
kb_check0: call kb_getch ;skip extended character
kb_check: call kb_chk ;check for character
jz kb_exitst ;:nothing available
call kb_xlat ;check if extended character
jb kb_check0 ;:extended character, skip
kb_extst2: inc dx ;clear Z flag
kb_exitst: pop ds ;exit, flags modified
pop dx
pop cx
pop bx
retf 2
;
; AH=10: extended read
;
kb_extrd: call kb_getch ;get character
call kb_exlat ;convert extended codes
jmp kb_exit
;
; AH=11: extended status
;
kb_extst: call kb_chk ;check status
jz kb_exitst ;:nothing, return Z flag
call kb_exlat
jmp kb_extst2 ;return result
;
; AH=12: extended shift status
;
kb_extsh: xor ah,ah
mov al,[m_kbf1] ;system request shift
test al,kb_fsys ;system request ?
jz kb_extsh2
mov ah,80h ;yes: set bit 7
kb_extsh2: and al,01110011xb
or ah,al
mov al,[m_kbf3] ;right control and alt keys
and al,00001100xb
or ah,al
;
; AH=02: return current shift status
;
kb_shift: mov al,[m_kbf] ;get shift status
jmp kb_exit
;
; AH=03: set key repetition rate
;
kb_rate: cmp al,5 ;correct command ?
jnz kb_exit
cmp bl,31 ;test rate
ja kb_exit
cmp bh,3 ;test delay
ja kb_exit
push ax ;save AX
shl bh,5
mov al,0f3h ;set repeat rate / delay command
call kb_send ;send to keyboard
#if def STPC_KBD ;funky KBC - insist on acknowledge
xor cx,cx
kbrate2: mov al,[m_kbf2]
test al,kb_ferr ;transmit error ?
jnz kbrate8
test al,kb_fack ;acknowledge ?
jnz kbrate3 ;:yes
dec cx
jnz kbrate2 ;keep waiting
jmp kbrate8 ;bail out
kbrate3: and byte [m_kbf2],!kb_fack ;clear acknowledge flag
#endif
mov al,bl ;combine delay, rate
add al,bh
call kb_send
kbrate8: pop ax ;restore AX
jmp kb_exit
;
; AH=05: place scan code in buffer
;
kb_write: mov al,1 ;error status
cli ;prevent conflict
mov bx,[m_kbtail] ;^kb buffer
inc bx ;increment
inc bx
cmp bx,[m_kbend] ;at end ?
jnz kb_write2
mov bx,[m_kbstart] ;yes: go to start
kb_write2: cmp bx,[m_kbhead] ;buffer full ?
jz kb_write3 ;:yes
xchg bx,[m_kbtail] ;update tail, get old value
dec ax ;clear AL
mov [bx+bofs],cx ;store scan code
kb_write3: sti ;end of critical section
jmp kb_exit
;
; get scan code from buffer
;
kb_getch0: sti ;reenable interrupts
hlt ;wait for next event
kb_getch: cli ;critical section
mov bx,[m_kbhead] ;^head of buffer
cmp bx,[m_kbtail] ;= tail of buffer ?
jz kb_getch0 ;yes: wait
mov ax,[bx+bofs] ;get scan code
inc bx ;increment pointer
inc bx
cmp bx,[m_kbend] ;at end ?
jnz kb_getch2
mov bx,[m_kbstart] ;yes: go to start
kb_getch2: mov [m_kbhead],bx ;update pointer
sti ;end of critical section
ret
;
; check if there is anything in buffer (Z set if not)
;
kb_chk: cli ;critical section
mov bx,[m_kbhead] ;^head of buffer
cmp bx,[m_kbtail] ;= tail of buffer ?
sti ;end of critical section
mov ax,[bx+bofs] ;get scan code
ret
;
; check if extended character, set C if yes
;
kb_xlat: cmp ah,84h ;extended ?
jbe kb_xlat83
cmp ah,0e0h
jnz kb_stc1 ;:bad
mov ah,1ch ;keypad Enter fixed code
cmp al,13 ;keypad Enter ?
jz kb_xlatok ;:yes
cmp al,10 ;keypad ^Enter
jz kb_xlatok ;:yes
mov ah,35h ;keypad /
jmp short kb_xlatok
kb_xlat83: cmp ax,00e0h ;extension ?
jz kb_xlatok
cmp ax,00f0h
jz kb_xlatok
cmp al,0f0h ;fill-in ?
jz kb_stc1
cmp al,0e0h
jnz kb_xlatok
mov al,0
kb_xlatok: clc ;ok to use
ret
kb_stc1: stc ;extended code - bad
ret
;
; translate extended characters
;
kb_exlat: cmp al,0f0h ;special ?
jnz kb_exlat2
or ah,ah ;0: more special
jz kb_exlat2
mov al,0
kb_exlat2: ret
;
; initialize keyboard controller
;
kb_ini:
#if ! def XTKBD
#if def NO_KBC ;bail quickly if no KBC present
in al,kb_stat ;check status
cmp al,0ffh ;nothing ?
jnz kb_ini0
mov byte [tmp_kbc],0ffh ;set flag - KBC not present
stc
ret
kb_ini0:
#endif
xor cx,cx
kb_ini1: in al,kb_stat ;check status
mov bl,al
and al,1 ;buffer full ?
jz kb_ini2
in al,kb_dat ;flush data
kb_ini2: and bl,2
jz kb_ini3 ;:empty
loop kb_ini1
kb_ini9: stc ;error
ret
kb_ini3: mov al,0aah ;self test command
call kb_cmd
jb kb_ini9 ;:timeout
call kb_read ;wait for data
jb kb_ini9
cmp al,55h ;expect $55 response
jnz kb_ini9
mov al,0abh ;test interface
call kb_cmd
jb kb_ini9 ;:timeout
call kb_read ;wait for data
jb kb_ini9
cmp al,0 ;expect 0 response
jnz kb_ini9
mov al,60h ;write mode register
call kb_cmd
jb kb_ini9
mov al,6dh ;initial mode (keep system flag off,
;disable mouse interface)
call kb_writ
jb kb_ini9
#else ;XT keyboard
in al,port61
out iowait,ax
or al,0c0h ;set reset bit
out port61,al
out iowait,ax
and al,7fh ;clear reset bit
out port61,al
#endif
kb_clc1: clc ;ok
ret
;
; send keyboard command AL
;
kb_cmd: out kb_stat,al ;send command
kb_cmd1: out iowait,ax
;
; wait until input (to 8042) buffer empty, C if timeout
;
kb_ibf: xor cx,cx
kb_ibf2: out iowait,ax
in al,kb_stat
and al,2 ;input buffer full ?
jz kb_clc1 ;:ok return
loop kb_ibf2
stc
ret
;
; send keyboard data AL
;
kb_writ: out kb_dat,al
jmp kb_cmd1
;
; wait until output (from 8042) buffer full, read data -> AL
;
kb_read: xor cx,cx
kb_obf2: out iowait,ax
in al,kb_stat
and al,1 ;output buffer full ?
jnz kb_obf3
loop kb_obf2
stc
ret
kb_obf3: in al,kb_dat
clc
ret
;
; second keyboard initialization (after base memory test)
;
kb_inb:
#if def NO_KBC ;skip if no KBC present
ror byte [tmp_kbc],1
jb kb_inb9
#endif
call kb_ibf ;wait for 8042 ready
in al,kb_stat ;anything in 8042 output buffer ?
and al,1
jz kb_inb2 ;:no
in al,kb_dat
mov [tmp_kbd],al ;save keyboard response
cmp al,0aah ;keyboard test ok ?
jz kb_inb9 ;:yes, don't reset again
kb_inb2: mov al,0ffh ;reset keyboard
out kb_dat,al
call kb_read ;get acknowledge
kb_inb9: mov byte [m_kbf],kb_fnums ;set Numlock
mov byte [m_kbf3],kb_fkbx ;assume enhanced keyboard
mov ax,m_kbbuf-bofs ;initialize keyboard buffer pointers
mov [m_kbstart],ax
mov [m_kbhead],ax
mov [m_kbtail],ax
mov word [m_kbend],m_kbbuf9-bofs
ret
;
; third keyboard initialization (after extended memory test)
;
kb_inc:
#if def NO_KBC ;skip if no KBC present
ror byte [tmp_kbc],1
jnb kb_inc1
ret
kb_inc1:
#endif
cmp byte [tmp_kbd],0aah ;keyboard reset ok ?
jz kb_inc2 ;:yes
call kb_read ;wait until data in buffer
jb kb_err
cmp al,0aah ;AA = keyboard response
jz kb_inc2 ;:ok
kb_err: inc byte [tmp_kbfail]
#if ! def NO_KBC
mov si,offset msg_kbd ;"Keyboard failure"
call v_msg
#endif
kb_inc2: call kb_ibf ;wait for 8042 ready
mov al,0f4h ;enable keyboard
out kb_dat,al
jmp kb_read ;get acknowledge
;
; set keyboard LEDs, enable keyboard
;
kb_ind:
#if def NO_KBC ;skip if no KBC present
ror byte [tmp_kbc],1
jnb kb_ind1
ret
kb_ind1:
#endif
#if def KEY_RATE
mov ax,0305h ;set keyboard repeat rate
mov bx,KEY_RATE
int 16h
#endif
call disakbd ;disable keyboard interface
#if def LED_UPDATE
mov dx,iowait
call setleds ;set keyboard LEDs
#endif
;-> fall through
;
; enable AT kbd
;
enakbd: cli
call waitkbd
mov al,0aeh
out kb_stat,al
sti
ret