📄 kbdcode.inc
字号:
; MMURTL Operating System Source Code
; Copyright 1991,1992,1993, Richard A. Burgess
; ALL RIGHTS RESERVED
; Version x0.8
;
;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.
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 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 FAR PTR _ISendMsg ;tell him to come and get it...
KbdExit:
PUSH 1
CALL FAR 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 PROC NEAR
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
ReadKbdBuf ENDP
;
;========================================================
;
; 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 XLateDone ;Yes, leave the key in AL
;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 AL, 0E0h ;Key PREFIX???
JNE KB006 ;NO...
MOV ECX, 50 ;Try 50 times to get second char
KB002:
CALL ReadKbdBuf
CMP EAX, 0
JNE KB003 ;We got another char
LOOP KB002 ;Back to get another char
JMP XLateDone ;Guess one isn't comming...
KB003:
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 KB006
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:
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, 0FFh ;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?
MOV DH, 1 ;Indicates key came numeric pad
;See if shift key is down and shift all keys it is is
TEST CL, ShftDownMask ;Either shift key down?
JZ KB025 ;No, go look for locks
JMP SHORT KB027 ;Yes, 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
CMP DL, 0ADh ;Do not 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 comming from the primary
;translation table, this means the key was from the
;numeric keypad so we set the numpad bit in status
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
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 dGlobalKey, 0
JE KST01 ;No global key came in
KBDGlobal1:
PUSH KbdGlobExch
PUSH OFFSET KbdMsgBuf1L ;Where to return pRqBlk
CALL FAR PTR _CheckMsg ;Check to see if RqWaiting
OR EAX, EAX ;Yes if ZERO
JZ KBDGlobal2 ;Rq waiting for global
MOV 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 FAR 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 FAR PTR _Respond
JMP KBDGlobal1 ;Go back to see if other want it
KST01:
CMP ddVidOwner, 2 ;Debugger has video
JNE KST01ND ;NOT in Debugger
PUSH 20
CALL FAR 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 FAR PTR _WaitMsg ;Wait for the message
;If we got here we got a Request or Msg from ISR
CMP 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 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 FAR PTR _CheckMsg ;Check to see if another msg came in
OR EAX, EAX ;Yes if ZERO
JNZ KBDServiceTask ;No Rq/Msg waiting, Go back to the top
;Fall thru to check 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 FAR PTR _Respond
JMP KBDServiceTask ;Go back to the top
KSTRead:
MOV EAX, [EBX.RqOwnerJob] ;Who's 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 FAR 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 FAR 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 FAR PTR _Respond
JMP KBDServiceTask ;Go back to the top
KSTRead02:
CMP [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 FAR PTR _Respond
JMP KBDServiceTask ;Go back to the top
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -