; ; 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