
;/*************************************************************************
;*
;* SOURCE FILE NAME = INIT.ASM
;*
;* DESCRIPTIVE NAME = Device Independent init routines
;*
;* 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         02/29/92
;*
;* DESCRIPTION  Device Independent init routines
;*
;* FUNCTIONS    Mouse_Init        ()
;*              InitFSCB2         ()
;*              FindQSize         ()
;*              FindTypeOverRider ()
;*              FindRelaxed       ()
;*              FindSType         ()
;*              FindForceMouseON  ()    ;@140921 DCAF
;*              Emi_Init          ()
;*              SkipWhiteSpace    ()
;*              gmDeviceInit      ()
;*              SetupForWait      ()
;*
;* NOTES        This file contains the Mouse Device Driver
;*              initialization code.  It is disposed of after
;*              successful initialization.  This is the last module
;*              in the link list.
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   02/29/92  @V2.0XXX01  DCR 509
;*   06/10/95  @V3.0PMS01 124938  Added support to allow Inhibit bit for
;*                                password control on 8042 - PM Schoeller
;*   06/16/95  @V3.0PMS02 xxxxxx  REMOVED the fix for defect #84853 as this
;*                                has caused a regression in detecting the
;*                                PDI port if a data stream device such as
;*                                a continous stock feed is attached to the
;*                                serial port.
;*                                ADDED code to make the MOUSE.SYS device
;*                                driver look for the SERIAL= parameter
;*                                which is documented in the online help and
;*                                use this parameter as a switch to decide
;*                                which port (PDI, Serial, BUS) to look at
;*                                first.  PM Schoeller
;*   10/20/95  @140921            Add new parameter to report presence of PDI
;*                                even when there is none.
;*
;**************************************************************************


.386p

.xlist
        include mouse.inc
        include basemaca.inc
        include infoseg.inc
        include emiidc.inc                                          ;emi
        include devclass.inc                                        ;emi
        include singleq.inc                                         ;emi
.list

;*
;*    External Mouse Module Data References
;*


       extrn  Num_Grps          : byte
       extrn  TypeName          : byte
       extrn  STypeName         : byte
       extrn  DDD               : byte
       extrn  DDD2              : byte
       extrn  DeviceData        : byte
       extrn  Mouse$            : byte
       extrn  DfltEQs           : byte
       extrn  SG0               : byte
       extrn  SG1               : byte
       extrn  SG3               : byte
       extrn  TypeOverRider     : byte
       extrn  SType             : byte
       extrn  ForceMouseON      : byte  ;@140921 DCAF
       extrn  ABIOS_Mch         : byte
       extrn  Enable_8259       : byte
       extrn  Disable_8259      : byte
       extrn  Enable_28259      : byte
       extrn  Disable_28259     : byte
       extrn  EmiDD             : byte                             ;emi
       extrn  EmiDDName         : byte                             ;emi
       extrn  EmiFlags          : byte                             ;emi
       extrn  EmiMvt            : byte                             ;emi
       extrn  Int_Packet        : byte                             ;emi
       extrn  SInt_Packet       : byte                             ;emi
       extrn  MEvent            : byte                             ;emi
       extrn  DeviceData        : byte                             ;emi
       extrn  Relaxed           : byte
       extrn Init_Time           : byte

       extrn  DDDInit           : word
       extrn  Eq_Length         : word
       extrn  GDT_Seg           : word
       extrn  SMData            : word
       extrn  usQSize           : word
       extrn  PortBase          : word
       extrn  First_Port        : word
       extrn  Dev_LID           : word
       extrn  DevStatus         : word
       extrn  EMaskMax          : word                             ;emi
       extrn  fNullMouse        : byte                             ;SRD
       extrn  fNullMouseParm    : byte                             ;SRD

       extrn  Device_Help       : dword
       extrn  _Device_Help      : dword
       extrn  InfoSegAddr       : dword

       extrn  PDDCMD_MSEEntry   : near
       extrn  DOSSMREGISTERDD   : far

       extrn CheckforPDIDevice   : near
       extrn PDI_Int_Handler     : near
       extrn PDIInit             : near
       extrn SetupCOMForMouse    : near
       extrn ResetSerialMouse    : near

       extrn CheckforMSSDevice   : near
       extrn MSS_Int_Handler     : near
       extrn InitComPort         : near
       extrn MSS_Find_Int        : near

       extrn CheckforINPDevice   : near
       extrn INP_Int_Handler     : near
       extrn InportInit          : near

       extrn CheckforBUSDevice   : near
       extrn BUS_Int_Handler     : near
       extrn BusInit             : near
       extrn EmiEntryPoint       : near                         ;emi

       extrn _RM_MSE_CreateDriver  :far
       extrn _RM_MSE_CreateAdapter :far
       extrn _RM_MSE_CreateDevice  :far
       extrn _RM_MSE_AllocPorts    :far
       extrn _RM_MSE_AllocIRQ      :far
       extrn _RM_MSE_DestroyDriver :far


       public Mouse_Init
       public InitFSCB2
       public FindQSize
       public FindTypeOverRider
       public FindSType
       public FindSerial                    ;@V3.0PMS02
       public SkipWhiteSpace
       public gmDeviceInit
       public SetupForWait
       public IsWaitOver

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

CSEG2  SEGMENT   WORD  PUBLIC  USE16 'SWAPCODE'
CSEG2  ENDS

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

ENDCODE   EQU   $           ; start of init throw away code


;************************************************************************
;*
;*  FUNCTION NAME :  Mouse_Init
;*
;*  DESCRIPTION   :  Mouse Device Driver H/W Initialization
;*                     Routine.
;*
;*                   This is the main initialization routine.  It
;*                      performs the following steps:
;*                         1.  Gets system variables and sets up msgs.
;*                         2.  Parse the config.sys parameters.
;*                         3.  Issue DevHlp AttachDD on TYPE= parm
;*                             device driver name.
;*                         4.  Initialize session control blocks
;*
;*  NOTES         :  This routine is discarded after initialization.
;*
;*  ENTRY POINT   :  Mouse_Init        LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the OS/2 Init request block.
;*
;*  RETURN-NORMAL :  Request Block status field set to indicate
;*                   function complete, no error.
;*
;*  RETURN-ERROR  :  Request Block pointer fields set to indicat
;*                   initialization failure.
;*
;*  EFFECTS       :  Stack is clean on return, AX, CX, DX, SI, and DI
;*                   registers are changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  NONE
;*
;*  EXTERNAL REFERENCES:
;*     DevHelps   :  GetDOSVar, AttachDD
;*
;************************************************************************

Mouse_Init  Proc  Far

      ?frame = 0                         ; Get Local/Temp Stack Frame
      LocalVar TempES,  WORD             ; For ES register
      LocalVar TempBX,  WORD             ; For BX register
      LocalVar TempDI,  WORD             ; For DI register

      EnterProc

      mov  TempES, es                    ; Save register values in
      mov  TempBX, bx                    ; Temporary Stack Frame

      mov  es:[bx].PktStatus, 0          ; Clear RB Error Status Flag
;*
;* Save Device Help router entry point.
;*
      mov  di, word ptr es:[bx].InitDevHlp  ; Load DevHlp Entry Pt Offset
      mov  word ptr Device_Help, di         ; Save DevHlp Offset
      mov  word ptr _Device_Help, di        ; Save DevHlp Offset
      mov  di, word ptr es:[bx].InitDevHlp+2; Load DevHlp Entry Pt Selector
      mov  word ptr Device_Help+2, di       ; Save DevHlp Selector
      mov  word ptr _Device_Help+2, di      ; Save DevHlp Selector
;*
;* Use DevHlp (GetDOSVar) to get a pointer to the GDT
;*

      mov  al, GDTINFOINDEX              ; Request GDT InfoSeg value = 1
      mov  dl, DevHlp_GetDOSVar          ; DevHelp function number
      call Device_Help                   ; On Return AX:BX -> to req var

      .if <c>                            ; GetDOSVar failed
         jmp  mi_error
      .endif

      mov  es, ax                        ; Get the GDT level 0 selector and
      mov  ax, word ptr es:[bx]          ; Overwrite the level 3 Selector
      mov  GDT_Seg, ax                   ; Save GDT Selector

      xor  si, si
      mov  es, word ptr GDT_Seg          ; Use the GDT Infoseg selector to
      mov  al, es:[si].SIS_MaxScrnGrp    ; Groups in the system.
      mov  Num_Grps, al                  ; Save # SG's value

;*
;* Use DEVHLP (GetDOSVar) to get LDT InfoSeg
;*
      push  es
      mov   al, LDTINFOINDEX              ; get LDT InfoSeg variable
      mov   dl, DevHlp_GetDOSVar          ; Devhelp function number
      call  Device_Help                   ; Invoke GetDOSVar function
                                          ; AX:BX points to LDT InfoSeg
      mov   es, ax                        ; Get LDT info addr
      les   bx, dword ptr es:[bx]         ; LDT InfoSeg Addr
      mov   word ptr InfoSegAddr,bx
      mov   word ptr InfoSegAddr+2,es
      pop   es
;*
;* Register with the Resource Manager
;*
      inc Init_Time
      pusha
      push es
      mov ax, 1                             ; MOUSESYS
      push ax
      call _RM_MSE_CreateDriver
      pop ax
      pop es
      popa
;*
;* Initialize the extended mouse interface (EMI)                           ;emi
;*                                                                          ;emi

      call Emi_Init                                                       ;emi

      mov  es, TempES                    ; Restore register values from
      mov  bx, TempBX                    ; Temporary Stack Frame

;*
;* Now begin parsing the config.sys line.  Field InitParms points to the
;* 1st character after device= on the line for the MOUSE.SYS dd.
;*

      les  di, es:[bx].InitParms         ; load address to config.sys line
      mov  si, di                        ; save starting point
;*
;* We will first search for the last occasion of the backslash character.
;* This will then point us to MOUSE.SYS and whatever follows. This search
;* was added for @V2.0XXX01 In this @V2.0XXX01 we added support for extended chars
;* in the DEVICE=  line of config.sys. If no backslash chars are encountered
;* our pointer remains at the 1st char after the device= statement.
;*

      .while <<byte ptr es:[di]> ne 0>   ; For all chars on line
         .if <<byte ptr es:[di]> eq '\'> ; If lower case alpha char
            mov  si, di                  ; New starting point
            inc  si
         .endif
         inc di
      .endwhile

      mov  di, si                        ; es:di -> MOUSE.SYS ...
      mov  al, es:[di]
;*
;* Skip over MOUSE.SYS to the 1st non blank character or EOL is reached.
;*

      .while < al ne ' ' > AND           ; Skip everything until a
      .while < al ne ',' > AND           ; Blank, comma, Tab, or EOLN
      .while < al ne TAB > AND           ; Is encountered
      .while < al ne LF > AND
      .while < al ne CR > AND
      .while <al ne 0>
         inc  di                         ; Update line index
         mov  al, es:[di]                ; Get next char
      .endwhile
;*
;* At this point ES:DI points to the first character after MOUSE.SYS and
;* AL holds that character value. We will convert the remaining characters
;* to upper case.
;*

      mov  TempDI, di
      push di
      .while < al ne 0>
         .if <al ge 'a'> AND       ; and if a lower case letter
         .if <al le 'z'>
            add  al, 'A'-'a'       ; convert to upper case
            mov  es:[di], al
         .endif
         inc  di
         mov  al, es:[di]
      .endwhile
      pop  di

      call FindSerial              ; @V3.0PMS02 Look for SERIAL= override

      call FindRelaxed

      mov  es, TempES              ; offset to char string
      mov  di, TempDI              ; offset to char string

      call  FindQSize
      .if <c>
         jmp  mi_error
      .endif

      mov  ax, usQSize
      imul ax, ELRec_Size          ; QSize value in AX, use it to
      mov  Eq_Length, ax           ; Calc event que size (Bytes)

      call  FindTypeOverRider
      .if <c>
         jmp  mi_error
      .endif

      .if <TypeOverRider eq TRUE>

         lea  si, TypeName                                          ; SRD 
         .if < <byte ptr [si]  > eq 'N'> AND                        ; SRD 
         .if < <byte ptr [si+1]> eq 'U'> AND                        ; SRD 
         .if < <byte ptr [si+2]> eq 'L'> AND                        ; SRD 
         .if < <byte ptr [si+3]> eq 'L'> AND                        ; SRD 
         .if < <byte ptr [si+4]> eq 'M'> AND                        ; SRD 
         .if < <byte ptr [si+5]> eq 'O'> AND                        ; SRD 
         .if < <byte ptr [si+6]> eq 'U'> AND                        ; SRD 
         .if < <byte ptr [si+7]> eq 'S'> AND                        ; SRD 
         .if < <byte ptr [si+8]> eq 'E'>                            ; SRD 
            mov  fNullMouseParm,TRUE                                ; SRD
            call gmDeviceInit                                       ; SRD 
            jc  mi_error                                            ; SRD
         .else                                                      ; SRD 
           mov  bx, offset TypeName  ; offset to dependent DD name
           mov  di, offset DDD       ; attachDD return structure
           mov  dl, DevHlp_AttachDD  ; function number
           call Device_Help          ; go do the attach
           .if <nc>                  ; if successfull
              or   DDDInit, DI_IDC   ; show IDC init needed
           .else                     ; else we are now attached
              jmp  mi_error
           .endif                    ; end error check on attach
         .endif                                                     ; SRD
      .else
         mov  es, TempES           ; offset to char string  @140921 DCAF
         mov  di, TempDI           ; offset to char string  @140921 DCAF
         call gmDeviceInit
         jc  mi_error
      .endif

      mov  es, TempES                    ; offset to char string
      mov  di, TempDI                    ; offset to char string

      call FindSType

      .if <SType eq TRUE>
        .if <fNullMouse eq FALSE>           ; Skip SType if NullMouse    SRD
           mov  bx, offset STypeName       ; offset to 2nd dependent DD name
           mov  di, offset DDD2            ; attachDD return structure
           mov  dl, DevHlp_AttachDD        ; function number
           call Device_Help                ; go do the attach
           .if <nc>                        ; if successfull
              or   DDDInit, DI_IDC         ; show IDC init needed
           .else                           ; else we are now attached
              jmp  mi_error
           .endif                          ; end error check on attach
        .endif                                                         ; SRD
      .endif

      lea  si, Mouse$                    ; set ds:si -> mouse$ in data seg
      push CSEG2                         ;
      pop  es                            ;
      mov  di, offset PDDCMD_MSEEntry    ; es:di -> 16:16 entry
      mov  dl, DevHlp_RegisterPDD        ; specify function
      call Device_Help                   ; go call function

;*
;*     Now register ourselves with the session manager so that we will be
;*     notified of all screen group switch control.  If that works then
;*     initialize the pre-allocated screen group control blocks (harderror,
;*     shell, and pop-up).  Then set the end of code and data segments so
;*     that both will be shrunk.
;*

      push ds
      push offset SMData
      call DOSSMREGISTERDD

      .if <ZERO ax>
         mov  bx, offset DfltEQs
         lea  si, SG0                    ; offset of SG0
         call InitFSCB2                  ; initialize it
         mov  [si].E_Queue, bx           ; Get pointer to event queue

         lea  si, SG1                    ; offset of SG1
         call InitFSCB2                  ; initialize it
         add  bx, Eq_Length              ; next queue area
         mov  [si].E_Queue, bx           ; store starting offset

         lea  si, SG3                    ; offset of SG3
         call InitFSCB2                  ; initialize it
         add  bx, Eq_Length              ; next queue area
         mov  [si].E_Queue, bx           ; store starting offset
         add  bx, Eq_Length              ; total size of 3 event queues
         mov  dx, bx                     ; size of preallocated event queues
      .else
         jmp  mi_error
      .endif

      mov  es, TempES                    ; restore init packet selector
      mov  bx, TempBX                    ; restore init packet offset

      .if <DeviceData.MouseType eq PDI_DEVICE> AND  ;@140921 DCAF
      .if <ForceMouseON eq FALSE>                   ;@140921 DCAF Make sure we realy have a mouse
         lea   ax, CheckforMSSDevice     ; 56543
      .elseif <DeviceData.MouseType eq MSS_DEVICE>
         lea   ax, INP_Int_Handler
      .elseif <DeviceData.MouseType eq INP_DEVICE>
         lea   ax, BUS_Int_Handler
      .elseif <DeviceData.MouseType eq BUS_DEVICE>
         lea   ax, CheckforPDIDevice
      .else
         lea   ax, PDI_Int_Handler
      .endif

      mov  word ptr es:[bx].InitEcode, ax   ; set end of code
      mov  ax, dx                           ; add size of 3 event queues
      mov  word ptr es:[bx].InitEdata, ax   ; send end of data
      jmp  mi_exit

mi_error:
      pusha
      call _RM_MSE_DestroyDriver
      popa
      mov  es, TempES                    ; LocalVar = Req Blk Selector
      mov  bx, TempBX                    ; LocalVar = Req Blk Offset
      or   es:[bx].PktStatus, INITBAD    ; Flag Hard Init Err = ABORT
      mov  word ptr es:[bx].InitEcode, 0 ; set end of code
      mov  word ptr es:[bx].InitEdata, 0 ; set end of data

mi_exit:
      mov Init_Time, 0
      LeaveProc
      ret                         ; return to strategy

Mouse_Init  EndP

;************************************************************************
;*
;*  FUNCTION NAME :  InitFSCB2
;*
;*  DESCRIPTION   : Initialize the Full Screen Control Block
;*
;*                  This routine is called to initial the control
;*                  block used for a Full Screen Group.
;*
;*  NOTES         : This routine is an exact duplicate of InitFSCB. By
;*                  adding a copy here we are able to put InitFSCB into
;*                  the swappable code segment. This routine is only used
;*                  at init time therefore it will be discarded with
;*                  the rest of the init code.
;*
;*  INPUT         :  ds:si points to the FSCB to initialize
;*
;*  OUTPUT        : ds:si points to the control block
;*
;*  SIDE EFFECTS  :  stack is clean.
;*
;************************************************************************
;* PSEUDOCODE :
;*
;* BeginSub  InitFSCB2
;*
;*  call DDDD(DisableDevice) to disable the mouse
;*  return
;*
;* EndSub  InitFSCB2
;*
;************************************************************************

InitFSCB2  proc  near


        mov [si].Hdle_Cntr, 0        ; Init handle counter to zero

        mov ax, si                   ; Get offset to start of FS CB
        add ax, SRec_Size            ; End of FS CB is start of event queue
        mov [si].E_Queue, ax         ; Get pointer to event queue

        mov [si].Eq_PID, 0           ;
        mov [si].D_Status, 0
        mov [si].Chain_Size, 0       ;
        mov [si].Chain_Hdle, 0       ;
        mov [si].Screen_Entp, 0      ;
        mov [si].Screen_Tble, 0      ;
        mov [si].Screen_DOff, 0      ;
        mov [si].Screen_DSeg, 0      ;
        mov [si].MLength, 0          ;
        mov [si].Ptr_Flags, 0        ;
        mov [si].Cur_Config, 0       ;
        mov [si].CfgOffset, 0        ;
        mov [si].CfgSelector, 0      ;
        mov  [si].ConstrX0,0            ;set the default constraints to
        mov  [si].ConstrY0,0            ;  be outrageously large.  If we get
        mov  [si].ConstrY1,32767        ;    a screen larger than 32767,32767
        mov  [si].ConstrX1,32767        ;      this will be a problem. -RAR
        ret

InitFSCB2  endp

;************************************************************************
;*
;*  FUNCTION NAME :  FindQSize
;*
;*  DESCRIPTION   :  Find the QUEUE size specified by the
;*                     caller via the QSIZE= parameter in the
;*                     CONFIG.SYS file.
;*
;*  FUNCTION      :  This routine is called with ES:DI pointing to the
;*                   first character after DEVICE=. It first looks for
;*                   the last occurance of the backslash '\' character
;*                   and resets the pointer to the next character
;*                   which should be the first character of the device
;*                   driver name. It then resets the pointer to the
;*                   first character after the device driver name.
;*                   It changes all lower case letters to uppercase
;*                   letters for less character testing. It then
;*                   looks for the keywords QSIZE, then =, then
;*                   COM. The next character after COM is the port
;*                   number. The number is checked if it is between
;*                   1 and 8. If so, this number is returned to
;*                   the caller in the AX register with the carry
;*                   flag clear.
;*
;*  ENTRY POINT   :  FindQSize         LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to DEVICE=uest block.
;*
;*  RETURN-NORMAL : Carry flag clear
;*                  AX = com port number
;*
;*  RETURN-ERROR  :  Carry flag set
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*                   Init time strategy request.
;*
;************************************************************************


FindQSize  proc  near

       push  es
       push  si
       push  di

       .while < <byte ptr es:[di]> ne 'Q'>
         .if < <byte ptr es:[di]> ne 0 >
            inc  di
         .else
           .if  <bit EmiFlags nz EMI_ACTIVE>           ;emi
              mov  usQSize, DEFAULT_QSIZE              ;emi
           .else                                       ;emi
              mov  usQSize, 10
           .endif                                      ;emi
           clc                                         ;emi
           jmp fqs_exit
         .endif
       .endwhile

       .if < <byte ptr es:[di+1]> ne 'S'> OR
       .if < <byte ptr es:[di+2]> ne 'I'> OR
       .if < <byte ptr es:[di+3]> ne 'Z'> OR
       .if < <byte ptr es:[di+4]> ne 'E'>
          stc
          jmp  fqs_exit
       .endif

       add di, 5
       call  SkipWhiteSpace

       .if < <byte ptr es:[di]> eq '='>
          inc  di
       .else
          stc
          jmp  fqs_exit
       .endif

       call SkipWhiteSpace

        xor     si,si
nxtdig: mov     al,es:[di]
        cmp     al,' '
        je      eodigs
        cmp     al,TAB
        je      eodigs
        cmp     al,0
        je      eodigs
        cmp     al,'0'
        jl      badext
        cmp     al,'9'
        jg      badext
        xor     ah,ah
        sub     al,'0'
        imul    si,10
        add     si,ax
        inc     di
        jmp short nxtdig
eodigs: cmp     si,0
        jle     badext
notmin: cmp     si,100
        jle     goodex
badext: stc
        jmp short fqs_exit
goodex: mov     usQSize,si
        clc
fqs_exit:
        pop     di
        pop     si
        pop     es
        ret

FindQSize  endp

;************************************************************************
;*
;*  FUNCTION NAME :  FindTypeOverRider
;*
;*  DESCRIPTION   :  Find the TYPE= over rider
;*
;*                   This routine is called with ES:DI pointing to the
;*                   first whitespace character after MOUSE.SYS on the
;*                   DEVICE= line in the CONFIG.SYS file. It will
;*                   search for the first occurance of TYPE= and
;*                   grab the device driver name specified. The
;*                   device driver name will be copied to the TypeName
;*                   location which will be used for idc communication.
;*
;*
;*  ENTRY POINT   :  FindTypeOverRider       LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the first character after MOUSE.SYS
;*                   on the DEVICE= line in the CONFIG.SYS file.
;*
;*                    TypeOverRider has been initialized to TRUE
;*
;*
;*  RETURN-NORMAL : Carry flag clear
;*                          TypeName updated
;*                          TypeOverRider = TRUE if found
;*                                        = FALSE not found
;*
;*                          ES:DI points to the first whitespace character
;*                                after the device name just found.
;*
;*  RETURN-ERROR  :  Carry flag set
;*
;*  EXIT-NOTE     : The TypeOverRider will be set to FALSE if
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT:
;*           Init time strategy request.
;*
;************************************************************************

FindTypeOverRider  proc  near

       push es
       push di
;*                                                                        ;emi
;* the following code fixes a bug in the GA code that wouldn't allow      ;emi
;* QSIZE and TYPE parms                                                   ;emi
;*                                                                        ;emi

       .repeat                                                            ;emi
          mov  al, byte ptr es:[di]                                       ;emi
          .while <al ne 'T'>                                              ;emi
            .if <zero al>              ; At EOL                           ;emi
               mov TypeOverRider,FALSE ; default is TRUE                  ;emi
               clc                     ; indicate NONE found              ;emi
               jmp fto_exit                                               ;emi
             .endif                                                       ;emi
             inc di                                                       ;emi
             mov  al, byte ptr es:[di]                                    ;emi
          .endwhile                                                       ;emi

          inc di                                                          ;emi

          .if < <byte ptr es:[di-2]> ne 'S'> AND  ; Might be "STYPE"      ;emi
          .if < <byte ptr es:[di+0]> eq 'Y'> AND                          ;emi
          .if < <byte ptr es:[di+1]> eq 'P'> AND                          ;emi
          .if < <byte ptr es:[di+2]> eq 'E'>                              ;emi
             add di, 3                                                    ;emi
             call  SkipWhiteSpace                                         ;emi
             .leave <<byte ptr es:[di]> eq '='>   ; Leave when '=' found  ;emi
          .endif                                                          ;emi
       .until                                                             ;emi

       inc  di                                    ; skip the '=' sign     ;emi

       call SkipWhiteSpace

       lea  si, TypeName
       mov  al, es:[di]

       .while < al ne 0>   AND          ; save DD Device Driver entry point
       .while < al ne ' '> AND
       .while < al ne TAB>
          mov  [si], al
          inc  si
          inc  di
          mov  al, es:[di]
       .endwhile

fto_exit:
       pop  di
       pop  es
       ret

FindTypeOverRider  endp

;************************************************************************
;*
;*  FUNCTION NAME :  FindSerial                                @V3.0PMS02
;*
;*  DESCRIPTION   :  Find the SERIAL= keyword
;*
;*                   This routine is called with ES:DI pointing to the
;*                   first whitespace character after MOUSE.SYS on the
;*                   DEVICE= line in the CONFIG.SYS file. It will
;*                   search for the first occurance of SERIAL=
;*
;*  ENTRY POINT   :  FindSerial             LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the first character after MOUSE.SYS
;*                   on the DEVICE= line in the CONFIG.SYS file.
;*
;*
;*  RETURN-NORMAL : Carry flag clear
;*
;*
;*  RETURN-ERROR  :  None
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*           Init time strategy request.
;*
;************************************************************************

FindSerial        proc  near                          ; BEGIN  @V3.0PMS02

       push es
       push di
       mov DeviceData.ComNum, 0        ; Initialize ComNum to zero


       .repeat
          mov  al, byte ptr es:[di]
          .while <al ne 'S'>
            .if <zero al>              ; At EOL
               clc                     ; indicate not found
               jmp fs_exit
             .endif
             inc di
             mov  al, byte ptr es:[di]
          .endwhile

          inc di

          .if < <byte ptr es:[di+0]> eq 'E'> AND
          .if < <byte ptr es:[di+1]> eq 'R'> AND
          .if < <byte ptr es:[di+2]> eq 'I'> AND
          .if < <byte ptr es:[di+3]> eq 'A'> AND
          .if < <byte ptr es:[di+4]> eq 'L'> AND
          .if < <byte ptr es:[di+5]> eq '='> AND
          .if < <byte ptr es:[di+9]> gt '0'> AND
          .if < <byte ptr es:[di+9]> lt '5'>
                mov  al, byte ptr es:[di+9]        ; Get COMx Number
                sub  al,'0'                        ; ASCII to Integer
                mov  DeviceData.ComNum, al         ; Store Number in structure
                clc                                ; Clear Carry
                jmp  fs_exit                       ; Got it so we're done

          .endif

       .until

fs_exit:
       pop  di
       pop  es
       ret

FindSerial        endp                                 ; END  @V3.0PMS02


;************************************************************************
;*
;*  FUNCTION NAME :  FindRelaxed
;*
;*  DESCRIPTION   :  Find the RELAXED keyword
;*
;*                   This routine is called with ES:DI pointing to the
;*                   first whitespace character after MOUSE.SYS on the
;*                   DEVICE= line in the CONFIG.SYS file. It will
;*                   search for the first occurance of RELAXED
;*
;*  ENTRY POINT   :  FindRelaxed             LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the first character after MOUSE.SYS
;*                   on the DEVICE= line in the CONFIG.SYS file.
;*
;*
;*  RETURN-NORMAL : Carry flag clear
;*
;*                    ES:DI points to the first whitespace character
;*                     after the device name just found.
;*
;*  RETURN-ERROR  :  Carry flag set
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*           Init time strategy request.
;*
;************************************************************************

FindRelaxed        proc  near

       push es
       push di

       .repeat
          mov  al, byte ptr es:[di]
          .while <al ne 'R'>
            .if <zero al>              ; At EOL
               clc                     ; indicate not found
               jmp fr_exit
             .endif
             inc di
             mov  al, byte ptr es:[di]
          .endwhile

          inc di

          .if < <byte ptr es:[di+0]> eq 'E'> AND
          .if < <byte ptr es:[di+1]> eq 'L'> AND
          .if < <byte ptr es:[di+2]> eq 'A'> AND
          .if < <byte ptr es:[di+3]> eq 'X'> AND
          .if < <byte ptr es:[di+4]> eq 'E'> AND
          .if < <byte ptr es:[di+5]> eq 'D'>
                mov     Relaxed,1     ; relax our sync checking
          .endif
       .until

fr_exit:
       pop  di
       pop  es
       ret

FindRelaxed        endp


;************************************************************************
;*
;*  FUNCTION NAME :  FindSType
;*
;*  DESCRIPTION   :  Check to see if the STYPE= parameter
;*                     has been specified on the DEVICE=
;*                     line in the CONFIG.SYS file.
;*
;*  FUNCTION      :  This routine is called with ES:DI pointing to the
;*                    first whitespace character after MOUSE.SYS on the
;*                    DEVICE= line in the CONFIG.SYS file.
;*
;*  ENTRY POINT   :  FindSType               LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the first character after MOUSE.SYS
;*                     on the DEVICE= line in the CONFIG.SYS file.
;*
;*                      SType has been initialized to FALSE
;*
;*
;*  RETURN-NORMAL : SType = TRUE if found
;*                     = FALSE not found
;*
;*  RETURN-ERROR  :  Carry flag set
;*
;*  EFFECTS:
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*                    Init time strategy request.
;*
;************************************************************************


FindSType  proc  near
;*
;* the following code fixes a bug in the GA code that wouldn't allow     ;emi
;* QSIZE and STYPE parms                                                 ;emi
;*                                                                       ;emi

       .repeat                                                            ;emi
          mov  al, byte ptr es:[di]                                       ;emi
          .while <al ne 'S'>                                              ;emi
            .if <zero al>                                                 ;emi
               clc                                                        ;emi
               jmp fst_exit                                               ;emi
             .endif                                                       ;emi
             inc di                                                       ;emi
             mov  al, byte ptr es:[di]                                    ;emi
          .endwhile                                                       ;emi
          inc di                                                          ;emi
          .if < <byte ptr es:[di+0]> eq 'T'> AND                          ;emi
          .if < <byte ptr es:[di+1]> eq 'Y'> AND                          ;emi
          .if < <byte ptr es:[di+2]> eq 'P'> AND                          ;emi
          .if < <byte ptr es:[di+3]> eq 'E'>                              ;emi
             add di, 4                                                    ;emi
             call  SkipWhiteSpace                                         ;emi
             .leave <<byte ptr es:[di]> eq '='>                           ;emi
          .endif                                                          ;emi
       .until                                                             ;emi
       inc  di    ; skip the = sign                                       ;emi

       call SkipWhiteSpace

       lea  si, STypeName
       mov  al, es:[di]

       .while < al ne 0>   AND
       .while < al ne ' '> AND
       .while < al ne TAB>
          mov  [si], al
          inc  si
          inc  di
          mov  al, es:[di]
          mov  SType, TRUE
       .endwhile

fst_exit:
       ret

FindSType  endp

;* @DCAF Begin
;************************************************************************
;*
;*  FUNCTION NAME :  FindForceMouseON
;*
;*  DESCRIPTION   :  Find the FORCEON keyword
;*
;*                   This routine is called with ES:DI pointing to the
;*                   first whitespace character after MOUSE.SYS on the
;*                   DEVICE= line in the CONFIG.SYS file. It will
;*                   search for the first occurance of FORCEON
;*
;*  ENTRY POINT   :  FindForceMouseON        LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the first character after MOUSE.SYS
;*                   on the DEVICE= line in the CONFIG.SYS file.
;*
;*
;*  RETURN-NORMAL : Carry flag clear
;*
;*                    ES:DI points to the first whitespace character
;*                     after the device name just found.
;*
;*  RETURN-ERROR  :  Carry flag set
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*           Init time strategy request.
;*
;************************************************************************

FindForceMouseON        proc  near

       push es
       push di

       .repeat
          mov  al, byte ptr es:[di]
          .while <al ne 'F'>
            .if <zero al>             ; At EOL
              clc                     ; indicate not found
              jmp fmo_exit
            .endif
            inc di
            mov  al, byte ptr es:[di]
          .endwhile

          inc di

          .if < <byte ptr es:[di+0]> eq 'O'> AND
          .if < <byte ptr es:[di+1]> eq 'R'> AND
          .if < <byte ptr es:[di+2]> eq 'C'> AND
          .if < <byte ptr es:[di+3]> eq 'E'> AND
          .if < <byte ptr es:[di+4]> eq 'O'> AND
          .if < <byte ptr es:[di+5]> eq 'N'>
            mov  ForceMouseON, TRUE   ; If no mouse attached, lie.
          .endif
       .until

fmo_exit:
       pop  di
       pop  es
       ret

FindForceMouseON   endp
;* @DCAF End


;********************************************************************
;*
;*  FUNCTION NAME :  Emi_Init
;*
;*  DESCRIPTION   :  Initialize EMI
;*
;*  FUNCTION      :  Make connection with the emi driver. Check to see
;*                   if the aux port is being used by the emi driver.
;*
;*                   This is here instead of in EMI.ASM so it will
;*                   get freed after initialization.
;*
;*  ENTRY POINT   :  Emi_Init           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  none
;*                   DS - MOUSE$ data selector
;*
;*  RETURN-NORMAL : OK
;*
;*  RETURN-ERROR  :  Never.
;*
;*  EFFECTS       :  Set global switch indicating if emi is active and
;*                   whether the Aux port is being used.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  NONE
;*
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE
;*     DevHelps   :  AttachDD
;*
;************************************************************************


                                                                        ;emi
Emi_Init proc  near                                                     ;emi
;*                                                                      ;emi
;* attach to the emi driver                                             ;emi
;*                                                                      ;emi

  mov  bx, offset EmiDDName        ; driver name                        ;emi
  mov  di, offset EmiDD            ; attachDD return structure          ;emi
  mov  dl, DevHlp_AttachDD         ; function number                    ;emi
  call Device_Help                 ; go do the attach                   ;emi
  .if  nc                          ; if successfull                     ;emi
     or   EmiFlags,EMI_ACTIVE+EMI_NEED_CONFIG ;present and needs config ;emi
;*                                                                      ;emi
;* see if emi will be using the aux port by searching the device table  ;emi
;* for emi devices that request use of the aux port                     ;emi
;*                                                                      ;emi

     mov  al, DHGETDOSV_DEVICECLASSTABLE                                ;emi
     mov  cx, DEVCLASS_INPUT    ; input class                           ;emi
     mov  dl, DevHlp_GetDOSVar  ; function number                       ;emi
     call Device_Help                                                   ;emi
     .if  nc                                                            ;emi
        mov  es, ax                                                     ;emi
        mov  cx, es:[bx].DCCount                                        ;emi
        .if  <nonzero cx>                                               ;emi
           add  bx,DCTableEntries-DCCount                               ;emi
           .repeat                                                      ;emi
              .if  <bit es:[bx].DCFlags nz REG_EXT_IF> AND              ;emi
              .if  <bit es:[bx].DCFlags nz REG_AUX>                     ;emi
                 or   EmiFlags,EMI_AUX_BUSY ;aux port to be used by emi ;emi
              .endif                                                    ;emi
           .loop                                                        ;emi
        .endif                                                          ;emi
     .endif                                                             ;emi

;*                                                                      ;emi
;* fill in the Mouse Variable Table                                     ;emi
;*                                                                      ;emi

     lea si, EmiMvt                                                     ;emi
                                                                        ;emi
     lea ax, EmiEntryPoint                ; IDC entry point             ;emi
     mov word ptr EmiMvt.EmiEntry,ax                                    ;emi
     mov ax, cs                                                         ;emi
     and ax, 0fff8h                                                     ;emi
     mov word ptr EmiMvt.EmiEntry+2,ax                                  ;emi
                                                                        ;emi
     lea ax,Int_Packet                    ; Interrupt packets           ;emi
     mov word ptr EmiMvt.IntPacket,  ax                                 ;emi
     mov word ptr EmiMvt.IntPacket+2,ds                                 ;emi
     lea ax,SInt_Packet                                                 ;emi
     mov word ptr EmiMvt.SIntPacket,  ax                                ;emi
     mov word ptr EmiMvt.SIntPacket+2,ds                                ;emi
                                                                        ;emi
     lea ax,MEvent.Mon_Time               ; Where to pass time stamp    ;emi
     mov word ptr EmiMvt.TimeStamp,  ax                                 ;emi
     mov word ptr EmiMvt.TimeStamp+2,ds                                 ;emi
                                                                        ;emi
     lea ax,DeviceData                    ; Where to find DeviceData    ;emi
     mov word ptr EmiMvt.SDevData,ax                                    ;emi
     mov word ptr EmiMvt.SDevData+2,ds                                  ;emi
                                                                        ;emi
     lea ax,EMaskMax                      ; Where to find Event Mask    ;emi
     mov word ptr EmiMvt.EventMask,ax                                   ;emi
     mov word ptr EmiMvt.EventMask+2,ds                                 ;emi
                                                                        ;emi
  .endif                                                                ;emi
  ret                                                                   ;emi
Emi_Init  Endp                                                          ;emi

;************************************************************************
;*
;*  FUNCTION NAME :  SkipWhiteSpace
;*
;*  DESCRIPTION   :  This routine will skip over all tabs and
;*                     blank spaces.
;*
;*  FUNCTION      :  This routine is called with ES:DI pointing a
;*                   character string. The pointer will be incremented
;*                   to point to the first non-whitespace character
;*
;*  ENTRY POINT   :  SkipWhiteSpace    LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:DI points to the character string.
;*
;*  RETURN-NORMAL : Always
;*                    ES:DI - will point to the first non-whitespace
;*                       character encountered.
;*
;*  RETURN-ERROR  :  None
;*
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  None.
;*
;*  CONTEXT       :
;*                    Init time strategy request.
;*
;************************************************************************


SkipWhiteSpace  proc  near

        .while < <byte ptr es:[di]> eq ' '> OR
        .while < <byte ptr es:[di]> eq TAB >
           inc  di
        .endwhile
        ret

SkipWhiteSpace  endp

;*********************************************************************
;*
;*  FUNCTION NAME :  gmDeviceInit
;*
;*  DESCRIPTION   :  Generic Pointing Device Support Init
;*
;*  FUNCTION      :  This routine initializes the hardware dependent
;*                   device driver.
;*
;*  ENTRY POINT   :  gmDeviceInit      LINKAGE:  CALL NEAR
;*
;*  INPUT         :  ES:BX points to the request block.
;*
;*  RETURN-NORMAL :  Device is initialized.
;*
;*  RETURN-ERROR  :  Device left disabled.
;*
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES   :  None
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES   :  NONE
;*
;*********************************************************************


gmDeviceInit  Proc  Near
       ;@140921 DCAF Begin
       ?frame = 0                         ; Get Local/Temp Stack Frame
       LocalVar TempES,  WORD             ; For ES register
       LocalVar TempDI,  WORD             ; For DI register

       EnterProc

       mov TempES, es                     ; Save pointer to
       mov TempDI, di                     ;  command line parameters
       ;@140921 DCAF End

;*
;* Now check to make sure we are loading on an ABIOS machine.
;*

       mov  al, 0bh                      ; APD Device ID
       mov  bl, 1                        ; Get 1st LID
       xor  dh, dh                       ; reserved, must be 0
       mov  dl, DevHlp_GetLIDEntry       ; ABIOS function
       call Device_Help                  ; invoke Dev Help

       .if <nc>                          ; If this is an ABIOS machine
           mov  ABIOS_Mch, TRUE          ; ABIOS_Mch initially set to FALSE
           mov  dl, DevHlp_FreeLIDEntry
           call Device_Help              ; give LID back for now
       .elseif < ax ne Error_ABIOS_Not_Present >
           mov  ABIOS_Mch, TRUE
       .endif

;;************************* @V3.0PMS02 BEGIN **************************
;;*
;;* @V3.0PMS02 - The changes from defect #84853 are causing regressions
;;*              on machines which continous data feeds attached to the
;;*              the serial ports.  What needs to be done is to check if
;;*              the user has used the SERIAL= override and implement
;;*              this first (i.e. autodetect which serial port).  We
;;*              keep the basic code in place for compatibility and to
;;*              keep as much of the autodetection code in place.
;;*


       .if <DeviceData.ComNum eq 0>

          .if <bit EmiFlags z  EMI_AUX_BUSY>                             ;emi

             call  CheckforPDIDevice
             .if  <nc>
                mov  DeviceData.MouseType, PDI_DEVICE
                mov  DeviceData.IRQ, 12
                mov  ax, offset PDI_Int_Handler
                jmp  jc1
             .endif

          .endif                                                         ;emi

       .endif                              ; There is no SERIAL= override

;;*************************   @V3.0PMS02 END   ***************************

;;*
;;* 84853 - Move this code down below so it checks for serial mouse first.
;;*
;;*       .if <bit EmiFlags z  EMI_AUX_BUSY>                             ;emi
;;*          call  CheckforPDIDevice
;;*          .if  <nc>
;;*             mov  DeviceData.MouseType, PDI_DEVICE
;;*             mov  DeviceData.IRQ, 12
;;*             mov  ax, offset PDI_Int_Handler
;;*             jmp  jc1
;;*          .endif
;;*       .endif                                                         ;emi

       call  CheckforMSSDevice
       .if  <nc>
          mov  DeviceData.MouseType, MSS_DEVICE
          mov  bx, PortBase
          mov  DeviceData.ComPort, bx
;* AGGGH!  and  bx, 0f00h
;*         inc  bh
;*  THIS   mov  DeviceData.IRQ, bh
;*   IS
;*  VERY   mov  cl, bh
;* COM1-4  mov  ax, 0001h             ; Build 8259 IC Mask
;* SPEC-   shl  ax, cl                ; from returned IRQ #
;*  IFIC

          call MSS_Find_Int           ; find selected interrupt level
          jnc  havint

          mov  bx, PortBase           ; couldn't autodetect... hardwire it
          and  bx, 0f00h
          inc  bh
          mov  DeviceData.IRQ, bh

          mov  cl, bh
          mov  ax, 0001h              ; Build 8259 IC Mask
          shl  ax, cl                 ; from returned IRQ #

havint:   mov  DeviceData.IRQ,bh
          mov  Disable_8259, al       ; Save Disable 8259 Mask
          mov  Disable_28259, ah      ; Save Disable 2nd 8259 Mask
          not  ax                     ; Invert Mask for Enable Bits
          mov  Enable_8259, al        ; Save Enable 8259 Mask
          mov  Enable_28259, ah       ; Save Enable 2nd 8259 Mask

          mov  dx,PortBase            ;DEBUG
          mov  cx,LONGDELAY           ;DEBUG
          call SetupCOMForMouse       ;DEBUG
          call ResetSerialMouse       ;DEBUG

          mov  ax, offset MSS_Int_Handler
          jmp  jc1
       .endif
;;*
;;* 84853  This was moved here from above.
;;*

;;*
;;* @V3.0PMS02 - Although this may appear to be redundant code, we will
;;*              leave the check below for the PDI device.  This allows
;;*              the autodetection mechanism to remain intact in the
;;*              case where the SERIAL= is on the MOUSE.SYS line but
;;*              there is no serial mouse.  EXAMPLE:  Review defect
;;*              84853 which created this problem - An IBM Thinkpad in
;;*              a docking station with the serial mouse attached to the
;;*              docking station.  If the Thinkpad is removed from the
;;*              docking station, now the mouse needs to revert back to
;;*              the PDI interface.  This allows a seamless transition
;;*              and keeps the basic autodetection mechanism working.
;;*

       .if <bit EmiFlags z  EMI_AUX_BUSY>                             ;emi
          call  CheckforPDIDevice
          .if  <nc>
             mov  DeviceData.MouseType, PDI_DEVICE
             mov  DeviceData.IRQ, 12
             mov  ax, offset PDI_Int_Handler
             jmp  jc1
          .endif
       .endif                                                         ;emi

       .if <ABIOS_Mch eq FALSE>
          call CheckforINPDevice
          .if <nc>
             mov  DeviceData.MouseType, INP_DEVICE
             mov  DeviceData.IRQ, al
             mov  ax, offset INP_Int_Handler
             jmp  jc1
          .endif

          call CheckforBUSDevice
          .if <nc>
             mov  First_Port, BUS_First_Possible
             mov  DeviceData.MouseType, BUS_DEVICE
             mov  DeviceData.IRQ, al
             mov  ax, offset BUS_Int_Handler
             jmp  jc1
          .endif

       .endif

; If we reach this point we haven't found any pointing devices. See if user  ; SRD
; specified a null mouse.  If so, install a null mouse unless EMI is active. ; SRD
                                                                             ; SRD
       .if <fNullMouseParm eq TRUE> AND                                      ; SRD
       .if <bit EmiFlags z EMI_ACTIVE>                                       ; SRD
;          mov  DeviceData.MouseType, INP_DEVICE                             ; SRD 
           mov  DeviceData.MouseType, NULL_DEVICE                            ; SRD
           mov  DeviceData.IRQ, 12                                           ; SRD
           mov  ax, offset PDI_Int_Handler                                   ; SRD
           mov  fNullMouse, TRUE                                             ; SRD
           or   DevStatus, gREADENABLE   ; We are now ready for events       ; SRD
           mov  TypeOverRider, FALSE     ; Nullmouse isn't a valid override  ; SRD
           clc                           ; Return no error                   ; SRD
           jmp  jc2                                                          ; SRD 
       .endif                                                                ; SRD 
;*
;* If we reach this point we haven't found any pointing devices. We must
;* still load because the install program has to be able to call the ioctl
;* GetPointerDeviceID.
;*
       ;@140921 DCAF Begin
       mov es, TempES
       mov di, TempDI
       call FindForceMouseON
       ;
       ; Note that the following comparison could set the cy flag
       ;  when ForceMouseON is 0
       ;
       .if <ForceMouseON eq TRUE>              ; If we've been told to lie then
         mov  DeviceData.MouseType, PDI_DEVICE ;  say that we found a PDI
       .endif
       ;
       ;@140921 DCAF End

       clc                                ; nothing found
       jmp  jc2

;*
;* Now go claim the IRQ level.
;*

jc1:
;     If we got here, we detected a pointing device.  If user had specified  ; SRD
;     TYPE=NULLMOUSE, ignore it.                                             ; SRD
       .if <fNullMouseParm eq TRUE>                                          ; SRD
           mov  TypeOverRider, FALSE     ; Nullmouse isn't a valid override  ; SRD
       .endif
       xor bh, bh
       mov bl, DeviceData.IRQ              ; get IRQ needed

       pusha
       push es
       push bx
       call _RM_MSE_AllocIRQ
       or ax, ax
       pop bx
       pop es
       popa
       jne  short IRQTaken

       mov  dh, 01h                        ; share the level
       mov  dl, DevHlp_SetIRQ              ; function number
       call Device_Help                    ; go do it

       .if <c>                             ; if error
          xor  dh, dh                      ; IRQ level as unshared
          call Device_Help                 ; try again
          .if <c>                          ; if error
             jmp  jc2
          .endif
       .endif
IRQTaken:

      .if <DeviceData.MouseType eq PDI_DEVICE>
         call  PDIInit
      .elseif <DeviceData.MouseType eq MSS_DEVICE>
         call  InitComPort
      .elseif <DeviceData.MouseType eq INP_DEVICE>
         call  InportInit
      .elseif <DeviceData.MouseType eq BUS_DEVICE>
         call  BusInit
      .endif

      or   DevStatus, gREADENABLE         ; We are now ready for events

      pusha
      push es
      mov al, DeviceData.MouseType
      xor ah, ah
      push ax
      call _RM_MSE_CreateAdapter
      pop ax
      call _RM_MSE_CreateDevice
      pop  es
      popa

jc2:
       LeaveProc   ;@140921 DCAF
       ret
gmDeviceInit  endp


;******************************************************************************
;*
;* FUNCTION NAME   : SetupForWait
;*
;* DESCRIPTION     : This procedure accepts the number of milliseconds that we
;*                   we will want to delay for and will set things up for wait.
;*
;* ENTRY           : CX            Number of milliseconds to delay for
;*                   GDT_Seg       Gives bimodal address of System Info Seg
;*
;* EXIT            : BX:CX         Dword value giving ending time
;*                   ES:DI         Points at dword in SIS giving current time
;*                   Interrupts enabled
;*
;*                   ALTERS  BX, CX, DI, ES
;******************************************************************************

SetupForWait  proc  near

        xor     bx,bx                 ; BX:CX give # msecs to delay.
        mov     es, GDT_Seg           ; ES address SIS.
        mov     di, SIS_MsCount       ; ES:DI points at msec counter.

        cli                           ; Interrupts off while accessing time.
        add     cx,word ptr es:[di]   ; Determine ending time by adding the
        adc     bx,word ptr es:[di+2] ;  amount of the delay to the time.
        sti                           ; Make sure interrupts are enabled!

        ret

SetupForWait  endp

;*****************************************************************************
;*
;* FUNCTION NAME: IsWaitOver
;*
;* DESCRIPTION  : This procedure accepts the current time and the ending time
;*                and retruns an indication of whether the current time is past
;*                the ending time.
;* ENTRY        :
;*                   BX:CX        Ending time value (double word)
;*                   ES:DI        Points at current time (double word)
;* EXIT         :
;*                   Carry clear  Current time is not past ending time
;*                   Carry set    Current time is past ending time
;*
;*                   ALTERS  none
;******************************************************************************


IsWaitOver  proc  near

        cli                             ; No interrupts (time may change).
        cmp     bx,word ptr es:[di+2]   ; Compare high words first.
                                        ; Current time exceeds ending time,
                                        ;  leave with carry set.
        jne     short iwo_leave         ; Current time does not exceed ending
                                        ;  time, leave with carry clear.
        cmp     cx,word ptr es:[di]     ; High words are equal. Return with
                                        ;  result of comparison of low words.

iwo_leave:                              ; Carry set or clear appropriately.
        sti                             ; Interrupts ok again.
        ret

IsWaitOver  endp

CSEG     ENDS
         END
