home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
DEV
/
MOUSE
/
SERIAL.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-04-14
|
25KB
|
778 lines
;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT Copyright (C) 1995 IBM Corporation
;
; The following IBM OS/2 WARP source code is provided to you solely for
; the purpose of assisting you in your development of OS/2 WARP device
; drivers. You may use this code in accordance with the IBM License
; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
; Copyright statement may not be removed.;
;*****************************************************************************/
;/*************************************************************************
;*
;* SOURCE FILE NAME = SERIAL.ASM
;*
;* DESCRIPTIVE NAME = Serial Mouse specific code
;*
;*
;* VERSION V2.0
;*
;* DATE 07/16/91
;*
;* DESCRIPTION This file contains the code specific to serial
;* mice.
;*
;* The list of the currently known serial pointing
;* devices that are detectible are listed below;
;*
;* MS Serial Mouse
;* MS BallPoint Mouse
;* MousePen by Appoint
;*
;* Other serial known serial pointing devices are
;* listed below;
;*
;* NOTES Autodetection not implemented for these
;*
;* PC Mouse System Mouse
;* Visi On Mouse
;* Logitech Serial Mouse
;* Kensignton Serial Mouse
;*
;* FUNCTIONS
;*
;*
;*
;*
;* STRUCTURES NONE
;*
;* EXTERNAL REFERENCES
;*
;* NONE
;*
;* EXTERNAL FUNCTIONS
;*
;* NONE
;*
;* CHANGE ACTIVITY =
;* DATE FLAG APAR CHANGE DESCRIPTION
;* -------- ---------- ----- --------------------------------------
;* mm/dd/yy @Vr.mpppxx xxxxx xxxxxxx
;* 04/04/93 53232 Add support for Logitech middle button
;**************************************************************************
.xlist
include mouse.inc
; include infoseg.inc
.list
.386p
;*
;* External Mouse Module Data References
;*
extrn DeviceData : byte
extrn actvirqbit : word
extrn gMEvent : byte
extrn LATLSBSave : byte
extrn LATMSBSave : byte
extrn LCRSave : byte
extrn MCRSave : byte
extrn IERSave : byte
extrn ABIOS_Mch : byte
extrn oddpts : word
extrn Int_Packet : word
extrn PortBase : word
extrn DevStatus : word
extrn ByteCount : word
extrn GDT_Seg : word
extrn Device_Help : dword
extrn SetupForWait : near
extrn IsWaitOver : near
extrn GIDC_Entry : far
extrn _RM_MSE_AllocPorts :far
extrn _RM_MSE_DeallocPorts :far
CSEG SEGMENT WORD PUBLIC USE16 'CODE'
ASSUME CS:CSEG, SS:nothing, ES:nothing, DS:nothing
;*
;* Module Procs made Public for other Mouse Modules
;*
public CheckforMSSDevice
public TestforMSSDevice
public SaveCOMSetting
public RestoreCOMSetting
public SetupCOMForMouse
public ResetSerialMouse
public InitComPort
;/***************************************************************************
;*
;* FUNCTION NAME = CheckforMSSDevice
;*
;* DESCRIPTION = This procedure will attempt to find a serial mouse
;* connected to the serial port at the given base I/O address
;*
;*
;* INPUT = NONE
;*
;* OUTPUT = carry clear A serial mouse was found
;* AL IRQ # for the mouse
;* BL Bit mask giving interrupt level
;* DX Base address of COM port
;* COM port is set up for mouse and mouse has been reset.
;*
;* carry set No mouse was found
;*
;* ALTERS AX, BX, CX
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR = NONE
;*
;* CALLS = TestforMSSDevice CONTEXT = INIT.
;**************************************************************************/
CheckforMSSDevice proc near
push es
mov cx, SHORTDELAY
cfmd_1:
mov DeviceData.ComNum, 0
.repeat
push 40h
pop es
xor bh, bh
mov bl, DeviceData.ComNum
shl bx, 1
mov dx, word ptr es:[bx]
mov PortBase, dx
inc DeviceData.ComNum
.if <NONZERO dx>
pusha
push dx
call _RM_MSE_AllocPorts
or ax, ax
pop dx
popa
jnz PortCOMClaimed
call TestforMSSDevice
jnc cmd_exit
pusha
call _RM_MSE_DeallocPorts
popa
PortCOMClaimed:
.endif
.until <DeviceData.ComNum eq 4>
;*
;* No response on normal BIOS com port addresses... now try others...
;*
mov si,offset oddpts
mov DeviceData.ComNum,255 ;255=non-standard port address
mov dx, word ptr [si]
.repeat
mov PortBase, dx
.if <NONZERO dx>
pusha
push dx
call _RM_MSE_AllocPorts
or ax, ax
pop dx
popa
jnz short PortMSSClaimed
push si
call TestforMSSDevice
pop si
jnc cmd_exit
pusha
call _RM_MSE_DeallocPorts
popa
PortMSSClaimed:
.endif
add si,2
mov dx, word ptr [si]
.until <dx eq 0>
.if <cx eq SHORTDELAY>
mov cx, LONGDELAY
jmp cfmd_1
.endif
mov DeviceData.ComNum, 0
stc
cmd_exit:
pop es
ret
CheckforMSSDevice endp
;/***************************************************************************
;*
;* FUNCTION NAME = TestforMSSDevice
;*
;* DESCRIPTION = This procedure will attempt to find a serial mouse
;* connected to the serial port at the given base I/O address.
;*
;*
;*
;*
;*
;*
;*
;*
;* INPUT = DX Base address of COM port to be tested
;* CX Delay time between power up and power down
;*
;* OUTPUT = carry clear A serial mouse was found
;* AL IRQ # for the mouse
;* BL Bit mask giving interrupt level
;* DX Base address of COM port
;* COM port is set up for mouse and mouse has been reset.
;*
;* carry set No mouse was found
;*
;* ALTERS AX, BX, CX
;*
;* RETURN-NORMAL = NONE.
;*
;*
;* RETURN-ERROR = NONE.
;*
;* CALLS = SaveCOMSetting, SetupCOMForMouse, RestoreCOMSetting
;* ResetSerialMouse
;**************************************************************************/
TestforMSSDevice proc near
push dx
address IIR FROM RXB
in al,dx ; AL=contents of Interrupt ID reg.
pop dx
.if <bit al z 0f8h> ; Make sure bits 3-7 are all 0!
call SaveCOMSetting ; Save the current setting
call SetupCOMForMouse ; Set up COM port to talk to mouse.
call ResetSerialMouse ; Reset mouse to see if it is there.
.if <c>
call RestoreCOMSetting ; No Mouse! Restore COM port.
.endif
.else
stc
.endif
ret
TestforMSSDevice endp
;/***************************************************************************
;*
;* FUNCTION NAME = SaveCOMSetting
;*
;* DESCRIPTION = This procedure will save the current state of the
;* COM port given.
;*
;* INPUT = DX Base address of COM port.
;*
;* OUTPUT = NONE. ALTERS AX.
;*
;*
;* RETURN-NORMAL = NONE.
;*
;*
;* RETURN-ERROR = NONE.
;*
;*
;**************************************************************************/
SaveCOMSetting proc near
push dx ; Save base I/O address.
address LCR FROM 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 FROM LCR ; Get address of high word of divisor
DelayIn al,dx ; latch and save its current contents.
mov LATMSBSave, al
address LATLSB FROM LATMSB ; Get address of low word of divisor
DelayIn al,dx ; latch and save its current contents.
mov LATLSBSave, al
address LCR FROM 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 FROM LCR ; Get address of Modem Control Register
DelayIn al,dx ; and save its current contents.
mov MCRSave, al
address IER FROM 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
;/***************************************************************************
;*
;* FUNCTION NAME = RestoreCOMSetting
;*
;* DESCRIPTION = This procedure will restore the state of the COM port
;*
;* INPUT = DX Base address of COM port.
;*
;* OUTPUT = NONE. ALTERS AX.
;*
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR = NONE
;*
;*
;**************************************************************************/
RestoreCOMSetting proc near
push dx ; Save base I/O address.
address LCR FROM RXB ; Get address of Line Control Register.
mov al,LC_DLAB ; Set up to access divisor latches.
DelayOut dx,al
address LATMSB FROM LCR ; Get address of high word of divisor
mov al, LATMSBSave ; and restore it.
DelayOut dx,al
address LATLSB FROM LATMSB ; Get address of low word of divisor
mov al, LATLSBSave ; and restore it.
DelayOut dx,al
address LCR FROM 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 FROM LCR ; Get addres of Modem Control Register
mov al, MCRSave ; and restore it.
DelayOut dx,al
address IER FROM 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
;/***************************************************************************
;*
;* FUNCTION NAME = SetupCOMForMouse
;*
;* DESCRIPTION = This procedure will set up the given COM port so that
;* it can talk to a serial mouse.
;*
;* INPUT = DX Base address of COM port to set up
;*
;* OUTPUT = COM port set up, all interrupts disabled at COM port
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR = NONE
;*
;*
;**************************************************************************/
SetupCOMForMouse proc near
push dx ; Save base I/O address.
address LCR FROM RXB ; Get address of Line Control Reg.
mov al, LC_DLAB ; Set up to access divisor latches.
DelayOut dx,al
address LATMSB FROM 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 FROM 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 FROM LATLSB ; Get address of Line Control Reg.
mov al, LC_BITS7+LC_STOP1+LC_PNONE ;7 data bits, 1 stop bit, no parity
DelayOut dx,al ; Set up data format.
address IER FROM LCR ; Get address of Int. Enable Register
xor al, al ; Disable all interrupts at the COM
DelayOut dx,al ; port level.
address LSR FROM 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
;/***************************************************************************
;*
;* FUNCTION NAME = ResetSerialMouse
;*
;* DESCRIPTION = This procedure will reset a serial mouse on the given COM
;* port and will return an indication of whether a mouse
;* responded or not
;*
;* INPUT = ENTRY DX Base I/O address of COM port to use
;* CX Number of msecs to use for delays
;*
;* OUTPUT = EXIT carry clear Mouse responded and is now reset
;*
;* carry set No mouse responded!
;*
;* NOTES = This routine assumes that all interrupts at the COM port
;* have been disabled
;*
;* RETURN-NORMAL = NONE
;*
;*
;* RETURN-ERROR = NONE
;*
;*
;**************************************************************************/
ResetSerialMouse proc near
push dx
push cx
address MCR FROM RXB ; 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 ; Setup BX:CX & ES:DI for delay
;*
;* Now, we wait the specified amount of time, throwing away any stray data
;* data that we receive. This gives the mouse time to properly reset itself.
;*
address RXB FROM MCR ; Get address of Receive Buffer.
.repeat
DelayIn al,dx ; Read and ignore any stray data.
call IsWaitOver ; Determine if we've delayed enough.
.until <c>
address LSR FROM RXB ; Get address of Line Status Reg.
DelayIn al,dx ; Read it to clear any errors.
address MCR FROM LSR ; Get address of Modem Control Reg.
mov al, MC_DTR+MC_RTS+MC_OUT2 ; DTR,RTS,OUT2 active. OUT1 inactive.
DelayOut dx,al ; This powers up the mouse.
pop cx ; Get amount of time to delay.
call SetupForWait ; Setup BX:CX & ES:DI for delay
;*
;* We give the mouse the specified amount of time to respond by sending us
;* an M or a B for a Ballpoint device. If it doesn't, or we get more than
;* 3 characters that aren't an M or a B, we return a failure indication.
;*
address LSR FROM MCR ; Get address of Line Status Reg.
mov si,3 ; Read up to 3 chars from port.
rsm_lookforMorB:
.repeat
DelayIn al,dx ; Get current status.
test al,LS_DR ; Is there a character in Receive Buff?
jnz short rsm_gotchar ; Yes! Go and read it.
call IsWaitOver ; No, determine if we've timed out.
.until <c> ; Haven't timed out; keep looking.
jmp short rsm_leave ; Timed out. Leave with carry set.
rsm_gotchar:
address RXB FROM LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Get character that was sent to us.
cmp al, 'M' ; Is it an M?
je short rsm_lookfor3but ; Yes! The mouse must be out there. ;
cmp al, 'B' ; Was it a B?
je short rsm_leave ; Yes, we have a ballpoint.
address LSR FROM RXB ; Oh well. Get address of LSR again.
dec si ; Have we read 3 chars yet?
jnz short rsm_lookforMorB ; Nope, we'll give him another try.
stc ; Didn't find an M. Indicate failure.
jmp short rsm_leave ; No mouse, let exit.
rsm_lookfor3but: ;
mov cx,SHORTDELAY ; Get amount of time to delay.
call SetupForWait ; Setup BX:CX & ES:DI for delay
address LSR FROM RXB ; Get address of Line Status Reg.
.repeat
DelayIn al,dx ; Get current status.
test al,LS_DR ; Is there a character in Receive Buff?
jnz short rsm_tst3but ; Yes! Go and read it.
call IsWaitOver ; No, determine if we've timed out.
.until <c> ; Haven't timed out; keep looking.
clc ; clear carry since we found MS mouse
jmp short rsm_leave ; Timed out. Leave now
rsm_tst3but:
address RXB FROM LSR ; Get address of Receive Buffer.
DelayIn al,dx ; Get character that was sent to us.
.if <al eq '3'> ; Is three button mouse attached?
mov DeviceData.NumButt, 3 ; Indicate three button mouse
.endif
clc ; clear carry since we found MS mouse
;
rsm_leave:
pop cx
pop dx
ret
ResetSerialMouse endp
; Interrupt Entry Points for MSS_Find_Int
intjtb proc far
COPT1 equ $
tint00: call minint
COPT2 equ $
tint01: call minint
tint02: call minint
tint03: call minint
tint04: call minint
tint05: call minint
tint06: call minint
tint07: call minint
tint08: call minint
tint09: call minint
tint10: call minint
tint11: call minint
tint12: call minint
tint13: call minint
tint14: call minint
tint15: call minint
intjtb endp
minint proc near
pop ax ;ax=ret offset for IRQ determination
mov bx,COPT2-COPT1
sub ax,offset tint01
idiv bl
xor ah,ah
mov si,ax
inc actvirqbit[si]
stc ;don't claim the interrupt
db 0cbh ; far RET
minint endp
;/***************************************************************************
;*
;* FUNCTION NAME = MSS_Find_Int
;*
;* DESCRIPTION = Find out what IRQ is selected for 8250
;*
;* INPUT = BX = base port of chip
;* DS = our DS
;*
;* OUTPUT = NONE
;*
;*
;* RETURN-NORMAL = NC - BH=IRQ level
;* AL=8259 mask byte
;* AH=2nd 8259 mask byte
;* RETURN-ERROR = C - multiple or no interrupt level found
;*
;**************************************************************************/
public MSS_Find_Int
MSS_Find_Int proc near
push bx
mov ax,offset tint01
mov bx,1
mov dx,01bh ; non-shared & SetIRQ
finnx: call Device_Help ; invoke Dev Help
add ax,COPT2-COPT1
inc bx
cmp bx,16
jne finnx
pop bx ; get base port back
mov dx,bx
add dx,3
in al,dx
and al,7Fh ;DLAB=0
out dx,al
sub dx,2
mov al,2
out dx,al ; turn on THRE interrupts
add dx,3
mov al,12 ; turn on Out1 & Out2 for IRQs
; RTS & DTR are off so that mouse is
; dead; this prevents interrupts from
; stuff other than what we're doing.
out dx,al
jmp $+2
jmp $+2
mov dx,bx ; get back to THR
out dx,al
jmp $+2
jmp $+2
jmp $+2
jmp $+2
jmp $+2
jmp $+2
out dx,al ; fill THR after THR has gone to TSR
mov cx,0FFFFh
spinr: loop spinr
add dx,1 ; get to IER
mov al,0
out dx,al ; turn off THRE interrupts
add dx,3
mov al,0Fh ; turn on OUT2, OUT1, RTS & DTR
out dx,al
jmp $+2
jmp $+2
mov bx,1
mov dx,01ch ; release the IRQ
finn2: call Device_Help ; invoke Dev Help
inc bx
cmp bx,16
jne finn2
mov si,offset actvirqbit ;get bitmap of triggered ints
;*
;* SI now has the starting offset to an array of interrupt counts... we want
;* to find which one had exactly 2 INTs (since we generated 2).
;*
xor bx,bx
fsornx: cmp byte ptr [si],2
jz fndint
inc bx
inc si
cmp bx,16
jne short fsornx
multint:stc ;opps! multiple or no interrupts!
ret
fndint: mov ax,1
push cx
mov cl,bl
mov bh,bl
shl ax,cl
pop cx
clc
ret
MSS_Find_Int endp
;/***************************************************************************
;*
;* FUNCTION NAME = InitComPort
;*
;* DESCRIPTION = Enable mouse IRQ level at the 8259.
;*
;*
;* INPUT = AX = function code
;* DS = our DS
;* ES = callers DS
;*
;* OUTPUT = none (Stack is clean on return. AX, CX, DX, SI, and DI
;* registers are changed.)
;*
;* RETURN-NORMAL = Always, mouse IRQ enabled.
;*
;*
;* RETURN-ERROR = n/a
;*
;*
;**************************************************************************/
InitComPort proc near
cli
mov dx, PortBase ; get base port
;*
;* Set Data avail in INT Enable Reg
;*
address IER FROM RXB
mov al, IERMASK
delayout dx, al
;*
;* Read stray data
;*
address RXB FROM IER
xor cx, cx ; Loop for a while
joesloop:
delayin al, dx
loop joesloop
sti ; allow ints now
;*
;* We must zero out the BIOS Date Area for the Communications Line
;* Port Base address.
;* 40:0 for Com Port 1
;* 40:2 for Com Port 2
;* 40:4 for Com Port 3
;* 40:6 for Com Port 4
;*
mov bl, DeviceData.ComNum
cmp bl, 255 ; nonstandard port address?
je inidun
dec bl
xor bh, bh
shl bx, 1
push 40h
pop es
mov word ptr es:[bx], 0
.if <ABIOS_Mch eq TRUE>
mov al, 06h ; Async Device ID
mov bl, DeviceData.ComNum ; Get 1st LID
xor dh, dh ; reserved, must be 0
mov dl, DevHlp_GetLIDEntry ; ABIOS function
call Device_Help ; invoke Dev Help
.endif
inidun: ret
InitComPort endp
CSEG ENDS
END