📄 md.asm
字号:
; Interrupts have to be disabled from the time we find the buffers
; empty and write the command byte until the time that the data that
; the command produces is read. Therefore, we will disable and enable
; interrupts each time through the loop to ensure that interrupts will
; not be disabled for too long a time.
;
wcr_loop:
cli ; Disable ints before reading status.
in al,STATUS_8042 ; Get 8042's current status.
test al,I_FULL + O_FULL ; Are input and output buffers empty?
jz wcr_success ; Yes! Go write the command byte.
sti ; Nope. Reenable ints and keep trying
loop wcr_loop ; the desired number of times.
dec ah
jnz wcr_loop
;
; Interrupts are enabled.
;
pop ax ; Restore registers.
pop cx
stc ; Show that we failed.
ret
;
; Interrupts are disabled and carry is clear (from TEST instruction).
;
wcr_success:
pop ax ; Get saved command byte.
out CONTROL_8042,al ; Write command byte out.
pop cx ; Restore register.
ret ; Carry is already clear.
WriteControlRegister ENDP
;*****************************************************************************
;
; MouseIntOff
;
; This procedure will disable the mouse and mouse interrupts at the 8042
; level.
;
; Note that it assumes that the keyboard is enabled upon entry to this
; procedure.
;
; ENTRY none
;
; EXIT Carry clear Mouse and mouse interrupts are disabled.
;
; Carry set Some error occurred.
;
; ALTERS AL
;
; CALLS WriteControlRegister, Read8042CommandByte, Write8042CommandByte
;
MouseIntOff PROC NEAR
mov al,CMD8042_DISABLE_AUX ; Disable the aux device.
call WriteControlRegister
jc mioff_leave ; Leave if error.
mov al,CMD8042_DISABLE_KBD ; Disable the keyboard.
call WriteControlRegister
jc mioff_leave ; Leave if error.
; INTERRUPTS DISABLED!!
call Read8042CommandByte ; Get the current command byte.
; INTERRUPTS ENABLED!!
jc mioff_cleanup ; Leave if error.
and al,not AUX_INT_ENABLE ; Disable mouse interrupts.
call Write8042CommandByte ; Write out altered command byte.
mioff_cleanup:
pushf ; Save return status.
mioff_reenable_kbd:
mov al,CMD8042_ENABLE_KBD ; Reenable the keyboard.
call WriteControlRegister ; If an error occurs, keep trying to
jc mioff_reenable_kbd ; reenable it.
; INTERRUPTS DISABLED!!
popf ; Restore return status.
; INTERRUPTS ENABLED!!
mioff_leave: ; Carry set/clear appropriately.
ret
MouseIntOff ENDP
;*****************************************************************************
;
; CheckForMSMouse
;
; This procedure checks to see if a Microsoft mouse or IBM mouse
; is attached to the auxiliary interface of the 8042.
;
; ENTRY Mouse interrupts disabled.
;
; EXIT Carry clear A PS/2 style mouse was found
; AX MS, IBM , Logitech
; Mouse interface disabled.
; Mouse is reset.
;
; Carry set PS/2 mouse was not found
;
; ALTERS AX, CX
;
; CALLS SendToMouse, SendToMouseAndTestData, GetMouseData
; WriteControlRegister, ResetPS2Mouse
;
CheckForMSMouse PROC NEAR
mov al,CMD8042_ENABLE_AUX ; Make sure aux interface is enabled
call WriteControlRegister ; so we can talk to the mouse.
jc cfmm_leave ; Leave if we can't enable it.
mov cx,5 ; Only 5 tries at this!
cfmm_retry:
call ResetPS2Mouse ; Try to reset the mouse.
jc cfmm_failure ; Try again if we failed.
; call CheckForLogitechPS2 ; Check for Logitech PS/2 Mouse.
; jc noLogiTech ; Logitech mouse not found
; mov ax,LT_PS2MOUSE
; jmp short cfmm_cleanup ; mouse type determined
;
; The following sequence of commands checks to see if the mouse that we
; just succeeded in resetting is a Microsoft mouse.
;
; Note that we have to check to determine if the mouse responds with either
; MCMD_ACK or with what was sent because of the differences between
; the 200ppi and 400ppi PS/2 style mouse. The 200ppi mouse responds
; with MCMD_ACKs, while the 400ppi mouse responds with whatever was
; sent to it.
;
noLogiTech:
mov al,MCMD_ECHO ; Send Select Echo Command.
call SendToMouse
jc cfmm_failure ; Try again if we failed.
mov ax,'GG' ; Next "command" in signature.
call SendToMouseAndTestData
jc cfmm_failure ; Try again if we failed.
mov ax,'DD' ; Next "command" in signature.
call SendToMouseAndTestData
jc cfmm_failure ; Try again if we failed.
mov ax,'GG' ; Next "command" in signature.
call SendToMouseAndTestData
jc cfmm_failure ; Try again if we failed.
mov al,MCMD_KILL_ECHO ; Leave Echo mode.
call SendToMouse
jnc cfmm_signature_sent ; If successful, have sent signature.
cfmm_failure:
loop cfmm_retry ; Try again.
;
; at this point there is no mouse on AUX port at all
;
stc ; carry set for no mouse at all.
jmp short cfmm_cleanup
;
; At this point, we have sent the signature string to the mouse.
; If we have a Microsoft mouse out there, it will respond to a
; Microsoft extended command. If there is no response we have an
; IBM mouse.
;
; Note that we have to test to see if the mouse responds with either a
; MCMD_ACK or a MCMD_RESEND. This is because a 200ppi mouse responds
; with MCMD_ACK, while a 400ppi mouse responds with MCMD_RESEND.
;
cfmm_signature_sent:
mov ax,(MCMD_RESEND SHL 8) + MCMD_MS_VERS ; Set command and return.
call SendToMouseAndTestData
jc cfmm_cleanup ; Leave if unable to send command.
; IBM Mouse fails on this call because it will not send data in
; response to the above Microsoft version command
call GetMouseData ; Read current version number.
jc noVerNumber ; must have IBM mouse
mov ax,MSPS2_MOUSE ; return MS PS2 Mouse.
jmp short cfmm_cleanup ; mouse type determined
noVerNumber:
mov ax,IBMPS2_MOUSE ; ax = IBM PS/2 mouse found.
clc ; clear carry to show mouse presence
;
; Disable the auxiliary interface before leaving.
;
cfmm_cleanup:
; carry set here means no PS/2 mouse
pushf ; Save state of carry.
push ax ; Save version number.
cfmm_disable_aux:
mov al,CMD8042_DISABLE_AUX ; Disable the auxiliary interface.
call WriteControlRegister
jc cfmm_disable_aux ; Make sure aux interface is disabled.
pop ax ; Restore version number.
popf ; Restore carry.
;
; We have found a Microsoft mouse. The version number is in AL.
;
cfmm_leave:
; carry clear means mouse present, al indicates its type
; carry set upon return means no mouse found
ret
CheckForMSMouse ENDP
;*****************************************************************************
;
; SendToMouse
;
; This procedure sends a byte of command or data to the mouse.
; Because it appears that the mouse always acknowledges the
; sending of this byte, this is also tested for here.
;
; ENTRY AL Byte of command/data to send
;
; EXIT Carry clear Command/data byte sent, mouse sent MCMD_ACK
; Interrupts enabled.
;
; Carry set Command/data byte not sent, or mouse never
; sent back MCMD_ACK
; Interrupts enabled.
;
; ALTERS AX
;
; CALLS SendToMouseAndTestData
;
SendToMouse PROC NEAR
mov ah,MCMD_ACK ; We will only check for MCMD_ACK being
; returned from mouse.
IF2
.ERRNZ ($ - SendToMouseAndTestData) ; Because we fall into it.
ENDIF
SendToMouse ENDP
;*****************************************************************************
;
; SendToMouseAndTestData
;
; This procedure sends a byte of command or data to the mouse.
; It will then test to ensure that the mouse either sent
; back what the caller is expecting or MCMD_ACK.
;
; ENTRY AL Byte of command/data to send
; AH Byte of data the mouse is to return
;
; EXIT Carry clear Command/data byte sent, mouse responded
; correctly
; Interrupts enabled.
;
; Carry set Command/data byte not sent, or mouse never
; responded correctly
; Interrupts enabled.
;
; ALTERS AX
;
; CALLS WriteControlRegister, WriteInputBuffer, CheckMouseData
;
SendToMouseAndTestData PROC NEAR
push ax ; Save command/data byte.
mov al,CMD8042_WRITE_AUX ; Tell 8042 we want to send a byte to
call WriteControlRegister ; the auxiliary device.
pop ax ; Get saved command/data byte.
jc stmatd_leave ; Leave if error.
; INTERRUPTS DISABLED!
call WriteInputBuffer ; Send data/command to aux dev.
; INTERRUPTS ENABLED!
jc SendToMouseAndTestData ; Retry if unsuccessful.
mov al,MCMD_ACK ; Make sure mouse acknowledges that
; command/data byte was sent.
if2 ; Pass 2 of the assembler
.errnz ($ - CheckMouseData) ; Because we drop into it
endif ; Pass 2 of the assembler
SendToMouseAndTestData ENDP
;*****************************************************************************
;
; CheckMouseData
;
; This procedure checks that the next byte that the mouse sends us is
; what we were expecting it to send.
;
; Note that this procedure cannot be called with interrupts disabled.
; If it is, interrupts will potentially be left off for a
; long time.
;
; ENTRY AL One possible data byte the mouse can send
; AH A second valid data byte the mouse can send
; Interrupts enabled
;
; EXIT Carry clear Mouse sent data we were expecting
;
; Carry set Mouse didn't send data, or sent something we
; weren't expecting.
;
; ALTERS none
;
; CALLS GetMouseData
;
CheckMouseData PROC NEAR
push bp ; Save BP.
push ax ; Save data bytes to test for.
mov bp,sp ; Address data bytes on stack.
call GetMouseData ; Get next byte of data from mouse.
jc cmd_leave ; Leave if error.
cmp al,ah ; Is it what we were expecting?
je cmd_leave ; Yes! Leave with carry clear.
cmp al,byte ptr [bp] ; Is it other byte we were expecting?
je cmd_leave ; Yes! Leave with carry clear.
stc ; Nope, show error and leave.
cmd_leave: ; Carry set/clear appropriately.
pop ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -