📄 kbd.8
字号:
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
jz kb_write ;AH=05: place scan code in buffer
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
mov al,bl ;combine delay, rate
add al,bh
call kb_send
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:
; jb kb_err2 ;&
; call hexbyt ;&
;kb_err2: ;&
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -