;/*************************************************************************
;*
;* SOURCE FILE NAME = IOGET.ASM
;*
;* DESCRIPTIVE NAME = Mouse Device Driver, Protect Mode IOCtls
;*
;* COPYRIGHT    COPYRIGHT IBM CORPORATION, 1991, 1992
;*              Copyright Microsoft Corporation, 1990
;*              LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
;*              REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
;*              RESTRICTED MATERIALS OF IBM
;*              IBM CONFIDENTIAL
;*
;* VERSION      V2.0
;*
;* DATE         08/30/91
;*
;* DESCRIPTION  This file contains Mouse DD Protect Mode IOCt
;*              Get worker routines.
;*
;* FUNCTIONS    IOMR_NB    (60h)  - Performs the Mouse IOCtl function
;*              IOMR_MC    (61h)  - Performs the Mouse IOCtl function
;*              IOMR_GS    (62H)  - Performs the Mouse IOCtl function
;*              IOMR_RD    (63H)  - Performs the Mouse IOCtl function
;*              IOMR_QS    (64H)  - Performs the Mouse IOCtl function
;*              IOMR_GM    (65h)  - Performs the Mouse IOCtl function
;*              IOMR_GF    (66h)  - Performs the Mouse IOCtl function
;*              IOMR_GP    (67h)  - Performs the Mouse IOCtl function
;*              IOMR_PS    (68h)  - Performs the Mouse IOCtl function
;*              IOMR_TH    (69H)  - Performs the Mouse IOCtl function
;*              IOMR_GV    (6A)   - Performs the Mouse IOCtl function
;*              IOMR_ID    (6bh)  - Performs the Mouse IOCtl function
;*              IOMR_CS    (   )  - Set the mouse constrained area
;*              IOMR_CQ    (   )  - Query the mouse constrained area
;*
;*
;* NOTES        This file contains Mouse DD Protect Mode IOCt
;*              Get worker routines.
;*
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;**************************************************************************



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

CPUMODE 386

;*
;*    External Mouse Module Data References
;*


       extrn  CallSessn            : byte
       extrn  FgndSessn            : byte
       extrn  DDD                  : byte
       extrn  Ptr_Rec              : byte
       extrn  DeviceData           : byte
       extrn  PrescottDsp          : byte
       extrn  ScreenKeypad         : byte
       extrn  MEvent               : byte       ; GRADD
       extrn  Int_Packet           : byte       ; GRADD

       extrn  Eq_Length            : word
       extrn  Sem_PID              : word

       extrn  Device_Help          : dword
       extrn  InfoSegAddr          : dword
       extrn  Sem_Time             : dword
       extrn  Ctl_Sem              : dword

       extrn  SaveExtModeData      : near
       extrn  SaveCfgData          : near
       extrn  GetCfgDataOffset     : near
       extrn  PtrDrawCheck         : near
       extrn  QueueRead            : near
       extrn  EnableMouse          : near
       extrn  DisableMouse         : near


CSEG2   SEGMENT   WORD  PUBLIC USE16 'SWAPCODE'
        ASSUME    CS:CSEG2, SS:NOTHING, ES:NOTHING, DS:NOTHING

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


       public  IOMR_NB       ; Cat 7 - func 60h
       public  IOMR_MC       ; Cat 7 - func 61h
       public  IOMR_GS       ; Cat 7 - func 62h
       public  IOMR_RD       ; Cat 7 - func 63h
       public  IOMR_QS       ; Cat 7 - func 64h
       public  IOMR_GM       ; Cat 7 - func 65h
       public  IOMR_GF       ; Cat 7 - func 66h
       public  IOMR_GP       ; Cat 7 - func 67h
       public  IOMR_PS       ; Cat 7 - func 68h
       public  IOMR_TH       ; Cat 7 - func 69h
       public  IOMR_GV       ; Cat 7 - func 6ah
       public  IOMR_ID       ; Cat 7 - func 6bh
       public  IOMR_CQ       ; Cat 7 - func 6dh
       public  IOMR_XY       ; Cat 7 - func 6eh (GRADD)


;************************************************************************
;*
;*  FUNCTION NAME :  IOMR_NB    (60h)
;*
;*  DESCRIPTION   :  Performs the Mouse IOCtl function
;*                   IOMR_NB, get number mouse buttons.
;*
;*                   Return the number of buttons on the mouse to the
;*                   caller.  Number of button is written to the
;*                   address in the data field.
;*
;*  ENTRY POINT   :  IOMR_NB           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*                   SI has offset to current session control block.
;*
;*  RETURN-NORMAL :  number of buttons written to user data area.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*     DevHelps   :  NONE.
;*
;************************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_NB  (get number of mouse buttons)
;*
;*  copy number of mouse buttons to user data area
;* return
;*
;* EndSub  IOMR_NB
;*
;***********************************************************************

IOMR_NB  proc  near

       push es                         ; Save es
       les  di, es:[bx].GIODataPack
       xor  ah, ah
       mov  al, fs:DeviceData.NumButt  ; get number of buttons
       mov  word ptr es:[di], ax       ; put in user data area
       pop  es                         ; Restore es
       ret                             ; Return to Generic IOCtl Handler Rtn

IOMR_NB  EndP


;***********************************************************************
;*
;*  FUNCTION NAME :  IOMR_MC    (61h)
;*
;*  DESCRIPTION   :  Performs the Mouse IOCtl function
;*                   IOMR_MC, get number mickeys/centimeter.
;*
;*                   Writes the number of mickeys per centimeter to
;*                   the user address in the data field of the request
;*                   block.  Value written is a word.
;*
;*  ENTRY POINT   :  IOMR_MC           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*                   SI has offset to current session control block.
;*
;*  RETURN-NORMAL :  Caller's address contains requested data.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_MC  (get mickeys/cm for mouse)
;*
;* move mickeys per cm to user data area
;* return
;*
;* EndSub  IOMR_MC
;*
;***********************************************************************

IOMR_MC  proc  near

       push es                         ; save es
       les  di, es:[bx].GIODataPack    ; load es with selector
       mov  al, fs:DeviceData.NumMics  ; Get value in register
       xor  ah, ah                     ; clear upper byte
       mov  word ptr es:[di], ax       ; Write Data to user addr
       pop  es                         ; restore es
       ret                             ; Return to Generic IOCtl Handler Rtn

IOMR_MC  EndP

;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_GS  (62H)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                  IOMR_GS, get device status flags.
;*
;*                  Writes 1 word to the address in the data field of
;*                  the request block.  This word is the session's
;*                  device status flags.  Reserved bits are set to 0.
;*
;*  ENTRY POINT   :  IOMR_GS           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*                   SI has offset to current session control block.
;*
;*  RETURN-NORMAL :  Session's device status flags returned.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE:
;*
;* BeginSub  IOMR_GS  (get session device status)
;*
;*  disable system interrupts
;*  mask off reserved bits in device status
;*  move masked device status to user area
;*  enable system ints
;*  return
;*
;* EndSub  IOMR_GS
;*
;************************************************************************

IOMR_GS  proc near

       push es                         ; save es
       cli                             ; Hold interrupts for data write
       les  di, es:[bx].GIODataPack    ; load selector to data area
       mov  ax, [si].D_Status          ; Get SG device status field flags
       and  ax, DevStatRet             ; Ensure SQ Mode not reported
       mov  es:[di], ax                ; Put Status flags in caller addr
       sti                             ; Enable interrupts, data write
       pop  es                         ; restore es
       ret                             ; Return to Generic IOCtl Handler Rtn

IOMR_GS  EndP


;***********************************************************************
;*
;*  FUNCTION NAME : IOMR_RD  (63H)
;*
;*  DESCRIPTION   : Performs the Mouse IOCtl function
;*                   IOMR_RD, read event queue.
;*
;*                  Writes a 10 byte mouse event record to the address
;*                  in the data field of the request block.  The
;*                  format is that of an event queue element.  The
;*                  parmlist field points to a 1 word value that
;*                  indicates what type of read to do.  Two types are
;*                  valid, Wait and NoWait.  If Wait is specified then
;*                  the caller will block until data is available. If
;*                  NoWait is specified then a NULL event will be
;*                  returned if no data is available.  In either case
;*                  a valid record is returned if data is available.
;*                  If SingleQ mode is active for the session then
;*                  a request error is returned.  If the event queue
;*                  is busy then a GENERAL FAILURE is returned. Ints
;*                  disabled during event queue access.
;*
;*  ENTRY POINT   : IOMR_RD           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*                   SI has offset to current session control block.
;*
;*  RETURN-NORMAL :  Event queue element returned.
;*
;*  RETURN-ERROR  :  Error return code set in Request Block Status
;*                   field.
;*
;*  EFFECTS       :  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  Req_Err
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*     DevHelps   :  GetDOSVar, ProcBlock, SemClear, SemRequest,
;*                   and VerifyAccess.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_RD  (read session's event queue)
;*
;*  IF <SingleQ mode not active>
;*    IF <event queue is NOT Busy>
;*       IF <event queue is empty>
;*          IF <read type is BLOCK>
;*             call Device_Help(SemClear) to release mouse semaphore
;* REBLOCK:    call Device_Help(ProcBlock) to block the thread
;*             disable system ints
;*             IF <block worked>
;*                IF <queue still empty>
;*                   goto REBLOCK
;*                ENDIF
;*                call Device_Help(SemRequest) to get mouse semaphore
;*                IF <SemRequest worked>
;*                   call Device_Help(GetDOSVar) to get LDT infoseg
;*                   IF <GetDOSVar worked>
;*                      save calling session
;*                      save PID
;*                      calculate MSCB offset
;*                      set status to no error
;*                   ELSE
;*                      set general failure
;*                   ENDIF
;*                   IF <SingleQ mode is now active>
;*                      set request error
;*                      set error status
;*                   ENDIF
;*                ELSE
;*                   clear semaphore ownership
;*                   set general failure
;*                   set error status
;*                ENDIF
;*             ELSE   /*  proc block failed  */
;*                set general failure
;*                set error status
;*                IF <character call interrupted>
;*                   set request packet to character int error
;*                ENDIF
;*             ENDIF
;*             set request block to NOT busy
;*          ELSEIF <read type is invalid>
;*             set parameter error
;*             set error status
;*          ENDIF
;*       ENDIF
;*
;*       IF <status indicates no error>
;*          call Device_Help(VerifyAccess) to check user data area
;*          IF <access OK>
;*             IF <event queue is NOT empty>
;*                call QueueRead to read an event
;*             ELSE
;*                write a NULL record to the user data area
;*             ENDIF
;*          ELSE
;*             set parameter error
;*          ENDIF
;*       ENDIF
;*
;*    ELSE  /*  event queue is busy  */
;*       set general failure
;*    ENDIF
;* ELSE     /*  single queue mode is active  */
;*    set general failure
;* ENDIF
;* return
;*
;* EndSub  IOMR_RD
;*
;************************************************************************

IOMR_RD  PROC  near

TempES        equ  <(word ptr [bp-2])>     ; For ES register
TempBX        equ  <(word ptr [bp-4])>     ; For BX register
TempSI        equ  <(word ptr [bp-6])>     ; for SI register

    Enter  6,0
    mov  TempES, es                        ; Save Local Var's
    mov  TempBX, bx
    mov  TempSI, si

    test [si].D_Status, SQ_Mode            ; Check SQ Mode Flag Bit
    .if  z  near                           ; If not in SQ Input Mode

       cli                                 ; Disable interrupts
       test [si].D_Status, Busy_Mask       ; Check Event Que Busy Bit
       .if  z  near                        ; If Event Que not busy with I/O

         sub  ax, ax                       ; Clear Local Error Flag
         .if <[si].Eq_Size eq al> near     ; If Queue is empty then

           les  di, es:[bx].GIOParaPack    ; load selector to data area
           xor  ax, ax                     ; clear local error flag
           mov  bx, word ptr es:[di]       ; Get User ReadType Parm value

           .if <bx eq 01h> near            ; If ReadType = Block Request
             or   [si].D_Status, Block_Mask  ; Set Thread Blocked bit

             mov  bx, TempBX               ; Restore Request Block
             mov  es, TempES               ; Address into ES:BX

             or   es:[bx].PktStatus, ReqBlk_Busy ; Set Req Blk as busy

             mov  ax, fs:Sem_PID           ; Get current Sem PID
             mov  [si].Eq_PID, ax          ; Save as Eq owner PID

;*
;* Use DEVHLP (SemClear) to release the control RAM Semaphore
;*

             mov  bx, offset Ctl_Sem       ; Low word of sem address
             mov  ax, fs                   ; High word of sem address
             mov  dl, DevHlp_SemClear      ; Devhelp function number
             call fs:Device_Help           ; Invoke SemClear function

             cli                           ; Disable interrupts to Block

             mov  fs:Sem_PID, 0000h        ; Clear Sem ownership PID


;*
;* Use DEVHLP (Block) to sleep the requesting thread
;*

reblock:

             mov  bx, ds                     ; Event queue address low word
             mov  ax, [si].E_Queue           ; Event queue address high word
             mov  di, word ptr fs:Sem_Time   ; Semaphore Timeout Limit High
             mov  cx, word ptr fs:Sem_Time+2 ; And Low word values == -1
             xor  dh, dh                     ; Interruptible sleep
             mov  dl, DevHlp_ProcBlock       ; Devhelp function number
             push fs                         ; save fs because not saved
             call fs:Device_Help             ; Invoke Block Function
             pop  fs                         ; restore fs

;*
;* Process continues here after being blocked for queue data.  First restore
;* necessary variable stored on stack.
;*

             cli                            ; Hold ints from Block enable

             .if nc near                    ; If Block worked then

               .if <[si].Eq_Size eq 0>      ; If Que is empty then
                  jmp  reblock              ; Return and wait for data
               .endif                       ; Empty Que Tests

;*
;* Invoke DEVHLP (SemRequest) to get the control semaphore
;*

            mov  bx, offset Ctl_Sem         ; Low word of sem address
            mov  ax, fs                     ; High word of sem address
            mov  di, word ptr fs:Sem_Time   ; Semaphore Timeout Limit High
            mov  cx, word ptr fs:Sem_Time+2 ; And Low word values == -1
            mov  dl, DevHlp_SemRequest      ; Devhelp function number
            call fs:Device_help             ; Invoke SemRequest function

            .if nc                          ; If SemRequest worked then


             les  bx,fs:InfoSegAddr

             mov  ax, es:[bx].LIS_CurScrnGrp    ; Get LDT SG ID
             mov  fs:CallSessn, al              ; Save LDT SG ID

             mov  cx, es:[bx].LIS_CurProcID     ; Get LDT PID
             mov  fs:Sem_PID, cx                ; Save LDT PID

;*
;* Restore SI to PID's Screen Group CB Offset
;*                  mov  bl, fs:CallSessn
;*                  xor  bh, bh
;*                  shl  bx, 1
;*                  mov  si, fs:Session_CB_Off[bx]
;*

                    and  [si].D_Status, NOT Block_Mask   ; Clear Block bit
                    xor  ax, ax                ; Clear Error Tracking Flag
                    mov  [si].Eq_PID, ax       ; Clear Sem ownership PID

                  test [si].D_Status, SQ_Mode  ; Check SQ Input Mode Bit
                  .if  nz                      ; If in SQ Input Mode then
                    mov  bx, TempBX            ; Restore Request Block
                    mov  es, TempES            ; Address into ES:BX
                    mov  es:[bx].PktStatus, UNKNOWNCMD
                    inc  ax                    ; Set Error Tracking Flag
                  .endif                       ; SQ Input Mode Tests

               .else                           ; If SemRequest failed then
                 mov  fs:Sem_Pid, 0000h        ; clear semaphore ownership
                 GenFail                       ; Set Req Blk Status for failure
               .endif                          ; SemRequest test

             .else                             ; Proc block failed
               GenFail                         ; Set General failure error
               .IF nz                          ; If Char call Intrrptd
                 mov  es, TempES               ; Reset IOCtl address
                 mov  bx, TempBX               ;
                 mov  es:[bx].PktStatus, CHARINT ; set Char Int Err
               .endif                          ; end char int Test
             .endif                            ; end Block test

             mov  bx, TempBX                   ; Restore Request Block
             mov  es, TempES                   ; Address into ES:BX

             mov  cx, NOT ReqBlk_Busy          ; Get Req Blk Busy bit mask
             and  es:[bx].PktStatus, cx        ; Set Req Blk Status bit 9 OFF

           .elseif <bx ne 0>                   ; else if invalid read type
             ParmErr                           ; Set parameter error
             mov  ax, 1                        ; Set local Error Flag
           .endif                              ; end type of read test
         .endif                                ; Empty event queue test

;*
;* Continue processing here.  If there was a local error then stop.  If
;* not then check access to the user event record.  If there are elements
;* in the event queue then copy the oldest to the  user area.  If the
;* event queue is empty then a NOWAIT read was requested and no data
;* has arrived yet, so return a NULL event to the user.
;*

         .if <ax eq 0> near                      ; If no local errors then

           mov  bx, TempBX                       ; Restore Request Block
           mov  es, TempES                       ; Address into ES:BX

           mov  ax, GIODataSelector              ; Selector for Data Access
           mov  di, GIODataOffset                ; offset to data area
           mov  cx, ELRec_Size                   ; Event Record Length
           mov  dh, 1                            ; Read/Write Access
           mov  dl, DevHlp_VerifyAccess          ; Specify DevHlp Func
           call fs:Device_Help                   ; Invoke VerifyAccess

           .if <nc> near                         ; If data access OK
             mov  es, ax                         ; load selector to data area
             .if <[si].Eq_Size gt 0>             ; If Event Que Not Empty then
               or   [si].D_Status, Busy_Mask     ; Set Event Que Busy bit
               push es                           ; push user selector
               push di                           ; push user offset
               call QueueRead                    ; go read the queue
               and  [si].D_Status, NOT Busy_Mask  ; Reset Que Busy Bit
             .else                          ; If Event Que is Empty then
               xor  ax, ax                  ; set ax to 0
               cld                          ; Fill User Element Data
               rep  stosb                   ; Record with zeros
             .endif                         ; Event Queue Size Tests

             mov  bx, TempBX            ; Restore Request Block
             mov  es, TempES            ; Address into ES:BX

           .else                        ; access to data address failed
             ParmErr                    ; Flag Invalid parameter
           .endif                       ; end data address check
         .endif                         ; Local error(s) test

       .else                            ; If Que busy bit is on then
         GenFail                        ; Set error return code in Req Blk
       .endif                           ; Que busy bit tests

       sti                              ; Data Updated, allow ints

    .else                               ; If SQ Mode is Active then
       mov  es:[bx].PktStatus, UNKNOWNCMD
    .endif                              ; SQ Input Mode Tests

    mov  es, TempES                     ; restore packet selector
    mov  bx, TempBX                     ; restore packet offset
    Leave                               ; Clear local Stack variables

    RET                                 ; Return to IOCTL Handler Rtn
IOMR_RD  ENDP


;***********************************************************************
;*
;*  FUNCTION NAME :  IOMR_QS  (64H)
;*
;*  DESCRIPTION   :  Performs the Mouse IOCtl function
;*                     IOMR_QS, get event queue status.
;*
;*                  Writes 2 words to the address in the data field
;*                  of the request block.  1st word is the number of
;*                  elements in the session's event queue, 2nd word
;*                  is the event queue max size (QSIZE= xx).  If
;*                  SingleQ mode is active then a request error is
;*                  returned.  Ints are disabled during operations.
;*
;*  ENTRY POINT   :  IOMR_QS           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*                   SI has offset to current session control block.
;*
;*  RETURN-NORMAL :  Number of elements and event queue size are
;*                returned.
;*
;*  RETURN-ERROR  :  Error return code set in Request Block status
;*               field.
;*
;*  EFFECTS       :  Stack is clean on return.  Regs not preserved.
;*                   registers are changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  Req_Err.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE.
;*     DevHelps   :  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_QS  (get event queue status)
;*
;* IF <session is not in single queue mode>
;*    move current number of elements in queue to user data area
;*    calculate max number of queue elements
;*    move max elements to user data area
;* ELSE
;*    set request error
;* ENDIF
;* return
;*
;* EndSub  IOMR_GS
;*
;************************************************************************

IOMR_QS  PROC  near

       push es                                ; save es

       test [si].D_Status, SQ_Mode            ; Check SQ Input Mode Bit
       .if z  NEAR                            ; If not in SQ Input Mode
          les  di, es:[bx].GIODataPack        ; load selector to data area
          cli                                 ; Hold interrupts for Data Read
          mov  al, [SI].Eq_Size               ; Get current Event Size
          cbw                                 ; make word for return value
          mov  es:[di][0], ax                 ; Put Size into user's data area
          mov  dl, ELRec_Size                 ; Get # of bytes per que element
          mov  ax, fs:Eq_Length               ; Get total # of bytes per queue
          idiv dl                             ; Calc # of que elements
          cbw                                 ; Get a word value for return
          mov  es:[di][2], ax                 ; Return Max # of Que Elements
          sti                                 ; Data updated, allow interrupts
       .else                                  ; If SQ Mode is Active then
          mov  es:[bx].PktStatus, UNKNOWNCMD  ; set unknown command error
       .endif                                 ; SQ Input Mode Tests

       pop  es                                ; restore es
       ret                                    ; Return to IOCTL Handler Rtn

IOMR_QS  ENDP


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_GM    (65h)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                     IOMR_GM, get session's event mask.
;*
;*  FUNCTION:  Writes 1 word to the address in the data field of
;*             the request block.  Word written is the session's
;*             event mask.
;*
;*  ENTRY POINT:  IOMR_GM           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always Session's event mask is returned.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_GM  (get session event mask)
;*
;* disable system ints
;* move session event mask to user data area
;* enable system ints
;* return
;*
;* EndSub
;*
;************************************************************************

IOMR_GM  PROC  near

       push es                       ; save es
       les  di, es:[bx].GIODataPack  ; load selector to data area
       mov  ax, [si].E_Mask          ; Get SG Event Mask value and
       mov  es:[di], ax              ; Put it in caller's address
       pop  es                       ; restore es
       ret                           ; Return to Generic IOCtl Handler Rtn

IOMR_GM  ENDP


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_GF    (66h)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                     IOMR_GF, get session's scaling factors.
;*
;*  FUNCTION:  Writes 2 words to the address in the data field
;*             of the request block.  1st word is the row
;*             scaling factors, 2nd is the column scaling
;*             factors.
;*
;*  ENTRY POINT:  IOMR_GF           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always, user address contains requested data.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*           ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_GF  (get session scaling factors)
;*
;* copy session scaling factors to user data area
;* return
;*
;* EndSyb  IOMR_GF
;*
;***********************************************************************

IOMR_GF  proc near

       push es                         ; save es
       les  di, es:[bx].GIODataPack    ; load selector to data area
       mov  ax, [si].RowScale_Fact     ; Get current Row Scaling Factor
       mov  es:[di].Parm1, ax          ; Write value to user address
       mov  ax, [si].ColScale_Fact     ; Get current Col Scaling Factor
       mov  es:[di].Parm2, ax          ; Write value to user address
       pop  es                         ; restore es
       ret                             ; Return to Generic IOCTL Handler

IOMR_GF  endp


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_GP    (67h)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                     IOMR_GP, get pointer screen position.
;*
;*  FUNCTION:  Writes 2 words to the address in the data field of
;*             the request block.  1st word is the X coordinate,
;*             2nd word is the Y coordinate.
;*
;*  ENTRY POINT:  IOMR_GP           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always, user address contains requested data.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*           ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;*  BeginSub  IOMR_GP  (get session pointer position)
;*
;* disable system ints
;* copy current pointer position to user data area
;* enable system ints
;* return
;*
;* EndSub  IOMR_GP
;*
;***********************************************************************

IOMR_GP  proc near

       push es                         ; save es
       cli                             ; Hold interrupts for data read
       les  di, es:[bx].GIODataPack    ; load selector to data area
       mov  ax, [si].Ptr_Row_Pos       ; Get current Ptr Row coord
       mov  cx, [si].Ptr_Col_Pos       ; Get current Ptr Col coord
       mov  es:[di].Parm1, ax          ; Write Row coord to user address
       mov  es:[di].Parm2, cx          ; Write Col coord to user address
       sti                             ; Enable interrupts, data read
       pop  es                         ; Restore es
       ret                             ; Return to IOCTL Handler Rtn.

IOMR_GP  ENDP


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_PS    (68h)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                     IOMR_PS, get session's pointer image data.
;*
;*  FUNCTION:  Writes the pointer image buffer to the address in
;*             the data field of the request block, and writes
;*             the pointer definition data to the address in the
;*             parmlist field.  If the user area is large enough
;*             then the data is written, otherwise the buffer
;*             size required is written and a request error is
;*             returned.
;*
;*  ENTRY POINT:  IOMR_PS           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Pointer image data is retrurned.
;*
;*  RETURN-ERROR  :  Require size for data is returned, status field
;*               in request block set to error code.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  PhysToVirt, UnPhysToVirt, VerifyAccess.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  IOMR_PS  (get session pointer image data)
;*
;* save size of users ptr image buffer
;* put actual size of ptr image buffer in user's buffer
;* IF <user's buffer is large enough>
;*    move pointer image data to user's ptr image buffer
;*    get physical address of ptr definition record
;*    get length of definition record from ptr image data
;*    call Device_Help(VerifyAccess) to check access to user def buffer
;*    IF <access OK>
;*       disable system ints
;*       call Device_Help(PhysToVirt) to get virtual address
;*       IF <PhysToVirt worked>
;*          copy ptr definition record to user's definition buffer
;*          call Device_Help(UnPhysToVirt) to clear temp selectors
;*       ELSE
;*          set general failure error
;*       ENDIF
;*       enable system ints
;*    ELSE
;*       set parameter error
;*    ENDIF
;* ELSE
;*    set parameter error
;* ENDIF
;*
;* return
;*
;* EndSub  IOMR_PS
;*
;************************************************************************

IOMR_PS  PROC  near

TempES        equ  <(word ptr [bp-2])>     ; For ES register
TempBX        equ  <(word ptr [bp-4])>     ; For BX register
TempSI        equ  <(word ptr [bp-6])>     ; for SI register
TempDS        equ  <(word ptr [bp-8])>     ; for DS register

       Enter 8,0
       mov  TempES, es                ; Save Local Var's
       mov  TempBX, bx
       mov  TempDS, ds
       mov  TempSI, si

       cli                               ; Hold interrupts for PhysToVirt

       les  di, es:[bx].GIODataPack      ; load selector to data area
       mov  ax, es:[di].Buf_Len          ; Get size of caller's buffer length
       mov  bx, ds:[si].Ptr_Imagelen     ; Put actual pointer image buffer
       mov  es:[di].Buf_Len, bx          ; Length in caller's record

       .if <ax ge bx> near and           ; If caller's buffer is big enough and
       .if <bx gt 0> near                ; The Screen group has a defined ptr
          mov  bx, [si].Ptr_Width        ; Copy SG CB values to caller record
          mov  es:[di].PWidth, bx        ; Load current ptr width
          mov  bx, [si].Ptr_Height       ; Copy SG CB values to caller record
          mov  es:[di].PHeight, bx       ; Load current ptr height
          mov  bx, [si].Ptr_ColHot       ; Copy SG CB values to caller record
          mov  es:[di].Col_Hot, bx       ; Load current ptr column hot spot
          mov  bx, [si].Ptr_RowHot       ; Copy SG CB values to caller record
          mov  es:[di].Row_Hot, bx       ; Load current ptr row hot spot
          mov  ax, word ptr [si].Ptr_BuffHigh     ; Get SG CB Ptr Image
          mov  bx, word ptr [si].Ptr_BuffLow      ; Buf Addr for copy
          mov  cx, [si].Ptr_Imagelen     ; Get Ptr Image Buffer Len (Bytes)
          push cx                        ; Save reg trashed by DevHlp Call
          mov  dh, 0                     ; Return in DS:SI
          mov  dl, DevHlp_PhysToVirt     ; Devhelp function number
          call fs:Device_Help            ; Invoke PhysToVirt Function
          pop  cx                        ; Restore reg trashed by DevHlp
          .if nc                         ; If PhysToVirt worked then
             cli                         ; Hold interrupts for PhysToVirt
             mov  es, TempES             ; Restore ES:BX to Request
             mov  bx, TempBX             ; Block Address
             mov  ax, GIOParaSelector     ; Selector for Data Access
             mov  di, GIOParaOffset       ; offset to data area
             mov  dh, 1                   ; Specify Read/Write Access
             mov  dl, DevHlp_VerifyAccess ; Specify DevHlp Func
             call fs:Device_Help          ; Invoke VerifyAccess

             .if nc                       ; If User Address Verified then

                mov  es, ax               ; Put User Data Sel back in ES
                                          ; ES:DI has Data parm address
                                          ; Copy Buf DS:SI to caller ES:DI
                                          ; CX has # of bytes from PysToVirt
                cld                       ; Increment SI, & DI
                rep  movsb                ; Copy 1 byte at a time.

             .else                         ; If an Invalid user address then
                ParmErr                    ; Flag Invalid parameter
             .endif                        ; User Address Verification Tests

             mov  ds, TempDS               ; Restore Mouse DSEG address

             mov  dl, DevHlp_UnPhysToVirt  ; Devhelp function number
             call fs:Device_Help           ; Invoke UnPhysToVirt Function

          .else                       ; If PhysToVirt failed then
             GenFail                  ; Set Err Return in Status field
          .endif                      ; PhysToVirt Tests

       .else                          ; If Caller's buf too small or NO
          ParmErr                     ; SG Ptr then Flag Invalid Parm
       .endif                         ; Caller Buf_Len value check

       mov  es, TempES                ; Restore ES:BX to Request
       mov  bx, TempBX                ; Block Address
       mov  ds, TempDS                ; Restore Mouse DSEG address
       mov  si, TempSI                ; Restore SG CB Offset
       sti                            ; Data updated, allow interrupts
       Leave                          ; Clear local Stack variables

       ret                            ; Return to IOCTL Handler Rtn

IOMR_PS  ENDP


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_TH  (69H)
;*
;*  DESCRIPTION  :  Performs the Mouse IOCtl function
;*                     IOMR_TH, return session threshold values.
;*
;*  FUNCTION:  The data address field points to a 10 byte buffer
;*             in user memory where the session threshold values
;*             are returned.  The 1st word is the length of the
;*             buffer.  If the length is < 10 then only the
;*             requested bytes are returned.
;*
;*  ENTRY POINT:  IOMR_TH           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Session threshold data copied to user data
;*                area.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return. Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  NONE
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE
;*     DevHlps:   NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;*  BeginSub  IOMR_TH
;*
;* CopyLength <- 10
;* IF <user buffer length lt 10>
;*    CopyLength <- user data buffer length field
;* ENDIF
;*
;* copy CopyLength bytes of threshold data to user data area
;* set user data area to CopyLength
;* return
;*
;* EndSub  IOMR_TH
;*
;***********************************************************************

IOMR_TH  proc  near

       push es                                 ; save es
       les  di, dword ptr es:[bx].GioDatapacx  ; get address of user area

       mov  cx, 10                    ; length of data
       .if <es:[di].THLength lt 10>   ; if user wants less than 10 bytes
          mov  cx, es:[di].THLength   ; then give him what he wants
       .endif                         ; end length test

       and  cx, 0fffeh                ; round odd # down
       mov  es:[di].THLength, cx      ; set length to what we will copy
       add  di, 2                     ; point to where to put data
       push si                        ; save MSCB offset
       add  si, Level1                ; si points to start of threshold data
       cld                            ; go forward
       rep  movsb                     ; move the data
       pop  si                        ; restore MSCB offset
       pop  es                        ; restore es

       ret                            ; return

IOMR_TH  EndP



;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_GV (6A)
;*
;*  DESCRIPTION  : Performs the mouse IOCtl function
;*                    IOMR_GV, get the mouse driver version #.
;*
;*  FUNCTION:  The datalist field of the request block points to
;*             a word where the driver version level is returned.
;*             A value of 1 indicates that the following are
;*             supported:
;*                  1.  IOMW_SM with data area parm added and
;*                      mode data length of 34 bytes.
;*                  2.  IOMW_SD with data parm added.
;*                  3.  IOMW_RS with data parm added.
;*                  4.  IOMW_MD new IOCtl.
;*                  5.  IOMR_GV new IOCtl.
;*
;*  ENTRY POINT:  IOMR_GV           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always,value 1 written to user data area.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  None.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES: None.
;*     DEVHLPS:  NONE.
;*
;***********************************************************************
;* PSEUDOCODE :
;*
;*  BeginSub  IOMR_GV  (get mouse version)
;*
;* write mouse version to user data area
;* return
;*
;* EndSub  IOMR_GV
;*
;***********************************************************************

IOMR_GV  PROC  near

       ret                                 ; return to IOCtl routine

IOMR_GV  EndP


;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_ID    (6bh)
;*
;*  DESCRIPTION     :  Performs the Mouse IOCtl function
;*                     IOMR_ID, get pointer device ID.
;*
;*  FUNCTION:  The caller passes in the following data
;*             packet:
;*
;*
;*  USHORT usPDevID;          /* Primary Pointing Device ID
;*  USHORT usPComPortNum;     /* Primary Com Port Number
;*  USHORT usSDevID;          /* Secondary Pointing Device ID
;*
;*  The supported Pointing Device IDs are:
;*          0 = unknown
;*          1 = Bus Mouse
;*          2 = Serial Mouse
;*          3 = Inport Mouse
;*          4 = PS/2 Style Pointing Device
;*          5 = IBM PS/2 8516 Touch Display
;*          6 = Logitech mouse
;*          7 = Screen Reader Keypad
;*          8 - 65,535 = reserved
;*
;*  ENTRY POINT:  IOMR_ID           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always, user address contains requested data.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*           ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************

IOMR_ID  proc near

       push es                             ; save es
       les  di, es:[bx].GIODataPack        ; get address of use area
       mov  al, fs:DeviceData.MouseType
       xor  ah, ah
       mov  word ptr es:[di], ax           ; usPDevID
       mov  al, fs:DeviceData.ComNum
       xor  ah, ah
       mov  word ptr es:[di+2], ax         ; usPComPortNum

      .if <fs:ScreenKeypad eq TRUE>
          mov  ax,KYP_DEVICE
          mov  es:[di],ax
      .endif
;*
;* If a Prescott Touch Display exists then we determinne if it is either
;* the primary or seondary pointing device. If DeviceData.MouseType is
;* equal to UNKNOWN_DEVICE then the Prescott device is primary ELSE
;* it is secondary.
;*

       .if  <fs:PrescottDsp eq TRUE>       ; If a Prescott exists then
          mov  ax, PSC_DEVICE              ; Get Prescott Device ID

          .if <fs:DeviceData.MouseType eq UNKNOWN_DEVICE>
             mov  word ptr es:[di], ax                ; Prescott is primary
             mov  word ptr es:[di+4], UNKNOWN_DEVICE  ; Nothing is secondary
          .else
             mov  word ptr es:[di+4], ax   ; Prescott is secondary
          .endif

       .else                               ; No secondary device
          xor  ax, ax
          mov  word ptr es:[di+4], ax      ; usSDevID
       .endif
       pop  es                             ; restore es

       ret                                 ; Return to IOCTL Handler Rtn.

IOMR_ID  ENDP

;***********************************************************************
;*
;*  FUNCTION NAME:  IOMR_CQ    (6Dh)
;*
;*  DESCRIPTION     :  Query the mouse's current constrained region
;*
;*  FUNCTION:  The caller passes in the following data
;*             packet:
;*
;*
;*  USHORT X0;                /* Upper left corner (inclusive) of constraint
;*  USHORT Y0;                /*
;*  USHORT X1;                /* Lower right corner (inclusive) of constraint
;*  USHORT Y1;                /*
;*
;*  ENTRY POINT:  IOMR_CQ           LINKAGE:  CALL NEAR
;*
;*  INPUT:  ES:BX points to the request block.
;*          SI has offset to current session control block.
;*
;*  RETURN-NORMAL  :  Always, user address contains requested data.
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS:  Stack is clean on return.  Regs not preserved.
;*
;*  INTERNAL REFERENCES:
;*           ROUTINES:  NONE.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHelps:  NONE.
;*
;***********************************************************************

IOMR_CQ  proc near

       push es                             ; save es
       push di
       les  di, es:[bx].GIODataPack        ; get address of use area
       mov  ax, [si].ConstrX0
       stosw
       mov  ax, [si].ConstrY0
       stosw
       mov  ax, [si].ConstrX1
       stosw
       mov  ax, [si].ConstrY1
       stosw
       pop  di
       pop  es                             ; restore es

       ret                                 ; Return to IOCTL Handler Rtn.

IOMR_CQ  ENDP

; GRADD START
;      /******************* START OF SPECIFICATIONS *********************/
;      /*                                                               */
;      /*  SUBROUTINE NAME:  IOMR_XY    (6eh)                           */
;      /*                                                               */
;      /*  DESCRIPTIVE NAME:  Performs the Mouse IOCtl function         */
;      /*                     IOMR_XY, get latest mouse position.       */
;      /*                                                               */
;      /*  INPUT:  ES:BX points to the request block.                   */
;      /*          SI has offset to current session control block.      */
;      /*                                                               */
;      /*  The caller passes in the following data packet:              */                             */
;      /*  Upon return from this call, these fields will have           */                             */
;      /*  the latest event information.                                */                             */
;      /*                                                               */
;      /*  USHORT te_X             X coordinate                         */
;      /*  USHORT te_Y             Y coordinate                         */
;      /*  DWORD  te_TimeStamp     Timestamp (msecs since boot)         */
;      /*  USHORT te_Event         Event Mask                           */
;      /*  USHORT te_usReserved    Reserved for future use              */
;      /*                                                               */
;      /*  NOTE: PMDD is mucking with MEvent packet so we should not    */
;      /*        use it here!                                           */
;      /*                                                               */
;      /******************* END  OF  SPECIFICATIONS *********************/

IOMR_XY  proc near


       and  [si].D_Status, NOT PtrDraw
       mov  ax, fs:MEvent.Mon_Col_Pos
       cmp  [si].usLastX, ax           ; Users last row
       jnz  newevent

       mov  ax, fs:MEvent.Mon_Row_Pos
       cmp  [si].usLastY, ax           ; Users last row
       jnz  newevent

       push bx
       mov  bx, offset Ctl_Sem         ; Low word of sem address
       mov  ax, fs                     ; High word of sem address
       mov  dl, DevHlp_SemClear        ; Devhelp function number
       push fs
       call fs:Device_Help             ; Invoke SemClear function
       pop  fs
       pop  bx

       mov  [si].fBlocked, 1           ; Flag indicating that we are blocked

       push bx
       mov  bx, ds                     ; Event queue address low word
       lea  ax, [si].CursorBlockID     ; Event queue address high word
       mov  di, -1                     ; Wait forever
       mov  cx, -1                     ;             ...
       xor  dh, dh                     ; Interruptible sleep
       mov  dl, DevHlp_ProcBlock       ; Devhelp function number
       push fs                         ; save fs because not saved
       call fs:Device_Help             ; Invoke Block Function
       pop  fs                         ; restore fs
       pop  bx

       mov  [si].fBlocked, 0           ; No longer blocked

newevent:

       lgs  di, es:[bx].GIODataPack

       mov  ax, fs:MEvent.Mon_Col_Pos
       mov  gs:[di].te_X, ax           ; Write Col coord to user address
       mov  [si].usLastX, ax           ; Last col given

       mov  ax, fs:MEvent.Mon_Row_Pos
       mov  gs:[di].te_Y, ax           ; Write Row coord to user address
       mov  [si].usLastY, ax           ; Last row given

       mov  eax, fs:MEvent.Mon_Time
       mov  gs:[di].te_TimeStamp, eax

       mov  ax, fs:Int_Packet.Abs_Event
       mov  gs:[di].te_Event, ax


       ret                             ; Return to IOCTL Handler Rtn.

IOMR_XY  ENDP

; GRADD END

CSEG2   ENDS
        END
