;*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 = MON.ASM                                                                           
;*                                                                                                                
;* DESCRIPTIVE NAME = Mouse Device Driver Protect Mode IOCtls                        
;*                    and Monitor Handler Rtns.         
;*
;*                                                                         
;* VERSION      V2.0                                                       
;*                                                                         
;* DATE         08/14/91
;*                                                                         
;* DESCRIPTION                                
;*                                                                         
;* FUNCTIONS    Monitor_Handler      - Monitor Handler Routine
;*             
;* NOTES        This file contains Monitor and Event queue support
;*              functions.  See the linker control file for the  .
;*              location in the link list.                        
;*             
;*             
;* STRUCTURES   NONE                                                       
;*                                                                         
;* EXTERNAL REFERENCES   SingleQ DD, Device Dependent DD.                                                  
;*                       ProcRun.                                                                          
;*                                                                   
;*                                                                         
;* EXTERNAL FUNCTIONS                                                      
;*                                                                         
;*              NONE                                                       
;*                                                                         
;* CHANGE ACTIVITY =                                                       
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION                       
;*   --------  ----------  -----  --------------------------------------   
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx                                  
;*   07/27/92              DCAF   FIX
;**************************************************************************
                                                                    

.386p

.xlist
        include basemaca.inc
        include osmaca.inc
        include mouse.inc
        include infoseg.inc
        include singleq.inc
.list

CPUMODE 386

;*
;*    External Mouse Module Data References
;*

       extrn  Num_Grps             : byte
       extrn  MEvent               : byte
       extrn  SQDD                 : byte

       extrn  FgndCB               : dword

       extrn  QueueWrite           : far
       extrn  EnableMouse          : near
       extrn  DisableMouse         : near
       extrn  FindCB               : near

       EXTRNFAR Update_Ptr

DSEG   SEGMENT   WORD  PUBLIC  USE16 'DATA'
DSEG   ENDS

CSEG2    SEGMENT   WORD  PUBLIC USE16 'SWAPCODE'
         ASSUME    CS:CSEG2, SS:nothing, ES:nothing, DS:nothing, FS:DSEG

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

       public  Monitor_Handler


;************************************************************************
;*                                                              
;*  FUNCTION NAME :  Monitor_Handler
;*                                                              
;*  DESCRIPTION   :  Mouse Device Driver Monitor Handler
;*                     Routine.                                 
;*                                                              
;*  FUNCTION      :  This routine is invoked when an event has
;*                   finished traveling down a session's monitor chain
;*                   If SingleQ mode is active the event is sent to   
;*                   to the SingleQ Device Driver.  Otherwise the     
;*                   routine QueueWrite is called to place the event  
;*                   in the session's event queue.  All records rec-  
;*                   eived when a flush is in progress are discarded. 
;*                   If a flush record is received data queueing is   
;*                   reenabled.  If the event queue is busy when an   
;*                   event is received it is discarded. If a process  
;*                   is blocked on mouse data it is awakened by issu- 
;*                   ing a ProcRun DevHelp.                           
;*                                                              
;*  ENTRY POINT   :  Monitor_Handler                               
;*     LINKAGE    :  CALL FAR
;*                                                              
;*  INPUT         :  Monitor Output Buffer address in ES:SI.
;*                                                                            
;*                        MB_Len           DW                                 
;*                        MFlags           DW                                 
;*                        EMask            DW                                 
;*                        EMTime           DD                                 
;*                        Row_Pos          DW                                 
;*                        Col_Pos          DW                                 
;*                                                              
;*  RETURN-NORMAL :  Always
;*                                                          
;*  RETURN-ERROR  :  N/A
;*                                                              
;*  EFFECTS       :  Stack is clean on return.  NO registers changed.
;*                                                              
;*  INTERNAL REFERENCES:                                        
;*     ROUTINES:  QueueWrite                                    
;*                                                              
;*  EXTERNAL REFERENCES:                                        
;*     ROUTINES:  SingleQ Device Driver, DDDD(Disable_Device,   
;*                Enable_Device)                                
;*     DevHlps:   ProcRun                                       
;*                                                              
;*************************************************************************
;*
;*BeginSub  Monitor_Handler
;*
;*   call DDDD(Disable_Device) to stop monitor interrupts
;*
;*   IF <monitor record is not a flush record>
;*      determine what session event is for by matching to output
;*         buffer
;*      session_num <- 0
;*
;*      WHILE <monitor output buffer != output buffer for session_num AND
;*             session_num lt max_session>
;*         session_num <- session_num + 1
;*         IF <buffers match>  set buffer found
;*      ENDWHILE
;*
;*      IF <buffer found>
;*         IF <session_num event queue not busy>
;*restart:    set session_num event queue to BUSY
;*            call QueueWrite to put event in session event queue
;*            IF <thread(s) blocked>
;*               call DeviceHelp(ProcRun) to let them run
;*            ENDIF
;*            set session_num event queue NOT BUSY
;*         ENDIF
;*      ENDIF
;*   ENDIF
;*
;*   call DDDD(Enable_Device) to allow mouse interrupts
;*   return
;*
;*EndSub  Monitor_Handler
;*
;************************************************************************
 
MONITOR_HANDLER  PROC  FAR
       ASSUME    CS:CSEG2, SS:nothing, ES:nothing, DS:nothing, FS:DSEG

        mov  ax, DSEG                         ; We must set up FS to
        mov  fs, ax                           ; the base Mouse data sel

        pusha                                 ; Save Registers for local use

        call DisableMouse                     ; disable mouse


;*   Since the monitor record does not contain the session number that
;*   the event belongs to, we must search through all sessions to find
;*   the address of the monitor output buffer (which is part of that
;*   session's control block).  For obvious reasons it is most likely
;*   that the event belongs to the current foreground session.  This
;*   session is checked first.  If it does not belong here than a search
;*   of all sessions is made to find the correct one.  If one is not found
;*   then the event is ignored.

        test word ptr es:[si][2], 4           ; See if this is a flush record.
        .if <z> near                          ; If not a Flush Record then
           mov  di, si                        ; es:di -> Monitor Out Buffer

;*
;*      Find the session the monitor output buffer belongs to.
;*      First we will check if it is the foreground session.
;*      es:di -> Monitor Output Buffer
;*

           mov  ax, 1                         ; assume buffer not found
           lds  si, fs:FgndCB                 ; Get the foreground sessions CB
           add  si, MB_Len                    ; Monitor Buffer Offset
           mov  dx, ds
           mov  bx, es
           .if <bx eq dx> and                 ; If selectors are the same (and)
           .if <di eq si>                     ; If the offsets are the same

;*
;*             At this point we know that the monitor output buffer
;*             passed into this call is for the foreground session.
;*             So we will just fall through.
;*

              xor  ax, ax                     ; set flag for buffer found
           .else

     ;*
     ;* At this point we know that the monitor output buffer
     ;* passed into this call is not for the foreground session.
     ;* We will now loop through the rest of the CBs for full screen
     ;* sessions.
     ;*

              xor  bx, bx                     ; 1st SG Number = 0

              .while <bl lt fs:Num_Grps>      ; If more SG's to check and Mon

                 push fs
                 pop  ds
                 call FindCB                  ; On return DS:SI -> FS CB
                 add  si, MB_Len              ; Monitor Buffer Offset
                 mov  ax, ds
                 mov  dx, es
                 .if <ax eq dx> and           ; If selectors match  (and)
                 .if <di eq si>               ; The offsets match, then
                    xor  ax, ax               ; buffer found
                    .leave                    ; We have found the right CB
                 .endif
                 inc  bl                      ; Try next SG CB

              .endwhile                       ; SG CB Search Loop

           .endif

;*
;*          At this point both (ds:si) and (es:di) point to the Monitor Output
;*          Buffer of the session being monitored if found.  If not found
;*          something is wrong.
;*

           .if <ax eq 0> near                 ; If Mon Buf was found then
              sub si, MB_Len                  ; Get back to top of CB

;*
;*      DCAF CHANGE - We should check the SQ_Mode flag and write the event
;*      to the singleq if it is active. If SQ_Mode is not active then we
;*      write the event to the full screen event queue.
;*

              test [si].D_Status, SQ_Mode     ; Check to if SQ mode active
              .if nz near                     ; if active then

                 xor  cx, cx                  ; Clear Save/Restore Count

                 push si                      ; Save SG CB Offset

;*
;*            - We were using the       packet address. Instead
;*                      of using the passed in packet we were using the
;*                      MEvent packet which is never filled for application
;*                      injected packet (i.e. fake packets).
;*

                 mov  si, di                       ; Offset to passed packet
                 add  si, 4                        ; Point to EMask

;*              mov  si, offset MEvent.Mon_Emask   ; Get event offset
;* End of           
;*

                 mov  ah, 02h                   ; Specify Mouse DD calling
                 mov  al, ElRec_Size            ; Specify data rec size
                 mov  bh, 02h                   ; Specify TimeStamp offset

                 mov  bl, 02h                   ; Specify Write Function

                 push fs
                 push es                        ; Save user data selector
                 push SQDD.ProtDS               ; Get SQ DD DS selector
                 pop  es                        ; Load into ES for call
                 call dword ptr fs:SQDD.ProtEntry  ; Invoke SQ DD func
                 pop  es                        ; Restore selector
                 pop  fs
                 pop  si                        ; Restore SG CB offset

              .else
                 test [si].D_Status, Busy_Mask   ; Check Event Que Busy Bit
                 .if  z  near                    ; If Event Que not busy
                    or   [si].D_Status, Busy_Mask  ; Set busy bit in DevStatus
                    push es                      ; selector of event record
                    mov  bx, di                  ; get event offset
                    add  bx, 4                   ; update to point to event data
                    push bx                      ; put off of mon rec on stack
                    call QueueWrite              ; go put in queue

                    and  [si].D_Status, NOT Busy_Mask  ; Reset Que Busy Flag
                 .endif                          ; Event Queue Busy Test

              .endif

              mov  cx, [si].Col_Pos              ; get new column
              mov  dx, [si].Row_Pos              ; net new row
              CALLFAR Update_Ptr                 ; update the pointer image

           .endif                             ; Mouse Mon Buf Address Tests
        .else                                 ; If a Flush Record then
           sub  si, MB_Len                    ; Get SG CB Offset
           and  es:[si].D_Status, NOT Q_Flush ; Reset Dev Status Flush Flag
        .endif                                ; Flush Record Test

        call EnableMouse                      ; then enable the mouse

        popa                                  ; Restore Original Reg values
        ret                                   ; Return to Monitor Dispatcher

MONITOR_HANDLER  endp

CSEG2 ENDS
      END
