This is an interrupt handler (one of more than two dozen) extracted from RODENT.SYS which is a shareware mouse driver written for OS/2 versions 2.0 and later. RODENT.SYS contains 15,000 lines of assembly with only two bugs found since it was released in July of 1993. Other than minor formatting for HTML presentation, this code is exactly as found in the original source code.
title Copyright (c) 1993..1996 by Michael Lee Finney. All rights reserved.
;
; Interface:
;
; InterruptHandler()
;
; Description:
;
; The mouse interrupt handler entry points follow. The actual interrupt
; handler used depends on the communication protocol. These handlers will
; eat mouse packets which don't change from the previous packet -- it is
; more efficient to ignore them here than at a higher level in the operating
; system.
;
; Exit:
;
; Carry clear.
;
; Side effects:
;
; Stack is clean, registers ax, bx, cx, dx, si, di and es are altered.
; These routines are communication protocol specific.
;
; Notes:
;
; The device dependent packet is converted into either a relative device
; independent packet or an absolute device independent packet. The relative
; packet has the format...
;
; Word 0: Event status
; 0000 0000 0000 0000 - no button pressed and no motion
; 0000 0000 0000 0001 - motion only
; 0000 0000 0... .010 - button 1 pressed and mouse moved
; 0000 0000 0..0 1..0 - button 2 pressed and mouse moved
; 0000 0000 001. ...0 - button 3 pressed and mouse moved
; 0000 0000 0... .100 - button 1 pressed and mouse not moved
; 0000 0000 0..1 0..0 - button 2 pressed and mouse not moved
; 0000 0000 010. ...0 - button 3 pressed and mouse not moved
;
; Word 1: Column movement (delta-X) in mickeys (signed 2's complement)
;
; Word 2: Row movement (delta-Y) in mickeys (signed 2's complement)
;
; The absolute packet has the format...
;
; Word 0: Event status
; 0000 0000 0000 0000 - no button pressed and no motion
; 0000 0000 0000 0001 - motion only
; 0000 0000 0... .010 - button 1 pressed and mouse moved
; 0000 0000 0..0 1..0 - button 2 pressed and mouse moved
; 0000 0000 001. ...0 - button 3 pressed and mouse moved
; 0000 0000 0... .100 - button 1 pressed and mouse not moved
; 0000 0000 0..1 0..0 - button 2 pressed and mouse not moved
; 0000 0000 010. ...0 - button 3 pressed and mouse not moved
;
; Word 1: Row position, top = 0
;
; Word 2: Column position, left = 0
;
; Word 3: Number of row positions (maximum row position)
;
; Word 4: Number of column positions (maximum column position)
;
dseg segment
lastEvnt dw 00000h
accelrat dw NoAccelerate
intrMap db 32 dup(0)
dseg ends
;
; Interface:
;
; InterruptHandlerMP()
;
; Description:
;
; Handles interrupts for the MP communication protocol. Packet bytes are
; accumulated until the packet is complete. The packet is translated to
; common relative event format and then sent to the device independent event
; handler. The interrupt handler is not exited until no more characters are
; available from the mouse. In conjunction with FIFO buffering this can
; reduce the system overhead required for the mouse -- especially for higher
; reporting rates.
;
; Notes:
;
; The MP communication protocol returns either a 3 or 4 byte packet, and
; has the format...
;
; Byte 0: x... .... Undefined
; .1.. .... Sync byte, marks first byte of packet
; ..L. .... Left button (button 1) status, 1 = depressed
; ...R .... Right button (button 2) status, 1 = depressed
; .... YY.. High order bits of Delta-Y (signed 2's complement)
; .... ..XX High order bits of Delta-X (signed 2's complement)
;
; Byte 1: x... .... Undefined
; .0.. .... 0 = Non-Sync byte
; ..XX XXXX Low order bits of Delta-X (column)
;
; Byte 2: x... .... Undefined
; .0.. .... 0 = Non-Sync byte
; ..YY YYYY Low order bits of Delta-Y (row)
;
; Byte 3: x... .... Undefined
; .0.. .... 0 = Non-Sync byte
; ..M. .... Middle button (button 3) status, 1 = depressed
; ...T TTTT Device type, 00000 = mouse
;
; The fourth byte is only returned for three-button serial mice. Further,
; the fourth byte is only returned when the middle button is pressed or
; released, so either a three button or four button packet must be handled.
;
cseg segment
align 4
InterruptHandlerMP proc far
cli ;
mov dx,mskPrt8259 ; Disable interrupts at 8259 to
in al,dx ; avoid reentrant interrupts
or al,disable8259 ; after eoi has been issued
out dx,al ;
sti ;
mov al,deviceData.irq ;
mov dl,DevHlp_Eoi ; Call DeviceHelp to issue eoi
call deviceHelp ;
intrMP1: mov dx,deviceData.portAddr ;
add dx,lsr ;
in al,dx ; Read line status register both to
MyIoDelay ; clear errors and check for data,
test al,lsrData ; if no more data then exit
jz intrMP2 ;
add dx,rxb-lsr ; Read data byte from serial port
in al,dx ;
and al,7fh ;
test al,sync7Bit ;
jz intrMP3 ; Accumulate packet bytes in
mov byteCnt,1 ; mEvent. Incomplete packets
mov mEvent[0],al ; and spurious data will be
jmp short intrMP1 ; discarded.
intrMP2: cli ;
mov dx,mskPrt8259 ;
in al,dx ; Enable mouse interrupts at 8259
and al,enable8259 ;
out dx,al ;
clc ; Indicate our interrupt
ret ;
intrMP3: mov di,byteCnt ; Packets may be either three or
or di,di ; four bytes in length.
jz intrMP1 ;
mov mEvent[di],al ; Process all packets when three
inc di ; bytes have been received. If a
mov byteCnt,di ; fourth byte is received process
cmp di,sizPktMP-1 ; the packet again, but set deltaX
jc intrMP1 ; and deltaY to zero since they
jz intrMP4 ; have been seen. When handling
mov byteCnt,0 ; a three byte packet, the last
and mEvent[0],070h ; state of the fourth byte of the
mov mEvent[1],0 ; last four-byte packet will be
mov mEvent[2],0 ; used (or zero if none).
intrMP4: test devStatus,readEnable ; If reporting disabled then do
jz intrMP1 ; nothing further for packet
mov ah,mEvent[0] ;
mov bl,ah ; Put delta-X into dx and delta-Y
mov bh,mEvent[3] ; into bx
add bh,bh ;
and bx,4030h ;
or bl,bh ; Get event flags in si
shr bx,4 ; if button pressed and moved
xor bh,bh ; 0000 0000 00M0 R0L0
movzx si,intrMap[bx] ; if button pressed only
mov al,mEvent[1] ; 0000 0000 0M0R 0L00
shl al,2 ; if move only
shr ax,2 ; 0000 0000 0000 0001
mov dh,al ; if no button pressed & not moved
sar dx,8 ; 0000 0000 0000 0000
mov al,mEvent[2] ;
shl al,2 ; Where L, R and M are 1 if the
shr ax,2 ; corresponding button was pressed
mov bh,al ; and 0 otherwise
sar bx,8 ;
xor dx,colRvFlg ; Optionally reverse delta-X
add dx,colRvVal ;
xor bx,rowRvFlg ; Optionally reverse delta-Y
add bx,rowRvVal ;
mov cx,flipFlag ;
mov ax,dx ; Optionally exchange the X
shld dx,bx,cl ; and Y axis
shld bx,ax,cl ;
mov cx,si ; Move event flags into cx
mov ax,bx ;
or ax,dx ;
jnz intrMP5 ; Determine if there has been
add cx,cx ; motion since the last event
cmp cx,lastEvnt ; and adjust or discard event
jnz intrMP6 ; packet accordingly
jmp intrMP1 ;
intrMP5: cmp cx,1 ;
adc cx,0 ;
intrMP6: mov lastEvnt,cx ;
mov si,intPacketOff ; Set up packet addressing
push ds ;
mov ax,ds ;
mov ds,mseDd.protDs ; Put event flags, row movement and
mov es,ax ; column movement into event packet
mov [si].event,cx ;
call es:[accelrat] ; Accelerate/deaccelerate mouse
mov [si].colMov,dx ;
mov [si].rowMov,bx ; Go handle relative event,
mov ax,eventRelative ; interrupts are enabled
call es:mseDd.protEntry ; during processing. Handler
pop ds ; is NOT reentrant!
jmp intrMP1 ;
InterruptHandlerMP endp
cseg ends