Sample code -- interrupt handler (16-bit assembly)


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
         

[ Overview | Next ]