;*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 = PDI.ASM
;*
;* DESCRIPTIVE NAME = Pointing Device Interface (PDI) code
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/19/92
;*
;* DESCRIPTION  This file contains the PDI specific routines used
;*              by the generic pointing device driver.
;*
;*              Currently known and supported PDI devices are;
;*
;*              IBM PS/2 Mouse
;*              MS PS/2 Mouse
;*              Logitech PS/2 Mouse
;*              Kensington Expert Mouse (really trackball device)
;*
;* FUNCTIONS    CheckforPDIDevice
;*              Enable_Ints        -Enable keyboard Interface
;*              ResetMouse         -Reset PS/2 mouse.
;*              IsScrnKeypad       -Determine if a ScreenReader 18-key
;*                                   keypad is plugged into PDI port
;*              ResetPrescott      -Reset prescott display
;*              WriteInputBuffer   -Send a byte of data to 8042 (port 60h).
;*              SendToMouse        -Send command to auxillary device
;*              Read8042Data       -Wait until there is data in the output
;*                                  buffer and return it in AL.
;*              GetMouseData       -Read a byte of data to auxillary device
;*              SetSampleRate      -Send the SetSampleRate Command (0f3h)
;*                                   to the Aux device
;*              SetScaling         -Send the SetScaling 2:1 Command (0E7h)
;*              SetResolution      -Send the SetResolution Command (0e8h)
;*                                   to the Aux device.
;*              EnablePDI          -Enable the Aux Device
;*              ClearAuxPort       -Read all Aux port data
;*            WriteControlRegister -Send a command byte to the
;*                                   8042's control register (64h)
;*              PDIInit            -Gets the PDI LID if on ABIOS system
;*
;*
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   04/04/93              53232  Add support for Logitech middle button
;**************************************************************************



.xlist
       include basemaca.inc
       include mouse.inc
.list

.386p

;*
;*    External Mouse Module Data References
;*

       extrn TranslateMode       : byte
       extrn AUXPortExists       : byte
       extrn DeviceData          : byte
       extrn ABIOS_Mch           : byte
       extrn PrescottDsp         : byte
       extrn ScreenKeypad        : byte
       extrn Init_Time           : byte

       extrn Int_Packet          : word
       extrn SynchFlag           : word                ;           

       extrn HotPlugHandle       : dword
       extrn Device_Help         : dword

       extrn SetupForWait        : near
       extrn IsWaitOver          : near
       extrn HookHotPlugPDI      : far

       extrn  WriteControlRegister : near

       extrn  _RM_MSE_AllocPorts   : far
       extrn  _RM_MSE_AllocPort2   : far
       extrn  _RM_MSE_DeallocPorts : far
       extrn  _RM_MSE_DeallocPort2 : far

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

       public  CheckforPDIDevice
       public  Enable_Ints
       public  ResetMouse
       public  ResetPrescott
       public  WriteInputBuffer
       public  SendToMouse
       public  Read8042Data
       public  GetMouseData
       public  SetSampleRate
       public  SetScaling
       public  SetResolution
       public  EnablePDI
       public  ClearAuxPort
       public  PDIInit
       public  EnableKbdInt
       public  DisableKbdInt
       public  Find3ButtonMouse                      ;           

;************************************************************************
;*
;*  FUNCTION NAME  :  CheckforPDIDevice
;*
;*  DESCRIPTION    :  This routine firsts issues the Disable Keyboard
;*                    Interface (ADh) to the controller. It then issues
;*                    a Write Controller Ram (60h) command. It writes
;*                    a 54h to the controller where the bits are
;*                    defined below.
;*
;*  We need to disable interrupts for both keyboard and mouse
;*  during this init routine. There are various controller
;*  commands that would cause an IRQ 1. The keyboard DD would
;*  probably think the interrupt was a scan code and get
;*  confused. The mouse does not register its interrupt handler
;*  until the end of the init routine which makes sense. Why
;*  complicate the interrupt handler when the only thing
;*  needed after init time is mouse event handling
;*
;*
;*  ENTRY POINT   : CheckforPDIDevice   LINKAGE:  CALL NEAR
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL : Carry Flag clear
;*
;*  RETURN-ERROR  :  Carry Flag Set
;*
;*  EFFECTS       :  Changes ES
;*
;*  INTERNAL REFERENCES:
;*     ROUTINES:  None.
;*
;*  EXTERNAL REFERENCES:
;*     ROUTINES:  NONE.
;*     DevHlps:  None.
;*
;*            This routine firsts issues the Disable Keyboard
;*            Interface (ADh) to the controller. It then issues
;*            a Write Controller Ram (60h) command. It writes
;*            a 54h to the controller where the bits are
;*            defined below;
;*
;*************************************************************************

CheckforPDIDevice  proc  near

;*************************************************************************
;* WARNING 10/24/91:
;*
;* It is necessary to first check if POST has found a pointing device
;* plugged into the AUX (PS/2) port. Some clones were responding to the
;* test AUX interface command (0a9h) as if they had a system mouse port
;* when in fact they did not. When the preceeding AUX commands were sent
;* to the controller the 8042 clone chip was leaving the keyboard in a
;* disabled state. The word at 40h:10h is defined as the Equipment flags
;* word. This word can also be retrieved via an Int 11h call. Bit 2 of
;* this word is the Pointing device installed bit. POST will attempt to
;* do a reset (0ffh) command to the AUX device. If the AUX device responds
;* with an 0aah (POR complete) this bit is turned ON. This is supposed to
;* be an industry standard and every system seems to set this bit correctly
;* to date.
;**************************************************************************

       push 40h
       pop  es
       mov  ax, word ptr es:[10h]     ; Equipment flags
       test ax, 4                     ; Bit 2 - Pointing device installed
       jnz  pdi_ok
       cmp  ABIOS_Mch,TRUE            ; ABIOS machines ALWAYS have PDI port
       jz   pdi_ok
       stc
       jmp  pdi_return

pdi_ok:
       mov al, Init_Time
       .if <al ne 0>
          pusha
          push es
          push 60h
          call _RM_MSE_AllocPorts
          pop dx
          or ax, ax
          jnz short PortPDIClaimed
          push 64h
          call _RM_MSE_AllocPort2
          or ax, ax
          pop ax
PortPDIClaimed:
          pop es
          popa
          jnz  pdi_claimed
       .endif

       call DisableKbdInt             ; disable keyboard interrupt

       mov  al, 0adh                  ; Disable the keyboard.
       call WriteControlRegister      ; send command to controller (64h)
       jc   pdi_error

       mov  al, 20h                   ; Tell 8042 that we want to read the
       call WriteControlRegister      ; controller command byte from (60h)
       jc   pdi_error

       call Read8042Data              ; read the controller command byte.
       jc   pdi_error

       and  al, 40h
       mov  TranslateMode, al         ; save keyboard translate mode

       mov  al, 60h                   ; Tell 8042 that we want to write the
       call WriteControlRegister      ; controller command byte from (60h).
       jc  pdi_error


;**************************************************************************
;* The bit definitions for the controller command byte on any system that
;* has an AUX port are listed below;
;*
;*      Bit   Function
;*
;*  0  7 -  Reserved (Always set to 0)
;*  1  6 -  IBM Keyboard Translate Mode
;*  0  5 -  Disable AUX Device  (0 = Enabled state, 1 = disabled state)
;*  1  4 -  Disable Keyboard    (0 = Enabled state, 1 = disabled state)
;*  0  3 -  Reserved (Always set to 0)
;*  1  2 -  System Flag (Always set to 1)
;*  0  1 -  Enable Auxiliary Interrupt (0 = No Aux Ints, 1 = AUX ints enabled)
;*  0  0 -  Enable Keyboard Interrupt  (0 = No Kbd Ints, 1 = Kbd ints enabled)
;*
;* NOTE: I have noticed that this byte is initially set to 65h on systems
;*       with an AUX port and 45h on systems without an AUX port.
;*
;* WARNING!!! On family1 systems without an AUX port the AUX related
;*            bits (1 and 5) should always be set to zero.
;**************************************************************************

       mov  al, 54h                   ; Write the command byte to controller
       call WriteInputBuffer          ; Send it to 8042 port (60h).
       jc  pdi_error

;*
;* We will now issue the 8042 command to test the auxiliary interface.
;* This command only exists on 8042s that support an auxiliary device. If
;* the test succeeds, a 00h will be placed in the 8042's output buffer.
;* If no output appears in the 8042's output buffer, it is assumed that the
;* 8042 does not support an auxiliary device.
;*

;*
;* WARNING: The testing of the auxiliary interface will more than likely
;*       up an auxiliary device attached to it. Therefore, the auxiliary
;* device should be initialized after calling this procedure.
;*
       mov  al, 0a9h                  ; Command to test the auxiliary
       call WriteControlRegister      ; device.
       jc   pdi_error                 ; Leave if error.

       call Read8042Data              ; Read test results from port (60h)
       jc   pdi_error                 ; No auxiliary device.

;*
;* WARNING - On certain clones I have noticed that we consistantly
;* get back a 01 from the 0xA9 command. This means that the AUX device
;* clock line is stuck low. If we ignore this error and continue on
;* everything works ok. The reset command follows so it is sufficient
;* to say that if we get data back from the 8042 then we have an AUX
;* port. The rest of the code will ensure that a functional pointing
;* device is attached to the system.  (3/4/92)
;*

;***   .if <ZERO al>                  ; Was the byte we got 0?
          mov  AUXPortExists, TRUE    ; It was initialized to FALSE
;**  .else
;**     jmp  pdi_error
;**  .endif

       call IsScrnKeypad              ; is it a screen reader keypad?
       jc   notpres

       call ResetPrescott
notpres:

       call ResetMouse
       jc  pdi_error

       call Find3ButtonMouse          ;           

       call SetSampleRate
       jc  pdi_error

       call SetResolution
       jc  pdi_error

       call SetScaling
       jc  pdi_error

       call EnablePDI
       jc  pdi_error

;*
;* Now enable the keyboard and aux interfaces and the aux interrupts.
;*
       mov  bl, 07h                   ; both kbd and aux
       or   bl, TranslateMode
       call Enable_Ints
       .if  <nc>
          mov  DeviceData.IRQ,12      ; set IRQ level (system defined)
          jmp  pdi_exit
       .endif

pdi_error:
       .if <AUXPortExists eq TRUE>
          mov  bl, 25h                ; We have an AUX port
          or   bl, TranslateMode
          call Enable_Ints
          mov  al, 0a7h               ; Disable Auxilary Device Interface
          call WriteControlRegister
          call ClearAuxPort           ; clear the aux port
       .else
          mov  bl, 05h                ; No AUX port, bits are slightly different
          or   bl, TranslateMode
          call Enable_Ints
       .endif

       mov al, Init_Time
       .if <al ne 0>
          pusha
          push es
          call _RM_MSE_DeallocPorts
          call _RM_MSE_DeallocPort2
          pop es
          popa
       .endif

pdi_claimed:
       stc

pdi_exit:
       call EnableKbdInt              ; enable keyboard interrupt
pdi_return:
       ret

CheckforPDIDevice  endp


;****************************************************************
;*
;*  FUNCTION NAME  :  Enable_Ints
;*
;*  DESCRIPTION    :  Enable keyboard interface
;*
;*                    This routine firsts issues an Enable Keyboard
;*                    Interface (AEh) to the controller. It then issues
;*                    a Write Controller Ram (60h) command. It writes
;*                    the caller's value to the controller RAM.
;*
;*  ENTRY POINT   :  Enable_Ints       LINKAGE:  CALL NEAR
;*
;*  INPUT         :  BL = value to write to controller RAM
;*
;*  RETURN-NORMAL :  Keyboard enabled and IRQ 1 activated.
;*
;*  RETURN-ERROR  :  N/A.
;*
;*  EFFECTS       :  None
;*
;*
;****************************************************************

Enable_Ints  proc  near

        mov  al, 0aeh                  ; Enable the keyboard.
        call WriteControlRegister      ; send command to controller (64h)
        jc   ei_exit

        mov  al, 60h                   ; Tell 8042 that we want to write the
        call WriteControlRegister      ; command byte.
        jc   ei_exit                   ; Leave if we have an error.

        mov  al, bl                    ; Write callers value
        call WriteInputBuffer          ; Send it to 8042.

ei_exit:
        ret

Enable_Ints  endp


;****************************************************************
;*
;*  FUNCTION NAME :  ResetMouse
;*
;*  DESCRIPTION   : This procedure attempts to reset a PS/2
;*                    mouse. It does this by sending a reset
;*                    command to the mouse and checking to
;*                    ensure that it passed its diagnostics.
;*
;*   INPUT        :  Mouse interrupts disabled.
;*
;*   OUTPUT       :   Carry clear     Mouse has been reset correctly
;*                     AL              ID Code
;*
;*   RETURN-ERROR :  Carry set  Error condition.
;*
;*   ALTERS       : AX, CX
;*
;*   CALLS        : SendToMouse, GetMouseData
;*
;****************************************************************

ResetMouse  proc  near

        mov   al, 0ffh                ; Send the reset command to the mouse.
        call  SendToMouse
        jc   rm_exit
        call GetMouseData             ; Get response from the mouse
        .if <al ne 0fah>
           stc
           jmp  rm_exit
        .endif

        call GetMouseData             ; Get response from the mouse
        .if <al ne 0aah>
           stc
           jmp  rm_exit
        .endif

        call GetMouseData             ; Get response from the mouse
        .if <ZERO al>
           clc
        .else
           stc
        .endif

rm_exit:
        ret

ResetMouse  endp


;****************************************************************
;*
;*  FUNCTION NAME :  IsScrnKeypad
;*
;*  DESCRIPTION   :  This procedure attempts to determine
;*                   if a ScreenReader 18-key keypad is
;*                   plugged into the PDI port
;*
;*  INPUT         :  This routine must be called after the 8042 has
;*                   been put in disable mode.
;*
;*  OUTPUT        :  Carry clear     No keypad attached
;*                   Carry set       Keypad attached
;*
;****************************************************************

IsScrnKeypad proc  near
        mov   al, 0f2h                ; Read the device type attached
        call  SendToMouse
        jc   ik_exit

        call GetMouseData             ; Get response (should be ACK x'FA')
        cmp  al,0FAh
        jne  ik_exit

        call GetMouseData             ; Get ID (should be x'01' for pad)
        cmp  al,01
        jne  ik_exit
        mov  ScreenKeypad,TRUE
        stc
        ret
ik_exit:
        clc
        ret

IsScrnKeypad endp


;****************************************************************
;*
;*  FUNCTION NAME  : ResetPrescott
;*
;*  DESCRIPTION    : This procedure attempts to reset a
;*                    Prescott display by sending a reset
;*                    command to the device and checking to
;*                    ensure that it passed its diagnostics.
;*
;*   INPUT         : Mouse interrupts disabled.
;*
;*   OUTPUT        : Carry clear     Mouse has been reset correctly
;*                     AL              ID Code
;*
;*   EXIT ERROR    : Carry set  Error condition.
;*
;*   ALTERS        : AX, CX
;*
;*   CALLS         : SendToMouse, GetMouseData
;*
;****************************************************************

ResetPrescott proc  near

        mov   al, 0bbh                ; Send the reset command to the
        call  SendToMouse             ; 8516 Touch Display
        jc   rp_exit

        call GetMouseData             ; Get response from the 8516 display
        .if <al ne 0cah>
           stc
           jmp  rp_exit
        .endif

        mov  dx, 99
rp_loop:
        mov  cx, 100                  ; Wait for 100 millisecs
        call SetupForWait
        .repeat
           call IsWaitOver
        .until <c>

        in   al, 64h                 ; Get current 8042 status.
        and  al, 21h                 ; We're only interested in Aux OBF bits
        cmp  al, 21h                 ; If OBF and Aux data then
        jz   rp_data                 ; It's OK to proceed
        dec  dx
        jnz  rp_loop
        stc
        jmp  rp_exit

rp_data:                             ; There is mouse data to be read.

        in   al, 60h                 ; Read byte of data from Prescott
        mov  bl, al
        in   al, 64h
        test al, 0c0h                ; Parity Error + General Time-Out bits
        jnz  rp_loop                 ; should be off

        .if <bl ne 0abh> AND
        .if <bl ne 0cdh>
           stc
           jmp  rp_exit
        .endif

        call GetMouseData             ; Get response from the mouse
        .if <al eq 2>
           mov  PrescottDsp, TRUE
           clc
        .else
           stc
        .endif

rp_exit:
        ret

ResetPrescott  endp


;****************************************************************
;*
;*  FUNCTION NAME :  WriteInputBuffer
;*
;*  DESCRIPTION   : This procedure will send a byte of data to the
;*                  8042 (port 60h).
;*
;*  NOTES         : Before the data is sent to the 8042 both the input
;*                  buffer full and output buffer full bits of the status
;*                  register must be off.
;*
;*               This procedure sends a byte of data to the 8042's
;*               input buffer. It should not be called unless the
;*               8042 has already been set up to expect this byte of data.
;*
;*               Only 64K attempts will be made before timing out.
;*
;*   INPUT        : AL - Data byte to be sent.
;*
;*   OUTPUT       : Carry clear - Data sent sucessfully
;*                  Carry set   - Data not sent, error condition.
;*
;*   ALTERS       : CX register
;*
;****************************************************************

WriteInputBuffer  proc  near

;*
;* Upon entry, it is assumed that a command has just been sent to the
;*  8042. Therefore, we will wait until the 8042 has removed the command
;*  byte from its input buffer before doing anything else.
;*

        push ax                      ; Save callers value to be written
        xor  cx, cx                  ; Loop counter

wib_retry:
        in   al, 64h                 ; Get 8042's current status.
        test al, 03h                 ; Is the in/out buffer still full?
        jz   wib_ok                  ; It's OK to proceed
        loop wib_retry               ; Try again.
        stc                          ; Error condition
        pop  ax                      ; Callers value on top of stack
        jmp  short wib_exit          ; Return with failure.

wib_ok:                              ; Input and output buffers are empty.
        pop  ax                      ; Get saved data byte.
        out  60h, al                 ; Send data byte.
        clc                          ; Show success.

wib_exit:
        ret

WriteInputBuffer  endp


;****************************************************************
;*
;*  FUNCTION NAME : SendToMouse
;*
;*  DESCRIPTION   : This procedure will send a command to the
;*                  auxiliary device
;*
;*  NOTES         : The routine first sends a Write to Auxiliary Device
;*                  (D4h) command to the controller. It then sends the
;*                  callers command which was passed in (AL register)
;*                  to port 60h which is the Aux device at this time.
;*
;*   INPUT        :  AL - Command to be sent.
;*
;*   OUTPUT       :  Carry clear - Command sent sucessfully
;*                   Carry set   - Command not sent, error condition.
;*
;****************************************************************

SendToMouse  proc  near

        push ax                      ; Save command/data byte.
        mov  al, 0d4h                ; Tell 8042 we want to send a byte to
        call WriteControlRegister    ; the auxiliary device.
        pop  ax                      ; Get saved command/data byte.
        jc   stm_exit                ; Leave if error.
        call WriteInputBuffer        ; Send data/command to aux dev.
stm_exit:
        ret

SendToMouse  endp


;****************************************************************
;*
;*  FUNCTION NAME  :  Read8042Data
;*
;*  DESCRIPTION    : This procedure will wait until there is data
;*                   in the output buffer and return it in AL.
;*
;*  NOTE: Before the data is read the output buffer full bit
;*        must be on in the 8042 Controller Status Register.
;*
;*        Only 64K attempts will be made before timing out.
;*
;*  INPUT         : N/A
;*
;*  OUTPUT        :  Carry clear - AL holds the data byte
;*                   Carry set   - Error condition.
;*
;****************************************************************

Read8042Data  Proc  Near

        xor  cx,cx

rd_retry:
        in   al, 64h              ; Read status port of 8042
        test al, 01h              ; Is the output buffer full
        jnz  rd_ok                ; If so, it's OK to proceed
        loop rd_retry             ; try again
        stc                       ; Error condition
        jmp  rd_exit

rd_ok:
        in  al, 60h               ; get data
        clc                       ; clear carry for no error

rd_exit:
        ret

Read8042Data  endp


;****************************************************************
;*
;*  FUNCTION NAME :  GetMouseData
;*
;*  DESCRIPTION   : This procedure will try to read a byte of
;*                  data from the auxiliary device.
;*
;*  NOTE: Only 15*64K attempts will be made before timing out.
;*
;*        I have seen instances where 64K times is not
;*        enough time for the AUX output buffer full bit to
;*        turn on. This happened on the reset mouse command.
;*        It seems that 15*64K is enough for all systems to
;*        date. (WARNING - 8/15/90)
;*
;*   INPUT        :  N/A
;*
;*   OUTPUT       : Carry clear     Read was successfully
;*                  AL              The byte of data that was read
;*
;*                  Carry set       The byte of data could not be read
;*
;*   ALTERS       : CX and AX registers
;****************************************************************

GetMouseData  Proc  Near


        mov  ah, 15                  ; Outer loop counter is 15
gmd_outer:
        xor  cx,cx                   ; Inner loop counter is 64K
gmd_inner:
        in   al, 64h                 ; Get current 8042 status.
        and  al, 21h                 ; We're only interested in Aux OBF bits
        cmp  al, 21h                 ; If OBF and Aux data then
        jz   gmd_ok                  ; It's OK to proceed
        loop gmd_inner               ; Keep trying the desired number of
        dec  ah
        jnz  gmd_outer
        xor  al,al
        stc
        jmp  gmd_exit

gmd_ok:                              ; There is mouse data to be read.
        in   al, 60h                 ; Read byte of data from mouse.
        clc

gmd_exit:
        ret

GetMouseData  endp


;****************************************************************
;*
;*  FUNCTION NAME  :  SetSampleRate
;*
;*  DESCRIPTION    :  Send the SetSampleRate Command (0f3h)
;*                     to the Aux device.
;*
;*  NOTES: The sample rate was previously set to 100 reports
;*         per second by the Reset command. We will set it to
;*         60 reports per second.
;*
;*  ENTRY POINT   :          LINKAGE:  CALL NEAR
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL :  Carry Flag clear.
;*
;*  RETURN-ERROR  :  Carry Flag set.
;*
;*
;****************************************************************

SetSampleRate  proc  near

       mov  al, 0f3h          ; set sample rate command
       call SendToMouse       ; send command to mouse
       jc   ssr_exit

       call GetMouseData      ; wait for response
       .if <c> or
       .if <al ne 0fah>
           stc
          jmp  ssr_exit
       .endif

       mov  al, PDI_SAMPLERATE ; sample rate of 60/sec (was 40/sec)
       call SendToMouse       ; send command to mouse
       jc   ssr_exit

       call GetMouseData
       .if <c> or
       .if <al ne 0fah>
          stc
          jmp  ssr_exit
       .endif

ssr_exit:
       ret

SetSampleRate endp

;****************************************************************
;*
;*  FUNCTION NAME :  SetScaling
;*
;*  DESCRIPTION   :  Send the SetScaling 2:1 Command (0E7h)
;*
;*  NOTES         : The scaling rate was previously set to 1:1
;*
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL :  Carry Flag clear.
;*
;*  RETURN-ERROR  :  Carry Flag set.
;*
;*
;****************************************************************

SetScaling  proc  near

       mov  al, 0e7h          ; set sample rate command
       call SendToMouse       ; send command to mouse

       call GetMouseData      ; wait for response
       .if <c> or
       .if <al ne 0fah>
           stc
       .endif

       ret

SetScaling endp

;****************************************************************
;*
;*  FUNCTION NAME :  SetResolution
;*
;*  DESCRIPTION   :  Send the SetResolution Command (0e8h)
;*                     to the Aux device.
;*
;*  NOTES: The resolution was previously set to 4 counts per mm
;*         (100 ppi) by the Reset command. We use this call
;*         to set the resolution to 8 counts per mm or 200ppi.
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL :  Carry Flag clear.
;*
;*  RETURN-ERROR  :  Carry Flag set.
;*
;*
;****************************************************************

SetResolution  proc  near

          mov  al, 0e8h          ; set resolution
          call SendToMouse       ; send command to mouse
          jc   sr_exit           ; error, exit init bad

          call GetMouseData
          .if <c> or
          .if <al ne 0fah>
             stc
             jmp  sr_exit
          .endif

          mov  al, PDI_RESOLUTION ; resolution of 8 counts/mm
          call SendToMouse       ; send command to mouse
          jc   sr_exit           ; error, exit init bad

          call GetMouseData
          .if <al ne 0fah>
             stc
          .else
             mov  DeviceData.NumMics, 80  ; 80 mickeys/cm
          .endif
sr_exit:
          ret

SetResolution  endp

;****************************************************************
;*
;*  FUNCTION NAME  :  EnablePDI
;*
;*  DESCRIPTION    :  Enable the Aux Device.
;*
;*                   This routine sends the Enable command (0f4h) to
;*                   the auxiliary device.
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL :  Carry Flag clear.
;*
;*  RETURN-ERROR  :  Carry Flag set.
;*
;*
;****************************************************************

EnablePDI  proc  near

       mov  al, 0f4h          ; enable pointing device
       call SendToMouse       ; send command to mouse
       .if <nc>
          call GetMouseData      ; wait for response
          .if <al ne 0fah>
             stc
          .endif
       .endif
       ret

EnablePDI  endp


;****************************************************************
;*
;*  FUNCTION NAME :  ClearAuxPort
;*
;*  DESCRIPTION   : This procedure will read all the aux port data
;*                  until the controller status register's bits
;*                  indicate that there is no more aux data to
;*                  be read.
;*
;*  NOTE: This routine will only exit when the Output Buffer
;*        Full and Auxiliary Output Full bits are OFF in the
;*        controller status register (port 64h).
;****************************************************************

ClearAuxPort  Proc  Near

       in   al, 64h              ; read status port of 8042
       and  al, 21h              ; get AOBF and OBF bits only

       .while <al eq 21h>        ; While AUX data is in output buffer
          in   al, 60h           ; read aux data
          MyIODelay              ; Generate delay between I/O instructions
          in   al, 64h           ; read status port of 8042
          and  al, 21h           ; get AOBF and OBF bits only
       .endwhile

       ret

ClearAuxPort  EndP


;****************************************************************
;*
;*  FUNCTION NAME  :  PDIInit
;*
;*  DESCRIPTION    :  Gets the PDI LID if on ABIOS system
;*
;*                   This routine will check to see if we are on an
;*                   ABIOS system. If so, it will obtain the LID for
;*                   the PDP device.
;*
;*  NOTE          :  This routine is only called if we have detected
;*                   a PDP device.
;*
;*  ENTRY POINT   :  PDIInit           LINKAGE:  CALL NEAR
;*
;*  INPUT         :  DS = Base data selector
;*
;*  RETURN-NORMAL :  Always, mouse LID obtained
;*
;*  RETURN-ERROR  :  N/A.
;*
;*  EFFECTS       : Stack is clean on return.  AX, CX, DX, SI, and DI
;*                  registers are changed.
;****************************************************************

PDIInit  proc  near

       .if <ABIOS_Mch eq TRUE>
          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
       .endif

       lea   eax, HookHotPlugPDI            ; 16 bit offset to Hot Plug handler
       mov   ebx, 0FFFFFFFFh                ; RESERVED
       mov   dl, DevHlp_AllocateCtxHook
       call  Device_Help

       .if <nc>
          mov   HotPlugHandle,  eax
       .endif

        ret

PDIInit  endp

KBD_INT_MASK    equ     02h

EnableKbdInt    proc near
        pushf
        cli
        push    ax
        in      al, 21h              ; read current status
        and     al, not KBD_INT_MASK ; unmask KBD
        out     21h, al              ; out new value
        MyIODelay
        pop     ax
        sti
        popf
        ret
EnableKbdInt    endp

DisableKbdInt   proc near
        pushf
        cli
        push    ax
        in      al, 21h              ; read current status
        or      al, KBD_INT_MASK     ; mask KBD
        out     21h, al              ; out new value
        MyIODelay
        pop     ax
        sti
        popf
        ret
DisableKbdInt   endp

;*********************************************************************
;*
;*  FUNCTION NAME :  Find3ButtonMouse                ;           
;*
;*  DESCRIPTION   :  Send the SetResolution Command (0e8h), 1 count/mm
;*                   to the Aux device followed by three SetScaling
;*                   Commands (0e6h).  This is followed by a read of the
;*                   status register.
;*
;*  NOTES: The algorithym was supplied by Logitech for detecting and
;*         supporting their three button mice on the PDI port.
;*
;*  INPUT         :  N/A
;*
;*  RETURN-NORMAL :  Carry Flag clear.   DeviceData.NumButt updated.
;*
;*  RETURN-ERROR  :  Carry Flag set.
;*
;*
;****************************************************************

Find3ButtonMouse proc  near

       mov  al, 0e8h                 ; set resolution
       call SendToMouse              ; send command to mouse
       jc   fb_exit                  ; error, exit init bad

       call GetMouseData             ; verify set resolution worked
       .if <c> or
       .if <al ne 0fah>
          stc
          jmp  fb_exit
       .endif

       mov  al, 00h                  ; set resolution to 1 count per mm
       call SendToMouse              ; send command to mouse
       jc   fb_exit                  ; error, exit init bad

       call GetMouseData             ; verify set resolution worked again
       .if <al ne 0fah>
          stc
       .else

          mov  al, 0e6h              ; set scaling = 1:1
          call SendToMouse           ; send command to mouse
          jc   fb_exit

          call GetMouseData          ; verify set scaling worked
          jc   fb_exit
          cmp  al, 0fah
          jnz  fb_exit

          mov  al, 0e6h              ; set scaling = 1:1
          call SendToMouse           ; send command to mouse
          jc   fb_exit

          call GetMouseData          ; verify set scaling worked
          jc   fb_exit
          cmp  al, 0fah
          jnz  fb_exit

          mov  al, 0e6h              ; set scaling = 1:1
          call SendToMouse           ; send command to mouse
          jc   fb_exit

          call GetMouseData          ; verify set scaling worked
          jc   fb_exit
          cmp  al, 0fah
          jnz  fb_exit

          mov  al, 0e9h              ; status request (will generate 3 bytes)
          call SendToMouse           ; send command to mouse
          jc   fb_exit
                                     ; We must clear all three bytes from data
                                     ; port.

          call GetMouseData          ; Verify status request worked
          jc   fb_exit
          cmp  al, 0fah
          jnz  fb_exit

          call GetMouseData          ; Throw away Standard status info
          jc   fb_exit               ; BYTE 1

          call GetMouseData          ; Logitech Number of mouse buttons
          jc   fb_exit               ; BYTE 2

          .if <al eq 3>              ; Three buttons reported?
             mov DeviceData.NumButt, al
          .endif

          call GetMouseData          ; Throw away firmware revision number
                                     ; BYTE 3
       .endif

fb_exit:
        clc                          ; Never return an error
        ret

Find3ButtonMouse endp

CSEG     ENDS
         END
