Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

48KB

Developing Your Own 32-Bit Operating System — Chapter-25: Keyboard Code

  • Source: /library/Developing Your Own 32-Bit Operating System/source-file.pdf
  • PDF pages: 563–592
  • Pages without text: 563

25 Keyboard Code

542] Part PV ■ The Operating System Source Code The keyboard code is probably one of the most complicated source files, second only to the file system. The keyboard code is complicated because it has a little bit of everything in it. It con- tains an interrupt service routine, multilevel lookup tables, a complete system service with an additional task, and several hardware handling calls. Even though the keyboard is technically a device, it does not use the standard MMURTL de- vice-driver interface. There are several reasons for this. The first is that the keyboard was one of the very first devices coded on the system. The second reason is that the keyboard is only an input device and is always shared among applications. Another reason is that the keyboard I/O ports, which actually go to an 8042 (or equivalent) microprocessor, are used for a wide variety of things. The keyboard is a device found on almost all system boards on PC-AT ISA-compat- ible platforms. Keyboard Data The data portion of the file is much larger than for most of the files in MMURTL. It has sev- eral look-up tables used to translate scan codes from what was supposed to be a standardized system. The systems are not as standardized as I once thought. Some of them support all of the modes for the IBM PC-AT, and some of them support only two out of three. I stuck with the most common scan code set, which was the original scan set 2 for the PC-AT. I have the original PC-AT documentation and PS/2 documentation. Some of the ISA machines support PS/2 scan sets, but only the original scan set 2 was supported on all of the systems I tested. Hence, I use it to support the widest array of machines possible. There are three tables that provide the translation. The first provides the initial translation from the raw scan codes; the second is for the scan codes that are preceded by the E0 hex escape sequence; and the third is for shifted keystrokes. See Listing 25.1. Listing 25.1 . Keyboard data and tables. .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

Chapter 25 M Keyboard Code [7TT 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 KbdHoldExch DD 0 KbdGlobExch DD 0 KbdWaitExch DD 0 KbdTempExch DD 0 ;llsed by the Kbd Process ;llsed for requestors that don't own the keyboard ;Used to hold Global CTRL-ALT requests ;Used for Kbd Wait-For-Key requests ;Used to rifle thru requests dGlobalKey DD 0 dfPrefix DD 0 KbdMsgBufIL DD 0 KbdMsgBuflH DD 0 ;Global Key Found, else 0 ;Message buffers for Kbd Service 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 pKbdln DD OFFSET rgbKbdBuf ;ptr to next char going in pKbdOut DD OFFSET rgbKbdBuf ;ptr to next char going out bKbdMode DB 0 fKBDInitDone DB 0 ;ZER0 for Cooked, 1 for RAW ;Set true when KBD Service is up and running KbdState KbdLock DB 0 DB 0 ;(See State Masks below) ; (See Lock Masks below) rgdKBBuf DD 40h DUP (0) ;64 Dwords for translated key buffer dKBCnt DD 0 pKBIn DD OFFSET rgdKBBuf pKBOut DD OFFSET rgdKBBuf ;ptr to codes comming in ;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

544] Part PV ■ The Operating System Source Code Listing 25.1. continued ; 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. KbdTable DB 0 DB 01 Bh DB 031 h DB 032h DB 033h DB 034h DB 035h DB 036h DB 037h DB 038h DB 039h DB 030h DB 02Dh DB 03Dh DB 008h DB 009h DB 071 h DB 077h DB 065h DB 072h DB 074h DB 079h DB 075h DB 069h DB 06Fh DB 070h DB 05Bh ESC 1 2 3 4 5 6 7 8 9 BkSpc TAB q SHIFT Value 21h 40h 23h 24h 25h 5Eh 26h 2Ah 28h 29h 5Fh 2Bh 51h 57h 45h 52h 54h 59h 55h 49h 4Fh 50h 7Bh

Chapter 25 Keyboard Code |
541 ] 1B 7Dh CR 1C LCtrl 1D Special handling a 1E 41h s 1F 53h d 20 44h f 21 46h g 22 47h h 23 48h 1 24 4Ah k 25 4Bh 1 (L) 26 4Ch ; 27 3Ah 28 22h 29 7Eh LfShf 2A Special handling \ 2B 7Ch z 2C 5Ah X 2D 58h c 2E 43h V 2F 56h b 30 42h n 31 4Eh m 32 4Dh , 33 3Ch 34 3Eh / 35 3Fh RtShf 36 Special handling Num * 37 Num pad LAlt 38 Special handling Space 39 CpsLk 3A Special handling F1 3B F2 3C F3 3D F4 3E F5 3F F6 40 F7 41 F8 42 F9 43 F10 44 NumLk 45 Special handling ScrLk 46 Special handling Num 7 47 37h Num Home Num 8 48 38h Num Up Num 9 49 39h Num Pg Up Num - 4A Num Pad Num 4 4B 34h Num Left Num 5 4C 35h Num (Extra code Num 6 4D 36h Num Right Num + 4E Num Pad Num 1 4F 31h Num End Num 2 50 32h Num Down Num 3 51 33h Num Pg Dn Num 0 52 30h Num Insert Num . 53 2Eh Num Del

H Part TV ■ The Operating System Source Code Listing 25.1. continued 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 001 h 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-AT. All PCs 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!

Chapter 25 ■ Keyboard Code E nKbdTable2 EQU 16 KbdTable2 DB 052h, 060h ; Insert DB 04Fh, 061 h ;End DB 050h, 062h ;Down DB 051 h, 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 058h, 070h ; Right ALT DOWN DB 01Dh, 071 h ; Right Ctrl DOWN DB 0B8h, 0F0h ; Right ALT UP DB 09Dh, 0F1h ; Right Ctrl UP These are special cause we track UP & DOWN! ! ! ;This table provides shift level values for codes from the primary KbdTable. ;In Shift -ON state ALL keycodes are translated through this table. ;In CAPS LOCK state codes 61 h to 7Ah are translated through this table ;In NUM LOCK state only 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

348] Part PV ■ The Operating System Source Code Listing 25.1. continued DB 1Dh 1D DE 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 41 h 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

Chapter 25 M Keyboard Code 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 1

DB 41 h 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 i J DB 4Bh 6B k K DB 4Ch 6C 1 L DB 4Dh 6D 1 M DB 4Eh 6E n N DB 4Fh 6F 0 0 DB 50h 70 P P DB 51 h 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 KbdScvStack DD 127 DUP(0) ;512 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

I rcQ I Part PV ■ The Operating System Source Code Listing 25.1. continued PARITYERROR EQU 10000000b GENERALTIMEOUT EQU 01000000b AUXOUTBUFFFULL EQU 00100000b INHIBITSWITCH EQU 00010000b COMMANDDATA EQU 00001000b SYSTEMFLAG EQU 00000100b INPUTBUFFFULL EQU 00000010b OUTPUTBUFFFULL EQU 00000001b Keyboard Code The keyboard code is divided into several sections. The first section is the ISR; the second is a small routine that reads scan codes from the raw ISR buffers; the third is the shift translation code, followed by the keyboard service, and finally all of the support routines. Keyboard ISR The keyboard ISR places all raw scan codes into a 32-byte buffer. When a code is placed in the buffer, a message is sent to the keyboard service to tell it that the raw buffer has something in it. This uses ISendMsg ( ) , which is used by ISRs to send messages when interrupts are disabled. See Listing 25.2. Listing 25.2. Keyboard ISR 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 jshould 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, pKbdln ;Set up pointer X0R 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?

Chapter 25 ■ Keyboard Code H KbdEnd: JB KbdEnd MOV ESI, OFFSET rgbKbdBuf ;Back to beginning of buffer MOV pKbdln, ESI ;Set up pointer for next time CMP BYTE PTR f KBDInitDone, 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 OFFFFFFFFh ; 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 raw 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 ST I RETN Keyboard Translation When the keyboard is notified that raw scan codes have been placed in the keyboard buffer, this routine is called to translate them and place them in the final 64-key buffer. Some inter- rupts may not necessarily result in a key code being sent to the final buffer. For instance, if you press the Shift key and then let it go without pressing another key, the result will be no addi- tional key codes in the final buffer. See Listing 25.3.

B Part PV ■ The Operating System Source Code Listing 25.3. Keyboard translation code. ; 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 CMP BL, 1 JNE KB001 JMP KB029A ;See if we are RAW... (for testing ONLY) ;N0 - keep going ;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. CMP df Prefix, 1 JE KB003 CMP AL, 0E0h JNE KB006 MOV df Prefix, 1 JMP XLateDone Key PREFIX??? No Yes, We got an E0. MOV dfPrefix, 0 ;No prefix MOV ESI, OFFSET KbdTable2 MOV ECX, nKbdTable2 CMP BYTE PTR [ESI] , AL JE KB005 INC ESI INC ESI DEC ECX JNZ KB004 JMP XLateDone ;Two bytes further into table 2 ;Go to next table entry ;No translation - ignore it KB005: INC ESI XOR EAX, EAX MOV AL, [ESI] ;One byte further over to get Xlate byte ;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. MOV dfPrefix, 0 XOR EBX, EBX XOR ECX, ECX ;No prefix

Chapter 25 Keyboard Code ra MOV BL, KbdState MOV CL, KbdLock CMP AL, 45h JNE KB007 BTC ECX, NmLockBit JMP KB022 ;BL has Shift, Alt, Ctrl states ;BH has Num, Caps, & Scroll Lock ;Key = NumLock ? ;NO. .. ; Compliment bit KB007: CMP AL, 3Ah JNE KB008 BTC ECX, CpLockBit JMP KB022 ;Caps Lock? ; Compliment bit in BH CMP AL, 46h JNE KB009 BTC ECX, ScLockBit JMP KB022 ;Scroll Lock? ; Compliment bit in BH CMP AL, 2Ah JNE KB010 BTS EBX, ShftLeftBit JMP KB021 ;Char Left Shift On? KB010: CMP AL, 36h JNE KB011 BTS EBX, ShftRiteBit JMP KB021 iRight Shift On? KB011 : CMP AL, 0AAh JNE KB012 BTR EBX, ShftLeftBit JMP KB021 ;Left Shift Off? CMP AL, 0B6h JNE KB013 BTR EBX, ShftRiteBit JMP KB021 ; Right Shift Off? KB013: CMP AL, 1Dh JNE KB014 BTS EBX, CtrlLeftBit JMP KB021 Left Ctrl On? CMP AL, 71 h JNE KB015 BTS EBX, CtrlRiteBit JMP KB021 Right Ctrl On’

I
554 Part TV ■ The Operating System Source Code Listing 25.3. continued KB015: CMP AL, 09Dh JNE KB016 BTR EBX, CtrlLeftBit JMP KB021 ;Left Ctrl Off? CMP AL, 0F1h JNE KB017 BTR EBX, CtrlRiteBit JMP KB021 ;Right Ctrl Off? CMP AL, 38h JNE KB018 BTS EBX, AltLeftBit JMP KB021 Left Alt On? KB018: CMP AL, 70h JNE KB019 BTS EBX, AltRiteBit JMP KB021 ; Right Alt On? KB019: CMP AL, 0B8h JNE KB020 BTR EBX, AltLeftBit JMP KB021 ;Left Alt Off? KB021 CMP AL, 0F0h JNE KB023 BTR EBX, AltRiteBit MOV KbdState, BL JMP XLateDone ; Right Alt Off? :Put Kbd Shift State back KB023: MOV KbdLock, CL CALL SetKbdLEDS JMP XLateRawKBD Put Kbd Lock State back Set LEDs on keyboard ;We jumped here if it wasn't a key that is specially handled TEST AL, 80h JNZ XLateDone OR AL.AL JZ XLateDone ;Check for high bit (key-up code) ;Go back, else fall through ;Zero not a valid code ;Go back, else fall through

Chapter 25 B Keyboard Code 0 ;If we got here, IT'S AN EDIT KEY DOWN! ;Now we lookup the code and do a single translation. AND EAX, 07Fh MOV ESI, OFFSET KbdTable MOV DL, BYTE PTR [ESI+EAX] OR AL.AL JZ XLateDone MOV CL, KbdState MOV CH, KbdLock ;Chop off any upper bit junk |Set up to index table [Save in DL ;Zero not a valid code ;Go back, else fall through ;Get Shift state ;Get lock state KB024: KB026: ;T0 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 JZ SHORT KB024 MOV DH, 1 ;High bit set? ; Indicates key came numeric pad See if shift key is down and shift all keys if it is TEST CL, ShftDownMask JZ KB025 CMP DL, 21 h JB KB025 CMP DL, 7Eh JA KB025 JMP SHORT KB027 ; Either shift key down? ;No, go look for locks ;Is key < ' ' ;Yes, look for locks ;Is key > ‘-’ ;Yes, look for locks ;In-range, go do the translation KB025: ;See if key is from Numeric Keypad (high bit will be set) TEST DL, 80h ;High bit set? JZ KB026 ;N0 AND CH, NmLockMask ;Yes, is NumLock ON JZ KB026 CMP DL, 0ADh ;Do not shift DASH (-) Special Case JE KB026 JMP SHORT KB027 ;Do the shift Xlation ;See if Caps Lock is on and if key is between 61 h and 7Ah ;do the translation TEST CH, CpLockMask JZ KB029 CMP DL, 61 h JB KB029 CMP DL, 7Ah JA KB029 ;Is CpLock ON ;No ;Is key >= ‘a’ ;No ;Is key <= ‘z’ ;No Fall through to do the translation

Part PV ■ The Operating System Source Code Listing 25.3. continued 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 jtranslation table, this means the key was from the jnumeric keypad so we set the numpad bit in status MOV AH, DH SHL EAX, 8 MOV AL, KbdState MOV AH, KbdLock SHL EAX, 8 AND DL, 7Fh MOV AL, DL ;Num Pad indicator ;Get Shift state ;Get lock state ;Lop of high bit (if there) ;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 JZ KB029A TEST AH, AltDownMask JZ KB029A ; Either Ctrl Down? ;No ; Either Alt Down? ;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 CMP EBX, 64 JE XLateDone MOV ESI, pKBIn MOV [ESI], EAX INC dKBCnt ADD ESI, 4 CMP ESI, OFFSET rgdKBBuf JB KB030 MOV ESI, OFFSET rgdKBBuf ;See if buffer full ; number of DWords in final buffer ;Buffer is FULL. . ;Get ptr to next IN to final buffer ;Move into buf ;One more DWord in the buf ;Reset to buf beginning MOV pKBIn, ESI JMP XLateRawKBD ;Save ptr to next in XlateDone: XOR EAX, EAX RETN

Chapter 25 ■ Keyboard Code Reading the Final Buffer This routine is called to take a key out of the final buffer if one is available. This buffer rgdKBBuf holds the 32-bit fully encoded key value. See Listing 25.4. Listing 25.4. Read keyboard buffer code. H 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 ;0ne 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 The Keyboard Service KBDServiceTask is a complete system service. It services five codes, including Abort (0) . It handles requests from multiple clients; this means it must hold the requests for those jobs that do not own the keyboard. When the keyboard is reassigned to a new job, the requests it was holding must be reevaluated to see whether the new job had an outstanding keyboard request. This service also accepts messages from the keyboard ISR to indicate that translation of raw keyboard scan codes must be done. See Listing 25.5.

558 Part PV ■ The Operating System Source Code Listing 25.5. Keyboard system service code. 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 ; JE KST01 No global key came in KBDGloball : PUSH KbdGlobExch PUSH OFFSET KbdMsgBuflL CALL FWORD PTR _CheckMsg OR EAX, EAX JZ KBDGl0bal2 MOV DWORD PTR dGlobalKey, JMP KBDServiceTask ;Where to return pRqBlk ; Check to see if RqWaiting ;Yes if ZERO ;Rq waiting for global ;Wipe out global key (no one wants it) ; Start over again KBDGlobal2: MOV EBX, KbdMsgBuflL MOV ESI, [EBX+pData1] OR ESI, ESI JNZ KBDGlobal3 PUSH EBX PUSH ErcNullPtr CALL FWORD PTR _Respond JMP KBDServiceTask jpRqBlk into EBX ;Ptr where to return key ;Is it null?? (Bad news if ;No, probably good ptr ;Yes, BAD PTR. Push pRqBlk ;Push error ;Go back to the top SO) KBDGlobal3: MOV EDX, dGlobalKey MOV [ESI], EDX PUSH EBX PUSH 0 CALL FWORD PTR _Respond JMP KBDGloball ;Give em the key! ;Push pRqBlk ;Push NO ERROR ;Go back to see if others want it KST01 CMP DWORD PTR ddVidOwner, 2 ; Debugger has video JNE KST01ND PUSH 20 CALL FWORD PTR Sleep CALL XLateRawKBD JMP KBDServiceTask ;NOT in Debugger ; Processes RAW buffer ;Go back to the top KST01ND: PUSH KbdMainExch PUSH OFFSET KbdMsgBuflL CALL FWORD PTR _WaitMsg See if someones “Requesting” Wait for the message

Chapter 25 ■ Keyboard Code H ;If we got here we got a Request or Msg from ISR CMP DWORD PTR KbdMsgBuf 1L, 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 KST02 : CMP DWORD PTR dGlobalKey, JNE KBDGloball PUSH KbdWaitExch PUSH OFFSET KbdMsgBuf 1L CALL FWORD PTR _CheckMsg OR EAX, EAX JNZ KBDServiceTask ;If we got here we've got MOV EBX, KbdMsgBuf 1L MOV CX, [EBX+ServiceCode] ;A global key came in ;See if owner is waiting for a key ;Where to return Request or msg ;Check to see if another msg came in ;Yes if ZERO ;No Rq/Msg waiting, Go back to the top ;Fall thru to check request Request from Main or Wait ;pRqBlk into EBX ;Save in CX Exch CMP CX, 0 JE KSTAbort CMP CX, 1 JE KSTRead CMP CX, 2 JE KSTReadGlobal CMP CX, 3 JE KSTCancelGlobal CMP CX, 4 JE KSTAssignKbd PUSH EBX PUSH ErcBadSvcCode CALL FWORD PTR _Respond JMP KBDServiceTask Job Abort Notify ReadKbd ReadKbdGlobal CancelGlobal AssignKBD HOMEY DON'T SERVICE THAT! Bad service code ;Go back to the top KSTRead : MOV EAX, [EBX+RqOwnerJob] CMP EAX, KbdOwner JE KSTRead00 PUSH EBX PUSH KbdHoldExch CALL FWORD PTR MoveRequest JMP KBDServiceTask KSTRead00: CALL ReadKBFinal CMP EAX, 0 JE KSTRead02 MOV ESI, [EBX+pData1] CMP ESI, 0 JNE KSTRead01 PUSH EBX PUSH ErcNullPtr ;Whose Request is it? This guy owns it! Not the owner, so send to Hold Exch ;Go back to the top ;Get Code from Buf (Uses EAX, ESI) ;No Key in Final Buffer ;Go see if they asked to wait ;Ptr where to return key ;Is it null?? (Bad news if so) ;No, probably good ptr ;Yes, BAD PTR. Push pRqBlk ;Push error

560 Part IV ■ The Operating System Source Code Listing 25.5. continued CALL FWORD PTR _Respond JMP KBDServiceTask KSTRead01 : MOV [ESI], EAX PUSH EBX PUSH 0 CALL FWORD PTR _Respond JMP KBDServiceTask KSTRead02: CMP DWORD PTR [EBX+dData0] , 0 ;Go back to the top ;Give them the key code ;RqHandle ;NO Error ;Go back to the top ;Wait for key? 0 in dData0 = Don't wait JNE KSTRead04 PUSH EBX PUSH ErcNoKeyAvail CALL FWORD PTR _Respond JMP KBDServiceTask KSTRead04: PUSH EBX PUSH KbdWaitExch CALL FWORD PTR _MoveRequest JMP KBDServiceTask ;Yes ; Error Code (No key to give you) ;Go back to the top ;They opted to wait for a key ;Send em to the wait exch ;Go back to the top KSTAbort: ;Respond to all requests we are holding for Job in dData0 ;with Ere 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] MOV KbdAbortJob, EAX KSTAbort10: PUSH KbdWaitExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR CheckMsg OR EAX, EAX JNZ KSTAbort20 MOV EDX, KbdMsgBuf2L MOV EBX, [EDX+RqOwnerJob] CMP EBX, KbdAbortJob JE KSTAbort 11 PUSH EDX PUSH KbdMainExch CALL FWORD PTR MoveRequest JMP KSTAbort 10 ;Get aborting job number ;this is aborting job ;Check the WaitExch ;See if he was “waiting” for a key ;Where to return Request ;Yes (someones waiting) if ZERO ;No more waiters ;pRq of holding job into EDX ;Go to respond with Ere ;Else move Request to MainKbd Exch ; to be reevaluated ;Go back to look for more waiters KSTAbort 11 : PUSH EDX PUSH ErcOwnerAbort CALL FWORD PTR _Respond JMP SHORT KSTAbort 10 Respond to this request cause he's dead

Chapter 25 B Keyboard Code |
561 KSTAbort20: PUSH KbdHoldExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR CheckMsg OR EAX, EAX JNZ KSTAbort30 MOV EDX, KbdMsgBuf2L MOV EBX, [EDX+RqOwnerJob] CMP EBX, KbdAbortJob JE KSTAbort21 PUSH EDX PUSH KbdMainExch CALL FWORD PTR MoveRequest JMP KSTAbort20 ;Check HoldExch for dead job ;See if anyone is on hold ;Where to return Request ;Yes (someone's holding) if ZERO ;No more holders ;pRq of holding job into EDX ;Go to respond with Ere ;Else move Request to MainKbd Exch ; to be reevaluated. It's not him. ;Go back to look for more holders KSTAbort21 : PUSH EDX PUSH ErcOwnerAbort CALL FWORD PTR _Respond JMP SHORT KSTAbort20 Respond to this request cause he's dead ;Go back to look for more holders KSTAbort30: PUSH KbdGlobExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR _CheckMsg OR EAX, EAX JNZ KSTAbort40 MOV EDX, KbdMsgBuf2L MOV EBX, [EDX+RqOwnerJob] CMP EBX, KbdAbortJob JE KSTAbort31 PUSH EDX PUSH KbdMainExch CALL FWORD PTR _MoveRequest JMP KSTAbort30 ;Check GlobalExch for dead job ;See if anyone is at global ;Where to return Request ;Yes (someones holding) if ZERO ;No more holders ;pRq of holding job into EDX ;Go to respond with Ere ;Else move Request to MainKbd Exch ; to be reevaluated ;Go back to look for more globals KSTAbort31 : PUSH EDX PUSH ErcOwnerAbort CALL FWORD PTR _Respond JMP SHORT KSTAbort30 Respond to this request cause he's dead KSTAbort40: MOV EBX, KbdMsgBuflL PUSH EBX PUSH 0 CALL FWORD PTR _Respond JMP KBDServiceTask Respond to original abort Req pRqBlk of original Abort Request Error Code (OK) Go back to the top KSTReadGlobal: PUSH EBX PUSH KbdGlobExch CALL FWORD PTR _MoveRequest JMP KBDServiceTask ;They want a global key iSend em to the Global exch ;Go back to the top

562 Part IV The Operating System Source Code Listing 25.5. continued ;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] CMP EAX, KbdOwner JNE KSTAssign01 PUSH EBX PUSH 0 CALL FWORD PTR Respond JMP KBDServiceTask KSTAssign01 : MOV KbdOwner, EAX KSTAssign02: PUSH KbdWaitExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR _CheckMsg OR EAX, EAX JNZ KSTAssign03 MOV EDX, KbdMsgBuf2L PUSH EDX PUSH KbdMainExch CALL FWORD PTR _MoveRequest JMP KSTAssign02 KSTAssign03: PUSH KbdHoldExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR _CheckMsg OR EAX, EAX JNZ KSTAssign04 MOV EDX, KbdMsgBuf2L PUSH EDX PUSH KbdMainExch CALL FWORD PTR _MoveRequest JMP KSTAssign03 KSTAssign04: MOV EBX, KbdMsgBufIL PUSH EBX PUSH 0 CALL FWORD PTR _Respond JMP KBDServiceTask ;Get new owner ;New Owner! ;Same owner ;Error Code (OK) ;Go back to the top ;Set new owner ;Move all waiters to main exch ;See if anyone is “waiting” for a key ;Where to return Request ;Yes (someones waiting) if ZERO ;No more waiters ;pRq into EDX ;Move Request to MainKbd Exch ; to be reevaluated ;Go back to look for more waiters ; Waiters have been moved, Respond to Req ;See if anyone is on hold ;Where to return Request ; Yes ‘if ZERO ;No more holders ;pRq into EDX ;Move Request to MainKbd Exch ; to be reevaluated ;Go back to look for more holders Holders have been moved, Respond to Req pRqBlk of original Assign Request Error Code (OK) 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 ;

Chapter 25 ■ Keyboard Code |
563 KSTCancel10: PUSH KbdGlobExch PUSH OFFSET KbdMsgBuf2L CALL FWORD PTR _CheckMsg OR EAX, EAX JNZ KSTCancel20 MOV EDX, KbdMsgBuf2L MOV EBX, [EDX+RqOwnerJob] CMP EBX, KbdCancelJob JE KSTCancein PUSH EDX PUSH KbdMainExch CALL FWORD PTR _MoveRequest JMP KSTCancel10 KSTCancein : PUSH EDX PUSH ErcNoKeyAvail CALL FWORD PTR _Respond JMP SHORT KSTCancel10 KSTCancel20: MOV EBX, KbdMsgBufIL PUSH EBX PUSH 0 CALL FWORD PTR Respond JMP KBDServiceTask ;Check GlobalExch for canceled job ;See if anyone is at global ;Where to return Request ;Yes (someones holding) if ZERO ;No more globals ;pRq of holding job into EDX ;Go to respond with Ere ;Else move Request to MainKbd Exch ; to be reevaluated ;Go back to look for more globals ;Respond to this request ;cause he cancelled it! ;Back to check for more Respond to original cancel Req pRqBlk of original Request Error Code (OK) ;Go back to the top Keyboard Procedural Interface When programs don't need the power of the request interface, such as multiple asynchronous requests, services can provide a blocking procedural call to make the application's job easier. This code actually makes the request for the caller. The caller doesn't have to know anything about the request interface to use this. See Listing 25.6. Listing 25.6. Code for blocking read keyboard call. 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

Part IV ■ The Operating System Source Code Listing 25.6. continued 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 MOV EBP, ESP SUB ESP, 4 ; Save the Previous FramePtr ; Set up New FramePtr ; One DWORD local var MOV EAX, OFFSET KBDSvcName PUSH EAX ' KEYBOARD PUSH 1 ;Service Code (Read Keyboard) MOV ECX.pRunTSS MOV EBX,[ECX+TSS_Exch] PUSH EBX Get TSSExch for our use Exchange (TSS Exch) LEA EAX, [EBP-4] PUSH EAX ;Rq Handle (Local Var) PUSH 0 MOV EAX, [EBP+16) PUSH EAX PUSH 4 PUSH 0 PUSH 0 jnpSend ;Key Code return (Their Ptr) ;pData1 ;Size of key code ;pData2 ;cbData2 XOR EAX, EAX CMP DWORD PTR [EBP+12], 0 JE ReadKbdl MOV EAX, 1 ; Don't wait for Key? ;No wait ;Set up to wait! ReadKbdl PUSH EAX PUSH 0 PUSH 0 CALL FWORD PTR Request ;Wait value (dData0) ;make the Request ;The request is made. Now we call Wait! Get TSS Exch for our use MOV ECX.pRunTSS MOV EBX,[ECX+TSS_Exch] PUSH EBX ADD ECX,TSS_Msg PUSH ECX CALL FWORD PTR _WaitMsg Pass exchange (for WaitMsg) Offset of TSS msg area ;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?

Chapter 25 ■ Keyboard Code H JNZ ReadKbdEnd MOV ECX.pRunTSS ADD ECX,TSS_Msg MOV EBX, [ECX] MOV EAX, [ECX+4] ReadKbdEnd: MOV ESP, EBP POP EBP RETF 8 ;YES. . . . bummer ;Get TSSMsg area so we can get error ;Offset of TSS msg area ;pRqBlk (lets look! ! ) ;Service error in second DWord Rtn to Caller & Remove Params from stack Debugger Keyboard The debugger requires a special function to read the keyboard. This allows the debugger to completely bypass the keyboard system service so it doesn't have to go through the kernel for anything. This reads keystrokes directly from the final coded buffer. See Listing 25.7. Listing 25.7. Debugger read keyboard code. 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 MOV EBP, ESP RDKB0: RDKB1 CALL ReadKBFinal OR EAX, EAX JNZ RDKB1 PUSH 2 CALL FWORD PTR _Sleep JMP RDKB0 MOV ESI, [EBP+8] MOV [ESI], EAX XOR EAX, EAX MOV ESP, EBP POP EBP RETN 4 Save the Previous FramePtr Set up New FramePtr ;Get Code from Buf (Uses EAX, ESI) ;Got a key?? (non zero) ;No. Loop back again ;Sleep for 20 ms ;Check again ;Ptr where to return key Rtn to Caller & Remove Params from stack

566] PartIV The Operating System Source Code Keyboard Hardware Set Up InitKBD is called very early in the operating system initialization code to set up the keyboard hardware. The 8042 provides hardware interrupts, but you don't have to call SetIRQVector( ) because the keyboard interrupt routines address was known at build time. See Listing 25.8. Listing 25.8. Code to initialize the keyboard hardware. ;This sets the Keyboard Scan Set to #2 with 8042 interpretation ON PUBLIC InitKBD: PUSH 1 ;KBD IRQ CALL FWORD PTR MasklRQ CALL InBuffEmpty MOV AL,0FAh OUT DataPort.AL CALL OutBuffFull IN AL, DATAPORT CALL InBuffEmpty MOV AL,0F0h OUT DataPort.AL CALL OutBuffFull IN AL, DATAPORT ;Wait for Input Buffer to Empty ;Set ALL keys typematic/make/break ;Send Command to KBD (not 8042) ;Eat response ;Wait for Input Buffer to Empty ;Set Scan code set ;Send Command to KBD (not 8042) ;Eat response CALL InBuffEmpty MOV AL,02h OUT DataPort.AL CALL OutBuffFull IN AL, DATAPORT CALL InBuffEmpty MOV AL,060h OUT COMMANDPORT.AL CALL InBuffEmpty MOV AL,45h OUT DataPort.AL ;Wait for Input Buffer to Empty ;Scan set 2 ;Send Command ;Eat response ;Wait for Input Buffer to Empty ;Set up to write 8042 command byte ;Send Command ;Wait for Input Buffer to Empty ;Enable IBM Xlate ;Send Command PUSH 1 CALL FWORD PTR ;KBD IRQ UnMasklRQ CALL SetKbdLEDs RETN

Chapter 25 • Keyboard Code 567 Keyboard Service Initialization InitKBDService is called from the monitor to start the keyboard service. The service is a com- pletely separate task that runs in a loop servicing requests. This will be called only once, and it is called after the keyboard hardware and the keyboard ISR are functional. See Listing 25.9. Listing 25.9. Keyboard service initialization. PUBLIC _InitKBDService: ;A11 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 .-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 ;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 ;Used to “rifle” thru RqBlks waiting at an exchange. MOV EAX, OFFSET KbdTempExch ;Alloc Tmp exch for Kbd service PUSH EAX CALL FWORD PTR _AllocExch OR EAX, EAX ;Check for error on AllocExch

|368 Part PV ■ The Operating System Source Code Listing 25.9. continued JNZ InitKBDSvcEnd ;YUP, we got bad problems ;Spawn the Keyboard Service task MOV EAX, OFFSET KBDServiceTask PUSH EAX PUSH 7 ; Priority PUSH 0 ;f Debug MOV EAX, OFFSET KbdSvcStackTop PUSH EAX PUSH 1 ;0S 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 f KBDInitDone, 1 RETN ;We're UP! 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 Hardware Helpers The rest of the routines are used for various hardware functions, such as reading or writing the 8042 or keyboard data ports, as well as setting the keyboard LEDs to the proper state. See Listing 25.10. Listing 25.10. Low-level keyboard control code. This tells the 8042 Controller to Enable the Keyboard Device. KbdEnable: CALL InBuffEmpty ;Wait for Input Buffer to Empty

Chapter 25 ■ Keyboard Code 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 IBE1: IBE2: JMP IBE1 JMP 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: 0BF2: JMP OBF1 : JMP 0BF2: 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

Part PV ■ The Operating System Source Code Listing 25.10. continued PUSH 1 CALL FWORD PTR ;KBD IRQ CALL InBuffEmpty MOV AL,0EDh OUT DATAPORT ,AL ;Wait for Input Buffer to Empty ;Set/Reset Status Indicators ;Send KBD Command CALL OutBuffFull IN AL, DATAPORT ;Eat response CALL InBuffEmpty MOV AL.KbdLock AND AL,00000111b OUT DATAPORT, AL ;Wait for Input Buffer to Empty ;Get Current Lock Status Byte ;Mask all but low order 3 bits ;Send KBD Command CALL OutBuffFull IN AL, DATAPORT ;Eat response PUSH 1 CALL FWORD PTR POP EAX RETN ;KBD IRQ UnMasklRQ

Powered by TurnKey Linux.