📄 md.asm
字号:
ret
ResetSerialMouse2 ENDP
;*****************************************************************************
;
; ResetSerialMouse
;
; This procedure will reset a serial mouse on the given COM port and will
; return an indication of whether a mouse responded or not.
;
; The function now also checks for the presence of a 'B' as well as an
; 'M' to determine the presence of a pointing device. Also, if the 'M' is
; followed by a '3' the serial mouse is a Logitech.
;
; Mouse returns M
; Ballpoint returns B
;
; ENTRY DX Base I/O address of COM port to use
; CX Number of msecs to use for delays
;
; EXIT AX Mouse Type
;
;*****************************************************************************
ResetSerialMouse PROC NEAR
push dx ; Save environment.
push si
push di
push es
address IER RXB ; Get address of Interrupt Enable Reg.
DelayIn al,dx ; Get current contents of IER and
push ax ; save them.
push dx ; Save address of IER.
xor al,al ; Disable all interrupts at the
DelayOut dx,al ; COM port level.
address MCR IER ; Get address of Modem Control Reg.
mov al,MC_DTR ; Set DTR active; RTS, OUT1, and OUT2
DelayOut dx,al ; inactive. This powers down mouse.
push cx ; Save amount of time to delay.
call SetupForWait ; Set up BX:CX and ES:DI properly for
assume es:nothing ; upcoming delay loop.
address RXB MCR ; Get address of Receive Buffer.
;
; Now, we wait the specified amount of time, throwing away any stray
; data that we receive. This gives the mouse time to properly reset
; itself.
;
rsm_waitloop:
DelayIn al,dx ; Read and ignore any stray data.
call IsWaitOver ; Determine if we've delayed enough.
jnc rsm_waitloop ; If not, keep waiting.
; Wait is over.
address LSR RXB ; Get address of Line Status Reg.
DelayIn al,dx ; Read it to clear any errors.
address MCR LSR ; Get address of Modem COntrol Reg.
mov al,MC_DTR+MC_RTS+MC_OUT2 ; Set DTR, RTS, and OUT2 active
; OUT1 inactive.
DelayOut dx,al ; This powers up the mouse.
pop cx ; Get amount of time to delay.
call SetupForWait ; Set up BX:CX and ES:DI properly for
assume es:nothing ; the upcoming delay loop.
;
; We give the mouse the specified amount of time to respond by sending
; us an M. If it doesn't, or we get more than 5 characters that aren't
; an M, we return a failure indication.
;
address LSR MCR ; Get address of Line Status Reg.
mov si,5 ; Read up to 5 chars from port.
mov bl,'3' ; '3' will follow 'M' on Logitech.
mov bh,'B' ; 'B' for BALLPOINT
mov ah,'M' ; Get an M. (We avoid doing a cmp al,M
; because the M could be left floating
; due to capacitance.)
rsm_getchar:
DelayIn al,dx ; Get current status.
test al,LS_DR ; Is there a character in Receive Buff?
jnz rsm_gotchar ; Yes! Go and read it.
call IsWaitOver ; No, determine if we've timed out.
jnc rsm_getchar ; Haven't timed out; keep looking.
mov bx,NO_MOUSE
jmp short rsm_leave ; Timed out. Leave with NO_MOUSE.
rsm_gotchar:
address RXB LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Get character that was sent to us.
cmp al,ah ; Is it an M?
jne check_for_b
;
; We received an 'M', now wait for next character to see if it is a '3'.
;
mov cx,1 ; Wait between 55.5 and 111ms for
call SetupForWait ; next character.
address LSR RXB
rsm_waitfor3:
DelayIn al,dx ; Get current status.
test al,LS_DR ; Is there a character in Receive Buff?
jnz rsm_gotchar3 ; Yes! Go and read it.
call IsWaitOver ; No, determine if we've timed out.
jnc rsm_waitfor3 ; Haven't timed out; keep looking.
; Not a Logitech - must be a standard Microsoft compatible serial mouse.
jmp short rsm_notLT
rsm_gotchar3:
address RXB LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Get character that was sent to us.
cmp al,bl ; Is it a 3?
jne rsm_notLT
mov bx,LT_MOUSE ; Yes, we've found a Logitech M+ series,
address LSR RXB ; Choose Line Status Register.
jmp short rsm_leave ; 3 button mouse
rsm_notLT:
mov bx,SERIAL_MOUSE ; We didn't get the '3' after the 'M'
address LSR RXB ; Choose Line Status Register.
jmp short rsm_leave ; We still have a standard serial mouse.
check_for_b:
cmp al,bh ; Is it a B?
jne rsm_next_char
mov bx,MSBPOINT_MOUSE ; We've found a BallPoint Mouse
address LSR RXB ; Choose Line Status Register.
jmp short rsm_leave
rsm_next_char:
address LSR RXB ; Oh well. Get address of LSR again.
dec si ; Have we read 5 chars yet?
jnz rsm_getchar ; Nope, we'll give him another try.
; We've read many characters - No a single 'M' or 'B' in the lot.
mov bx,NO_MOUSE
rsm_leave:
pushf ; Save flags
; Clear out any extra incoming characters
mov cx,2 ; Get amount of time to delay.
call SetupForWait ; Set up BX:CX and ES:DI properly for
assume es:nothing ; the upcoming delay loop.
rsm_ClearAll:
DelayIn al,dx ; Read the LSR to clear any errors.
address RXB LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Read and ignore any stray data.
address LSR RXB ; Get address of Line Status Register.
rsm_ClearPort:
call IsWaitOver ; Determine if we've timed out.
jnc rsm_ClearAll ; Haven't timed out; keep looking.
popf ; Restore flags
pop dx ; Get address of IER.
pop ax ; Get old value of IER.
DelayOut dx,al ; Restore IER.
pop es ; Restore environment.
assume es:nothing
pop di
pop si
pop dx
mov ax,bx ; Set return value.
ret
ResetSerialMouse ENDP
;*****************************************************************************
;
; SetupForWait
;
; This procedure accepts the number of milliseconds that we will want
; to delay for and will set things up for the wait.
;
; ENTRY CX Number of Clock ticks to wait for.
;
; EXIT None.
;
; ALTERS CX
;
; CALLS none
;
SetupForWait PROC NEAR
push ax ; Do your saving !
push es
xor ax,ax
mov es,ax ; Point to 40:6C = 0:46C
mov ax,es:[LW_ClockTickCount] ; Get tick count in AX.
add ax,cx ; [Current + delay] = delay ends.
mov ds:[SemaphoreWord],ax ; Save ending time in Semiphore
pop es ; Restore now !
pop ax
ret
SetupForWait ENDP
;*****************************************************************************
;
; IsWaitOver
;
; This procedure accepts the current time and the ending time and
; return and indication of whether the current time is past
; the ending time.
;
; ENTRY None
;
; EXIT carry clear Current time is not past ending time
; carry set Current time is past ending time
;
; ALTERS none
;
; CALLS none
;
IsWaitOver PROC NEAR
push ax ; Preserve AX
push es ; Preserve ES
push bx
sti ; Hosebag BIOS bugs can't get me.
xor ax,ax
mov es,ax ; Point to 40:6C = 0:46C
mov ax,es:[LW_ClockTickCount] ; Get tick count in AX.
sti
mov bx,ds:[SemaphoreWord]
cmp bx,ax ; This will set carry accordingly.
pop bx
pop es ; Restore ES
pop ax ; Restore AX
ret
IsWaitOver ENDP
;*****************************************************************************
;
; LookForPS2Mouse
;
;*****************************************************************************
LookForPS2Mouse PROC NEAR
;
; Lets make the Int 15h, C201h BIOS call to reset the pointing device.
; If the call is supported, and returns success then we know that we have
; a PS/2 mouse.
;
stc
mov bx,0ffffh ; Initialize, see later if it changes.
mov ax,0c201h
int 15h ; Reset Pointing device.
jc No_PS2_Mouse ; Function call unsuccesful.
cmp bh,0ffh ; BH should be device ID, it should not
je No_PS2_Mouse ; be what we initialized it to (FF).
;
; The following sequence of Int 15h calls will determine if a Logitech
; PS/2 mouse is present. This information was obtained from Logitech.
;
mov ax,0C203h ; Set resolution to 1 cnt/mm
mov bh,0h
int 15h
jc PS2_Mouse
mov ax,0C206h ; Set scaling to 1:1
mov bh,1h
int 15h
jc PS2_Mouse
mov ax,0C206h ; Set scaling to 1:1
mov bh,1h
int 15h
jc PS2_Mouse
mov ax,0C206h ; Set scaling to 1:1
mov bh,1h
int 15h
jc PS2_Mouse
mov ax,0C206h ; Get status
mov bh,0h
int 15h
jc PS2_Mouse
or cl,cl ; Is resolution 1 cnt/mm?
jz PS2_Mouse ; Yes, then not a Logitech.
;
; If cl is not zero (i.e. 1 cnt/mm) then it is the number of buttons
; and we've found a Logitech 3-button PS/2 mouse
;
LT_PS2_Mouse:
mov ax,LT_PS2MOUSE
jmp short PS2MouseFound
PS2_Mouse:
mov ax,MSPS2_MOUSE
jmp short PS2MouseFound
No_PS2_Mouse:
mov ax,NO_MOUSE
PS2MouseFound:
ret
LookForPS2Mouse ENDP
;*****************************************************************************
;
; TestForPS2
;
; This procedure will attempt to find a PS/2 mouse in the system and
; return the results of this search.
;
; ENTRY fSingle8259 Non-zero if we have a single 8259A
;
; EXIT Carry clear A PS/2 style Microsoft mouse was found
; Mouse interrupts disabled at 8042.
; Mouse disabled at 8042.
; Mouse is reset.
;
; Carry set A PS/2 style Microsoft mouse was not found
;
; ALTERS AX, CX
;
; CALLS CheckForAuxSupport, MouseIntOff, CheckForMSMouse
;
TestForPS2 PROC NEAR
call CheckForLogitechPS2 ; Check for Logitech PS/2 Mouse.
; jmp tfp_leave
jc tfp_CheckForMS ; Check for MS/IBM mouse if not.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -