⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbdcode.inc

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 INC
📖 第 1 页 / 共 2 页
字号:
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 + -