www.pudn.com > hpbios.rar > AKBRD.ASM
; []===========================================================[] ; ; NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R) ; INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE ; DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED ; WRITTEN AUTHORIZATION FROM THE OWNER. ; ; []===========================================================[] ; ;---------------------------------------------------------------------------- ;Rev Date Name Description ;---------------------------------------------------------------------------- ;R28A 02/01/00 RCH Fixed bug for Millennium OS for legacy free system: ; 1. system fail to boot if USB keyboard is connected. ; 2. DOS prompt hang up. ; ;R28 10/18/99 RCH Support platform without KBC for legacy free system ;R27 09/29/99 CHG Added WFM Remote lockout service ;R25A 04/28/99 BAR Move Code to postint9.asm ;R26 01/22/99 PAL Remove "Bootblock_16K_Support" definition to use ; Automatic_Load_Awdflash option in FLASH_64k_Unit ;R25 06/26/98 DRS Add No_Automatic_Load_Awdflash_InPOST definition ; Some customers want to automatically load awdflash.exe, ; but they don't want this function during POST. ; They just want to automaticlly load awdflash.exe in BootBlock. ;R24 05/12/98 RAX Added code for Cyrix VSA save to disk support. PAGE 62,132 TITLE AKBRD .386 ; +---------------+ ; | | ; | INT 9 | ; | | ; +---------------+ ; .XLIST INCLUDE BIOS.CFG INCLUDE 8042.EQU INCLUDE 8259.EQU INCLUDE AKBRD.EQU INCLUDE POST.EQU INCLUDE COMMON.MAC INCLUDE BTROMSEG.EQU ifdef RPB_ENABLED include rpb.cfg ifndef RPB_ALWAYS_ENABLED extrn rpb_hot_keys:near endif ; RPB_ALWAYS_ENABLED endif ; RPB_ENABLED ;R26ifdef Bootblock_16K_Support ;R25A ifdef Automatic_Load_Awdflash ;R25A ifNdef No_Automatic_Load_Awdflash_InPOST ;R25 ;R25A extrn INT_Awdflash_Check:near ;R25A endif ;No_Automatic_Load_Awdflash_InPOST ;R25 ;R25A endif ;Automatic_Load_Awdflash ;R26endif ;Bootblock_16K_Support EXTRN KEYS:BYTE EXTRN REDO:NEAR EXTRN SETUP:NEAR .LIST PAGE G_RAM SEGMENT USE16 AT 40H INCLUDE G_RAM.INC G_RAM ENDS XGROUP GROUP XCODE XCODE SEGMENT USE16 PARA PUBLIC 'XCODE' ASSUME CS:XGROUP,ES:XGROUP XCODE ENDS DGROUP GROUP FCODE FCODE SEGMENT USE16 DWORD PUBLIC 'CODE' ASSUME CS:DGROUP PUBLIC BEEP_KEY PUBLIC KBD_INT PUBLIC BUFFER_8042_FULL PUBLIC UPDATE_LED PUBLIC INSERT_CHAR PUBLIC KB_OUT ALIGN 4 KBD_INT PROC NEAR ; This routine handles the interrupts generated by the keyboard ; ; ENTRY: NONE ; EXIT: NONE sti ; enable int cld push ds pusha mov bx,G_RAM ; set data seg mov ds,bx ASSUME DS:G_RAM ; MAKE 2 BYTE VARIABLES (scan_char,temp) mov bp,sp sub sp,2 ;R28Aifndef NO_KBC ;R28 mov ax,DISABLE_KBRD ; disable keyboard call kb_cntrlr_out ; READ SCAN FROM KEYBOARD (8042) cli call buffer_8042_full ; wait for controller to ; process disable keyboard in al,DATA8042 ; READ DATA FROM 8042 ;R28Aendif; NO_KBC ;R28 public PostInt9_to_AKBRD_Entry PostInt9_to_AKBRD_Entry: ; perform an INT 15H, function 4FH to allow hooks into keyboard ;R28Aifndef NO_KBC ;R28 stc ; set carry flag - in case of iret mov ah,04fh ; set function call int 15h ; do it jnc qwik_exit ; somebody else handled scan code mov scan_char,al ; save scan after int 15 sti ;;kevinifndef Graphics_Post ;;kevin test INIT_ERR_FLG,IEF_IN_POST; in POST? ;;kevin jz short Not_In_Post ;;kevin ;;kevin ifdef Bootblock_16K_Support ;;kevin ifdef Automatic_Load_Awdflash ;;kevin ifNdef No_Automatic_Load_Awdflash_InPOST ;R25 ;;kevin test byte ptr POST_Flag,AWDFLASH_ON ;will run AWDLFASH.EXE ;;kevin jnz short Not_In_Post ;YES ;;kevin endif ;No_Automatic_Load_Awdflash_InPOST ;R25 ;;kevin endif ;Automatic_Load_Awdflash ;;kevin endif ;Bootblock_16K_Support ;;kevin ;;kevin cmp al,KEY_OVERRIDE ; insert key pressed? ;;kevin jne short @F ;;kevin or byte ptr POST_FLAG,OVERRIDE_ON ;override key ;;kevin@@: ;;kevin cmp al,KEY_SETUP ; del key pressed? ;;kevin jne short @F ;;kevin test byte ptr SHFT_STAT,ALT+CTRL ;;kevin jnz short @F ;;kevin ;;kevin ifndef NO_DEL_KEY_ENTER_SETUP ;;kevin jmp Setup_Check ;;kevin else ;NO_DEL_KEY_ENTER_SETUP ;;kevin ifdef KEY_SETUP_SCAN_CODE ;;kevin jmp Setup_Check ;;kevin endif ;KEY_SETUP_SCAN_CODE ;;kevin endif ;NO_DEL_KEY_ENTER_SETUP ;;kevin@@: ;;kevin ;;kevin Not_In_Post: ;;kevinendif; Graphics_Post ;[]------------------------------------------------------[] ;R26ifdef Bootblock_16K_Support ;R25A ifdef Automatic_Load_Awdflash ;R25A ifNdef No_Automatic_Load_Awdflash_InPOST ;R25 ;R25A ;Check if flash key pressed(ALT+Fn) ? Far jump to flash loader ;R25A ;if yes. ;R25A test byte ptr POST_FLAG,SETUP_ON ; will run SETUP ? ;R25A jnz short @F ; YES ;R25A ;R25A cmp al,KEY_AWDFLASH ; Key to run flash ;R25A jne short @F ; utility ? ;R25A test byte ptr SHFT_STAT,ALT ; ALT ? ;R25A jz short @F ;R25A ;R25A test POST_FLAG,AWD_Str_Show ;R25A jz short @f ;R25A ;R25A mov sp,bp ; restore sp ;R25A popa ; restore all registers ;R25A pop ds ; restore DS ;R25A far_jmp,Xgroup_Segment ;R25A @@: ;R25A ;R25A endif ;No_Automatic_Load_Awdflash_InPOST ;R25 ;R25A endif ;Automatic_Load_Awdflash ;R25A ;R26endif ;Bootblock_16K_Support ;[]------------------------------------------------------[] ; check scan response cmp al,KB_RESEND JNE SHORT .D167 ; SKIP : NOT RESEND OR KB_FLAG_2,RESEND_RECV ; SET FLAG JMP SHORT QWIK_EXIT ; DONE .D167: CMP AL,KB_ACK JNE SHORT .D182 ; SKIP : NOT ACK OR KB_FLAG_2,ACK_RECV ; SET FLAG JMP SHORT QWIK_EXIT ; DONE .D182: CALL UPDATE_LED CMP AL,KBS_OVER ; is this an overrun char? JNE SHORT .D18F JMP .D806 ; OVERFLOW - ring bell ; check to see if there is a read id in progress .D18F: MOV AH,KB_FLAG_3 ; get flag TEST AH,READ_ID+LAST_AB ; check JE SHORT NO_READID ; no read id in progress JS SHORT FIRST_ID ; looking for 1st byte AND AH,NOT LAST_AB ; reset flags CMP AL,ID_101_2 ; is this the 2nd id byte JNE SHORT EX_READID ; if not, just clear flag OR AH,E101_KEY ; set 101 keyboard flag TEST AH,FORCE_NUM ; should we set num lock JZ SHORT EX_READID ; if not, just return OR SHFT_STAT,NUM_LK ; set num lock flag MOV KB_FLAG_3,AH ; restore flag CALL UPDATE_LED ; and send to keyboard JMP SHORT QWIK_EXIT ; leave FIRST_ID: AND AH,NOT(READ_ID+LAST_AB) ; reset flags CMP AL,ID_101_1 ; is this the first id byte JNE SHORT EX_READID ; if not, just clear flag OR AH,LAST_AB ; if yes, set LAST_AB flag EX_READID: MOV KB_FLAG_3,AH ; restore flag QWIK_EXIT: JMP .D86A NO_READID: CMP AL,0E0H ; is this an E0 char JNE SHORT TRY_E1 OR KB_FLAG_3,LAST_E0+E101_KEY ; set E0 flag JMP .D86A_EXIT ; return without reseting flag TRY_E1: CMP AL,0E1H ; is this an E1 char JNE SHORT NO_E OR KB_FLAG_3,LAST_E1+E101_KEY ; set E1 flag .DE1_E0: JMP .D86A_EXIT ; return without reseting flag NO_E: MOV TEMP,0 ; get values from 'keys' table lea si,Keys ; setup pointer in table mov dl,al ; save scan code in dl and ax,07fh shl ax,1 shl ax,1 add si,ax ; si = pointer to 'keys' table ; check groups and start process mov dh,KB_FLAG_3 ; get kb flag for later use ; check for shift (treat make/break shift the same) xor ax,ax mov al,cs:[si] ; get key type from table cmp al,SHIFT jne short keyt_1 ; skip : shift test dh,LAST_E1 ; are we in a E1 sequence jne short .de1_e0 ; return without resetting e1 test dh,LAST_E0 ; is this an E0 je short keyt_ret ; if not, exit test byte ptr cs:[si]+1,ALT+CTRL ; if this is alt or ctrl jne short keyt_ret ; continue processing normal jmp short qwik_exit ; else if shift, throw away ; process break codes keyt_1: test dl,80h ; dl contains scan code jz short keyt_3 ; skip : it is a make key and dl,07fh ; dl = make scan code cmp al,TOGGLE je short keyt_2 ; cont : this is a toggle key cmp dl,INS_KEY jne short keyt_ret_brk ; cont : this is the insert key ; indicate toggle key released keyt_2: mov al,cs:+1[si] not al and kbd_flg1,al ; process system key on at cmp dl,SYS_KEY jne short keyt_ret_brk ; return break : not sys key call int_kb_enable mov ax,8501h ; int 15 - sys req key pressed int 15h jmp short keyt_ret_brk ; return break ; check for if we should end hold state keyt_3: test KBD_FLG1,HOLD jz short keyt_ret ; hold active cmp dl,NUM_KEY jz short keyt_ret ; process key but don't end hold cmp dl,SYS_KEY jz short keyt_ret ; process key but don't end hold test SHFT_STAT,CTRL jnz short keyt_5 ; release hold if on cmp dl,CAPS_KEY jz short keyt_ret ; process key but don't end hold cmp dl,SCRL_KEY jz short keyt_ret ; process key but don't end hold keyt_5: and KBD_FLG1,NOT HOLD ; END HOLD STATE AND EAT CHARACTER keyt_ret_brk: mov ax,BREAK ; return break code ; jump to routine for key type keyt_ret: mov bx,ax ; get type cmp bx,BREAK ; check for value in bound jb short go_jmp ; good value mov bx,BREAK ; error go_jmp: shl bx,1 ; word offset jmp word ptr cs:jmptable[bx] ; jmp to routine even jmptable: dw offset SHIFT_S ; SHIFT dw offset ALPHA_S ; ALPHA dw offset ASCII_S ; ASCII dw offset FUNC_S ; FUNCTION dw offset KEYP_S ; KEYPAD dw offset TOG_S ; TOGGLE dw offset NUM_S ; NUMERIC dw offset F11_HND ; F11_F12 dw offset .D86A ; BREAK PAGE ; process shift: ; update flag on shift state shift_s: mov al,cs:+1[si] ; get bit mask mov ah,al ; save template test scan_char,80h ; check make/break je short .d24c ; goto make not al ; set break and SHFT_STAT,al ; clear flag test ah,ALT+CTRL ; is this an ALT or CTRL key JE SHORT .D260 ; no, we are done TEST DH,LAST_E0 ; is this a right shift key JE SHORT LEFT_BREAK AND KB_FLAG_3,AL ; clear right shift key JMP SHORT .D260 LEFT_BREAK: ROR AL,1 ; change template ROR AL,1 AND KBD_FLG1,AL ; clear left shift key JMP SHORT .D260 .D24C: OR SHFT_STAT,AL ; set make TEST AL,ALT+CTRL ; is this an ALT or CTRL key? JE SHORT .D260 ; no, we are done TEST DH,LAST_E0 ; is this an E0 shift (right) JE SHORT LEFT_MAKE OR KB_FLAG_3,AL ; set right shift key flag JMP SHORT .D260 LEFT_MAKE: SHR AL,1 ; change template SHR AL,1 OR KBD_FLG1,AL ; set left shift key flag ; CHECK FOR END OF ALT INPUT .D260: CMP SCAN_CHAR,0B8H JE SHORT NOT_D86A_L1 .D86A_L1: JMP .D86A ; DONE : END OF ALT INPUT NOT_D86A_L1: ; if(kchar = getd(ALT_INPUT,0)) /*does it exist ? */ MOV AL,ALT_INPUT OR TEMP,AL ; SET CHARACTER VALUE JZ SHORT .D86A_L1 ; DONE ; scan = 0; putd(ALT_INPUT,0,0); XOR AX,AX MOV SCAN_CHAR,AL MOV ALT_INPUT,AL ; 0 JMP .D7BA ; SAVE VALUE PAGE ; PROCESS ALPHA: ; CHECK FOR "SPACE" ALPHA_S: CMP SCAN_CHAR,57 JNE SHORT .D2A3 ; NOT SPACE MOV TEMP,20H ; SET "SPACE" VALUE JMP SHORT .D310 ; CHECK FLAG FOR FLAVOR (ALT, CNTR, ECT) .D2A3: TEST SHFT_STAT,ALT JNE SHORT .D310 .D2CB: TEST SHFT_STAT,CTRL JE SHORT .D2EC MOV AL,CS:+3[SI] ; ctrl code MOV TEMP,AL ; set TEMP to code from table JMP SHORT .D310 .D2EC: MOV AL,CS:+1[SI] ; GET ALPHA VALUE MOV TEMP,AL TEST SHFT_STAT,CAPS_LK JE SHORT .D30F AND TEMP,0DFH ; MAKE UPPER CASE .D30F: TEST SHFT_STAT,LT_SHFT + RT_SHFT JE SHORT .D310 XOR TEMP,20H ; SWITCH CASE .D310: JMP SWITCH_DONE ; PROCESS NON ALPHA ASCII CHARACTERS ; starting with the speed switching combination ASCII_S: MOV AL,SHFT_STAT ; check for ctrl alt +,- V2.08 AND AL,ALT+CTRL CMP AL,ALT+CTRL JNE .D31EB ifdef RPB_ENABLED ifndef RPB_ALWAYS_ENABLED mov al,BYTE PTR CS:[SI+1] ; pass in key Post_Func_Call rpb_hot_keys ; RPB hotkeys endif endif ; RPB_ENABLED CMP BYTE PTR CS:[SI+1],1BH ; escape key? JNE NOT_SETUP ;;kevinifndef Graphics_Post ;;kevinSetup_Check: ;;kevin TEST INIT_ERR_FLG,IEF_IN_POST ; in POST? ;;kevin JZ SHORT SAVE_FOR_POST ; no... ;;kevin or byte ptr POST_FLAG,SETUP_ON ;;kevin ;;kevin TEST INIT_ERR_FLG,IEF_SETUP_OK ; is POST occurring ;;kevin jz short save_for_post ;;kevin ;;kevin AND INIT_ERR_FLG,NOT IEF_SETUP_OK ; prevent further ;;kevin ; setup invocations ;;kevinendif; Graphics_Post if STD_Function EQ 1 ;Check if resume from Suspend To Disk (By BIOS) extrn Check_0V_Resume:near call Check_0V_Resume jnz short save_for_post endif ;STD_Function EQ 1 ifdef VSA_VGA ifdef S2D_SUPPORT extrn Check_VSA_resume:near call Check_VSA_resume jnz short save_for_post endif ;S2D_SUPPORT endif ;VSA_VGA ifdef HPM_Support ;Check if resume from Suspend To Disk (By HPM) extrn Check_HPM_Resume:Near Call Check_HPM_Resume jnz short save_for_post endif ;HPM_Support ;;kevinifndef Graphics_Post ;;kevin extrn Go_Cmos_Setup:near ;;kevin jmp Go_Cmos_Setup ;;kevinendif; Graphics_Post save_for_post: or byte ptr Init_Err_Flg,IEF_TO_ENTER_SETUP NOT_SETUP: ; CHECK FLAG FOR FLAVOR (ALT, CNTR, ECT) .D31EB: TEST SHFT_STAT,ALT JE SHORT .D336 ; jmp if not ALT CMP SCAN_CHAR,0FH ; is this a tab JNE SHORT .D335_2 MOV SCAN_CHAR,165 ; set code JMP SHORT .D335 ; put in checks for keypad / and keypad RETURN .D335_2: TEST DH,LAST_E0 ; is this extended code JE SHORT .D335 ; if not, finished CMP SCAN_CHAR,01CH ; keypad RETURN JNE SHORT .D335_1 ; next MOV SCAN_CHAR,166 ; set scan code JMP SHORT .D335 .D335_1: CMP SCAN_CHAR,035H ; keypad / JNE SHORT .D335 ; done MOV SCAN_CHAR,164 ; set scan code .D335: CMP SCAN_CHAR,084H ; is this in old range JBE SHORT .D335_A JMP .D310 ; if not leave code as 0 .D335_A: MOV TEMP,0F0H ; set extended function JMP .D310 ; yes, 101, ALTs defined .D336: TEST SHFT_STAT,CTRL ; ctrl characters? JE SHORT .D356 MOV AL,CS:+3[SI] ; ctrl code CMP SCAN_CHAR,0FH ; is this a tab JNE SHORT .D336_C ; check next case MOV SCAN_CHAR,094H ; tab is extended function .D336_F: MOV AL,0 ; set extended code JMP SHORT .D336_B .D336_C: CMP SCAN_CHAR,04AH ; is this keypad - JNE SHORT .D336_G ; no, check next case MOV SCAN_CHAR,142 ; ctrl - is extended function JMP SHORT .D336_F .D336_G: CMP SCAN_CHAR,04EH ; is this keypad + JNE SHORT .D336_D ; no, check extended keys MOV SCAN_CHAR,144 ; ctrl + is extended function JMP SHORT .D336_F .D336_D: TEST DH,LAST_E0 ; alternate function JE SHORT .D336_B ; if not, go home CMP SCAN_CHAR,035H ; is this keypad '/' JNE SHORT .D336_A ; if not, check next case MOV SCAN_CHAR,149 ; set scan code JMP SHORT .D336_F .D336_A: CMP SCAN_CHAR,01CH ; is this keypad RETURN JNE SHORT .D336_B .D336_E: MOV SCAN_CHAR,0E0H ; set prefix code .D336_B: MOV TEMP,AL ; set TEMP to code from table JMP SWITCH_DONE .D356: TEST SHFT_STAT,LT_SHFT + RT_SHFT JE SHORT .D368 ; jmp if no shift MOV AL,CS:+2[SI] ; shift code TEST DH,LAST_E0 ; is this alternate key JE SHORT .D336_B ; if not, finish CMP AL,03FH ; is this '?' (shift /) JNE SHORT .D368_A ; no, test for keypad RETURN ; yes, get unshifted code .D368: MOV AL,CS:+1[SI] ; unshifted code TEST DH,LAST_E0 ; is this alternate key JE SHORT .D336_B ; if not, finish CMP AL,02FH ; is this a '/' JE SHORT .D336_E ; yes, set prefix code .D368_A: CMP AL,0DH ; is this keypad RETURN JNE SHORT .D336_B ; return normal scan code JMP SHORT .D336_E ; set prefix code ; PROCESS NUMERIC NUM_S: .D375: TEST SHFT_STAT,ALT JNE SHORT .D375_A JMP .D336 ; CHECK STATES .D375_A: ADD SCAN_CHAR,118 ; make alt # JMP SWITCH_DONE PAGE ; PROCESS TOGGLE TOG_S: MOV AL,CS:+1[SI] ; CHECK IF ALREADY SET TEST KBD_FLG1,AL JE SHORT .D3AE ; NOPE CMP SCAN_CHAR,046H ; ? JNE SHORT .D86A_L4 ; SKIP TEST SHFT_STAT,CTRL JE SHORT .D86A_L4 ; SKIP .D3AE: OR KBD_FLG1,AL ; SET BIT ; CHECK FOR SYS KEY CMP SCAN_CHAR,84 JNE SHORT .D3E8 ; NOPE call int_kb_enable MOV AX,8500H INT 15H JMP .D87A ; CHECK FOR CAPS LOCK .D3E8: CMP SCAN_CHAR,58 JNE SHORT .D45F ; NOPE TEST SHFT_STAT,CTRL JNE SHORT .D86A_L4 XOR SHFT_STAT,CAPS_LK ; CHANGE FLAG CALL UPDATE_LED ; CHANGE LED .D86A_L4: JMP .D86A ; DONE ; CHECK FOR NUM LOCK .D45F: CMP SCAN_CHAR,69 JNE SHORT .D4E3 ; SKIP : NOT NUM LOCK TEST DH,LAST_E1 ; is this in a E1 sequence JNE SHORT HOLD_IT ; this is Pause TEST DH,E101_KEY ; is this a 101 JNE SHORT .D4CC ; yes, this is just num lock TEST SHFT_STAT,CTRL JE SHORT .D4CC ; SKIP : NOT CONTROL HOLD_IT: TEST KBD_FLG1,HOLD ; save hold state PUSHF OR KBD_FLG1,HOLD call kyb_enable MOV AL,END_OF_INT ; enable interrupts OUT A8259,AL CMP CON_MODE,7 ; is this color graphics JGE SHORT .D4B1 ; no, ignore MOV AL,CON_MODE_SET ; enable crt MOV DX,3D8H OUT DX,AL ; HOLD LOOP : AND EXIT .D4B1: POPF ; recover previous hold state JNZ SHORT .D4B1_EXIT ; exit if previous one set .D4B2: TEST KBD_FLG1,HOLD JNE SHORT .D4B2 ; LOOP .D4B1_EXIT: JMP .D87A ; RETURN : END OF INT 9 .D4CC: XOR SHFT_STAT,NUM_LK CALL UPDATE_LED JMP SHORT .D86A_L3 ; DONE ; CHECK FOR SCROLL LOCK .D4E3: CMP SCAN_CHAR,70 JNE SHORT TOG_DEL ; SKIP TEST DH,LAST_E0 ; is this ctrl Pause JNE SHORT .D4E3_A ; yes, this is break TEST DH,E101_KEY ; is this a 101 JNE SHORT .D555 ; then this is only scroll lock TEST SHFT_STAT,CTRL JE SHORT .D555 ; SKIP : NOT CONTROL .D4E3_A: MOV BX,KBD_BUF_LOCN ; clear keyboard buffer MOV PTR_KBD_BUF_HD,BX MOV PTR_KBD_BUF_TL,BX MOV BIOS_BRK,80H call kyb_enable INT 1BH ; user called break routine MOV SCAN_CHAR,0 JMP SWITCH_DONE .D555: XOR SHFT_STAT,SCRL_LK CALL UPDATE_LED .D86A_L3: JMP .D86A ; DONE ; PROCESS TOG_DEL: CMP SCAN_CHAR,83 JNE SHORT TOG_PRTS ; NOTTEST SHFT_STAT,ALT JE SHORT TOG_DEL_1 ; PROCESS OTHER'S TEST SHFT_STAT,CTRL JE SHORT ALT_DEL ; not ctrl/alt del ;================= R27 - WFM Remote Lockout Support ====================== ifdef WFM_RL_ENABLED cmp USER_REBOOT,0BEEFh ; Is it a WfM remote Lockout? jz SHORT ALT_DEL ; Jmp if yes endif ;WFM_RL_ENABLED ;================== R27 - WFM Remote Lockout Support ===================== ; PROCESS SYSTEM RESET (CONTROL ALT DELETE) MOV USER_REBOOT,CTRL_ALT_DEL ; RESET THE SYSTEM ifdef Out_64h_FEh_For_Warm_Boot ;Restart system by sending CPU reset , note that don't use method ;for CPU with SMI supported. mov cx,20 @@: mov al,0FEh out 64h,al loop @B endif ;Out_64h_FEh_For_Warm_Boot JMP REDO ; restart the POST ALT_DEL: TEST DH,LAST_E0 ; is this alternate del JZ SHORT .D86A_L3 ; if not, alt del not defined MOV SCAN_CHAR,163 ; return valid scan code JMP SHORT .D7A6_L1 TOG_DEL_1: TEST DH,LAST_E0 ; is this alternate del JZ SHORT NOT_ADEL MOV TEMP,0E0H ; yes, use E0 prefix NOT_ADEL: TEST SHFT_STAT,CTRL JZ SHORT NOT_CTRL_DEL MOV SCAN_CHAR,147 ; scan code JMP SHORT .D7A6_L1 NOT_CTRL_DEL: TEST SHFT_STAT,NUM_LK JE SHORT .D5DD ; SKIP : NOT NUM LOCK TEST SHFT_STAT,LT_SHFT + RT_SHFT JNE SHORT .D7A6_L1 .D5D4: TEST DH,LAST_E0 ; is this alternate del JNZ SHORT .D7A6_L1 ; then leave prefix = E0 MOV TEMP,'.' ;= '.' JMP SWITCH_DONE .D5DD: TEST SHFT_STAT,LT_SHFT + RT_SHFT JNE SHORT .D5D4 .D7A6_L1: JMP SWITCH_DONE ; LONG JUMP ; CHECK FOR PRINT SCREEN - changed for 101 keyboard TOG_PRTS: CMP SCAN_CHAR,55 ; check for print screen JNE SHORT .D7A6_L1 ; SWITCH DONE : NOT PRINT SCREEN TEST DH,LAST_E0 ; is this print screen on 101 - V3.02 JE SHORT NON_101_PRNT ; no, skip TEST SHFT_STAT,CTRL ; is this ctrl prntscrn JZ SHORT PRNT_IT ; if not, jmp to print screen JMP SHORT PRT_CTRL ; jmp to ctrl prntscrn NON_101_PRNT: TEST SHFT_STAT,ALT ; is it ALT * JE SHORT PRT_101_A ; not ALT MOV TEMP,0F0H ; set extended prefix JMP SWITCH_DONE PRT_101_A: TEST DH,E101_KEY ; is this a 101 JE SHORT PRT_84 TEST SHFT_STAT,CTRL ; is it CTRL * JE SHORT .D628 ; not CTRL MOV SCAN_CHAR,096H ; set extended function JMP SWITCH_DONE PRT_84: TEST SHFT_STAT,CTRL JE SHORT .D60E ; NOT CONTROL PRT_CTRL: MOV SCAN_CHAR,72H JMP SWITCH_DONE .D60E: TEST SHFT_STAT,LT_SHFT + RT_SHFT JE SHORT .D628 ; PRINT SCREEN PRNT_IT: call kyb_enable MOV AL,END_OF_INT ; end of interrupt OUT A8259,AL INT 5 ; print screen JMP .D870 .D628: MOV TEMP,'*' ;JMP SWITCH_DONE PAGE ; PROCESS KEYPAD KEYP_S: TEST SHFT_STAT,ALT JE SHORT .D68C ; NOT ALT TEST DH,LAST_E0 ; is this one of the alternate keys JE SHORT .D634_1 ; if not, numeric enter ADD SCAN_CHAR,050H ; convert to ALT key JMP SWITCH_DONE ; return keystroke .D634_1: MOV AL,ALT_INPUT ; PROCESS ALT - numeric enter MOV BL,10 MUL BL ; ax=ALT_INPUT*10 MOV BL,CS:+2[SI] AND BX,255 SUB BX,48 ; bx= next digit ADD AX,BX ; ax=ALT_INPUT*10+bx MOV ALT_INPUT,AL ; save .D86A_L2: JMP .D86A ; DONE : LONG JUMP .D68C: TEST DH,LAST_E0 ; is this an alternate keypad JZ SHORT NOT_AKEY ; jmp if not MOV TEMP,0E0H ; set alternate prefix NOT_AKEY: TEST SHFT_STAT,CTRL JE SHORT .D6AD ; NOT CONTROL MOV AL,CS:+3[SI] .D68C_A: MOV SCAN_CHAR,AL JMP SWITCH_DONE .D6AD: TEST SHFT_STAT,NUM_LK JE SHORT .D6D7 ; NOT NUM LOCK TEST SHFT_STAT,LT_SHFT + RT_SHFT JNE SHORT .D6E0 .D6CB: TEST DH,LAST_E0 ; is this alternate JNZ SHORT .D6EA ; V3.00 . ,finished if it is MOV AL,CS:+2[SI] ; otherwise return ASCII MOV TEMP,AL JMP SWITCH_DONE .D6D7: TEST SHFT_STAT,LT_SHFT + RT_SHFT JNE SHORT .D6CB .D6E0: CMP SCAN_CHAR,76 ; keypad 5 JNE SHORT .D6EA MOV TEMP,0F0H ; set prefix code JMP SHORT SWITCH_DONE ; send character .D6EA: CMP SCAN_CHAR,82 ; Insert JNE SHORT SWITCH_DONE MOV AL,CS:+1[SI] ; if Insert, set flags TEST KBD_FLG1,AL JNE SHORT .D86A_L2 ; DONE OR KBD_FLG1,AL XOR SHFT_STAT,INS_LK .D7A6_L5: JMP SHORT SWITCH_DONE PAGE ; PROCESS F11 and F12 - V2.09 F11_HND: ADD SCAN_CHAR,52 ; make ALT code TEST SHFT_STAT,ALT JNZ SHORT .D777 ; return alt code SUB SCAN_CHAR,2 ; make ctrl code TEST SHFT_STAT,CTRL JNZ SHORT .D777 ; return ctrl code SUB SCAN_CHAR,2 ; make shift code TEST SHFT_STAT,LT_SHFT + RT_SHFT JNZ SHORT .D777 ; return shift code SUB SCAN_CHAR,2 ; make unshifted code JMP SHORT .D777 ; return unshifted code ; PROCESS FUNCTION FUNC_S: TEST SHFT_STAT,ALT ; alt function? JE SHORT .D74F ADD SCAN_CHAR,45 ; return alt scan code JMP SHORT .D777 .D74F: TEST SHFT_STAT,CTRL ; ctrl function JE SHORT .D76B ADD SCAN_CHAR,35 ; return ctrl scan code JMP SHORT .D777 .D76B: TEST SHFT_STAT,LT_SHFT + RT_SHFT ; shifted function JE SHORT .D777 ADD SCAN_CHAR,25 ; return shift scan code .D777: PAGE ; SWITCH DONE SWITCH_DONE: CMP SCAN_CHAR,0FFH JNE SHORT .D86A_0 JMP .D86A ; DONE .D86A_0: CMP TEMP,0FFH JNE SHORT .D86A_1 JMP .D86A ; DONE .D86A_1: ; SAVE VALUE .D7BA: MOV CH,SCAN_CHAR ; SCAN CODE MOV CL,TEMP ; CHARACTER CALL INSERT_CHAR ; try to insert character JE SHORT .D806 ; if zero, then buffer overflow CLI call int_kb_enable MOV AX,9102H ; set interrupt complete flag MOV SP,BP INT 15H AND KB_FLAG_3, NOT (LAST_E1+LAST_E0) ; clear the E1 ; and E0 flags JMP SHORT KBD_INT_RET ; RETURN : END OF INT 9 ; BUFFER OVERFLOW : RING BELL .D806: MOV AL,END_OF_INT ; allow interrupts during OUT A8259,AL ; beep. MOV CX,5000H ; set length for beep CALL BEEP_KEY AND KB_FLAG_3, NOT (LAST_E1+LAST_E0) JMP .D870 ; don't send another END_OF_INT ; DONE : RETURN .D86A: AND KB_FLAG_3, NOT (LAST_E1+LAST_E0) ; clear the E1 ; and E0 flags .D86A_EXIT: CLI MOV AL,END_OF_INT ; END_OF_INT OUT A8259,AL .D870: call kyb_enable .D87A: CLI ;R28Aelse; NO_KBC ;R28 ;R28A mov al, END_OF_INT ;R28 End of INT ;R28A out A8259, al ;R28 ;R28Aendif; NO_KBC ;R28 MOV SP,BP ; RETURN FROM INT 9 KBD_INT_RET: POPA POP DS IRET KBD_INT ENDP PAGE ALIGN 4 ; 303A INSERT_CHAR PROC NEAR ; tries to place character into buffer - fails if buffer full ; INPUT ; CH = scan code to be placed on buffer ; CL = ascii code to be placed in buffer ; DS = 40H ; OUTPUT ; Zero flag = 1 - if failed ; = 0 - if successful ; MODIFIES AX,SI MOV AX,PTR_KBD_BUF_TL ; check for end of buffer ADD AX,2 CMP AX,KBD_BUFEND_LOCN JNE SHORT .D7F3 ; NOPE MOV AX,KBD_BUF_LOCN ; SET TO START .D7F3: CMP AX,PTR_KBD_BUF_HD ; MORE ROOM IN BUFFER JE SHORT .D7F3_1 ; NO, exit with z=1 ; ADD CHARACTER TO BUFFER MOV SI,PTR_KBD_BUF_TL MOV [SI],CX ; PUT CODE & CHAR IN BUFFER MOV PTR_KBD_BUF_TL,AX ; UPDATE TAIL .D7F3_1: RET INSERT_CHAR ENDP UPDATE_LED: ; Update the keyboard LED's ; Changed in V2.09 to only use ax and cx registers ; ENTRY ; DS = 40H ; EXIT ; NONE ; MODIFIES CX ; CHECK FLAGS pushf CLI PUSH AX ; save ax MOV AL,SHFT_STAT AND AL,70H ; get the state of the led keys MOV CL,4 SHR AL,CL MOV AH,KB_FLAG_2 AND AH,7 ; get the actual led settings CMP AL,AH ; check to see if the leds are right JE SHORT .D9FD ; NO CHANGE NEEDED AND KB_FLAG_2,0F8H ; update kb_flag_2 for new leds OR KB_FLAG_2,AL ; with value from current led state ;R28Aifndef NO_KBC ;R28 PUSH AX ; save led settings from al MOV AL,END_OF_INT ; ENABLE INT OUT A8259,AL MOV AL,LED_CMD ; SEND LED COMMAND CALL KB_OUT POP AX ; get led settings JNE SHORT .D9E9 ; jump if there is an error CALL KB_OUT JE SHORT .D9FD ; jump if there is an error .D9E9: MOV AL,KB_ENABLE ; SEND KEYBOARD ENABLE CALL KB_OUT ;R28Aendif; NO_KBC ;R28 .D9FD: POP AX ; restore popf RET PAGE ALIGN 4 BEEP_KEY PROC NEAR ; SOUND THE BELL ; ENTRY ; CX = loop counter ; EXIT ; NONE DATA8254 = 40H CTRL8254 = 43H IN AL,CTRL8042 IODELAY MOV AH,AL ; SAVE VALUE ;Reprogram speaker's tone DATA8254 = 40H CTRL8254 = 43H push ax mov al,0B6H out CTRL8254,al mov ax,533H out DATA8254+2,al mov al,ah NEWIODELAY out DATA8254+2,al NEWIODELAY pop ax OR AL,00000011B ; ON OUT CTRL8042,AL ALIGN 4 ; 304 CONSTANT DURATION LOOP SHORT $ AND AL,11111101B ; OFF OUT CTRL8042,AL IODELAY MOV AL,AH ; RESTORE VALUE OUT CTRL8042,AL RET BEEP_KEY ENDP PAGE ALIGN 4 KB_OUT PROC NEAR ; Output DATA byte to the keyboard ; ENTRY ; AL = BYTE ; EXIT ; AX = 0 - if ACK is received - Zero flag = 1 ; AX = FF - otherwise - Zero flag = 0 ; MODIFIES AX,CX ;R28Aifndef NO_KBC ;R28 push cx xor cx,cx MOV AH,AL ; SAVE AL wait_mouse_data_clear: in al,STAT8042 ;Read status test al,OBF_AUX ;AUX OBF (bit5) jz ready_to_out_command sti loop wait_mouse_data_clear ; wait mouse data be cleared mov ax,0ffh ;Set zero flag or ax,ax jmp .da41 ready_to_out_command: cli IN AL,DATA8042 ; CLEAR DATA PORT CALL BUFFER_8042_FULL ; wait till buffer empty MOV AL,AH ;Restore data OUT DATA8042,AL ; SEND DATA call Buffer_8042_Full ; Richard CALL OUT_8042_FULL ; check for byte in controller JZ SHORT .DA2B MOV AL,END_OF_INT ; byte has arrived from controller OUT A8259,AL .DA2B: IN AL,DATA8042 ; get byte CMP AL,KB_ACK ; is it ACK? MOV AX,0FFH ; if no, return ax=0FFH JNE SHORT .DA41 XOR AX,AX ; yes, return ax=0 .DA41: pop cx ;R28Aendif; NO_KBC ;R28 RET KB_OUT ENDP public int_kb_enable int_kb_enable: ;R28Aifndef NO_KBC ;R28 MOV AL,END_OF_INT ; END OF INT OUT A8259,AL ;R28Aendif; NO_KBC ;R28 public kyb_enable kyb_enable: MOV AX,ENABLE_KBRD ; enable keyboard PUBLIC KB_CNTRLR_OUT ALIGN 4 ; N3.03 KB_CNTRLR_OUT PROC NEAR ; Output CONTROL byte to the keyboard ; ENTRY ; AL = BYTE ; EXIT ; NONE ; Modifies CX, AX CLI CALL OUT_8042 STI RET KB_CNTRLR_OUT ENDP ALIGN 4 ;[]=============================================================[] ; Procedure Name: out_8042 ; ; Output a command to 8042 port 64h ; ; Inputs: al = command byte ; Output: zf = 0 : keyboard controller error ; zf = 1 : successful ; Destroy: ax, cx ; Author: Ken Chen ; Date: 06/21/90 ; ; Rev | Name | Date | TPR# | Description ; ------+-------+---------------+-------+------------------------------------- ; 1.00 | Ken | 06/21/90 | NEW | Initial revision ; ;[]=============================================================[] PUBLIC OUT_8042 OUT_8042 PROC NEAR ;R28Aifdef NO_KBC ;R28 ;R28A xor ah, ah ;zero flag ;R28 ;R28Aelse; NO_KBC ;R28 mov ah,al ; save al call Buffer_8042_Full ; wait till buffer empty, then jnz out_8042_ret mov al,ah out STAT8042,al ; send command call Buffer_8042_Full out_8042_ret: ;R28Aendif; NO_KBC ;R28 ret OUT_8042 ENDP ALIGN 4 ;[]=============================================================[] ; Procedure Name: out_8042_full ; Check for 8042 output buffer full ; Saves: ; Inputs: none ; Output: al = status register value ; zf = 0 : output buffer full ; zf = 1 : no output buffer full ; Destroy: ax, cx ; Author: Ken Chen ; Date: 06/21/90 ; ; Rev | Name | Date | TPR# | Description ; ------+-------+---------------+-------+------------------------------------- ; 1.00 | Ken | 06/21/90 | NEW | Initial revision ; ;[]=============================================================[] PUBLIC OUT_8042_FULL OUT_8042_FULL PROC NEAR mov ah,12 public Out_8042_Full1 Out_8042_Full1 label near ;R28Aifdef NO_KBC ;R28 ;R28A xor ah, ah ;zero flag ;R28 ;R28Aelse; NO_KBC ;R28 otrck: xor cx,cx inrck: in al,STAT8042 IFNDEF NO_NEWIODELAY_IN_8042_IO NEWIODELAY ENDIF ;NO_NEWIODELAY_IN_8042_IO test al,OBF_8042 jnz short onret loop short inrck dec ah jnz short otrck onret: ;R28Aendif; NO_KBC ;R28 ret OUT_8042_FULL ENDP ALIGN 4 ;[]=============================================================[] ; Procedure Name: buffer_8042_full ; Check for 8042 input buffer full ; Saves: ; Inputs: none ; Output: al = status register value ; zf = 0 : input buffer full ; zf = 1 : no input buffer full ; Destroy: al, cx ; Author: Ken Chen ; Date: 06/21/90 ; ; Rev | Name | Date | TPR# | Description ; ------+-------+---------------+-------+----------------------- ; 1.00 | Ken | 06/21/90 | NEW | Initial revision ; ;[]=============================================================[] PUBLIC BUFFER_8042_FULL BUFFER_8042_FULL PROC NEAR ;R28Aifdef NO_KBC ;R28 ;R28A xor ah, ah ;zero flag ;R28 ;R28Aelse; NO_KBC ;R28 xor cx,cx inrck1: in al,STAT8042 IFNDEF NO_NEWIODELAY_IN_8042_IO NEWIODELAY ENDIF ;NO_NEWIODELAY_IN_8042_IO and al,IBF_8042 loopnz short inrck1 ;R28Aendif; NO_KBC ;R28 ret BUFFER_8042_FULL ENDP FCODE ENDS END