;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/

;/*************************************************************************
;*                                                                         
;* SOURCE FILE NAME = STRATEGY.ASM                          
;*                                                                                                               
;* DESCRIPTIVE NAME = Strategy routine, IDC entry point, and                        
;*                    some IDC function support.   
;*
;*                                                                         
;* VERSION      V2.0                                                       
;*                                                                         
;* DATE         10/13/91
;*                                                                         
;* DESCRIPTION  This file is used by all device dependent DDs.                                    
;*              It should be the 2nd module in each device dependent                                                           
;*              DDs link list.
;*              
;* FUNCTIONS     Strategy         Device dependent DD stategy routine.   
;*               DeIns            DeInstall the device driver.           
;*               HIDC_Entry       Hardware DD IDC entry point.                                                                     
;*               Query_Config     Query the mouse hardware configuration.
;*               Read_Enable      Enable interrupt data reporting.       
;*               Read_Disable     Disable interrupt data reporting       
;*               Enable_Device    Enable mouse IRQ level.                
;*               Disable_Device   Disable the mouse IRQ level.           
;*               Deinstall_Device Deinstall the mouse DD.                
;*
;*             
;* STRUCTURES   NONE                                                       
;*                                                                         
;* EXTERNAL REFERENCES   Device_Init, Enable_Device,                                                   
;*                       Disable_Device.                                                               
;*                       DevDone.                                                                
;*                                                                         
;* EXTERNAL FUNCTIONS                                                      
;*                                                                         
;*              NONE                                                       
;*                                                                         
;* CHANGE ACTIVITY =                                                       
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION                       
;*   --------  ----------  -----  --------------------------------------   
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx                                  
;**************************************************************************
                                                                    

.xlist
       include devsym.inc
       include devhlp.inc
       include struc.inc
       include dddd.inc
.list

.286p

;*
;*    External Mouse Module Data References
;*

       extrn msename             : byte
       extrn Disable_8259        : byte
       extrn Enable_8259         : byte
       extrn DeviceData          : byte
       extrn MseDD               : byte

       extrn DevStatus           : word
       extrn IDC_Func            : word
       extrn IntPacketOff        : word
       extrn First_Port          : word
       extrn pComAddr            : word

       extrn Device_Help         : dword

       extrn Device_Init         : near

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

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

       public  Strategy
       public  HIDC_Entry
       public  Query_Config
       public  Read_Enable
       public  Read_Disable
       public  Enable_Device
       public  Disable_Device
       public  DeIns

;********************************************************************
;*                                                               
;*  FUNCTION NAME : Strategy                                   
;*                                                               
;*  DESCRIPTION   : Device dependent DD stategy routine.
;*                                                               
;*                  The routine handles all strategy requests to the
;*                  device dependent DD.  It is generic accross all   
;*                  hardware device drivers.  It supports two device  
;*                  requests, Init and DeInstall.  All others are     
;*                  returned Unknown Command.  The Init request calls 
;*                  the device specific initialization routine.       
;*                  The DeInstall command releases all resources      
;*                  claimed by this DD.                               
;*                                                               
;*  NOTES         : All request use the generic device request packet
;*                  format.
;*                                                               
;*  ENTRY POINT   :  Strategy           (PROTECT MODE ONLY)
;*     LINKAGE    :  CALL FAR
;*                                                               
;*  INPUT         :  ES:BX points to the request packet.
;*                                                               
;*  RETURN-NORMAL :  Request Block status field set to indicate     
;*                   function complete, no error.
;*                                                               
;*  RETURN-ERROR  :  Error codes set in Request Block status field.
;*                                                               
;*  EFFECTS       :  Stack is clean on return, NO registers changed.
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  Device_Init, DeIns                             
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:   DevDone.                                       
;*                                                               
;********************************************************************
;

Strategy  PROC  FAR

;*
;* First check to see if we have been initialized.  If not then the only
;* command that is allowed is an Init command.  If we have been de-installed
;* then no commands are allowed.
;*

       .if <<word ptr Device_Help+2> ne 0>  NEAR  AND  ; DevHelp address valid
       test DevStatus, DEINSTALLED
       .if <z>  near                                   ; and not de-installed
          .if <es:[bx].PktCmd eq CMDDeInstall>         ; If deinstall command
             push es                                   ; save packet selector
             push bx                                   ; and offset
             call DeIns                                ; go deinstall
             pop  bx                                   ; restore packet offset
             pop  es                                   ; and selector
             or   DevStatus, DEINSTALLED               ; flag we are uninstalled
          .else                                        ; else un supported cmd
             mov  es:[bx].PktStatus, UNKNOWNCMD        ; set error
          .endif
       .else                                   ; we have not installed
          .if <es:[bx].PktCmd eq CMDInit>      ; if this is an Init command
             call Device_Init                  ; call generic init command
          .else                                ; else no other commands allowed
             mov  es:[bx].PktStatus, UNKNOWNCMD  ; set error condition
          .endif
       .endif

       or   es:[bx].PktStatus, STDON           ; !! Set Blk Complete Flag   (KB)

       ret                                     ; return to system

Strategy  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  DeIns                                      
;*                                                               
;*  DESCRIPTION   :  DeInstall the device driver.
;*                                                               
;*                   Releases all system resources claimed.  Sets a
;*                   flag disabling support. Runs with Ints disabled.
;*                                                               
;*  ENTRY POINT   :  DeIns             LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  ES:BX points to the request block.
;*                                                               
;*  RETURN-NORMAL :  Always, DD is deinstalled.                     
;*                                                               
;*  RETURN-ERROR  :  N/A
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
;*                   registers are changed.
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  UnSetIRQ.                                       
;*                                                               
;********************************************************************
;

DeIns  PROC  NEAR
;**     ASSUME    CS:CSEG, SS:nothing, ES:nothing, DS:nothing


;*
;* Now go tell MOUSE$ that we are deinstalling.  Only do this if we have
;* already attached to MOUSE$.
;*

       test DevStatus, ATTACHED         ; see if attached to MOUSE$
       .if <nz>                         ; if so then go tell him to quit
          mov  ax, 0002h                ; read_disable function
          push ds                       ; save our ds
          push ds                       ; now put our ds --
          pop  es                       ; in es
          mov  ds, es:mseDD.ProtDS      ; set protect mode ds and
          call es:mseDD.ProtEntry       ; call protect mode entry
          pop  ds                       ; restore our ds value
       .endif

;*
;* Now call Deinstall_Device to do device specific shutdown as required.
;*

       call Deinstall_Device

;*
;* Last thing to do is release the IRQ level.
;*

       mov  bl, DeviceData.IRQ          ; Interrupt vector #
       xor  bh, bh
       mov  dl, DevHlp_UnSetIRQ         ; Devhelp function number
       call Device_Help                 ; Invoke UnSetIRQ Function

       ret                              ; Return to Request Handler Rtn.
DeIns  ENDP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  HIDC_Entry                                 
;*                                                               
;*  DESCRIPTION   :  Hardware DD IDC entry point.
;*                                                               
;*                   Route all IDC function requests.
;*
;*  ENTRY POINT   :  HIDC_Entry        LINKAGE:  CALL FAR
;*                                                               
;*  INPUT         :  AX = function code
;*                   DS = our DS
;*                   ES = callers DS
;*                   Other functions require register setup
;*                                                               
;*  RETURN-NORMAL :  Function performed, carry clear                
;*                                                               
;*  RETURN-ERROR  :  Function rejected, carry set.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
;*                   registers are changed.
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  Query_Config, Read_Enable, Read_Disable,       
;*                Enable_Device, Disable_Device                  
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  None.                                           
;*                                                               
;********************************************************************


HIDC_Entry  Proc  Far


;*
;* Check the function range.  If valid then call the appropriate function.
;* The routine called will set the carry flag and AX return values.  If the
;* function is not supported then the carry is set and AX is set to 1.
;*

       push bx                    ; !! save bx                       (KA)

       .if <ax ae 1>  AND         ; check the function range.
       .if <ax be 5>  AND         ; If it is in range then
       test DevStatus, DEINSTALLED  ; and we are not deinstalled
       .if <z>
          mov  bx, ax             ; put function number in bx for call
          dec  bx                 ; base call at 0 offset in table
          shl  bx, 1              ; convert to word call
          call IDC_Func[bx]       ; the requested funtion using the call table.
       .else                      ; Otherwise the function is out of
          stc                     ; range so set the the carry flag and
          mov  ax, 1              ; make AX non-zero.
       .endif                     ; End function range tests

       pop  bx                    ; !! restore bx                    (KA)
       ret                        ; return

HIDC_Entry  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Query_Config                               
;*                                                               
;*  DESCRIPTION   :  Query the mouse hardware configuration.
;*                                                               
;*                   Wrtie the mouse hardware device configuration
;*                   data to the address in ES:DI.
;*                                                               
;*  ENTRY POINT   :  Query_Config      LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  AX = function code                                   
;*                   DS = our DS                                          
;*                   ES = callers DS                                      
;*                   DI = offset to config data buffer                    
;*                                                                        
;*  RETURN-NORMAL :  Data written to buffer.  (always) carry clear  
;*                                                               
;*  RETURN-ERROR  :  N/A.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI  
;*                   registers are changed.                             
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None                                           
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  None.                                           
;*                                                               
;********************************************************************


Query_Config  Proc  Near

       mov  cx, es:[di].CfgDataLen          ; get length of data requested
       .if <cx gt CFGDATLEN>                ; if more than 6 bytes then
          mov  cx, CFGDATLEN                ; limit to 6 bytes
       .endif
       mov  si, offset DeviceData           ; get offset to device data
       cld                                  ; go forward
       rep  movsb                           ; move data to callers data area
       clc                                  ; clear carry for no error
       ret                                  ; return to IDC router

Query_Config  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Read_Enable                                
;*                                                               
;*  DESCRIPTION   :  Enable interrupt data reporting.
;*                                                               
;*                   Enables reporting of interrupt data packets to    
;*                            the independent DD.                               
;*                                                               
;*  ENTRY POINT   :  GIDC_Entry        LINKAGE:  CALL FAR
;*                                                               
;*  INPUT         :  AX = function code                                   
;*                   DS = our DS                                          
;*                   ES = callers DS                                      
;*                   DI = offset of interrupt packet data buffer          
;*                                                               
;*  RETURN-NORMAL :  Data reporting enabled, attached to MOUSE$,    
;*                    carry clear.
;*                                                               
;*  RETURN-ERROR  :  Carry set, data reporting still disabled.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
;*                   registers are changed.
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  AttachDD                                        
;*                                                               
;********************************************************************


Read_Enable  Proc  Near

       cli                                 ; disable interrupts
       test  DevStatus, ATTACHED           ; see if already attached to MOUSE$
       .if <z>                             ; No so lets go attach ourselves
          push di                          ; save input data area offset
          mov  bx, offset MseName          ; get offset to mouse name
          mov  di, offset MseDD            ; offset to put Attach addresses
          mov  dl, DevHlp_AttachDD         ; DevHelp function
          call Device_Help                 ; do the function
          pop  di                          ; restore input data rea offset
          .if <nc>                         ; if the AttachDD worked
             or   DevStatus, ATTACHED      ; indicate we're attached to MOUSE$
             or   DevStatus, READENABLE    ; set flag to enable intrpt reporting
             mov  IntPacketOff, di         ; save input data area offset
             clc                           ; set no error flag
          .else                            ; there was an error
             mov  ax, 1                    ; 1 = attach to MOUSE$ failed
             stc                           ; set error code for mouse$
          .endif                           ; end AttachDD worked test
       .else                               ; else already attached to MOUSE$
          or   DevStatus, READENABLE       ; Set flag to enable intrpt reporting
          clc                              ; clear error flag
       .endif                              ; end attached tests

       sti                                 ; enable interrupts
       ret                                 ; return to IDC router

Read_Enable  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Read_Disable                               
;*                                                               
;*  DESCRIPTION   :  Disable interrupt data reporting
;*                                                               
;*                   Disables the reporting of interrupt data packets
;*                    to the independent DD.
;*                                                               
;*  ENTRY POINT   :  Read_Disable      LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  AX = function code                                   
;*                   DS = our DS                                          
;*                   ES = callers DS                                      
;*                                                               
;*  RETURN-NORMAL :  Always, data reporting disabled.               
;*                                                               
;*  RETURN-ERROR  :  N/A.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI  
;*                   registers are changed.                             
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  None.                                           
;*                                                               
;********************************************************************
;

Read_Disable  Proc  Near

       cli                              ; disable ints for flag update
       or   DevStatus, NOT READENABLE   ; set flag to disable data reporting
       sti                              ; enable ints
       clc                              ; no errors
       ret                              ; return to IDC router

Read_Disable  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Enable_Device                              
;*                                                               
;*  DESCRIPTION   :  Enable mouse IRQ level.
;*                                                               
;*                   Enables the mouse device IRQ level at the 8259.
;*                                                               
;*  ENTRY POINT   :  Enable_Device     LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  AX = function code                                   
;*                   DS = our DS                                          
;*                   ES = callers DS                                      
;*                                                               
;*  RETURN-NORMAL :  Always, mouse IRQ enabled.                     
;*                                                               
;*  RETURN-ERROR  :  N/A.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI  
;*                   registers are changed.                             
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  None.                                           
;*                                                               
;********************************************************************
;

Enable_Device  Proc  Near

       or   DevStatus, DEVICEENABLED   ; show device is enabled
       pushf                           ; save state of IF
       cli                             ; Hold interrupts for 8259 Update
       in   al, 21h                    ; Get current Interrupt Mask
       and  al, Enable_8259            ; Set Mouse Interrupt IRQ Bit - OFF
       out  21h, al                    ; set innterrupt mask
       popf                            ; restore interrupt flag state
       xor  ax, ax                     ; set no error code
       clc                             ; no errors
       ret

Enable_Device  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Disable_Device                             
;*                                                               
;*  DESCRIPTION   :  Disable the mouse IRQ level.
;*
;*                   Disables the mouse IRQ level at the 8259.
;*                                                               
;*  ENTRY POINT   :  Disable_Device      LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  AX = function code
;*                   DS = our DS
;*                   ES = callers DS
;*                                                               
;*  RETURN-NORMAL :  Always, Mouse IRQ level disabled.              
;*                                                               
;*  RETURN-ERROR  :  N/A.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
;*                    registers are changed.
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*     DevHlps:  None.                                           
;*                                                               
;********************************************************************
;

Disable_Device  Proc  Near

       and  DevStatus, NOT DEVICEENABLED  ; show device is disabled
       pushf                              ; save state of IF
       cli                             ; Hold interrupts for 8259 Update
       in   al, 21h                    ; Get current Interrupt Mask
       or   al, Disable_8259           ; Set Mouse Interrupt IRQ Bit - ON
       out  21h, al                    ; Reset 8259 holding Mouse ints
       popf                            ; restore interrupt flag
       xor  ax, ax                     ; set no error code
       clc                             ; no error
       ret

Disable_Device  EndP


;********************************************************************
;*                                                               
;*  FUNCTION NAME :  Deinstall_Device                           
;*                                                               
;*  DESCRIPTION   :  Deinstall the mouse DD.
;*                                                               
;*                   This routine handles the specifis of deinstalling
;*                    the attached mouse device.  The general resource
;*                    releasing is done at a higher level and is
;*                    common to all supported devices.
;*                                                               
;*  ENTRY POINT   :  Deinstall_Device    LINKAGE:  CALL NEAR
;*                                                               
;*  INPUT         :  None.
;*                                                               
;*  RETURN-NORMAL :  Always.                                        
;*                                                               
;*  RETURN-ERROR  :  N/A.
;*                                                               
;*  EFFECTS       :  Stack is clean on return.                          
;*                   registers may be changed.                          
;*                                                               
;*  INTERNAL REFERENCES:                                         
;*     ROUTINES:  None.                                          
;*                                                               
;*  EXTERNAL REFERENCES:                                         
;*     ROUTINES:  NONE.                                          
;*                                                               
;********************************************************************

Deinstall_Device  Proc  Near

;*
;* release the ROM BIOS data area so someone can use the COM port
;*

       push es                         ; Save Init RB Selector
       mov  ax, CRT_Data_Seg           ; Get ROM BIOS Data Seg
       mov  es, ax                     ; Loaded into ES Reg
       mov  di, pComAddr               ; Get COMx 40:Offset value
       mov  ax, First_Port             ; Get COMx Base Port Address
       mov  word ptr es:[di], ax       ; Restore Port # in ROM BIOS
       pop  es                         ; Restore RB Selector
       ret

Deinstall_Device  EndP

CSEG     ENDS
         END
