;*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 = PCLOGIC.ASM
;*
;* DESCRIPTIVE NAME = PC Mouse systems and Logitech device
;*                    interrupt handler.   v
;*
;*
;* VERSION      V2.0
;*
;* DATE         07/08/91
;*
;* DESCRIPTION
;*
;* FUNCTIONS    Interrupt_Handler            Mouse device Interrupt Handler.
;*
;*
;* 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 pmode.inc
       include devsym.inc
       include devhlp.inc
       include struc.inc
       include dddd.inc
       include devhlpP.inc            ;76711
.list

.286p

;*
;*    External Mouse Module Data References
;*

       extrn Disable_8259        : byte
       extrn Enable_8259         : byte
       extrn DeviceData          : byte
       extrn MseDD               : byte
       extrn MEvent              : byte

       extrn DevStatus           : word
       extrn IntPacketOff        : word
       extrn First_Port          : word
       extrn ByteCount           : word

       extrn Device_Help         : dword

       extrn Enable_Device       : near
       extrn Disable_Device      : near


CSEG     SEGMENT   WORD  PUBLIC  'CODE'
         ASSUME    CS:CSEG, SS:nothing, ES:nothing, DS:nothing

;*
;*    Module Procs made Public for other Mouse Modules
;*

       public  Interrupt_Handler

;*******************************************************************
;*
;*  FUNCTION NAME :  Interrupt_Handler
;*
;*  DESCRIPTION   :  Mouse device Interrupt Handler.
;*
;*                   Reads mouse interrupts, translates to common
;*                   format, and sends them to the independent DD.
;*
;*  ENTRY POINT   :  Interrupt_Handler   LINKAGE:  CALL FAR
;*
;*  INPUT         :  None, except data from mouse device
;*
;*  RETURN-NORMAL :  Always, carry clear -- our interrupt.
;*
;*  RETURN-ERROR  :  N/A.
;*
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
;*                    registers are changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  None.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHlps:  See individual support routines.
;*
;*********************************************************************
;*
;*     The Mouse Systems Mouse returns a 5 byte packet whenever the
;*     hardware changes state (movement, button press, button release).                                       *
;*     Motion is reported positive  up and to the right (by mouse device)
;*
;*        Byte 1:  B7 : 1 = Sync byte.  Marks 1st byte of packet
;*                 B6-B3 : 0
;*                 B2 : Button 1 (Left)   status (0 = depressed)
;*                 B1 : Button 2 (Middle) status (0 = depressed)
;*                 B0 : Button 3 (Right)  status (0 = depressed)
;*
;*        Byte 2:  Delta X1            { The value for Delta-X
;*        Byte 3:  Delta Y1            { is formed by adding
;*        Byte 4:  Delta X2            { Delta-X1 and Delta-X2.
;*        Byte 5:  Delta Y2            { Ditto for Delta-Y.
;*
;***********************************************************************

Interrupt_Handler  Proc  Far

       ;*
       ;* issue the EOI and disable the IRQ
       ;*

       call Disable_Device            ; disable the device 1st
     ; IssueEOI                                             Remove 76711
       cli                                     ;            Add    76711
       DevEOI    <DeviceData.IRQ>,Device_Help  ;            Add    76711
       sti

;*
;* Read the async device.
;*

       ReadAsync                       ; read interrupt data
       mov  ah, 0f0h                   ; mask to check for sync bit
       and  ah, al                     ; mask off possible button stats

;*
;* If we get a Sync Byte in the middle of building an interrupt packet
;* without an error we have encountered the 16550 data error.  Latching
;* generates a RCV interrupt which is lost.  The error is generated
;* on the next data byte.
;*

       .if <ah eq SYNCBIT> AND         ; if 1st byte of packet
       .if <ByteCount eq 0>            ; and we need to start a packet
          inc  ByteCount               ; show that we have started
          mov  Mevent[0], al           ; save button data
       .elseif <ByteCount ne 0> NEAR   ; if a packet has started
          mov  di, ByteCount           ; get byte count for index
          mov  Mevent[di], al          ; save this byte
          inc  ByteCount
          .if <ByteCount eq PACKETSIZE>  NEAR ; if packet complete
             mov  ByteCount, 0         ; clear counter

;*
;* Button event is in this format:  xxxxx123 where 0=depressed.
;* The event mask is built using this byte.  Each button status is rotated
;* into the carry flag.  If the carry flag is 0 then the corresponding
;* button event for button pressed with motion is set in cx.  After all
;* buttons have been checked the motion counters are calculated.  If there
;* was no motion and there was a button depressed then cx is shifted to
;* put the button events in the without motion format.
;*

             xor  cx, cx              ; clear register to build event
             mov  ah, MEvent[0]       ; get button event
             shr  ah, 1               ; Put      3 stat in cy flag
             jc   b3up                ; if cy is set button 3 is up
b3down:      or   cx, 0008h           ; but 3 is down so set event bit           
b3up:        shr  ah, 1               ; put but 2 stat in cy flag
             jc   b2up                ; if cy is set button 2 is up
b2down:      or   cx, 0020h           ; but 2 is down so set event bit           
b2up:        shr  ah, 1               ; put but 1 stat in cy flag
             jc   b1up                ; if cy is set button 1 is up
b1down:      or   cx, 0002h           ; but 1 is down so set event bit
.386p
b1up:        push  eax
             push  edx
             movsx ax,byte ptr MEvent[1]  ; get 1st column movement byte
             movsx dx,byte ptr MEvent[3]  ;     2nd column movement byte
             add   ax,dx
             test  ax,8000h
             jnz   b13neg
             and   al,7Fh
             jmp short tstb24
b13neg:      or    al,80h
tstb24:      mov   bh,al
             movsx ax,byte ptr MEvent[2]  ; get 1st row movement byte
             movsx dx,byte ptr MEvent[4]  ;     2nd row movement byte
             add   ax,dx
             test  ax,8000h
             jnz   b24neg
             and   al,7Fh
             jmp short tstdun
b24neg:      or    al,80h
tstdun:      mov   bl,al
             pop   edx
             pop   eax
.286p
         ;   mov  bh, byte ptr MEvent[1] ; get 1st column movement byte
         ;   add  bh, byte ptr MEvent[3] ; add resid col movement byte
         ;   mov  bl, byte ptr MEvent[2] ; get 1st row movement byte
         ;   add  bl, byte ptr MEvent[4] ; add resid row movement byte
             neg  bl                  ; make downward mvmnt positive
             cmp  bx, 0               ; see if no column movement
             jne  movement            ; skip if there was
nomove:      shl  cx, 1               ; no mvmnt, cnvrt to w/o format
             jmp  pcm1                ; continue (exit if structure)
movement:    cmp  cx, 0               ; there was mvmnt, any buts down?
             jne  pcm1                ; if so then continue
             inc  cx                  ; no buts dwn, motion only event
pcm1:        Process_Packet           ; macro to process int data
          .endif                      ; end packet complete test
       .endif

       call Enable_Device             ; make sure IRQ enabled

       clc                            ; clear carry for our int

       ret                            ; return to intr hndlr

Interrupt_Handler  EndP

CSEG     ENDS
         END
