📄 md.asm
字号:
mov InputBytes+3, al
xor si, si ; Clear the loop counter
ACP_Loop:
mov al, [InputBytes+si] ; Read a byte from table
cmp al, 0FFh ; If it is FF or E0 (low Byte of I/O
je NoArcNet ; address we will assume that we read
; air.
cmp al, 0E0h
je NoArcNet
and al, 78h ; bits 6 through 3 (0XXX X000) should
; be constant
cmp si, 0h ; Is it first byte read ?
je ACP_First_Pass
cmp ACP_First, al ; is it equal to the first Byte read
jne NoArcNet
inc si ; point to next byte in table
cmp si, 4d ; have we done all four bytes
je ArcNetFound ; Yes, we have found an Arcnet Card
jmp ACP_Loop
ACP_First_Pass:
mov ACP_First, al
inc si ; point to next byte in table
jmp ACP_Loop
ArcNetFound:
mov ax, 1 ; return TRUE
jmp short ACP_End
NoArcNet:
xor ax, ax ; return FALSE
ACP_End:
cEnd ArcnetCardPresent
;*****************************************************************************
;
; LookForSerialMouse
;
;*****************************************************************************
LookForSerialMouse PROC NEAR
mov ax,CRT_Data_Seg ; Get ROM BIOS Data segment.
mov es,ax ; Establish addressability to it.
assume es:nothing
xor di,di ; Assume starting at COM1
serial_try_again:
mov dx,es:[di] ; Get base address of COM port to test.
or dx,dx ; Does this port exist?
jnz serial_test_port ; Yes, go and test it.
cmp di,4 ; If this is COM3 or COM4, use the
jb serial_next_port ; internal addresses for them.
je @F ; If we have COM3, DX=0.
inc dx ; If we have COM4, DX=2.
inc dx ; ...
@@:
mov bx,dx ; BX has index into our table.
cmp bx,2 ; Are we about to look at COM4 ?
jne NotCom4
cCall ArcnetCardPresent
or ax,ax ; if Arcnet Present do not do
jnz No_Serial_Mouse ; COM4 test as the Arcnet Card will
; be Reset.
NotCom4:
mov dx,COM_3_4_Addrs[bx] ; Get base address of the COM port.
serial_test_port:
;
; First, do a quick test to make sure something out there responds like a
; COM port.
;
push dx ; Save base address.
address IIR RXB ; Address Interrupt ID register.
DelayIn al,dx ; AL=contents of Interrupt ID reg.
pop dx ; Restore base address.
test al,0F8h ; Make sure bits 3-7 are all 0!
jnz serial_next_port ; No COM port -> no mouse.
call TestForSerial ; Is a serial mouse attached to port?
cmp ax,NO_MOUSE
jne Serial_Mouse_Found ; Yes!
serial_next_port: ; No serial mouse on this COM port.
add di,2 ; Otherwise, move to the next possible
cmp di,8 ; port and try there.
jb serial_try_again ; Look for COM1 through COM4.
No_Serial_Mouse:
mov ax,NO_MOUSE
Serial_Mouse_Found:
ret
LookForSerialMouse ENDP
;*****************************************************************************
;
; TestForSerial
;
;*****************************************************************************
TestForSerial PROC NEAR
call SaveCOMSetting
call SetupCOMForMouse ; Set up COM port to talk to mouse.
mov cx,SHORTDELAY ; Use a short delay time.
call ResetSerialMouse ; Reset mouse to see if it is there.
cmp ax,NO_MOUSE
jne TFS_Found
mov cx,LONGDELAY ; Maybe the mouse is just slow.
call ResetSerialMouse ; Reset mouse to see if it is there.
cmp ax,NO_MOUSE
jne TFS_Found
call TestForLogitechSerial ; Maybe it's a Logitech Series C
TFS_Found:
push ax ; Save return value
call RestoreCOMSetting
pop ax
ret
TestForSerial ENDP
;*****************************************************************************
;
; SaveCOMSetting
;
; This procedure will save the current state of the COM port given.
;
; ENTRY DX Base address of COM port.
;
; EXIT none
;
; ALTERS AX
;
; CALLS none
;
SaveCOMSetting PROC NEAR
push dx ; Save base I/O address.
address LCR RXB ; Get address of Line Control Register.
DelayIn al,dx ; Get current contents.
mov [LCRSave],al ; Save them.
or al,LC_DLAB ; Set up to access divisor latches.
DelayOut dx,al
address LATMSB LCR ; Get address of high word of divisor
DelayIn al,dx ; latch and save its current contents.
mov [LATMSBSave],al
address LATLSB LATMSB ; Get address of low word of divisor
DelayIn al,dx ; latch and save its current contents.
mov [LATLSBSave],al
address LCR LATLSB ; Get address of Line Control Register
mov al,[LCRSave] ; and disable access to divisor.
and al,NOT LC_DLAB
DelayOut dx,al
address MCR LCR ; Get address of Modem Control Register
DelayIn al,dx ; and save its current contents.
mov [MCRSave],al
address IER MCR ; Get address of Interrupt Enable Reg-
DelayIn al,dx ; ister and save its current contents.
mov [IERSave],al
pop dx ; Restore base I/O address.
ret
SaveCOMSetting ENDP
;*****************************************************************************
;
; RestoreCOMSetting
;
; This procedure will restore the state of the COM port.
;
; ENTRY DX Base address of COM port.
;
; EXIT none
;
; ALTERS AX
;
; CALLS none
;
RestoreCOMSetting PROC NEAR
push dx ; Save base I/O address.
address LCR RXB ; Get address of Line Control Register.
mov al,LC_DLAB ; Set up to access divisor latches.
DelayOut dx,al
address LATMSB LCR ; Get address of high word of divisor
mov al,[LATMSBSave] ; and restore it.
DelayOut dx,al
address LATLSB LATMSB ; Get address of low word of divisor
mov al,[LATLSBSave] ; and restore it.
DelayOut dx,al
address LCR LATLSB ; Get address of Line Control Register
mov al,[LCRSave] ; and restore it, disabling access to
and al,NOT LC_DLAB ; the divisor latches.
DelayOut dx,al
address MCR LCR ; Get addres of Modem Control Register
mov al,[MCRSave] ; and restore it.
DelayOut dx,al
address IER MCR ; Get address of Interrupt Enable Reg-
mov al,[IERSave] ; ister and restore it.
DelayOut dx,al
pop dx ; Restore base I/O address.
ret
RestoreCOMSetting ENDP
;*****************************************************************************
;
; SetupCOMForMouse
;
; This procedure will set up the given COM port so that it can talk to
; a serial mouse.
;
; ENTRY DX Base address of COM port to set up
;
; EXIT COM port set up, all interrupts disabled at COM port
;
; ALTERS AX
;
; CALLS none
;
SetupCOMForMouse PROC NEAR
push dx ; Save base I/O address.
address LCR RXB ; Get address of Line Control Reg.
mov al,LC_DLAB ; Set up to access divisor latches.
DelayOut dx,al
address LATMSB LCR ; Get address of high word of divisor
mov al,HIGH DIV_1200 ; latch and set it with value for
DelayOut dx,al ; 1200 baud.
address LATLSB LATMSB ; Get address of low word of divisor
mov al,LOW DIV_1200 ; latch and set it with value for
DelayOut dx,al ; 1200 baud.
address LCR LATLSB ; Get address of Line Control Reg.
mov al,LC_BITS7 + LC_STOP1 + LC_PNONE
DelayOut dx,al ; Set 7,n,1; disable access to divisor.
address IER LCR ; Get address of Int. Enable Register
xor al,al ; Disable all interrupts at the COM
DelayOut dx,al ; port level.
address LSR IER ; Get address of Line Status Reg.
DelayIn al,dx ; Read it to clear any errors.
pop dx ; Restore base I/O address
ret
SetupCOMForMouse ENDP
;*****************************************************************************
ResetSerialMouse2 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.
;
rsm2_waitloop:
DelayIn al,dx ; Read and ignore any stray data.
call IsWaitOver ; Determine if we've delayed enough.
jnc rsm2_waitloop ; If not, keep waiting.
rsm2_waitover:
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 3 characters that aren't
; an M, we return a failure indication.
;
address LSR MCR ; Get address of Line Status Reg.
mov si,0 ; Read up to 3 chars from port.
rsm2_lookforM:
DelayIn al,dx ; Get current status.
test al,LS_DR ; Is there a character in Receive Buff?
jnz rsm2_gotchar ; Yes! Go and read it.
call IsWaitOver ; No, determine if we've timed out.
jnc rsm2_lookforM ; Haven't timed out; keep looking.
jmp short rsm2_leave ; Timed out. Leave with carry set.
rsm2_gotchar:
address RXB LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Get character that was sent to us.
mov [SerialBuf+si],al
address LSR RXB ; Oh well. Get address of LSR again.
inc si ; Have we read 3 chars yet?
cmp si,10d
jne rsm2_lookforM ; Nope, we'll give him another try.
rsm2_leave:
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -