;*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 = EMI.ASM
;*
;* DESCRIPTIVE NAME = extended mouse interface
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  This file interfaces the mouse driver to the
;*              extended mouse driver througth the extend mouse
;*              interface (EMI)
;*
;* FUNCTIONS    Emi_Stock_Revent   Process a relative stock event packet.
;*              Emi                IDC call to the Emi driver
;*              EmiEntryPoint      Provide service functions for emi drive
;*              Emi_Config         Configure Emi devices
;*              Emi_BegSesSwitch   Indicate session switches
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   00/00/00              P 55236
;**************************************************************************


.386p

.xlist
  include emiidc.inc
  include mouse.inc
  include struc.inc
  include infoseg.inc
  include singleq.inc
.list

;*
;*    External Mouse Module Data References
;*

extrn Int_Packet  :byte
extrn SInt_Packet :byte
extrn EmiFlags    :byte
extrn EmiDD       :byte
extrn EmiMvt      :byte
extrn EmiSSI      :byte
extrn TypeOverRider : byte
extrn DDD           : byte

extrn GDT_Seg     :word
extrn DevStatus   : word

extrn Device_Help :dword
extrn FgndCB      :dword
extrn MEvent      :dword
extrn FgndSessn   : byte     ;          

extrn FindCB      :near

extrn Process_Absolute :near
extrn Process_Packet   :near
extrn  CalcPixelMvmnt       : near
extrn  CalcPtrPos           : near
extrn  CalcProtThreshold    : near

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

public Emi_Stock_Revent
public Emi_Stock_Aevent
public Emi_Config
public Emi
public Emi_far
public EmiEntryPoint
public Emi_BegSesSwitch
public Emi_EndSesSwitch
public Emi_BegVMChange
public Emi_EndVMChange

DSEG   SEGMENT   WORD  PUBLIC  USE16 'DATA'
DSEG   ENDS

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

;***************************************************************
;*
;*  FUNCTION NAME :  Emi_Stock_Revent
;*
;*  DESCRIPTION   :  Process a relative stock event packet.
;*
;*  FUNCTION      :  Pre-process a relative envent from the stock
;*                   device. Could be built in, or external. EMI
;*                   may determine that this packet should be ignored.
;*
;*  ENTRY POINT   :  Emi_Stock_Revent    LINKAGE:  CALL NEAR
;*
;*  INPUT         :  The packet pointed to by SInt_Packet
;*                   DS - MOUSE$ data selector
;*
;*  RETURN-NORMAL :  cy - skip this packet
;*                   nc - process this packet
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  Copy SInt_Packet to Int_Packet
;*
;**********************************************************************

Emi_Stock_Revent proc  near
  .if  <bit EmiFlags z EMI_READY>
                                ;whswhs only works for relative
     mov  ax,SInt_Packet.Event  ; setup interrupt packet
     mov  Int_Packet.Event,ax
     mov  eax,dword ptr SInt_Packet.Col_Mov
     mov  dword ptr Int_Packet.Col_Mov,eax
     push es                    ; setup time stamp
     mov  es,word ptr GDT_Seg
     mov  eax, es:SIS_MsCount
     mov  MEvent.Mon_time,eax
     pop  es
     call Process_Packet
  .else
     mov  ax,EMI_STK_REL
     call Emi            ;ax = function
  .endif
  xor  ax,ax             ; Clears Carry flag,
  ret
Emi_Stock_Revent Endp

Emi_Stock_Aevent proc  near
  .if  <bit EmiFlags z EMI_READY>
     mov  ax,SInt_Packet.Event  ; setup interrupt packet
     mov  Int_Packet.Event,ax

     mov  eax,dword ptr SInt_Packet.Y_Pos
     mov  dword ptr Int_Packet.Y_Pos, eax

     mov  eax,dword ptr SInt_Packet.Y_Size
     mov  dword ptr Int_Packet.Y_size, eax

     push es                    ; setup time stamp
     mov  es,word ptr GDT_Seg
     mov  eax, es:SIS_MsCount
     mov  MEvent.Mon_time,eax
     pop  es
     call Process_Absolute
  .else
     mov  ax,EMI_STK_ABS
     call Emi            ;ax = function
  .endif
  xor  ax,ax             ; Clears Carry flag,
  ret
Emi_Stock_Aevent Endp

;**********************************************************************
;*
;*  FUNCTION NAME :  Emi
;*
;*  DESCRIPTION   :  IDC call to the Emi driver
;*
;*  FUNCTION      :  IDC call to the Emi driver
;*
;*  ENTRY POINT   :  Emi                 LINKAGE:  CALL NEAR
;*                   Emi_far             LINKAGE:  CALL FAR
;*
;*  INPUT         :  AX - EMI IDC function
;*                   DS - MOUSE$ data selector
;*
;*  RETURN-NORMAL : nc - idc call successful
;*
;*  RETURN-ERROR  :  cy - idc call failed
;*
;*  EFFECTS       :  Depends on IDC call
;*
;*
;**********************************************************************


Emi proc  near
  .if <bit EmiFlags z EMI_ACTIVE>
     stc
     ret
  .endif
  push ds                       ;save regs
  push fs

  push ds
  pop  es
  mov  ds,EmiDD.ProtDS          ; get emi DS
  call es:EmiDD.ProtEntry       ; call emi driver

  pop  fs                       ; restore regs
  pop  ds
  ret
Emi Endp

Emi_far proc  far
  call  Emi
  ret
Emi_far Endp

;***************************************************************
;*
;*  FUNCTION NAME :  EmiEntryPoint
;*
;*  DESCRIPTION   :  Provide service functions for emi driver
;*
;*  FUNCTION      :  receive IDC calls from EMI driver
;*
;*  ENTRY POINT   :  EmiEntryPoint       LINKAGE:  CALL FAR
;*
;*  INPUT         :  AX - IDC Function
;*                   DS - MOUSE$ data selector
;*
;*  RETURN-NORMAL : nc - idc call successful
;*
;*  RETURN-ERROR  :  cy - idc call failed
;*
;*  EFFECTS       :  Depends on IDC call
;*
;*
;***************************************************************


EmiEntryPoint proc far

;*
;* Get screen resolution returns the current screen resolutions
;* returns cx = x screen extent
;*         dx = y screen extent
;*

  .if <ax eq EMI_GETRES_ABS>
     .if <<word ptr FgndCB+2> ne 0>
        les  si, FgndCB              ; get foreground session CB
        test es:[SI].MType, Graphics ; IF mode is a graphics mode
        .if  nz
           mov  cx,es:[si].GCol_Res  ; get the graphics resolutions
           mov  dx,es:[si].GRow_Res
        .else
           mov  cx,es:[si].TCol_Res  ; get the text resolutions
           mov  dx,es:[si].TRow_Res
        .endif
        xor ax,ax
     .else
        stc
     .endif

;*
;* convert device to screen coordinates
;*          cx= x device coord
;*          dx= y device coord
;* returns  cx= x screen coord
;*          dx= y screen coord
;*

  .elseif <ax eq EMI_CONVERT_REL>
     call convertRelative
;*
;* Process Packet requests
;*

  .elseif <ax eq EMI_ABS>
     call Process_Absolute
  .elseif <ax eq EMI_REL>
     call Process_Packet
  .elseif <ax eq EMI_DISABLE_STK> OR
  .if     <ax eq EMI_ENABLE_STK>
     call manageEnable
  .else
     stc
  .endif
  ret
EmiEntryPoint endp

;***************************************************************************
;* convert device to screen coordinates
;*          cx= x device coord
;*          dx= y device coord
;* returns  cx= x screen coord
;*          dx= y screen coord
;***************************************************************************

XCoord equ bp-4
YCoord equ bp-2
public convertRelative
convertRelative proc
  .if <<word ptr FgndCB+2> eq 0>
     stc
     ret
  .endif
  enter 4,0
  mov   [XCoord],cx
  mov   [YCoord],dx

  push ds                      ; Get mouse data seg               
  pop  fs                      ; put mouse ds in fs

  lds  si, FgndCB              ; get foreground session CB
  test [SI].MType, Graphics    ;  Test for Disp Mode Resolution
  .if  nz                      ; If in Graphics Mode then
    push [si].GCol_Res         ; push the graphics resolutions
    push [si].GRow_Res         ; on stack for use by CalcNewPtrPos
  .else                        ; else push the text resolutions
    push [si].TCol_Res         ; on stack for use by CalcNewPtrPos
    push [si].TRow_Res         ; 
  .endif                       ; end display mode type test


;*
;*      Calculate the row motion.  First determine the number of pixels moved
;*      by calling CalcPixelMvmnt.  If there was motion then apply the
;*      thresholding algorithm and calculate the new pointer position.  If there
;*      was no motion then the current row position is used.
;*

  ;*
  ;* Do some checking before calling CalcPixelMvmnt!!!          
  ;*

  mov  bl, fs:FgndSessn              ; Get Current Foreground SG ID
  test [si].D_Status, USS_Mode    ; see if the mode is supported
  .if <z>            AND          ; if it is and
  test [si].Ptr_Flags, SM_WinFlag ; if we not are in the middle of
  .if z              AND          ; setting the display mode and
  .if <[si].Hdle_Cntr gt 0>       ; and session has open mse support
     jmp  PassedChecks              ; go set event time
  .endif
   stc                            ; set error
   jmp Exeunt                     ; get out


PassedChecks:
  push [si].RowScale_Fact        ; row scale factor
  push dx                        ; raw row motions (mickeys)
  push [si].Row_Remain           ; row mickey motion remainder
  call CalcPixelMvmnt            ; calculate number of pixels moved
  add  sp, 6                     ; remove parameters from stack

  .if <ax ne 0>                  ; if there was pixel movement
     mov  dx,[YCoord]            ; push raw motion
     push dx                     ; push raw motion
     call CalcProtThreshold      ; do a protect mode threshold calc
     add  sp, 2                  ; remove parameter from stack

     push [si].Ptr_Row_Pos       ; ptr row pos (row res already there)
     push [si].Row_Cell_Size     ; row cell size
     push [si].Row_Cell_Remain   ; row cell motion remainder
     call CalcPtrPos             ; calculate new pointer position
     add  sp, 8                  ; remove parameters from stack
     mov  [YCoord],ax            ; this is the new row
  .else                          ; else no screen movement
     add  sp, 2                  ; remove row resolution from stack
     mov  ax, [si].Ptr_Row_Pos   ; get current row
     mov  [YCoord],ax            ; the new row is the old row
  .endif

;*
;*      Repeat the same steps for the column position (motion).
;*

  push [si].ColScale_Fact        ; col scale factor
  mov  ax,[XCoord]               ; raw col motions (mickeys)
  push ax                        ; 
  push [si].Col_Remain           ; col mickey motion remainder
  call CalcPixelMvmnt            ; calculate number of pixels moved
  add  sp, 6                     ; remove parameters from stack

  .if <ax ne 0>                  ; if there was pixel movement
     mov  cx,[XCoord]            ; push raw motion
     push cx                     ; 
     call CalcProtThreshold      ; do a protect mode threshold calc
     add  sp, 2                  ; remove parameter from stack

     push [si].Ptr_Col_Pos       ; ptr row pos (col res already there)
     push [si].Col_Cell_Size     ; coc cell size
     push [si].Col_Cell_Remain   ; coc cell motion remainder
     call CalcPtrPos             ; calculate new pointer position
     add  sp, 8                  ; remove parameters from stack
     mov  cx,ax                  ; this is the new col
  .else                          ; else no screen movement
     add  sp, 2                  ; remove col resolution from stack
     mov  cx, [si].Ptr_Col_Pos   ; get the current col
  .endif
  mov  dx,[YCoord]
  xor  ax,ax

Exeunt:
  push fs
  pop ds                         ; Finally...get the mouse seg into DS!
  leave
  ret
convertRelative endp

;**************************************************************************
;* disable / enable mouse device
;* ax = EMI_DISABLE_STK or EMI_ENABLE_STK
;***************************************************************************

public manageEnable
manageEnable proc
  .if <TypeOverRider eq TRUE>
     .if  <ax eq EMI_DISABLE_STK>
        mov  ax, DISABLEDEVICE
     .else
        mov  ax, ENABLEDEVICE
     .endif
     push ds
     push ds
     pop  es
     mov  ds,es:DDD.ProtDS
     call es:DDD.ProtEntry
     pop  ds
  .else
     .if  <ax eq EMI_DISABLE_STK>
        and  DevStatus, not gREADENABLE
     .else
        or   DevStatus, gREADENABLE
     .endif
  .endif
  ret
manageEnable endp

CSEG2    SEGMENT   WORD  PUBLIC  USE16 'SWAPCODE'
         ASSUME    CS:CSEG2, SS:nothing, ES:nothing, DS:nothing
;***********************************************************************
;*
;*  FUNCTION NAME :  Emi_Config
;*
;*  DESCRIPTION   :  Configure Emi devices
;*
;*                   Call the Emi driver at ring 0 to configure its
;*                   devices.
;*
;*  ENTRY POINT   :  Emi_Config         LINKAGE:  CALL NEAR
;*
;*  INPUT         :  none
;*                   DS - MOUSE$ data selector
;*
;*  RETURN-NORMAL : OK
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  May turn off EMI_ACTIVE if errors occur
;*
;*
;*************************************************************************



Emi_Config proc  near
  mov  ax,cs
  and  ax,03h
  .if  <zero ax>
     push es
     push bx
     and  EmiFlags,not EMI_NEED_CONFIG

     mov  ax, EMI_CONFIGURE
     lea  di, EmiMvt
     call Emi_far        ;ax = function is EMI_CONFIGURE
                         ;di = Mouse Variable Table address
     .if c
        and EmiFlags,not EMI_ACTIVE
     .else
        or EmiFlags, EMI_READY
     .endif
     pop  bx
     pop  es
  .endif
  ret
Emi_Config  Endp

;***************************************************************
;*
;*  FUNCTION NAME :  Emi_BegSesSwitch
;*
;*  DESCRIPTION   :  Indicate session switches
;*
;*                   Call the Emi driver to inform of session switchs
;*
;*  ENTRY POINT   :  Emi_BegSesSwitch   LINKAGE:  CALL NEAR
;*                   Emi_EndSesSwitch   LINKAGE:  CALL NEAR
;*                   Emi_BegVMChange    LINKAGE:  CALL NEAR
;*                   Emi_EndVMChange    LINKAGE:  CALL NEAR
;*
;*  INPUT         :  cx = caller's session
;*                   bx = future   session
;*                   ax = TRUE = fullscreen
;*                        FALSE = not fullscreen
;*                   FS - MOUSE$ data selector
;*
;*  RETURN-NORMAL : OK
;*
;*  RETURN-ERROR  :  Never.
;*
;*
;***************************************************************



emi_ret:
   ret

;**************************************************************************
; Indicate beginning of session switch
; cx = caller's session
; bx = future   session
; al = fullscreen flag (TRUE=fullscreen, FALSE = not)
;**************************************************************************

Emi_BegSesSwitch proc
  test fs:EmiFlags,EMI_ACTIVE
  jz   emi_ret
  mov  ah,SSI_START_SES_SWITCH
  jmp  short emi_cont


;**************************************************************************
; cx = caller's session
; bx = future   session
; es:di = video data
;**************************************************************************
Emi_BegVMChange:
  test fs:EmiFlags,EMI_ACTIVE
  jz   emi_ret

  push ds
  mov  ah,SSI_START_VM_CHANGE
  mov  al,TRUE
  push es
  pop  ds
  mov  si,di
  jmp  short emi_cont2

;**************************************************************************
; Indicate end of mode change
; cx = caller's session
; bx = future   session
; ds:si = video data
;**************************************************************************

Emi_EndVMChange:
  test fs:EmiFlags,EMI_ACTIVE
  jz   emi_ret

  push ds
  mov  ah, SSI_END_VM_CHANGE
  mov  al, TRUE
  jmp  short emi_cont2

;**************************************************************************
; Indicate end of session switch
; bx = future   session
; al = fullscreen flag (TRUE=fullscreen, FALSE = not)
;**************************************************************************

Emi_EndSesSwitch:
  test fs:EmiFlags,EMI_ACTIVE
  jz   emi_ret
  mov  ah,SSI_END_SES_SWITCH
  mov  cx, bx

emi_cont:
  push ds

;*
;* al    = TRUE = fullscreen, FALSE = not fullscreen
;* ah    = EMI system event
;* cx    = caller's session
;* bx    = future   session
;*
;* get the video mode info if its a full screen
;*

  .if  <nonzero al>
     push ax
     call FindCB           ; bx = session to find
                           ; returns ds:si = session data
     pop  ax
     .if  c
        xor  al,al
     .endif
     add  si, MLength
  .endif

emi_cont2:
;*
;* al    = TRUE = valid data, FALSE = no data
;* ah    = EMI system event
;* cx    = caller's session
;* bx    = future   session
;* ds:si = data
;* fs    = mouse data segment
;*
;* ds:si = session data

  .if  <nonzero al>
     mov  dl, [si].M_Type
     mov  fs:EmiSSI.Ssi_Mtype, dl
     mov  dl, [si].M_Color
     mov  fs:EmiSSI.Ssi_Color, dl
     mov  dx, [si].New_TRow_Res
     mov  fs:EmiSSI.Ssi_TRow_Res, dx
     mov  dx, [si].New_TCol_Res
     mov  fs:EmiSSI.Ssi_TCol_Res, dx
     mov  dx, [si].New_GRow_Res
     mov  fs:EmiSSI.Ssi_GRow_Res, dx
     mov  dx, [si].New_GCol_Res
     mov  fs:EmiSSI.Ssi_GCol_Res, dx
  .endif

  push fs
  pop  ds
  mov  EmiSSI.Ssi_Command,ah
  mov  EmiSSI.Ssi_InfoValid, al
  mov  EmiSSI.Ssi_Current, cx
  mov  EmiSSI.Ssi_Future, bx
;*
;* inform EMI driver
;*

  mov  ax,EMI_SYSEVENT
  lea  di, EmiSSI
  call Emi_far        ;ax    = function is EMI_SYSEVENT
                      ;ds:di = Sesssion Info
  pop  ds
  ret
Emi_BegSesSwitch endp

CSEG2    ends


CSEG     ENDS
         END
