📄 kbdcode.inc
字号:
KSTRead04:
PUSH EBX ;They opted to wait for a key
PUSH KbdWaitExch ;Send em to the wait exch
CALL FAR PTR _MoveRequest
JMP KBDServiceTask ;Go back to the top
KSTAbort:
;Respond with ErcOwnerAbort for job that aborted
KSTReadGlobal:
PUSH EBX ;They want a global key
PUSH KbdGlobExch ;Send em to the Global exch
CALL FAR PTR _MoveRequest
JMP KBDServiceTask ;Go back to the top
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 FAR 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 FAR 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 FAR PTR _MoveRequest
JMP KSTAssign02 ;Go back to look for more waiters
KSTAssign03: ;Waiter have been move, Respond to Req
PUSH KbdHoldExch ;See if anyone is on hold
PUSH OFFSET KbdMsgBuf2L ;Where to return Request
CALL FAR 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 FAR PTR _MoveRequest
JMP KSTAssign03 ;Go back to look for more holders
KSTAssign04: ;Waiter have been move, Respond to Req
MOV EBX, KbdMsgBuf1L ;pRqBlk of original Assign Request
PUSH EBX ;
PUSH 0 ;Error Code (OK)
CALL FAR PTR _Respond
JMP KBDServiceTask ;Go back to the top
KSTCancelGlobal:
;Rifle thru Global Hold and respond with no KeyKeyAvail
;to those with the same JobNum as dData0
PUSH EBX ;RqHandle
PUSH ErcBadSvcCode ;Don't do these yet
CALL FAR 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]
;
_ReadKBD PROC FAR
PUSH EBP ; Save the Previous FramePtr
MOV EBP,ESP ; Set up New FramePtr
SUB ESP, 4 ; Two DWORD local vars
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 FAR 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 FAR 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 (lets look!!)
MOV EAX, [ECX+4] ;Service error in second DWord
ReadKbdEnd:
MOV ESP,EBP ;
POP EBP ;
RETF 8 ; Rtn to Caller & Remove Params from stack
_ReadKbd ENDP
;=============================================================
;Special Call for Debugger so it doesn't have top 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]
;
ReadDbgKBD PROC NEAR
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 FAR 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
ReadDbgKbd ENDP
;=================================================
;This sets the Keyboard Scan Set to #2 with 8042 interpretation ON
;
InitKBD PROC NEAR
PUSH 1 ;KBD IRQ
CALL FAR 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 FAR PTR _UnMaskIRQ
CALL SetKbdLEDs
RETN
InitKBD ENDP
;=============================================================================
;This creates the Keyboard Task and Service.
;
_InitKBDService PROC NEAR
;All initail requests and messages from the ISR come to
;this exchange
MOV EAX, OFFSET KbdMainExch ;Alloc Main Kbd exch for service
PUSH EAX
CALL FAR 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 FAR 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 FAR 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 FAR 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 FAR 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 FAR 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 FAR PTR _RegisterSvc
InitKBDSvcEnd:
MOV fKBDInitDone, 1 ;We're UP!
RETN
_InitKBDService ENDP
;
;=============================================================================
;This tells the 8042 Controller to Disable the Keyboard device.
;=============================================================================
KbdDisable PROC NEAR
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
KbdDisable ENDP
;=============================================================================
; This tells the 8042 Controller to Enable the Keyboard Device.
;=============================================================================
KbdEnable PROC NEAR
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
KbdEnable ENDP
;
;=============================================================================
; Waits until the 8042 Input Buffer is EMPTY
;=============================================================================
InBuffEmpty PROC NEAR
PUSH EAX
PUSH ECX
MOV ECX,2FFFFh ;check 128k times
IBE:
JMP $+2
JMP $+2
IN AL,STATUSPORT ;Read Status Byte into AL
TEST AL,INPUTBUFFFULL ;Test The Input Buffer Full Bit
LOOPNZ IBE
POP ECX
POP EAX
RETN
InBuffEmpty ENDP
;=============================================================================
; 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 PROC NEAR
PUSH EAX
PUSH ECX
MOV ECX,2FFFFh
OBF:
JMP $+2
JMP $+2
IN AL,STATUSPORT ;Read Status Byte into AL
TEST AL,OUTPUTBUFFFULL ;Test The Output Buffer Full Bit
LOOPZ OBF
POP ECX
POP EAX
RETN
OutBuffFull ENDP
;=============================================================================
; This sets the indicators on the keyboard based on data in KbdState
;=============================================================================
SetKbdLEDs PROC NEAR
PUSH EAX
PUSH 1 ;KBD IRQ
CALL FAR 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 FAR PTR _UnMaskIRQ
POP EAX
RETN
SetKbdLEDs ENDP
;=======================================================
;Tone genration code is included with Kbd for lack of a
;better place. Two far calls provide everything you could ever need from
;the speaker.
; BEEP is a FAR call with no params that beeps the speaker
; at 300 Hz for 350ms.
; TONE is a FAR call with two parmas:
; 1) FREQ in HZ (a DD)
; 2) On time in 10ms increments (a DD)
;
;The clock freq to Timer 2 is 1.193182 Mhz
;To find the divisor of the clock, divide 1.193182Mhz by Desired Freq.
;
;================================================
;This does all work for BEEP and TONE
;EBX needs FREQ in HERTZ
;ECX needs length of tone in 10ms increments
BEEP_Work PROC NEAR
MOV AL, 10110110b ;Timer 2, LSB, MSB, Binary
OUT 43h, AL
XOR EDX, EDX
MOV EAX, 1193182 ;1.193182Mhz
DIV EBX ;DIVISOR is in EBX (Freq)
OUT 42h, AL ;Send quotient (left in AX)
MOV AL, AH
JMP $+2
JMP $+2
OUT 42h, AL
IN AL, 61h
OR AL, 00000011b
JMP $+2
JMP $+2
OUT 61h, AL
PUSH ECX ;
CALL FAR PTR _Sleep ;ECX is TIME ON in 50ms incs.
IN AL, 61h
JMP $+2
JMP $+2
AND AL, 11111100b
OUT 61h, AL
RETN
BEEP_Work ENDP
;================================================
_Beep PROC FAR
PUSH EBP ;
MOV EBP,ESP ;
MOV EBX, 800 ;Freq
MOV ECX, 35 ;350ms
CALL Beep_Work
MOV ESP,EBP ;
POP EBP ;
RETF
_Beep ENDP
;================================================
;TONE allows the caller to specify a frequency and duration of a tone
;from the speaker. This call uses Beep_Work (A NEAR call to do the job)
; PARAM 1 is a DD which is the FREQUENCY in HERTZ
; PARAM 2 is a DD which is the length of the tone in 50ms increments
;
ToneFreq EQU [EBP+10h]
ToneTime EQU [EBP+0Ch]
_Tone PROC FAR
PUSH EBP ;
MOV EBP,ESP ;
MOV EBX, ToneFreq
MOV ECX, ToneTime
CALL Beep_Work
MOV ESP,EBP ;
POP EBP ;
RETF 8
_Tone ENDP
;================= END OF MODULE ==================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -