⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbd.8

📁 PC x386 bios source code
💻 8
📖 第 1 页 / 共 2 页
字号:
        ;
        ; Keyboard BIOS
        ;
        ; (C)1997-2001 Pascal Dornier / PC Engines; All rights reserved.
        ; This file is licensed pursuant to the COMMON PUBLIC LICENSE 0.5.
        ;
        ; 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.
        ;
        ; 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    ;input 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
        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
        test    byte [m_kbf2],kb_ferr   ;transmit error ?
        jnz     setled8 ;:yes
        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     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
        jmp     overrun

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -