From: Richard Burgess <> Date: Tue, 7 Feb 1995 17:27:52 +0000 (+0000) Subject: autocommit for file dated 1995-02-07 17:27:52 X-Git-Url: https://pd.if.org/git/?p=mmurtl;a=commitdiff_plain;h=d1f8e393cee5fe76eeda57827b1e9381c51cc351 autocommit for file dated 1995-02-07 17:27:52 --- diff --git a/ossource/keyboard.asm b/ossource/keyboard.asm new file mode 100644 index 0000000..b02c0a6 --- /dev/null +++ b/ossource/keyboard.asm @@ -0,0 +1,1406 @@ +; MMURTL Operating System Source Code +; Copyright 1991,1992,1993,1994,1995 Richard A. Burgess +; ALL RIGHTS RESERVED +; Version 1.0 +; +.DATA ;Begin Keyboard Data +.INCLUDE MOSEDF.INC +.INCLUDE RQB.INC +.INCLUDE TSS.INC +.ALIGN DWORD + +EXTRN ddVidOwner DD + +;The keyboard service is designed to return the complete status +;of the keyboard shift, control, alt, and lock keys as well as +;the key in the buffer that the state applies to. +; +;This is done by using two buffers. The first is a "RAW" key buffer +;that holds keys from the interrupt service routine which contains +;all raw keystrokes including shift keys going up and down. +;This information is needed to build coherent keystroke information +; for an application. This buffer is 32 bytes long. +; +;The second buffer is 256 bytes and contains the translated information +;in the form of DWords (a 4 byte quantity times 64). This DWord contains the +;following information: +; +;Low byte (bits 0-7) Partially translated application keystroke +;Next byte (bits 8-15) Shift State (Ctrl, Shift, Alt) +;Next byte (bits 16-23) Lock State (CAPS, Num, Scroll) +;Hi Byte (bits 24-31) Key Source (Bit 1 Set = Key From Numeric Pad) +; +KBDSvcName DB 'KEYBOARD' + +KbdMainExch DD 0 ;Used by the Kbd Process +KbdHoldExch DD 0 ;Used for requestors that don't own the keyboard +KbdGlobExch DD 0 ;Used to hold Global CTRL-ALT requests +KbdWaitExch DD 0 ;Used for Kbd Wait-For-Key requests +KbdTempExch DD 0 ;Used to rifle thru requests + +dGlobalKey DD 0 ;Global Key Found, else 0 +dfPrefix DD 0 + +KbdMsgBuf1L DD 0 ;Message buffers for Kbd Service +KbdMsgBuf1H DD 0 + +KbdMsgBuf2L DD 0 +KbdMsgBuf2H DD 0 + +KbdOwner DD 1 ;Current owner of Kbd (Mon is default) +KbdAbortJob DD 0 ;Job that is aborting +KbdCancelJob DD 0 ;Job that is cancelling global request + +rgbKbdBuf DB 20h DUP (0) ;32 byte RAW buffer +dKbdCnt DD 0 +pKbdIn DD OFFSET rgbKbdBuf ;ptr to next char going in +pKbdOut DD OFFSET rgbKbdBuf ;ptr to next char going out +; +bKbdMode DB 0 ;ZERO for Cooked, 1 for RAW (testing) +fKBDInitDone DB 0 ;Set true when KBD Service is up and running +; +KbdState DB 0 ;(See State Masks below) +KbdLock DB 0 ;(See Lock Masks below) +; +rgdKBBuf DD 40h DUP (0) ;64 Dwords for translated key buffer +dKBCnt DD 0 +pKBIn DD OFFSET rgdKBBuf ;ptr to codes comming in +pKBOut DD OFFSET rgdKBBuf ;ptr to codes going out +; +; These "masks" are for keyboard states that change with special keys: +; They are BIT OFFSETS and NOT MASKS for logical operations!!!!! + +CtrlLeftBit EQU 0 +CtrlRiteBit EQU 1 +ShftLeftBit EQU 2 +ShftRiteBit EQU 3 +AltLeftBit EQU 4 +AltRiteBit EQU 5 +; +; Mask to tell if one of the 3 states exist (Ctrl, Shift, Alt) +CtrlDownMask EQU 00000011b +ShftDownMask EQU 00001100b +AltDownMask EQU 00110000b +; +; BIT OFFSETS +CpLockBit EQU 2 +NmLockBit EQU 1 +ScLockBit EQU 0 +; MASKS +CpLockMask DB 00000100b +NmLockMask DB 00000010b +ScLockMask DB 00000001b + +; +; The following special keys are processed by the Keyboard Task and handled +; as follows: +; NUMLOCK - Lights NumLock LED and processes keys accordingly +; SHIFT - Sets shift flag and processes keys accordingly +; CTRL - Sets Ctrl flag +; CAPSLOCK - Lights CapsLock LED and processes keys accordingly +; ALT - Sets Alt flag. +; SCRLLOCK - Lights ScrollLock LED and flag +; +; This table is used to translate all active editing keys from +; the raw value provided by the hardware. +; +; SHIFT +; Value +KbdTable DB 0; 00 +DB 01Bh ; Esc 01 +DB 031h ; 1 02 21h ! +DB 032h ; 2 03 40h @ +DB 033h ; 3 04 23h # +DB 034h ; 4 05 24h $ +DB 035h ; 5 06 25h % +DB 036h ; 6 07 5Eh ^ +DB 037h ; 7 08 26h & +DB 038h ; 8 09 2Ah * +DB 039h ; 9 0A 28h ( +DB 030h ; 0 0B 29h ) +DB 02Dh ; - 0C 5Fh _ +DB 03Dh ; = 0D 2Bh + +DB 008h ; BkSpc 0E +DB 009h ; TAB 0F +DB 071h ; q 10 51h +DB 077h ; w 11 57h +DB 065h ; e 12 45h +DB 072h ; r 13 52h +DB 074h ; t 14 54h +DB 079h ; y 15 59h +DB 075h ; u 16 55h +DB 069h ; i 17 49h +DB 06Fh ; o 18 4Fh +DB 070h ; p 19 50h +DB 05Bh ; [ 1A 7Bh +DB 05Dh ; ] 1B 7Dh +DB 00Dh ; CR 1C +DB 0h ; LCtrl 1D Special handling +DB 061h ; a 1E 41h +DB 073h ; s 1F 53h +DB 064h ; d 20 44h +DB 066h ; f 21 46h +DB 067h ; g 22 47h +DB 068h ; h 23 48h +DB 06Ah ; j 24 4Ah +DB 06Bh ; k 25 4Bh +DB 06Ch ; l (L) 26 4Ch +DB 03Bh ; ; 27 3Ah +DB 027h ; ' 28 22h +DB 060h ; ` 29 7Eh +DB 0h ; LfShf 2A Special handling +DB 05Ch ; \ 2B 7Ch +DB 07Ah ; z 2C 5Ah +DB 078h ; x 2D 58h +DB 063h ; c 2E 43h +DB 076h ; v 2F 56h +DB 062h ; b 30 42h +DB 06Eh ; n 31 4Eh +DB 06Dh ; m 32 4Dh +DB 02Ch ; , 33 3Ch +DB 02Eh ; . 34 3Eh +DB 02Fh ; / 35 3Fh +DB 0h ; RtShf 36 Special handling +DB 02Ah ; Num * 37 Num pad +DB 0h ; LAlt 38 Special handling +DB 020h ; Space 39 +DB 0h ; CpsLk 3A Special handling +DB 00Fh ; F1 3B +DB 010h ; F2 3C +DB 011h ; F3 3D +DB 012h ; F4 3E +DB 013h ; F5 3F +DB 014h ; F6 40 +DB 015h ; F7 41 +DB 016h ; F8 42 +DB 017h ; F9 43 +DB 018h ; F10 44 +DB 0h ; NumLk 45 Special handling +DB 0h ; ScrLk 46 Special handling +DB 086h ; Num 7 47 37h Num Home +DB 081h ; Num 8 48 38h Num Up +DB 085h ; Num 9 49 39h Num Pg Up +DB 0ADh ; Num - 4A Num Pad +DB 083h ; Num 4 4B 34h Num Left +DB 09Fh ; Num 5 4C 35h Num (Extra code) +DB 084h ; Num 6 4D 36h Num Right +DB 0ABh ; Num + 4E Num Pad +DB 08Bh ; Num 1 4F 31h Num End +DB 082h ; Num 2 50 32h Num Down +DB 08Ch ; Num 3 51 33h Num Pg Dn +DB 08Eh ; Num 0 52 30h Num Insert +DB 0FFh ; Num . 53 2Eh Num Del +DB 01Ch ; Pr Scr 54 SYS REQUEST +DB 000h ; 55 +DB 000h ; 56 +DB 019h ; F11 57 +DB 01Ah ; F12 58 +DB 000h ; 59 +DB 000h ; 5A +DB 000h ; 5B +DB 000h ; 5C +DB 000h ; 5D +DB 000h ; 5E +DB 000h ; 5F ;The following chars are subs from table2 +DB 00Eh ; Ins 60 Cursor pad +DB 00Bh ; End 61 Cursor pad +DB 002h ; Down 62 Cursor pad +DB 00Ch ; PgDn 63 Cursor pad +DB 003h ; Left 64 Cursor pad +DB 000h ; 65 +DB 004h ; Right 66 Cursor pad +DB 006h ; Home 67 Cursor pad +DB 001h ; Up 68 Cursor pad +DB 005h ; PgUp 69 Cursor pad +DB 07Fh ; Delete 6A Cursor pad +DB 0AFh ; / 6B Num Pad +DB 08Dh ; ENTER 6C Num Pad +DB 0h ; 6D +DB 0h ; 6E +DB 0h ; 6F +DB 0h ; 70 +DB 0h ; 71 +DB 0h ; 72 +DB 0h ; 73 +DB 0h ; 74 +DB 0h ; 75 +DB 0h ; 76 +DB 0h ; 77 +DB 0h ; 78 +DB 0h ; 79 +DB 0h ; 7A +DB 0h ; 7B +DB 0h ; 7C +DB 0h ; 7D +DB 0h ; 7E +DB 0h ; 7F +; +;This table does an initial character translation from the characters +;provided by the keyboard. The Kbd translates incoming keystrokes +;from the original scan set 2 for the IBM PC. All PCs are are set to this +;by default. Keys on the 101 keyboard that were common to the numeric +;keypad use a two character escape sequence begining with E0 hex. +;If we see an E0 hex we scan this table and provide the translation +;to another unique character which is looked up in the primary +;table above. This gives us unique single characters for every key. +; +nKbdTable2 EQU 16 +; +KbdTable2 DB 052h, 060h ;Insert + DB 04Fh, 061h ;End + DB 050h, 062h ;Down + DB 051h, 063h ;Pg Down + DB 04Bh, 064h ;Left + DB 04Dh, 066h ;Rite + DB 047h, 067h ;Home + DB 048h, 068h ;Up + DB 049h, 069h ;Pg Up + DB 053h, 06Ah ;Delete + + DB 037h, 06Bh ;Num / + DB 01Ch, 06Ch ;Num ENTER + + DB 038h, 070h ;Right ALT DOWN These are special cause we + DB 01Dh, 071h ;Right Ctrl DOWN track UP & DOWN!!! + DB 0B8h, 0F0h ;Right ALT UP + DB 09Dh, 0F1h ;Right Ctrl UP + + +;This table provides shift level values for codes from the primary KbdTable. +;In Shift-ON state, keycodes 21 - 7E hex are translated through this table. +;In CAPS LOCK state, codes 61h to 7Ah are translated through this table +;In NUM LOCK state, codes with High Bit set are translated +; + +KbdTableS DB 0; 00 +DB 38h ; 01 Up 8 Numeric pad +DB 32h ; 02 Dn 2 Numeric pad +DB 34h ; 03 Left 4 Numeric pad +DB 36h ; 04 Rite 6 Numeric pad +DB 39h ; 05 PgUp 9 Numeric pad +DB 37h ; 06 Home 7 Numeric pad +DB 07h ; 07 +DB 08h ; 08 +DB 09h ; 09 +DB 0Ah ; 0A +DB 31h ; 0B End 1 Numeric Pad +DB 33h ; 0C PgDn 3 Numeric pad +DB 0Dh ; 0D +DB 30h ; 0E Ins 0 Numeric pad +DB 0Fh ; 0F +DB 10h ; 10 +DB 11h ; 11 +DB 12h ; 12 +DB 13h ; 13 +DB 14h ; 14 +DB 15h ; 15 +DB 16h ; 16 +DB 17h ; 17 +DB 18h ; 18 +DB 18h ; 19 +DB 1Ah ; 1A +DB 1Bh ; 1B +DB 1Ch ; 1C +DB 1Dh ; 1D +DB 1Eh ; 1E +DB 35h ; 1F Blnk 5 Numeric pad +DB 20h ; 20 +DB 21h ; 21 +DB 22h ; 22 +DB 23h ; 23 +DB 24h ; 24 +DB 25h ; 25 +DB 26h ; 26 +DB 22h ; 27 ' " +DB 28h ; 28 +DB 29h ; 29 +DB 2Ah ; 2A +DB 2Bh ; 2B +DB 3Ch ; 2C , < +DB 5Fh ; 2D - _ +DB 3Eh ; 2E . > +DB 3Fh ; 2F / ? +DB 29h ; 30 0 ) +DB 21h ; 31 1 ! +DB 40h ; 32 2 @ +DB 23h ; 33 3 # +DB 24h ; 34 4 $ +DB 25h ; 35 5 % +DB 5Eh ; 36 6 ^ +DB 26h ; 37 7 & +DB 2Ah ; 38 8 * +DB 28h ; 39 9 ( +DB 3Ah ; 3A +DB 3Ah ; 3B ; : +DB 3Ch ; 3C +DB 2Bh ; 3D = + +DB 3Eh ; 3E +DB 3Fh ; 3F +DB 40h ; 40 +DB 41h ; 41 +DB 42h ; 42 +DB 43h ; 43 +DB 44h ; 44 +DB 45h ; 45 +DB 46h ; 46 +DB 47h ; 47 +DB 48h ; 48 +DB 49h ; 49 +DB 4Ah ; 4A +DB 4Bh ; 4B +DB 4Ch ; 4C +DB 4Dh ; 4D +DB 4Eh ; 4E +DB 4Fh ; 4F +DB 50h ; 50 +DB 51h ; 51 +DB 52h ; 52 +DB 53h ; 53 +DB 54h ; 54 +DB 55h ; 55 +DB 56h ; 56 +DB 57h ; 57 +DB 58h ; 58 +DB 59h ; 59 +DB 5Ah ; 5A +DB 7Bh ; 5B [ { +DB 7Ch ; 5C \ | +DB 7Dh ; 5D ] } +DB 5Eh ; 5E +DB 5Fh ; 5F +DB 7Eh ; 60 ` ~ +DB 41h ; 61 a A +DB 42h ; 62 b B +DB 43h ; 63 c C +DB 44h ; 64 d D +DB 45h ; 65 e E +DB 46h ; 66 f F +DB 47h ; 67 g G +DB 48h ; 68 h H +DB 49h ; 69 i I +DB 4Ah ; 6A j J +DB 4Bh ; 6B k K +DB 4Ch ; 6C l L +DB 4Dh ; 6D m M +DB 4Eh ; 6E n N +DB 4Fh ; 6F o O +DB 50h ; 70 p P +DB 51h ; 71 q Q +DB 52h ; 72 r R +DB 53h ; 73 s S +DB 54h ; 74 t T +DB 55h ; 75 u U +DB 56h ; 76 v V +DB 57h ; 77 w W +DB 58h ; 78 x X +DB 59h ; 79 y Y +DB 5Ah ; 7A z Z +DB 7Bh ; 7B +DB 7Ch ; 7C +DB 7Dh ; 7D +DB 7Eh ; 7E +DB 2Eh ; 7F Del . Numeric Pad + + +KbdSvcStack DD 255 DUP(0) ;1024 byte stack for KbsSvc +KbdSvcStackTop DD 0 + +;============================================================================= +;The following equates are for the hardware handling code. +;8042 Status Byte, Port Hex 0064 Read +;============================================================================= + +STATUSPORT EQU 64h +COMMANDPORT EQU 64h +DATAPORT EQU 60h + +PARITYERROR EQU 10000000b +GENERALTIMEOUT EQU 01000000b +AUXOUTBUFFFULL EQU 00100000b +INHIBITSWITCH EQU 00010000b +COMMANDDATA EQU 00001000b +SYSTEMFLAG EQU 00000100b +INPUTBUFFFULL EQU 00000010b +OUTPUTBUFFFULL EQU 00000001b + + +;==================Begin Keyboard Code =================== + +.CODE +; +; +;ISR for the keyboard. This is vectored to by the processor whenever +;INT 21 fires off. This puts the single byte from the 8042 +;KBD processor into the buffer. Short and sweet the way all ISRs +;should be... (most are not this easy though). This also sends +;a message to the KBD Task (using ISend) when the buffer is almost +;full so it will be forced to process some of the raw keys even +;if no keyboard requests are waiting. + +PUBLIC IntKeyBrd: ;Key Board (KB) INT 21 + PUSHAD ;Save all registers + MOV ESI, pKbdIn ;Set up pointer + XOR EAX,EAX + IN AL, 60h ;Read byte + MOV EBX, dKbdCnt ;See if buffer full + CMP EBX, 20h ;Buffer size + JE KbdEnd ;Buffer is full - Don't save it + MOV BYTE PTR [ESI], AL ;Move into buf + INC dKbdCnt ;One more in the buf + INC ESI ;Next byte in + CMP ESI, OFFSET rgbKbdBuf+20h ;past end yet? + JB KbdEnd + MOV ESI, OFFSET rgbKbdBuf ;Back to beginning of buffer +KbdEnd: + MOV pKbdIn, ESI ;Set up pointer for next time + + CMP BYTE PTR fKBDInitDone, 0 ;Service isn't ready for messages yet + JE KbdExit + + ;ISend a msg to Keyboard task + MOV EBX, KbdMainExch ;Yes - ISend Message to KbdTask + PUSH EBX ;exchange to send to + PUSH 0FFFFFFFFh ;bogus msg + PUSH 0FFFFFFFFh ;bogus msg + CALL FWORD PTR _ISendMsg ;tell him to come and get it... +KbdExit: + PUSH 1 + CALL FWORD PTR _EndOfIRQ + POPAD + IRETD + +;=============================================== +;This gets one byte from the Kbd Buffer and returns it in AL +;Zero is returned if no key exists. +; +ReadKBDBuf: + CLI + MOV ESI, pKbdOut ;Get ptr to next char to come out + MOV EAX, dKbdCnt ;See if there are any bytes + CMP EAX, 0 + JE RdKBDone ;No - Leave 0 in EAX + DEC dKbdCnt ;Yes - make cnt right + XOR EAX,EAX + MOV AL, BYTE PTR [ESI] ;Put byte in AL + INC ESI + CMP ESI, OFFSET rgbKbdBuf+20h ;past end yet? + JB RdKBDone + MOV ESI, OFFSET rgbKbdBuf ;Back to beginning of buffer +RdKBDone: + MOV pKbdOut, ESI ;Save ptr to next char to come out + STI + RETN +; +;======================================================== +; +; Reads and processes all bytes from the RAW keyboard buffer +; and places them and their proper state bytes and into the next DWord +; in the translated buffer if it is an edit key. + +XLateRawKBD: + CALL ReadKbdBuf + CMP EAX, 0 + JE XLateDone ;No + + MOV BL, bKbdMode ;See if we are RAW... (for testing ONLY) + CMP BL, 1 + JNE KB001 ;NO - keep going + JMP KB029A ;Yes, leave the key in AL for buffer + + ;Now we check to see if the byte is 0Eh which tells us + ;this is a two key code that needs to be translated from + ;our special table before processing. This turns the + ;two key code into a single code and sets a state + ;bit to indicate this. + +KB001: + CMP dfPrefix, 1 + JE KB003 + CMP AL, 0E0h ;Key PREFIX??? + JNE KB006 ;No + MOV dfPrefix, 1 ;Yes, We got an E0 + JMP XLateDone ; + +KB003: + MOV dfPrefix, 0 ;No prefix + MOV ESI, OFFSET KbdTable2 + MOV ECX, nKbdTable2 +KB004: + CMP BYTE PTR [ESI], AL + JE KB005 + INC ESI ;Two byte further into table 2 + INC ESI + DEC ECX + JNZ KB004 ;Go to next table entry + JMP XLateDone ;No translation - ignore it + +KB005: + INC ESI ;One byte further over to get Xlate byte + XOR EAX,EAX + MOV AL, [ESI] ;Fall thru to check on char... + + ;This next section checks for special keys (shift, alt, etc.) + ;BL has SHIFT state, CL has LOCK State, AL has byte from buffer. + +KB006: + MOV dfPrefix, 0 ;No prefix + XOR EBX, EBX + XOR ECX, ECX + MOV BL, KbdState ;BL has Shift, Alt, Ctrl states + MOV CL, KbdLock ;BH has Num, Caps, & Scroll Lock + + CMP AL, 45h ;Key = NumLock ? + JNE KB007 ;NO... + BTC ECX, NmLockBit ;Compliment bit + JMP KB022 +KB007: + CMP AL, 3Ah ;Caps Lock? + JNE KB008 + BTC ECX, CpLockBit ;Compliment bit in BH + JMP KB022 +KB008: + CMP AL, 46h ;Scroll Lock? + JNE KB009 + BTC ECX, ScLockBit ;Compliment bit in BH + JMP KB022 +KB009: + CMP AL, 2Ah ;Char Left Shift On? + JNE KB010 + BTS EBX, ShftLeftBit + JMP KB021 +KB010: + CMP AL, 36h ;Right Shift On? + JNE KB011 + BTS EBX, ShftRiteBit + JMP KB021 +KB011: + CMP AL, 0AAh ;Left Shift Off? + JNE KB012 + BTR EBX, ShftLeftBit + JMP KB021 + +KB012: + CMP AL, 0B6h ;Right Shift Off? + JNE KB013 + BTR EBX, ShftRiteBit + JMP KB021 + +KB013: + CMP AL, 1Dh ;Left Ctrl On? + JNE KB014 + BTS EBX, CtrlLeftBit + JMP KB021 + +KB014: + CMP AL, 71h ;Right Ctrl On? + JNE KB015 + BTS EBX, CtrlRiteBit + JMP KB021 + +KB015: + CMP AL, 09Dh ;Left Ctrl Off? + JNE KB016 + BTR EBX, CtrlLeftBit + JMP KB021 + +KB016: + CMP AL, 0F1h ;Right Ctrl Off? + JNE KB017 + BTR EBX, CtrlRiteBit + JMP KB021 +KB017: + CMP AL, 38h ;Left Alt On? + JNE KB018 + BTS EBX, AltLeftBit + JMP KB021 +KB018: + CMP AL, 70h ;Right Alt On? + JNE KB019 + BTS EBX, AltRiteBit + JMP KB021 +KB019: + CMP AL, 0B8h ;Left Alt Off? + JNE KB020 + BTR EBX, AltLeftBit + JMP KB021 +KB020: + CMP AL, 0F0h ;Right Alt Off? + JNE KB023 + BTR EBX, AltRiteBit +KB021: + MOV KbdState, BL ;Put Kbd Shift State back + JMP XLateDone ; +KB022: + MOV KbdLock, CL ;Put Kbd Lock State back + CALL SetKbdLEDS ;Set LEDs on keyboard + JMP XLateRawKBD ; + + ;We jumped here if it wasn't a key that is specially handled + +KB023: + TEST AL, 80h ;Check for high bit (key-up code) + JNZ XLateDone ;Go back, else fall through + + OR AL,AL ;Zero not a valid code + JZ XLateDone ;Go back, else fall through + + ;If we got here, IT'S AN EDIT KEY DOWN! + ;Now we lookup the code and do a single translation. + + AND EAX, 07Fh ;Chop off any upper bit junk + MOV ESI, OFFSET KbdTable ;Set up to index table + MOV DL, BYTE PTR [ESI+EAX] ;Save in DL + OR AL,AL ;Zero not a valid code + JZ XLateDone ;Go back, else fall through + + MOV CL, KbdState ;Get Shift state + MOV CH, KbdLock ;Get lock state + + ;TO let the user know if the key came from the Numeric + ;keypad we set the high bits in the first translation + ;table for these keys. This next piece of code tests for it + ;and sets the low bit in DH if it its. DH is later moved + ;into the high byte of the returned key code. + + MOV DH, 0 + TEST DL, 80h ;High bit set? + JZ SHORT KB024 + MOV DH, 1 ;Indicates key came numeric pad + + ;See if shift key is down and shift all keys it is is +KB024: + TEST CL, ShftDownMask ;Either shift key down? + JZ KB025 ;No, go look for locks + CMP DL, 21h ;Is key < ' ' + JB KB025 ;Yes, look for locks + CMP DL, 7Eh ;Is key > '~' + JA KB025 ;Yes, look for locks + JMP SHORT KB027 ;In-range, go do the translation + +KB025: ;See if key is from Numerc Keypad (high bit will be set) + + TEST DL, 80h ;High bit set? + JZ KB026 ;No + AND CH, NmLockMask ;Yes, is NumLock ON + JZ KB026 ;No + CMP DL, 0ADh ;Yes, but don't shift DASH (-) Special Case + JE KB026 + JMP SHORT KB027 ;Do the shift Xlation + +KB026: ;See if Caps Lock is on and if key is between 61h and 7Ah + ;do the translation + + TEST CH, CpLockMask ;Is CpLock ON + JZ KB029 ;No + CMP DL, 61h ;Is key >= 'a' + JB KB029 ;No + CMP DL, 7Ah ;Is key <= 'z' + JA KB029 ;No + ;Fall through to do the translation + +KB027: ;Do the shift translation and leave in DL + MOV AL, DL ;Put in AL + AND EAX, 07Fh ;Chop all above 7 bits + MOV ESI, OFFSET KbdTableS ;Set up to index table + MOV DL, BYTE PTR [ESI+EAX] ;Save in DL + ;Fall though to put key in final buffer + + ;Place DL in the LOW byte of the DWord to go into the + ;final buffer (the data the user will get) + ;If the high bit is set coming from the primary + ;translation table, this means the key was from the + ;numeric keypad so we set the numpad bit in status + ;which should already be in DH +KB029: + MOV AH, DH + SHL EAX, 8 ;Num Pad indicator + MOV AL, KbdState ;Get Shift state + MOV AH, KbdLock ;Get lock state + SHL EAX, 8 + AND DL, 7Fh ;Lop of high bit (if there) + MOV AL, DL + + ;EAX now has the buffered info for the user (Key, Shifts & Locks) + ;Now we put it in the DWord buffer if it is NOT a GLOBAL. + ;If global, we put it in dGlobalKey. + + TEST AH, CtrlDownMask ;Either Ctrl Down? + JZ KB029A ;No + TEST AH, AltDownMask ;Either Alt Down? + JZ KB029A ;No + + ;It IS a global key request! + MOV dGlobalKey, EAX ;Save it + JMP XLateRawKBD ;Back for more (if there is any) + +KB029A: + MOV EBX, dKBCnt ;See if buffer full + CMP EBX, 64 ;number of DWords in final buffer + JE XLateDone ;Buffer is FULL.. + MOV ESI, pKBIn ;Get ptr to next IN to final buffer + MOV [ESI], EAX ;Move into buf + INC dKBCnt ;One more DWord in the buf + ADD ESI, 4 + CMP ESI, OFFSET rgdKBBuf+100h ;40h * 4 + JB KB030 + MOV ESI, OFFSET rgdKBBuf ;Reset to buf beginning +KB030: + MOV pKBIn, ESI ;Save ptr to next in + JMP XLateRawKBD +XlateDone: + XOR EAX, EAX + RETN + +;======================================================== +; +; Returns a keyboard code from FINAL keyboard buffer. +; Returns zero in EAX if buffer is empty. +; +; IN : Nothing +; OUT: EAX has Key or 0 if none +; USED: EAX, ESI +; MODIFIES: dKBCnt, pKBOut +; +ReadKBFinal: + MOV EAX, dKBCnt + CMP EAX, 0 + JE KBFDone ;Nothing final buffer + DEC dKBCnt ;One more DWord in the buf + MOV ESI, pKBOut ;ptr to next code out + MOV EAX, [ESI] ;Put it in EAX + ADD ESI, 4 ;Next code please... + CMP ESI, OFFSET rgdKBBuf+100h ;Past end of buff? + JB KBF02 ;No + MOV ESI, OFFSET rgdKBBuf ;Yes, Reset to beginning +KBF02: + MOV pKBOut, ESI ;Update pKBOut +KBFDone: + RETN + +;======================================================== +; +; This is the keyboard Service task. It is an infinite loop +; that services requests from users of the keyboard. It +; calls XLateRawKBD to process raw keyboard buffer data, +; and waits at the KeyBoard Service Main Exchange for users. +; When it gets a request it checks the service code and handles +; it accordingly. + +KBDServiceTask: + CALL XLateRawKBD ;Processes RAW buffer if not empty + + CMP DWORD PTR dGlobalKey, 0 + JE KST01 ;No global key came in +KBDGlobal1: + PUSH KbdGlobExch + PUSH OFFSET KbdMsgBuf1L ;Where to return pRqBlk + CALL FWORD PTR _CheckMsg ;Check to see if RqWaiting + OR EAX, EAX ;Yes if ZERO + JZ KBDGlobal2 ;Rq waiting for global + MOV DWORD PTR dGlobalKey, 0 ;Wipe out global key (no one wants it) + JMP KBDServiceTask ;Start over again + +KBDGlobal2: + MOV EBX, KbdMsgBuf1L ;pRqBlk into EBX + MOV ESI, [EBX+pData1] ;Ptr where to return key + OR ESI, ESI ;Is it null?? (Bad news if so) + JNZ KBDGlobal3 ;No, probably good ptr + PUSH EBX ;Yes, BAD PTR. Push pRqBlk + PUSH ErcNullPtr ;Push error + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top +KBDGlobal3: + MOV EDX, dGlobalKey + MOV [ESI], EDX ;Give em the key! + PUSH EBX ;Push pRqBlk + PUSH 0 ;Push NO ERROR + CALL FWORD PTR _Respond + JMP KBDGlobal1 ;Go back to see if others want it + +KST01: + CMP DWORD PTR ddVidOwner, 2 ;Debugger has video + JNE KST01ND ;NOT in Debugger + PUSH 20 + CALL FWORD PTR _Sleep ; + CALL XLateRawKBD ;Processes RAW buffer + JMP KBDServiceTask ;Go back to the top + +KST01ND: + PUSH KbdMainExch ;See if someones "Requesting" + PUSH OFFSET KbdMsgBuf1L ; + CALL FWORD PTR _WaitMsg ;Wait for the message + + ;If we got here, we have a Request or a Msg the from ISR + + CMP DWORD PTR KbdMsgBuf1L, 0FFFFFFFFh ;Is it a msg from the KBD ISR? + JNE KST02 ;No, jump to handle Request + + ;If we got here, ISR sent msg to us (something in the buffer) + + CALL XLateRawKBD ;Processes RAW buffer + + CMP DWORD PTR dGlobalKey, 0 + JNE KBDGlobal1 ;A global key came in + + PUSH KbdWaitExch ;See if owner is waiting for a key + PUSH OFFSET KbdMsgBuf1L ;Where to return Request or msg + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX + JNZ KBDServiceTask ;No Rq/Msg waiting, Go back to the top, + ;or fall thru to check the request + +KST02: + ;If we got here we've got a Request from Main or Wait Exch + MOV EBX, KbdMsgBuf1L ;pRqBlk into EBX + MOV CX, [EBX+ServiceCode] ;Save in CX + + CMP CX, 0 ;Job Abort Notify + JE KSTAbort ; + CMP CX, 1 ;ReadKbd + JE KSTRead ; + CMP CX, 2 ;ReadKbdGlobal + JE KSTReadGlobal ; + CMP CX, 3 ;CancelGlobal + JE KSTCancelGlobal ; + CMP CX, 4 ;AssignKBD + JE KSTAssignKbd ; + PUSH EBX ;HOMEY DON'T SERVICE THAT! + PUSH ErcBadSvcCode ;Bad service code + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top + +;------------------------------------------------------- +KSTRead: + MOV EAX, [EBX+RqOwnerJob] ;Whose Request is it? + CMP EAX, KbdOwner + JE KSTRead00 ;This guy owns it! + PUSH EBX ;Not the owner, so send to Hold Exch + PUSH KbdHoldExch ; + CALL FWORD PTR _MoveRequest + JMP KBDServiceTask ;Go back to the top +KSTRead00: + CALL ReadKBFinal ;Get Code from Buf (Uses EAX, ESI) + CMP EAX, 0 ;No Key in Final Buffer + JE KSTRead02 ;Go see if they asked to wait + MOV ESI, [EBX+pData1] ;Ptr where to return key + CMP ESI, 0 ;Is it null?? (Bad news if so) + JNE KSTRead01 ;No, probably good ptr + PUSH EBX ;Yes, BAD PTR. Push pRqBlk + PUSH ErcNullPtr ;Push error + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top +KSTRead01: + MOV [ESI], EAX ;Give them the key code + PUSH EBX ;RqHandle + PUSH 0 ;NO Error + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top + +KSTRead02: + CMP DWORD PTR [EBX+dData0], 0 ;Wait for key? 0 in dData0 = Don't wait + JNE KSTRead04 ;Yes + PUSH EBX + PUSH ErcNoKeyAvail ;Error Code (No key to give you) + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top + +KSTRead04: + PUSH EBX ;They opted to wait for a key + PUSH KbdWaitExch ;Send em to the wait exch + CALL FWORD PTR _MoveRequest + JMP KBDServiceTask ;Go back to the top +;-------------------------------------------------------- + +KSTAbort: + ;Respond to all requests we are holding for Job in dData0 + ;with Erc with ErcOwnerAbort. Then respond to Abort + ;request last. Requests can be at the HoldExch, the WaitExch, + ;or the GlobalKeyExch. We must chack all 3! + ;Save abort job for comparison + + MOV EAX, [EBX+dData0] ;Get aborting job number + MOV KbdAbortJob, EAX ;this is aborting job + +KSTAbort10: ;Check the WaitExch + PUSH KbdWaitExch ;See if he was "waiting" for a key + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes (someone's waiting) if ZERO + JNZ KSTAbort20 ;No more waiters + MOV EDX, KbdMsgBuf2L ;pRq of holding job into EDX + MOV EBX, [EDX+RqOwnerJob] + CMP EBX, KbdAbortJob + JE KSTAbort11 ;Go to respond with Erc + PUSH EDX ;Else move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated + CALL FWORD PTR _MoveRequest + JMP KSTAbort10 ;Go back to look for more waiters +KSTAbort11: ; + PUSH EDX ;Respond to this request + PUSH ErcOwnerAbort ;cause he's dead + CALL FWORD PTR _Respond + JMP SHORT KSTAbort10 + +KSTAbort20: ;Check HoldExch for dead job + PUSH KbdHoldExch ;See if anyone is on hold + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes (someones holding) if ZERO + JNZ KSTAbort30 ;No more holders + MOV EDX, KbdMsgBuf2L ;pRq of holding job into EDX + MOV EBX, [EDX+RqOwnerJob] + CMP EBX, KbdAbortJob + JE KSTAbort21 ;Go to respond with Erc + PUSH EDX ;Else move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated. It's not him. + CALL FWORD PTR _MoveRequest + JMP KSTAbort20 ;Go back to look for more holders +KSTAbort21: ; + PUSH EDX ;Respond to this request + PUSH ErcOwnerAbort ;cause he's dead + CALL FWORD PTR _Respond + JMP SHORT KSTAbort20 ;Go back to look for more holders + +KSTAbort30: ;Check GlobalExch for dead job + PUSH KbdGlobExch ;See if anyone is at global + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes (someones holding) if ZERO + JNZ KSTAbort40 ;No more holders + MOV EDX, KbdMsgBuf2L ;pRq of holding job into EDX + MOV EBX, [EDX+RqOwnerJob] + CMP EBX, KbdAbortJob + JE KSTAbort31 ;Go to respond with Erc + PUSH EDX ;Else move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated + CALL FWORD PTR _MoveRequest + JMP KSTAbort30 ;Go back to look for more globals +KSTAbort31: ; + PUSH EDX ;Respond to this request + PUSH ErcOwnerAbort ;cause he's dead + CALL FWORD PTR _Respond + JMP SHORT KSTAbort30 + +KSTAbort40: ;Respond to original abort Req + MOV EBX, KbdMsgBuf1L ;pRqBlk of original Abort Request + PUSH EBX ; + PUSH 0 ;Error Code (OK) + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top +;---------------------------------------------------------- + +KSTReadGlobal: + PUSH EBX ;They want a global key + PUSH KbdGlobExch ;Send em to the Global exch + CALL FWORD PTR _MoveRequest + JMP KBDServiceTask ;Go back to the top +;----------------------------------------------------------- +;Assign a new owner for the keyboard. We must check to see +;if the new owner had any keyboard requests on hold. +;We do this by sending all the requests that were on hold +;back to the main exchange to be reevaluated. +;Then we respond to the original request. + +KSTAssignKBD: + ;Change owner of Kbd + MOV EAX, [EBX+dData0] ;Get new owner + CMP EAX, KbdOwner + JNE KSTAssign01 ;New Owner! + + PUSH EBX ;Same owner + PUSH 0 ;Error Code (OK) + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top +KSTAssign01: + MOV KbdOwner, EAX ;Set new owner + +KSTAssign02: ;Move all waiters to main exch + PUSH KbdWaitExch ;See if anyone is "waiting" for a key + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes (someones waiting) if ZERO + JNZ KSTAssign03 ;No more waiters + MOV EDX, KbdMsgBuf2L ;pRq into EDX + PUSH EDX ;Move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated + CALL FWORD PTR _MoveRequest + JMP KSTAssign02 ;Go back to look for more waiters +KSTAssign03: ;Waiter have been moved, Respond to Req + PUSH KbdHoldExch ;See if anyone is on hold + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes if ZERO + JNZ KSTAssign04 ;No more holders + MOV EDX, KbdMsgBuf2L ;pRq into EDX + PUSH EDX ;Move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated + CALL FWORD PTR _MoveRequest + JMP KSTAssign03 ;Go back to look for more holders +KSTAssign04: ;Holders have been moved, Respond to Req + MOV EBX, KbdMsgBuf1L ;pRqBlk of original Assign Request + PUSH EBX ; + PUSH 0 ;Error Code (OK) + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top +;------------------------------------------------------- + +KSTCancelGlobal: + ;Rifle thru Global Exch and respond with ErcNoKeyAvail + ;to those with the same JobNum as dData0 + MOV EAX, [EBX+dData0] ;Save Job that is cancelling global request + MOV KbdCancelJob, EAX ; + +KSTCancel10: ;Check GlobalExch for canceled job + PUSH KbdGlobExch ;See if anyone is at global + PUSH OFFSET KbdMsgBuf2L ;Where to return Request + CALL FWORD PTR _CheckMsg ; + OR EAX, EAX ;Yes (someones holding) if ZERO + JNZ KSTCancel20 ;No more globals + MOV EDX, KbdMsgBuf2L ;pRq of holding job into EDX + MOV EBX, [EDX+RqOwnerJob] + CMP EBX, KbdCancelJob + JE KSTCancel11 ;Go to respond with Erc + PUSH EDX ;Else move Request to MainKbd Exch + PUSH KbdMainExch ; to be reevaluated + CALL FWORD PTR _MoveRequest + JMP KSTCancel10 ;Go back to look for more globals +KSTCancel11: ; + PUSH EDX ;Respond to this request + PUSH ErcNoKeyAvail ;cause he cancelled it! + CALL FWORD PTR _Respond + JMP SHORT KSTCancel10 ;Back to check for more + +KSTCancel20: ;Respond to original cancel Req + MOV EBX, KbdMsgBuf1L ;pRqBlk of original Request + PUSH EBX ; + PUSH 0 ;Error Code (OK) + CALL FWORD PTR _Respond + JMP KBDServiceTask ;Go back to the top + +;============================================================= +;PUBLIC blocking call to read the keyboard. This uses the +;Default TSS exchange and the stack to make the request to +;the keyboard service for the caller. The request is a standard +;service code one (Wait On Key) request. +;If fWait is NON-ZERO, this will not return without a key unless +;a kernel/fatal error occurs. +; +;The call is fully reentrant (it has to be...). +; +; Procedural interface: +; +; ReadKbd(pKeyCodeRet, fWait): dError +; +; pKeyCodeRet is a pointer to a DWORD where the keycode is returned. +; [EBP+16] +; fWait is NON-ZERO to wait for a key. +; [EBP+12] +; +; Stack Variables: +; Hndl [EBP-4] +; +PUBLIC __ReadKBD: + PUSH EBP ; Save the Previous FramePtr + MOV EBP,ESP ; Set up New FramePtr + SUB ESP, 4 ; One DWORD local var + + MOV EAX, OFFSET KBDSvcName ;'KEYBOARD ' + PUSH EAX + + PUSH 1 ;Service Code (Read Keyboard) + + MOV ECX,pRunTSS ;Get TSS_Exch for our use + MOV EBX,[ECX+TSS_Exch] ;Exchange (TSS Exch) + PUSH EBX ; + + LEA EAX, [EBP-4] ;Rq Handle (Local Var) + PUSH EAX + + PUSH 0 ;npSend + MOV EAX, [EBP+16] ;Key Code return (Their Ptr) + PUSH EAX ;pData1 + PUSH 4 ;Size of key code + PUSH 0 ;pData2 + PUSH 0 ;cbData2 + + XOR EAX, EAX + CMP DWORD PTR [EBP+12], 0 ;Don't wait for Key? + JE ReadKbd1 ;No wait + MOV EAX, 1 ;Set up to wait! +ReadKbd1: + PUSH EAX ;Wait value (dData0) + + PUSH 0 + PUSH 0 + + CALL FWORD PTR _Request ;make the Request + + ;The request is made. Now we call Wait! + + MOV ECX,pRunTSS ;Get TSS_Exch for our use + MOV EBX,[ECX+TSS_Exch] ; + PUSH EBX ;Pass exchange (for WaitMsg) + ADD ECX,TSS_Msg ;Offset of TSS msg area + PUSH ECX + CALL FWORD PTR _WaitMsg ;Wait on it + + ;When we get here the caller should have the key code + ;HOWEVER, we want to pass any errors back via EAX + + OR EAX, EAX ;Was there a kernel error? + JNZ ReadKbdEnd ;YES.... bummer + MOV ECX,pRunTSS ;Get TSS_Msg area so we can get error + ADD ECX,TSS_Msg ;Offset of TSS msg area + MOV EBX, [ECX] ;pRqBlk + MOV EAX, [ECX+4] ;Service error in second DWord +ReadKbdEnd: + MOV ESP,EBP ; + POP EBP ; + RETF 8 ; Rtn to Caller & Remove Params from stack + +;============================================================= +;Special Call for Debugger so it doesn't have to pass thru +;the kernel Request mechanism for a keystroke. +;It acts like ReadKbd with fWait set to true. +;It sucks keys directly from the Final Keyboard buffer. +; +; Procedural interface: +; +; ReadDbgKbd(pKeyCodeRet) +; +; pKeyCodeRet is a pointer to a DWORD where the keycode is returned. +; [EBP+8] +; +PUBLIC ReadDbgKBD: + PUSH EBP ; Save the Previous FramePtr + MOV EBP,ESP ; Set up New FramePtr +RDKB0: + CALL ReadKBFinal ;Get Code from Buf (Uses EAX, ESI) + OR EAX, EAX ;Got a key?? (non zero) + JNZ RDKB1 ;No. Loop back again + PUSH 2 ;Sleep for 20 ms + CALL FWORD PTR _Sleep + JMP RDKB0 ;Check again +RDKB1: + MOV ESI, [EBP+8] ;Ptr where to return key + MOV [ESI], EAX + XOR EAX, EAX + MOV ESP,EBP ; + POP EBP ; + RETN 4 ; Rtn to Caller & Remove Params from stack + +;================================================= +;This sets the Keyboard Scan Set to #2 with 8042 interpretation ON +; +PUBLIC InitKBD: + + PUSH 1 ;KBD IRQ + CALL FWORD PTR _MaskIRQ + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,0FAh ;Set ALL keys typematic/make/break + OUT DataPort,AL ;Send Command to KBD (not 8042) + + CALL OutBuffFull ;Eat response + IN AL, DATAPORT + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,0F0h ;Set Scan code set + OUT DataPort,AL ;Send Command to KBD (not 8042) + + CALL OutBuffFull ;Eat response + IN AL, DATAPORT + + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,02h ;Scan set 2 + OUT DataPort,AL ;Send Command + + CALL OutBuffFull ;Eat response + IN AL, DATAPORT + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,060h ;Set up to write 8042 command byte + OUT COMMANDPORT,AL ;Send Command + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,45h ;Enable IBM Xlate + OUT DataPort,AL ;Send Command + + PUSH 1 ;KBD IRQ + CALL FWORD PTR _UnMaskIRQ + + CALL SetKbdLEDs + + RETN + +;============================================================================= +;This creates the Keyboard Task and Service. +; +PUBLIC _InitKBDService: + + ;All initial requests and messages from the ISR come to + ;this exchange + + MOV EAX, OFFSET KbdMainExch ;Alloc Main Kbd exch for service + PUSH EAX + CALL FWORD PTR _AllocExch + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + ;TempExch for testing + + MOV EAX, OFFSET KbdTempExch ;Alloc Hold Kbd exch for Kbd service + PUSH EAX + CALL FWORD PTR _AllocExch + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + ;Requests for ReadkeyBoard (ScvCode #1) that are from job + ;that currently owns the keyboard waits here if it wants + ;to wait for a key. + + MOV EAX, OFFSET KbdWaitExch ;Alloc Hold Kbd exch for Kbd service + PUSH EAX + CALL FWORD PTR _AllocExch + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + ;Requests for ReadkeyBoard (ScvCode #1) that are from jobs + ;that do NOT currently own the keyboard get sent here using + ;MoveRequest. + + MOV EAX, OFFSET KbdHoldExch ;Alloc Hold Kbd exch for Kbd service + PUSH EAX + CALL FWORD PTR _AllocExch + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + ;Requests for ReadkeyGlobal (SvcCode #3) wait here until we + ;get a global key from the keyboard. + ; + MOV EAX, OFFSET KbdGlobExch ;Alloc Global Wait exch for Kbd service + PUSH EAX + CALL FWORD PTR _AllocExch + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + ;Spawn the Keyboard Service task + + MOV EAX, OFFSET KBDServiceTask + PUSH EAX + PUSH 7 ;Priority + PUSH 0 ;fDebug + MOV EAX, OFFSET KbdSvcStackTop + PUSH EAX + PUSH 1 ;OS Job task + CALL FWORD PTR _SpawnTask + OR EAX, EAX ;Check for error on AllocExch + JNZ InitKBDSvcEnd ;YUP, we got bad problems + + MOV EAX, OFFSET KBDSvcName + PUSH EAX + PUSH KbdMainExch + CALL FWORD PTR _RegisterSvc +InitKBDSvcEnd: + MOV BYTE PTR fKBDInitDone, 1 ;We're UP! + RETN +; +;============================================================================= +;This tells the 8042 Controller to Disable the Keyboard device. +;============================================================================= + +KbdDisable: + PUSH EAX + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,0ADh ;Set Command to "Write the 8042 Command Byte" + OUT COMMANDPORT,AL ;Send Command + CALL InBuffEmpty ;Wait for Input Buffer to Empty + POP EAX + RETN + +;============================================================================= +; This tells the 8042 Controller to Enable the Keyboard Device. +;============================================================================= + +KbdEnable: + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,0AEh ;Set Command to "Write the 8042 Command Byte" + OUT COMMANDPORT,AL ;Send Command + CALL InBuffEmpty ;Wait for Input Buffer to Empty + RETN +; +;============================================================================= +; Waits until the 8042 Input Buffer is EMPTY +;============================================================================= + +InBuffEmpty: + PUSH EAX + PUSH ECX + MOV ECX,2FFFFh ;check 128k times +IBE: + JMP IBE1 +IBE1: + JMP IBE2 +IBE2: + IN AL,STATUSPORT ;Read Status Byte into AL + TEST AL,INPUTBUFFFULL ;Test The Input Buffer Full Bit + LOOPNZ IBE + POP ECX + POP EAX + RETN + +;============================================================================= +; Waits until the 8042 Output Buffer is FULL so we can read it +;============================================================================= +; +; Before calling this makes sure that the Keyboard interrupts have been +; masked so the keyboard interrupt doesn't eat the byte you're +; looking for!! +; +OutBuffFull: + PUSH EAX + PUSH ECX + MOV ECX,2FFFFh +OBF: + JMP OBF1: +OBF1: + JMP OBF2: +OBF2: + IN AL,STATUSPORT ;Read Status Byte into AL + TEST AL,OUTPUTBUFFFULL ;Test The Output Buffer Full Bit + LOOPZ OBF + POP ECX + POP EAX + RETN + +;============================================================================= +; This sets the indicators on the keyboard based on data in KbdState +;============================================================================= + +SetKbdLEDs: + PUSH EAX + + PUSH 1 ;KBD IRQ + CALL FWORD PTR _MaskIRQ + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,0EDh ;Set/Reset Status Indicators + OUT DATAPORT,AL ;Send KBD Command + + CALL OutBuffFull ;Eat response + IN AL, DATAPORT + + CALL InBuffEmpty ;Wait for Input Buffer to Empty + MOV AL,KbdLock ;Get Current Lock Status Byte + AND AL,00000111b ;Mask all but low order 3 bits + OUT DATAPORT,AL ;Send KBD Command + + CALL OutBuffFull ;Eat response + IN AL, DATAPORT + + PUSH 1 ;KBD IRQ + CALL FWORD PTR _UnMaskIRQ + POP EAX + RETN + +;================= END OF MODULE ==================