     Page  58,132
     Title   KBDTIME - Kbd Device Driver AIM Timer Code
     Name    KBDTIME

;/*************************************************************************
;*
;* SOURCE FILE NAME = KBDTIME.ASM
;*
;* DESCRIPTIVE NAME = Keyboard AIM Timer
;*
;* 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         11/17/90
;*
;* DESCRIPTION  Alternate Input Method Support Timer Handlers
;*
;* FUNCTIONS
;*
;*
;*
;*
;*
;* NOTES        DEPENDENCIES:  Controller or keyboard must be set to the PC compati-
;*                             ble scan code set.
;*              RESTRICTIONS:  Machine must be a 386 or compatible with a 386.
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01-15-93  @V2.0TPL01  59890  fix AIM activation with 0 timeout value
;*   02-04-94  ;rdw74592   74592  spec need filter not allways working
;*
;**************************************************************************


.286p
.sall
.xcref
.xlist
  Include basemaca.inc               ;DOS macros.
  Include osmaca.inc                 ;Macro file for OS/2 kernel
  CPUMODE 286
  Include struc.inc                  ;Structured assembly macros.
  Include devhlp.inc                 ;DevHlp & Signal equates, char queue structure.
  Include devsym.inc                 ;Device driver header definitions.
  Include kbdseg.inc                 ;Segment definitions.
  Include kbdddr.inc                 ;Keyboard Device Driver structures & equates.
  Include kbdaim.inc                 ;AIM
.list

 ;* External Routines

  EXTRNFAR TypaControl_Reset    ;AIM

 ;* External Variables

  Extrn FilterFlags            :Byte    ;AIM
  Extrn LastKey                :Byte    ;AIM
  Extrn FinalKey               :Byte    ;AIM
  Extrn Shift_Count            :Byte    ;AIM
  Extrn Beep_State             :Byte    ;AIM
  Extrn Filter_Ctrl            :Byte    ;AIM
  Extrn Rep_Count              :Word    ;AIM
  Extrn AIMFlags               :Word    ;AIM
  Extrn Acc_Ctrl               :Word    ;AIM
  Extrn Typematic_Ctrl         :Word    ;AIM
  Extrn Delay_Ctrl             :Word    ;AIM
  Extrn Comp_Acc_Ctrl          :Word    ;AIM
  Extrn Comp_Typematic_Ctrl    :Word    ;AIM
  Extrn Comp_Delay_Ctrl        :Word    ;AIM
  Extrn Comp_AIMTimeout        :Word    ;AIM
  Extrn Comp_Rep_Count         :Word    ;AIM
  Extrn AIMTimeOut             :Word    ;AIM
  Extrn DeviceHelp             :DWord


Code Segment
Assume  CS:Code,DS:DGROUP,ES:Nothing


BREAK <FilterTimeOut routine>
Public FilterTimeOut
FilterTimeOut Proc Far

;************************************************************************
;*
;* FUNCTION NAME =  FilterTimeout
;*
;* DESCRIPTION   =  Filter Key Timeout Timer Handler
;*
;*
;*                  Handles Timeout condition for Filter Key
;*
;* NOTES         =  This routine is called by Timer Service.
;*                  KbdInt and KbdBeep2KHz call DevHlp_TickCount to make
;*                  Timer Service invoke this routine immediately.
;*                  Always called in protect mode.
;*
;*
;*
;* INPUT         =  NONE
;*
;*
;* EXIT-NORMAL   =  Return to Timer Service
;*
;* EXIT-ERROR    =  see NORMAL above.
;*
;* EFFECTS       =  Beeps the speaker with 1000 Hz for 500 milliseconds,
;*                  decrements Beeps_Count by 1, sets Timer Service to
;*                  invoke itself every 64K ticks, and sets Timer Service
;*                  to invoke KbdBeep2KHz every 9 ticks (about 0.5 second
;*                  if Beep_State is larger than 0, otherwise set Timer
;*                  Service to invoke itself every 64K ticks.
;*
;* INTERNAL REFERENCES =
;*    ROUTINES:
;*      KbdBeep1KHz  - Beep with 1000 Hz for 500 milliseconds
;*      KbdBeep2KHz  - Beep with 2000 Hz for 500 milliseconds
;*
;*
;* EXTERNAL REFERENCES:
;*    ROUTINES: None
;*
;*    DEVHELPS: DevHlp_TickCount
;*
;*
;* PSEUDOCODE     =
;*
;*    Save AX, BX, DX, and SI Registers
;*
;*    If Filter Active mode bit in FilterFlags is on
;*
;*       If Filter Timeout bit in FilterFlags is off
;*
;*          Turn on Filter Timeout bit in FilterFlags
;*
;*       Else
;*          Turn on Typematic Delay mode bit and Repeat mode bit in
;*          FilterFlags
;*
;*          Call TypaControl_Reset to reset faking the typematic
;*          rate and delay
;*
;*          Call DevHlp_TickCount with 64K ticks (maximum) count for
;*          FilterTimeout
;*
;*          Set Beep_State to 2
;*
;*          Call DevHlp_TickCount with 1 tick (immediate) count for
;*          KbdBeep2KHz
;*
;*      .Endif
;*
;*   .Endif
;*
;*    Restore SI, DX, BX, and AX Registers
;*
;*    Return to the caller
;*
;********************************************************************

     SaveReg<AX,BX,DX,SI>

     Test   FilterFlags,FILTER_ACTIVE
    .If <nz>

        CALLFAR TypaControl_Reset

    .Endif

     Mov  AX, Offset KbdCode:FilterTimeOut       ; Shutoff timer handler ;@V2.0TPL01

     Mov  BX, MAXIMUM_TICK                       ;@V2.0TPL01
     Mov  DL, DevHlp_TickCount                   ;@V2.0TPL01
     Call [DeviceHelp]                           ;@V2.0TPL01

     Mov  Beep_State,DISABLE_BEEP                ;@V2.0TPL01

     RestoreReg<SI,DX,BX,AX>

     Ret

FilterTimeOut endp



BREAK <KBDBeep1KHz routine>
Public KBDBeep1KHz
KBDBeep1KHz Proc Far

;************************************************************************
;*
;* FUNCTION NAME= KBDBeep1KHz
;*
;* DESCRIPTION =  Beep with 1000 Hz
;*
;*              IBM Unique Code.  @IBM
;*
;*              Beep the speaker with 1000 Hz for 500 milliseconds
;*
;* NOTES        This routine is called by Timer Service.
;*              KbdInt and KbdBeep2KHz call DevHlp_TickCount to make
;*              Timer Service invoke this routine immediately.
;*              Always called in protect mode.
;*
;*              Relationships between  KBDBeep1kHz and KbdBeep2KHz
;*
;*              When DevHlp_Beep is called, DevHlp_Beep immediately
;*              access the speaker port to create the sound based on
;*              the given frequency, duration, and an option (preempt
;*              beep services: BEEP_OFF, BEEP_ON, BEEP_FREQ,
;*              BEEP_TIMED).  If Device Driver needs to make sound
;*              with two different frequencies continuously (e.g.
;*              1000 Hz for 0.5 second and 2000 Hz for 0.5 second
;*              to form 1 second sound), Device Driver must issue
;*              two DevHlp_Beep calls.  If second DevHlp_Beep call
;*              is issued before the first beeping completes, the
;*              first beeping is cut by the second beeping or a merged
;*              odd frequency is generated from the speaker.  It is
;*              necessary for the second DevHlp_Beep to be called
;*              after the first beeping is completed. If the
;*              continuous beeping is needed to be done from interrupt
;*              handler or time critical routine, the device driver
;*              cannot wait for the first beeping to end.  Therefore,
;*              Timer Service is used to solve this problem.
;*
;*
;*      KbdInt
;*
;*       +-------+
;*       | START |
;*       +---+---+
;*           |
;*           V        (1)
;* +---------------------+
;* |Call DevHlp_TickCount+--+
;* |for Beep1KHz with    |  |
;* |1 tick count         |  |
;* +---------------------+  |
;*           |              |
;*           V              |
;*       +-------+          |
;*       |  END  |          |
;*       +-------+          V
;*                    +---------------+
;*                    |               |
;*      +------------>| Timer Service |<-----------------------+
;*      |+----------->|               |<-------------------+   |
;*      ||         +--+               +-------+            |   |
;*      ||         |  +---------------+       |            |   |
;*      ||      (2)|                          | (7)        |   |
;*      ||         V   KBDBeep1KHz            V KBDBeep2KHz|   |
;*      || +------------------+       +------------------+ |   |
;*      || ³ Beep1KHz routine ³       ³ Beep2KHz routine ³ |   |
;*      || +------------------+       +------------------+ |   |
;*      ||         |                          |            |   |
;*      ||         V                          V            |   |
;*      ||  +-----------------+Yes   +-----------------+   |   |
;*      ||  |If Beep_State    +--+   |If Beep_State    |   |   |
;*      ||  |    = FINAL_BEEP ³  |+--+    = FINAL_BEEP |   |   |
;*      ||  +-----------------+  ||  +-----------------+   |   |
;*      ||         |No           ||Yes        |No          |   |
;*      ||         |             ||           |            |   |
;*      ||     (3) V             ||           V (8)        |   |
;*   +--+| +------------------+  ||   +------------------+ |   |
;*   |   | | Call DevHlp_Beep |  ||   | Call DevHlp_Beep | |   |
;*   | +-+ | with 1KHz for    |  ||   | with 2KHz for    | |   |
;*   | |   | 500 millisecond  |  ||   | 500 millisecond  | |   |
;*   | |   +------------------+  ||   +------------------+ |   |
;*   | |           |             ||           |            |   |
;*   | |       (4) V             ||           V (9)        |   |
;*   | | +---------------------+ || +---------------------+|   |
;*   | +-+Call DevHlp_TickCount| || |Call DevHlp_TickCount||   |
;*   |   |for Beep2KHz with    | || |for Beep1KHz with    |+   |
;*   |   |9 tick count         | || |9 tick count         |    |
;*   |   +---------------------+ || +---------------------+    |
;*   |             |             ||           |                |
;*   |         (5) V             ||           V  (10)          |
;*   |   +---------------------+ || +---------------------+    |
;*   +---+Call DevHlp_TickCount| || |Call DevHlp_TickCount|    |
;*       |for Beep1KHz with    |<+| |for Beep2KHz with    +----+
;*       |FFFFh tick count     |  +>|FFFFh tick count     |
;*       +---------------------+    +---------------------+
;*                |                          |
;*            (6) V                          V   (11)
;*        Return to Timer Service    Return to Timer Service
;*
;*
;*    Both Beep1KHz and Beep1KHz routines must be registered by Timer
;*    Service during initialization. The tick counts for these
;*    routines are set to 0FFFh which is the maximum.
;*    (18.9 ticks per second)
;*
;* (1) A device driver changes the tick count of Beep1KHz routine to
;*     1 tick count by calling DevHlp_TickCount.
;*
;* (2) Since the tick count for Beep1KHz is changed to 9 (0.5 second),
;*     Beep1KHz is invoked by Timer Service almost instantly.
;*
;* (3) Beep1KHz calls DevHlp_Beep with 1KHz for 500 milliseconds of
;*     duration to beep the speaker for 0.5 second with 1000 Hz.
;*
;* (4) Beep1KHz changes the tick count of Beep2KHz to 1 tick count by
;*     calling DevHlp_TickCount.
;*
;* (5) Beep1KHz changes its own tick count to 0FFFFH tick count by
;*     calling DevHlp_TickCount so that it will not be invoked for
;*     maximum amount of time.
;*
;* (6) Beep1KHz returns to Timer Service.
;*
;* (7) Since the tick count for Beep2KHz is changed to 9, Beep2KHz
;*     is invoked 0.5 second later by Timer Service.  When Beep2KHz
;*     is called, the first beeping by Beep1Khz is about to end.
;*
;* (8) Beep2KHz calls DevHlp_Beep with 2KHz for 500 milliseconds of
;*     duration to beep the speaker for 0.5 second with 2000 Hz.
;*
;* (9) Beep2KHz changes the tick count of Beep1KHz to 1 tick count by
;*     calling DevHlp_TickCount.
;*
;*(10) Beep2KHz changes its own tick count to 0FFFFH tick count by
;*     calling DevHlp_TickCount so that it will not be invoked for
;*     maximum amount of time.
;*
;*(11) Beep1KHz returns to Timer Service.
;*
;*
;*     Beep State        Explanayion
;*     --------------- ------------------------------------------
;*     FINAL_BEEP       No further beeping will be allowed
;*     ENABLE_TEST      Test if enabling Filter Key can be done
;*     DISABLE_BEEP     Beeping is forbidden
;*     COMEBACK_BEEP    Beeping bounced back from other beep routine
;*     ENABLE_BEEP      Beeping is allowed
;*
;*
;*
;* ENTRY POINT  KBDBeep1KHz
;*
;*    LINKAGE   NEAR
;*
;* INPUT        NONE
;*
;*
;*
;* EXIT-NORMAL  Return to Timer Service
;*
;* EXIT-ERROR   see NORMAL above.
;*
;* EFFECTS      Beeps the speaker with 1000 Hz for 500 milliseconds,
;*              decrements Beeps_Count by 1, sets Timer Service to
;*              invoke itself every 64K ticks, and sets Timer Service
;*              to invoke KbdBeep2KHz every 9 ticks (about 0.5 second)
;*              if Beep_State is larger than 0, otherwise set Timer
;*              Service to invoke itself every 64K ticks.
;*
;* INTERNAL REFERENCES:
;*    ROUTINES:
;*      KbdBeep1KHz  - Beep with 1000 Hz for 500 milliseconds
;*      KbdBeep2KHz  - Beep with 2000 Hz for 500 milliseconds
;*
;*
;* EXTERNAL REFERENCES:
;*    ROUTINES: None
;*
;*    DEVHELPS: DevHlp_TickCount
;*
;*
;*
;* PSEUDOCODE
;*
;*    Save AX, BX, DX, and SI Registers
;*
;*    If Beep_State is FINAL_BEEP
;*
;*       Call DevHlp_TickCount to set to invoke KbdBeep1KHz for
;*       every 64K ticks (maximum)
;*
;*    Else
;*
;*       Advance Beep_State to next state
;*
;*       If Beep_State is COMBACK_BEEP or FINAL_BEEP
;*
;*          KbdBeep macro for 1000 Hz and 500 milliseconds to
;*          beep speaker
;*
;*          Call DevHlp_TickCount to set to invoke KbdBeep1KHz for
;*          every 64K ticks (maximum)
;*
;*          Call DevHlp_TickCount to set to invoke KbdBeep2KHz for
;*          every 9 ticks (1/2 second)
;*
;*       Endif
;*
;*       If Beep_State is ENABLE_TEST
;*
;*          Set Beep_State to FINAL_BEEP
;*
;*          If LastKey is equal to FinalKey and
;*             Shift Count is larger than Filter_Ctrl
;*
;*             Set Typematic_Ctrl to Comp_Typematic_Ctrl
;*
;*             Set Acc_Ctrl to Comp_Acc_Ctrl
;*
;*             Set Delay_Ctrl to Comp_Delay_Ctrl
;*
;*             Set Repeat_Count to Comp_Repeat_Count
;*
;*             Turn on Filter Active mode bit in FilterFlags
;*
;*             If AIMTimeout is not 0
;*
;*                Turn on Timeout bit in FilterFlags
;*
;*                Call DevHlp_TickCount to set to invoke FilterTimeout
;*                for every Comp_AIMTimeout ticks
;*
;*             Endif
;*
;*          Endif
;*
;*       Endif
;*
;*       Call DevHlp_TickCount to set to invoke KbdBeep1KHz for
;*       every 64K ticks (maximum)
;*
;*    Endif
;*
;*    Restore SI, DX, BX, and AX Registers
;*
;*    Return to the caller
;*
;*********************************************************************


     SaveReg<AX,BX,CX,DX,SI>

    .If <Beep_State eq FINAL_BEEP>

        Mov AX, Offset KbdCode:KBDBeep1KHz

        Mov BX, MAXIMUM_TICK
        Mov DL, DevHlp_TickCount
        Call [DeviceHelp]

    .Else near

        Dec     Beep_State

       .If <Beep_State eq COMEBACK_BEEP> OR
       .If <Beep_State eq FINAL_BEEP>

           KbdBeep TimedBeep,DelFreq,NormDuration

           Mov AX, Offset KbdCode:KBDBeep2KHz

           Mov BX, HALF_SECOND_TICK
           Mov DL, DevHlp_TickCount
           Call [DeviceHelp]

       .Endif

       .If <Beep_State eq ENABLE_TEST>
           Mov Beep_State,FINAL_BEEP
           Mov AL,FinalKey
           Xor CX,CX
           Xor BX,BX
           Mov CL,Shift_Count
           Mov BL,Filter_Ctrl

;          .If <CX gt BX>  AND                                   ;rdw74592
;          .If <AL eq LastKey>                                   ;rdw74592

           .If <CX gt BX>                                        ;rdw74592

              Mov  BX,Comp_Typematic_Ctrl
              Mov  Typematic_Ctrl,BX
              Mov  BX,Comp_Acc_Ctrl
              Mov  Acc_Ctrl,BX
              Mov  BX,Comp_Delay_Ctrl
              Mov  Delay_Ctrl,BX
              Mov  BX,Comp_Rep_Count
              Mov  Rep_Count,BX

              Or   FilterFlags,FILTER_ACTIVE

              Mov  FinalKey,0
              Mov  LastKey,0

             .If <AIMTimeout eq 0>      ; Register timer handler        ;@V2.0TPL01
                 dec  Comp_AIMTimeout   ;   with infinite timeout       ;@V2.0TPL01
             .Endif                                                     ;@V2.0TPL01

              Or   FilterFlags,TIMEOUT

              Mov  AX, Offset KbdCode:FilterTimeOut

              Mov  BX, Comp_AIMTimeout
              Mov  DL, DevHlp_TickCount
              Call [DeviceHelp]

          .Endif

       .Endif

        Mov  AX, Offset KbdCode:KBDBeep1KHz

        Mov  BX, MAXIMUM_TICK
        Mov  DL, DevHlp_TickCount
        Call [DeviceHelp]

    .Endif

     RestoreReg<SI,DX,CX,BX,AX>

     Ret

KBDBeep1KHz endp



BREAK <KBDBeep2KHz routine>
Public KBDBeep2KHz
KBDBeep2KHz Proc Far

;**************************************************************************
;*
;* FUNCTION NAME KBDBeep2KHz
;*
;* DESCRIPTION   Beep with 2000 Hz
;*
;*
;* FUNCTION     Beep the speaker with 2000 Hz for 500 milliseconds
;*
;* NOTES        This routie is called by Timer Service.
;*              xxxxxx and KbdBeep1KHz call DevHlp_TickCount to make
;*              Timer Service invoke this routine immediately.
;*              Always called in protect mode.
;*
;* INPUT        NONE
;*
;*
;* EXIT-NORMAL  Return to Timer Service
;*
;* EXIT-ERROR   see NORMAL above.
;*
;* EFFECTS      Beeps the speaker with 2000 Hz for 500 milliseconds,
;*              decrements Beeps_Count by 1, sets Timer Service to
;*              invoke itself every 64K ticks, and sets Timer Service
;*              to invoke KbdBeep1KHz every 9 ticks (about 0.5 second)
;*              if Beep_State is larger than 0, otherwise set Timer
;*              Service to invoke itself every 64K ticks.
;*
;* INTERNAL REFERENCES:
;*    ROUTINES:
;*      KbdBeep1KHz  - Beep with 1000 Hz for 500 milliseconds
;*      KbdBeep2KHz  - Beep with 2000 Hz for 500 milliseconds
;*
;*
;* EXTERNAL REFERENCES:
;*    ROUTINES: None
;*
;*    DEVHELPS: DevHlp_TickCount
;*
;*
;*
;* PSEUCODE
;*
;*    Save AX, BX, DX, and SI Registers
;*
;*    If Beep_State is FINAL_BEEP
;*
;*       Call DevHlp_TickCount to set to invoke KbdBeep2KHz for
;*       every 64K ticks (maximum)
;*
;*    Else
;*
;*       Advance Beep_State to next state
;*
;*       KbdBeep macro for 2000 Hz and 500 milliseconds to
;*       beep speaker
;*
;*       Call DevHlp_TickCount to set to invoke KbdBeep2KHz for
;*       every 64K ticks (maximum)
;*
;*       Call DevHlp_TickCount to set to invoke KbdBeep1KHz for
;*       every 9 ticks (1/2 second)
;*
;*    Endif
;*
;*    Restore SI, DX, BX, and AX Registers
;*
;*    Return to the caller
;*
;*********************************************************************


     SaveReg<AX,BX,DX,SI>

    .If <Beep_State eq FINAL_BEEP>

        Mov     AX, Offset KbdCode:KBDBeep2KHz

        Mov     BX, 0FFFFh
        Mov     DL, DevHlp_TickCount
        Call    [DeviceHelp]

    .Else

        Dec     Beep_State

        KbdBeep TimedBeep,AddFreq,NormDuration

        Mov    AX, Offset KbdCode:KBDBeep2KHz

        Mov    BX, 0FFFFh
        Mov    DL, DevHlp_TickCount
        Call   [DeviceHelp]


        Mov    AX, Offset KbdCode:KBDBeep1KHz

        Mov    BX, HALF_SECOND_TICK
        Mov    DL, DevHlp_TickCount
        Call   [DeviceHelp]

    .Endif

     RestoreReg<SI,DX,BX,AX>

     Ret

KBDBeep2KHz endp


Code Ends
     End
