;*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.;
;*****************************************************************************/
    Page  58,132
    Title   KBDSCAN - Kbd Device Driver Scan Code Processor
    Name    KBDSCAN

;/*************************************************************************
;*
;* SOURCE FILE NAME = KBDSCAN.ASM
;*
;* DESCRIPTIVE NAME = PKBD Scan Code Processor
;*
;*
;* VERSION      V2.0
;*
;* DATE         15/03/92
;*
;* DESCRIPTION  All Keyboard scan codes are processed.
;*
;* FUNCTIONS    ProcessScanCode()    Interupt time scan code processor
;*
;*
;*
;*
;*
;*
;*
;* 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
;*                         B730591
;*                         B724802
;*                         46491
;*                         DCR 652
;*                         PTM 5625
;*                         DCR 1131
;*                         PTM 5992
;*                         PTM 2382
;*                         B785763
;*                         700700
;*                         DCR 408
;*                         B786969
;*                         B724802
;*                         DCR 513
;*                         DCR 8
;*                         B787171
;*                         PTMs 3090/3497
;*                         B733926
;*                         DCR 549
;*                         B786686
;*                         B787292
;*                         PTM 4990
;*                         B711290
;*                         PTM 6810
;*                         B789221
;*
;*
;**************************************************************************


.286p
.sall
.xcref
.xlist
  Include   mvdm.inc       ;*
  Include   osmaca.inc     ;*  Added for             Macro file for OS/2 kernel
  CPUMODE   286            ;*
  Include   struc.inc      ;* Structured assembly macros.
  Include   devhlp.inc     ;* DevHlp & Signal equates, char queue structure.
  Include   pmode.inc      ;*             - Mode macros.
  Include   devsym.inc     ;* Device driver header definitions.
  Include   infoseg.inc    ;* InfoSeg structure.
  Include   kbdseg.inc     ;* Segment definitions.
  Include   kbdddr.inc     ;* Keyboard Device Driver structures & equates.
  Include   kbddi.inc      ;* Specific device independent structures
  Include   vkbdpdd.inc    ;*
  Include   kbdaim.inc     ;* AIM  Alternate Input Methods Equates and Defs.
  Include   devhlpP.inc    ;* 76711
.list


;********* External Routines *************

  Extrn    StickyKeyProc     :Far
  Extrn    AccessKCB         :Near
  Extrn    PutInSQB          :Near
  Extrn    PurgeKIB          :Near
  Extrn    PutInVDMQ         :Near
  Extrn    SendVDDSC         :Near
  Extrn    HotKeyCheck       :Near
  Extrn    PutInKIB          :Near
  Extrn    KbdXlate          :Near
  Extrn    MonBlockCheck     :Near
  Extrn    SGActivation      :Near
  Extrn    VDDEntryPoint     :Near
  Extrn    ProcessFilter     :Far
  Extrn    DD_Entry          :Far


;********* External Variables  ***********

  Extrn    LockupFlags       :Byte       ;*           
  Extrn    AIMFlags          :Word       ;* AIM
  Extrn    IntFlags          :Byte
  Extrn    MiscFlags         :Byte
  Extrn    KbdIRQ            :Byte
  Extrn    KeyPacket1        :Word
  Extrn    KeyPacket2        :Word
  Extrn    SInfoSeg          :Word
  Extrn    KCBShFlgs         :Word
  Extrn    CurSG             :Word
  Extrn    IntFlagArea       :Word
  Extrn    CBDataSel         :Word
  Extrn    PSGPointers       :Word
  Extrn    PDDtoVDDSCPkt     :Word
  Extrn    SwitchPID         :Word
  Extrn    KCBFocusAddress   :DWord
  Extrn    SADump            :DWord
  Extrn    DeviceHelp        :DWord
  Extrn    SQHotKeyData      :Byte       ;*           
  Extrn    NumPadAccum       :Byte       ;*
  Extrn    KcbBlockId        :Word       ;*           
  Extrn    IntCount          :DWord      ;* PEN SUPPORT
  Extrn    CallBack          :Byte       ;* PEN SUPPORT
  Extrn    IDC_Write         :Word       ;* PEN SUPPORT
  Extrn    Keystroke2        :Byte

  StkFrameVars

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


Public ProcessScanCode
procedure ProcessScanCode,HYBRID

;/***************************************************************************
;*
;* FUNCTION NAME = ProcessScanCode
;*
;* DESCRIPTION   = Interrupt Time Scan Code Processor
;*
;*    All scan code interrupts are handled here. Once it is determinned
;*    where the scan code belongs it will be handled as follows;
;*
;*    PKBD DD - The Physical Keyboard Device Driver and its associated
;*              routines.
;*
;*    VKBD DD - The Virtual Keyboard Device Driver (handles all virtual
;*              real mode support).
;*
;*    SQDD - The Single Queue Device Driver (handles input data from
;*           the keyboard and mouse for the PM screen group.  It also
;*           handles interrupt driven shift state packets that may be
;*           sent at interrupt or task time in order to provide the PM
;*           session with the proper shift state.)
;*
;*    Monitor Chain - The Monitor Dispatcher and user monitor chains.
;*
;*    KIB - The Keyboard Input Buffer of available keystrokes.
;*
;* Notes:
;*        1) IF the system reboot sequence is recognized a branch to
;*           the system reboot function will be performed.
;*
;*        2) IF the Stand Alone Dump sequence is recognized, control
;*           will branch to system RAS.
;*
;* INPUT         =  AL scan code
;*
;* OUTPUT        =  Keystroke buffers data areas and state flags are updated.
;*
;*
;* RETURN-NORMAL =
;*
;*                 - Scan code is sent to the VDD for further processing.
;*                   (VDM session only)
;*                 - Scan code is place in VDM typahead buffer for non-
;*                   active VDMs.
;*                 - Keystroke is placed in the KIB for that session.
;*                   (Non PM session or Non VDM session)
;*                 - Keystroke is placed in the monitor chain of the current
;*                   session.  (FS session only)
;*                 - Keystroke is sent to the SingleQ. (PM session only)
;*
;*
;* RETURN-ERROR  = Speaker beeped and character discarded if monitor dis-
;*                 patcher can't accept the CharData record or if KIB ele-
;*                 ments are not available (if no monitors are registered)
;*                 OR if the Single Queue mode is in effect and the Single
;*                 Queue device driver did not accept the SQDR, OR if the
;*                 VDD did not accept the scan code for an active VDM.
;*
;* INTERNAL CALLS =
;*
;*         HotKeyUpdate   PutInKIB       AccessKCB
;*         KbdXlate       PutInSQB       HotKeyCheck   SGActivation
;*         SendVDDSC      ConsInpFilter  PutInVDMQ     StickKeyProc
;*
;* EXTERNAL CALLS =
;*      Routines:
;*      DevHelps:   DevHlp_MonWrite   DevHlp_SendEvent
;*                  DevHlp_PhystoVirt DevHlp_EOI
;*                  DevHlp_UnPhysToVirt
;*
;*************************************************************************/

   Test  AIMFlags,AIMActive           ; AIM  If AIM is active
   .If <nz>                            ; AIM
      Call ProcessFilter               ; AIM  Process Filter Key
      .If <c>                           ; AIM  If need to throw this interrupt
         Ret                    ; AIM  jump to the end
      .Endif                            ; AIM
   .Endif                              ; AIM
   Or IntFlags, Up_LEDs               ; Only in full screen

 ;* PEN SUPPORT

.386p
  push    eax
  push    bx
  push    es
  mov     eax, IntCount
  inc     eax
  mov     IntCount, eax
 .if < bit CallBack nz 01 >              ;* if callback is enabled.....
    and    CallBack, 0                   ;* clear out flag
    mov    ax, 2                         ;* indicate function is callback
    lea    bx, IDC_Write
    push   ds
    push   ds
    pop    es
    mov    ds,es:[bx].sinfo_service_ds
    call   es:[bx].sinfo_service_rtn
    pop    ds
 .endif
  pop     es
  pop     bx
  pop     eax
.286p

  Mov     SI,Offset KeyPacket1           ;* Point to Key Packet.
  Mov     [SI].DDFlags,0                 ;* Initialize ddflags to zero.
  Mov     ES,[SInfoSeg]                  ;* Get System Info Segment.
  Mov     CX,Word Ptr ES:[SIS_MsCount]   ;* Get first two bytes of timestamp.
  Mov     Word Ptr [SI].Key.Time,CX      ;* Save in Key record.
  Mov     CX,Word Ptr ES:[SIS_MsCount+2] ;* Get second two bytes.
  Mov     Word Ptr [SI].Key.Time+2,CX    ;* Save in Key record.
  Mov     CX,CurSG                       ;* Set SG number for use by KbdXlate.

 .If <CX ge sgidFirstVDM>                ;* If a VDM SGID
    Mov    CX,Dos3xBoxSG                 ;* We will be using SG 2 for VDMs
 .Endif

  Mov      DI,CX                         ;* Get Current Screen Group Number
  Shl      DI,1                          ;* Make it an offset
  Mov      DI,[PSGPointers+DI]           ;* Get Pointer to this SGs PSG
                                         ;*
  Mov      StkPSG, DI                    ;*            Save the PSGPointer
  Mov      BX,Word Ptr [DI].KCBAddress   ;* Get the physical address of KCB
  Mov      Word Ptr KCBFocusAddress,BX   ;*  with focus and save It
  Mov      BX,Word Ptr [DI].KCBAddress+2 ;* Get the physical address of KCB
  Mov      Word Ptr KCBFocusAddress+2,BX ;*  with focus and save It
                                         ;*            End
 LES       BX, Dword Ptr StkKCBO         ;* Get the KCB address from stack


Public XlateRetry
               ;*
XlateRetry:    ;* When KbdXlate finds any key break that belongs in another
               ;* SG, the correct PSG pointer, the correct KCB ptr is found
               ;* and a jump back to
               ;* here is made so that we can translate based on that SG.
               ;* NOTE: CX must be preserved between here & call to KbdXlate,
               ;* because it may have been set to another value before jump
               ;* back to the XlateRetry label above.
               ;*

  Mov      Byte Ptr [SI].KPacketLen,0    ;* Init Length low byte to zero.
  Mov      Byte Ptr [SI].KPacketLen+1,AL ;* Put scan code in KPacketLen high byte.
                                         ;* KPacketLen acts as "MonFlags" byte.
  Mov      [SI].Key.Scan,0               ;* Let the translation process...
  Mov      [SI].Key.XChar,0              ;* take care of these fields.

 ;*Initialize the state fields of the Key CharData record. Use PSG data.

  Mov      DL,ES:[BX].KCBDBCSFl          ;* Get interim char flags from KCB.
  Mov      [SI].Key.Status,DL            ;* Put in Key CharData rec.
  Mov      DL,ES:[BX].KCBDBCSSh          ;* Get DBCS shift status from KCB.
  Mov      [SI].Key.DShift,DL            ;* Put in Key CharData rec.
  Mov      DX,ES:[BX].KCBShift           ;* Get shift flags.
  Mov      [SI].Key.Shift,DX             ;* Put in Key CharData rec.
  Mov      [DI].ShiftFlags,DX            ;* Put copy of shiftFlags in PSG
  Mov      KCBShFlgs,DX             ;*            Save Shift Flags, we need them
                                    ;* when creating packet for E0 scan code.

                                         ;*            start
  Mov      DX, Word Ptr [DI].PSGFlags    ;* If this screen group is in a
 .If <bit [DI].PSGFlags nz NowPaused>    ;* paused state we must update the
    Or IntFlagArea.XlateFlags, SGPaused  ;* flags used by KbdXlate to show
 .Else                                   ;* Else
    And IntFlagArea.XlateFlags, NOT SGPaused  ;* Clear the flag
 .Endif                                  ;* this current state
                                         ;*            end

 .If <AL eq OtherKey> NEAR               ;* Enhanced keyboard secondary key prefix
    Or IntFlagArea.XKeyFlags, SecPrefix  ;* Indicate for next scan code.
    Jmp Spurious                  ;*             Do not pass E0's until we see
                                         ;* the next make/break scan code.
                                         ;* code we get.
 .ElseIf <AL eq OtherKey2> NEAR   ;* Enhanced keyboard secondary key prefix?
    Or [SI].DDFlags,SecPrefixCode        ;* Yes, set keytype in DD flagword.
    Or IntFlagArea.XlateFlags,E1Prefix   ;* Indicate so for
    Or IntFlagArea.XKeyFlags, SecPrefix  ;* next scan code

 .Else NEAR  ;* Not keyboard special scan code. Translate using the table.

    ;*
    ;* From here on, DI is the index of the current PSG we're using, SI
    ;* is the index to the Key Packet, ES is the KCB Selector and BX is the
    ;* offset of the KCB.
    ;*

   .If <bit AIMFlags nz AIMActive> AND;* AIM If AIM is active, segment locked down
   .If <bit AIMFlags z NonAIMScan>    ;* AIM If we are not updating the
                                      ;* AIM  shiftst before a SG switch
        Call StickyKeyProc            ;* AIM Call Sticky key processing for AIM sp.
       .If <bit AIMFlags nz ConsumeScan>;* AIM If we are not supposed to consume
           Jmp Spurious               ;* AIM  Carry Set means throw away this break.
       .Endif                         ;* AIM
   .Endif                                 ;* AIM
                                          ;*
    Push     DI                           ;* Save PSG pointer
    Push     SI                           ;* Save key packet offset
                                          ;*
    Mov      SI,offset KeyPacket2         ;* Move offset of KeyPacket2 into
    Mov      StkTmpL,SI                   ;* local stack varible.
    Mov      SI, Offset IntFlagArea       ;* Point to Flag Area to be used.
    Push     AX                           ;* Save reg from destruction
    Push     CX                           ;*            save SG number.
;;*    Mov      CX, DI                 ;*            Temp store PSG pointer in CX
    Mov      DH, ES_DI                    ;* Specify receiving registers
    Call     AccessKCB                    ;* ES:DI = KCB address
    Mov      AH, ES:[DI].KCBInpMode       ;* Get input mode to use.
    Mov      [SI].XInputMode, AH          ;* Save in Flag Area.
    Mov      AX,ES:[DI].KCBIxOffCP        ;* Get the index into the CP
                                          ;*
   .If <ES:[DI].KCBFlags ne CUSTOMCP>     ;* If the KCB flags specify
                                          ;* that the XT to use is in CPCB...
;;* This code can be removed becasue of Ted Mueller's fix
;;*                                          ;*                
;;*       Mov AX, DI                         ;* Save the KCB offset
;;*       Mov DI, CX                         ;* Get the PSG offset
;;*      .If <bit [DI].PSGFlags nz SQMODE> AND  ;* If Single Queue mode active AND
;;*      .If <bit MiscFlags nz MLayerMode>      ;* If Multi Layer code page
;;*                                             ;* is supported
;;*         Push ES                             ;* Save KCB sel
;;*         Mov  ES, CBDataSel                  ;* Get sel for CPCB data area.
;;*         Mov  DI, CPCBOFFSET+CPCBEntrySize   ;* Set offset to start of CPCB[1].
;;*         Add  DI, CPCBEntrySize              ;* Adjust offset to start of CPCB[2].
;;*
;;*       ;**
;;*       ;** Ari Erev/Ted Mueller fix.
;;*       ;**
;;*       ;** The following test forced ENGLISH layer if the key is
;;*       ;** directed to PM (SQMODE).
;;*       ;**
;;*       ;** It should be commented now, because we want the Kbd DD to support
;;*       ;** layering also for a PM (or VIO-Windowed) application.
;;*       ;*********************************************************************
;;*       ;**
;;*       ;**.If <ES:[DI].CPValue ne 0>  ; If secondary codepage loaded
;;*       ;**    Mov BX, Index2          ; Make the CPCB index 2
;;*       ;**.Else                       ; Else
;;*       ;**    Xor BX, BX              ; Make the CPCB index 0
;;*       ;**.Endif                      ; End if secondary codepage
;;*       ;**
;;*
;;*         Pop   ES                        ;* Get KCB sel
;;*         Mov   DI, AX                    ;* Get KCB offset
;;*         Mov   ES:[DI].KCBIxOffCP, BX    ;* Store index in KCB
;;*      .Endif                             ;* End if not a custom codepage
;;*                                         ;* V2.0XXX10 End
;;*
;;*        Mov   AX, BX                    ;* Put index into the accumulator.
       Mov   ES,CBDataSel              ;* so just get selector off stack
       Mov   DI,CPCBOFFSET             ;* and set up offset to CPCB
       Mov   CX,CPCBEntrySize          ;* Get size of CPCB
       IMul  CX                        ;* Compute offset into CPCB based on
                                         ;* index from the KCB
       Add   DI,AX                     ;* Add the offset into CPCB to first
                                         ;* offset
       Mov   ES,Word Ptr ES:[DI].CPVAddr  ;* Get high word of XTable V. addr.
   .Else                                 ;* Else KCB specified Custom CP
       ;* SaveReg<BP,CX,DX,SI>           ;* Save from PhysToVirt destruction
       ;* Mov AX,Word Ptr ES:[DI].KCBCPPhysAddr+2 ;* so get the physical address of the
       ;* Mov BX,Word Ptr ES:[DI].KCBCPPhysAddr   ;* custom translate table
       ;*
       ;* Now AXBX is physical address of XT
       ;*
       ;* Mov    CX,XTLen                ;* Get table length.
       ;* Mov    DH,ES_DI                ;* Tell DevHlp to put result in ES:DI.
       ;* Mov    DL,DevHlp_PhysToVirt    ;* Set DevHlp function.
       ;* Call   [DeviceHelp]            ;* Go get the pointer.
       ;* Mov    BX,DI                   ;* Put XTable offset in BX
       ;* RestoreReg<SI,DX,CX,BP>        ;* restore regs.

       

         Mov ES, Word Ptr ES:[DI].KCBCustSel  ;* get allocated selector value.
   .Endif                              ;* Endif Custom code page or not
    Xor   DI,DI                        ;* Get low word of XTable addr.

    Pop    CX                          ;*            restore SG number.
    Pop    AX                          ;* Restore original scan code
    Mov    BX,DI                       ;* Put XT offset in BX.
    Mov    DI,SI                       ;* Put XT flags area pointer in DI
    Pop    SI                          ;* Restore key packet offset

    Call   KbdXlate                    ;* Go translate this scan code.

    Pop    DI                          ;* Restore PSG pointer.
    Mov    BX,[SI].Key.Shift           ;* Get shift flags from CDR
    Mov    [DI].ShiftFlags,BX          ;* And put them in PSG data area

 ;* Gutted code for retranslation ,            

 .Endif                                  ;* Endif special scan code or not

  Pusha                              ;* Start of procrun for           
  Mov    AX, [DI].Shiftflags         ;* need to modify shiftflags
  And    AX, NOT (InsTogl+CapsTogl+NumTogl+ScrollTogl) ;* clear LEDs toggle bits
 .If <bit IntFlags nz KcbBlockSet> AND   ;*If Block is set AND
 .If <AX eq 0>                           ;*If Shift flags equal zero
      Mov    BX, KcbBlockId              ;*Get block ID
      Mov    AX, [KcbBlockId+2]          ;*Get block ID
      Mov    DL,DevHlp_ProcRun           ;*Run the Blocked process
      Call DeviceHelp                    ;*Do it
 .Endif                                  ;*
  Popa                                   ;*end of ptr           

   ;* Check if translation process sent us two packets to pass.

 .If <bit IntFlagArea.XSpecFlags nz UseTwoPac> ;* Check if passing 2 packets.
    Mov    SI,Offset DGROUP:KeyPacket2         ;* Point to KeyPacket2.
    Mov    Byte Ptr [SI].KPacketLen,0          ;* Clear "MonFlags" field.
 .Endif


Public TwoPackets
TwoPackets:    ;* Return here when translation process passes two packets.

 .If <bit MiscFlags z NoReadYet>      ;*  Check if anyone has asked for a key yet.
    Mov    DH,HotKeyDown              ;*  Set bit needed by next call.
    Mov    AX,IntFlagArea.XHotKeyShift;*  Get shift status from interrupt
                                      ;*  driven shift status for hot key checking
    Call HotKeyCheck                     ;*  Go check for SM hotkey.
 .Endif

    ;* Check for and process system keystrokes.

  Mov     BX,[SI].DDFlags                ;* Fetch DD Flags from Key Packet.
  And     BX,KeyTypeMask                 ;* Use only Key Type field.
 .If <BX b MaxSysKeyType> NEAR           ;* Is this a key type to process now?
    Shl    BX,1                          ;* Yes, so make BX an index.
    Jmp    CS:[BX][SysKeyChecks]         ;* Go process the keytype.

    ;*
    ;* Following is a case table for the System Key checks. Control will
    ;* merge again at the label "SysKeyCheckEnd" not far below.
    ;*

Even
Public SysKeyChecks,SysKeyCheckEnd,AckCodeChk,SecPrefixCodeChk,
Public OverRunCodeChk,ResendCodeChk,RebootKeyChk,DumpKeyChk,SysKeyCheckEnd,
Public BadAccCombo
SysKeyChecks Label Word              ;* Beginning of System Key checks case table.
      dw  SysKeyCheckEnd             ;* 0 = Always pass with no processing.
      dw  AckCodeChk                 ;* 1 = Ack from the keyboard.
      dw  SecPrefixCodeChk           ;* 2 = E0 prefix from the keyboard.
      dw  OverRunCodeChk             ;* 3 = Overrun code from the keyboard.
      dw  ResendCodeChk              ;* 4 = Resend code from the keyboard.
      dw  RebootKeyChk               ;* 5 = Last key of the Reboot sequence.
      dw  DumpKeyChk                 ;* 6 = Last key of the Stand Alone dump sequence.
      dw  SysKeyCheckEnd             ;* 7 = Shift Key being passed.
      dw  SysKeyCheckEnd             ;* 8 = Pause Key being passed.
      dw  SysKeyCheckEnd             ;* 9 = PSPause Key being passed. key.
      dw  SysKeyCheckEnd             ;* 10 = Wakeup Key being passed.
      dw  BadAccCombo                ;* 11 =     accent/char combo, beep only
MaxSysKeyType Equ ($-SysKeyChecks)/2


RebootKeyChk:                        ;* Last key of the Reboot sequence.
  Test LockupFlags,Lockup            ;*            If Desktop's Lockup
 .If <nz>                            ;*            is on, do not reboot
     Jmp SysKeyCheckEnd              ;*            the system.
 .Endif                              ;*           
                                     ;*             BEGIN
  Mov    AH, event_SM_CAD            ;* Specify DevHlp function
  Mov    DL,DevHlp_SendEvent         ;* Set DevHlp function for SendEvent.
  Call   [DeviceHelp]                ;* Call Device Help
  Jmp    SysKeyCheckEnd              ;* Go to bottom of case table.
                                     ;*            END

DumpKeyChk:                          ;* Last key of Stand Alone dump sequence.
    Test LockupFlags,Lockup          ;*            If Desktop's Lockup
   .If <nz>  OR                      ;*            is on, do not reboot
.386p                                ;* 84172-Or if NULL pointer then don't dump.
   .if <SADump eq 0>                 ;* 84172-We don't always install dump sequence
.286p                                ;* 84172- now so this check is needed.
       Jmp SysKeyCheckEnd            ;*            the system.
   .Endif                            ;*           
                                     ;*
    Mov    DL,DevHlp_UnPhysToVirt    ;* Specify DevHlp function
    Call   [DeviceHelp]              ;* Call Device Help
 ;  Mov    AL,KbdIRQ                 ;* Get Int. Request Level     Remove 76711
 ;  Mov    DL,DevHlp_EOI             ;* Specify DevHlp function    Remove 76711
 ;  Call   [DeviceHelp]              ;* Call Device Help           Remove 76711
    DevEOI <KbdIRQ>,DeviceHelp       ;*                            Add    76711
    clc                              ;* Clear Carry                Add    76711
    Jmp    [SADump]                  ;* Go to Stand Alone Dump.
                                     ;*
OverRunCodeChk:                      ;* Overrun code from the keyboard.
    Jmp Short SysKeyCheckEnd         ;* should never reach here
                                     ;*
AckCodeChk:                          ;* Ack from the keyboard.
    Jmp Short SysKeyCheckEnd         ;* should never reach here
                                     ;*
ResendCodeChk:                       ;* Resend code from the keyboard.
    Jmp Short SysKeyCheckEnd         ;* should never reach here
                                     ;*
BadAccCombo:                         ;*     accent/char combo, beep only
                                     ;*            BEGIN)
   .If <bit [DI].PSGFlags z SQMODE>  ;* Check for Single Queue mode.
        Or MiscFlags,BeepSpeaker     ;* Indicate to beep speaker.
   .Endif                            ;* Endif in Single Queue Mode
                                     ;*            END
    Jmp Short SysKeyCheckEnd         ;* Go to bottom of case table.

Public SecPrefixCodeChk
SecPrefixCodeChk:                    ;* E0,E1 prefix from the keyboard
                                     ;*              BEGIN
                                     
;*   Or [SI].DDFlags,NotSQPacket     ;* Flag as not a SQ packet
                                     ;*              END

Public SysKeyCheckEnd
SysKeyCheckEnd:                      ;* End of System Key checks case table.

 .Endif                              ;* End of System Key checks.

    ;*
    ;* We've now translated the scan code and checked for system keys and
    ;* keyboard special codes. If no-one has yet asked for a keystroke we
    ;* can quit now because in that case we have not started using an
    ;* active screen group.
    ;*

  Test MiscFlags,NoReadYet     ;* Check if anyone has asked for a key yet.
 .If <z> NEAR                  ;* If so, continue.

    ;*
    ;* If there are any monitors registered in this current SG, we
    ;* will attempt to pass the Key packet to the monitor dispatcher.
    ;* If it doesn't accept it we will beep the speaker. Either way
    ;* we will quit then.
    ;* If no monitors are registered we will check whether the end-of-
    ;* monitor-chain buffer has a record in it. If so, the KIB is full,
    ;* so we beep and quit. If that buffer is empty we copy Key into it.
    ;*
    ;* We then attempt to put the CharData record into the KIB. See
    ;* the notes in the PutInKIB subroutine for more details about
    ;* what happens then.  If PutInKIB fails, the record is left in
    ;* the end-of-monitor-chain buffer as the last element in the
    ;* KIB, which means the KIB is now full.
    ;*

   .If <[DI].MonsInstalled gt 0>               ;* If mons registered try to pass
      Or Byte Ptr [SI].KPacketLen,NotInserted  ;* Indicate that this
                                               ;* key isn't monitor inserted.
      Mov  AX,[DI].MonHandle             ;* Get monitor chain handle.
                                         ;* Address of Key Packet already
                                         ;* in SI, required by DevHlp call.
      Mov  CX,KeyPacketLen               ;* Set length of packet.
      Mov  DX, 0100h + DevHlp_MonWrite   ;* DH = NOWAIT for monitor accept
                                         ;* DL = DevHlp function.
      Call [DeviceHelp]                  ;* Go pass Key to monitor
     .If <c> AND                         ;* Did monitor dispatcher NOT accept AND
      Test [SI].Key.Status,1             ;* Is it a shift report packet
     .If <nz> OR                         ;* If it is OR
      Mov  DX,[SI].DDFlags               ;* Get DDFlags
      And  DX,ShiftMask                  ;* Clear all bits except shift value
     .If <DX ne ShiftMask>               ;* If its not a shift key then...
        Or MiscFlags,BeepSpeaker         ;* so indicate beep.
     .Endif

   .Else NEAR                  ;* No monitors, do Console-Input-Filtering now.

     .If <bit [DI].PSGFlags nz SQMODE> AND ;* Check for Single Queue mode.
     .If <bit [SI].DDFlags z NotSQPacket>  ;* If packet should go in SQ buffer
        And IntFlags, NOT Up_LEDs          ;* Turn off UP_LEDs Full Screen flag
        Push  SI
        Push  BX
       .If <bit SQHotKeyData nz 03>        ;*            ,If nonzero
          Call PutInSQB                    ;* Call SingleQ DD with Hot Key Info
       .Endif                              ;* Endif
        Pop   BX
        Pop   SI
        Call PutInSQB
     .Endif

                                         ;*            No VDM call to ConsInpfilter.
     .If <CurSG lt sgidFirstVDM>         

         Call ConsInpFilter              ;* Go send events as appropriate.
                                         ;*            END
        .If <nc> NEAR AND                ;* If ConsInpFilter said keep record
        .If <bit [DI].PSGFlags z SQMODE> ;*  AND If not PM

            Mov    DH,ES_DI              ;* Tell PhysToVirt where to put it.
            Push   DI                    ;* Save PSG pointer
            Call   AccessKCB             ;* Go get access to this SG's KCB
            Mov    BX,DI                 ;* Put KCB offset in BX
            Pop    DI                    ;* Restore PSG pointer
           .If <ES:[BX].KCBInPtr eq 0>   ;* End-of-chain buf already full
                 Or MiscFlags,BeepSpeaker;* Yes, indicate beep speaker.
           .Else                         ;* Otherwise, prepare to move record.
              Push   DS                  ;* Set up ES for...
              Pop    ES                  ;* ...data copying.
              Push   DI                  ;* Save DI.
              Add    DI,MonChainEnd+2    ;* Point to end-of-chain bfr (no length)
              Push   DI                  ;* Save for SI later.
              Mov    CX,KeyPacketLen     ;* Set length of monitor packet.
              Cld                        ;* Make sure we don't decrement.
              Rep    MovSB               ;* Move that record.
              Pop    SI                  ;* Set SI to end-of-chain buffer.
              Pop    DI                  ;* Restore pointer to PSG.
              Call   PutInKIB            ;* Go put record into this SG's KIB.
           .Endif

           ;*            Turn the NoReadYet flag back on if the
           ;* SwitchPID variable is still zero, which indicates that the
           ;* first screen switch has not taken place.  In this case, there
           ;* is really no session to speak of, so each read prior to
           ;* actually having sessions should be treated as if it's the
           ;* first read.  Reference  FirstReadCheck for processing
           ;* which occurs when this flag is still on...

          .If < bit IntFlags z FReadDone> AND     
          .If < SwitchPID e 0 >          ;* If no session manager yet,
               Or MiscFlags, NoReadYet   ;* Pretend every read is 1st.
          .Endif                         ;* End if no session manager.
                               ;*
        .Endif                 ;* End "ConsInpFilter didn't eat keystroke" and
                               ;*            Not in Single Queue Mode.
     .Endif                    ;*            Endif NOT VDM session.
   .Endif                      ;* End of "monitors installed or not" check.
                               ;* End of "no read yet" check.
                               
 .Else                         ;* Else no read has been done yet (booting up)
                               ;* ConsInpFilter not called, If Pause pressed
                               ;* PauseChk never called but SGPaused flag
                               ;* causes WakeUpChk to be called. CLEAR OUT
                               ;* THE SGPaused flag!
    And IntFlagArea.XlateFlags, NOT SGPaused

 .Endif



  Test Byte Ptr IntFlagArea.XSpecFlags, UseTwoPac
                                              ;* Check if passing two packets.
 .If <nz>                                     ;* Are we?
    Test Byte Ptr IntFlagArea.XSpecFlags, UseTwoAlt
                                              ;* Check to see if passing
                                              ;* Alt-Numpad packets.
   .If <z> AND
    Test Byte Ptr IntFlagArea.XSpecFlags, UseTwoE0
                                              ;* Check to see if we are passing
                                              ;* an E0 combination.
   .If <z>
        Or MiscFlags,BeepSpeaker              ;* If not, this is invalid accent
                                              ;* so beep the speaker.
   .Endif
    And    Byte Ptr IntFlagArea.XSpecFlags,0  ;* Clear out the XSpecFlags.
    Mov    SI,Offset DGROUP:KeyPacket1        ;* Point to first packet now.
    Jmp    TwoPackets                         ;* Go pass other packet.
 .Endif

  Push    AX                             ;*           
  Mov     AX,CurSG                       ;* Setup for next test and call.
 .If <AX lt sgidFirstVDM> AND            ;* Check if current SG isn't a VDM AND
 .If <NumPadAccum ne 0>                  ;* If not 0, We need to send
                                         ;* the Accumulation packet for a R-Alt.
                                         ;* NOTE that if we are in a VDM, 1:This
                                         ;* is skipped. 2:SendVddSc occurs 3:
                                         ;* NumPadAccum value is used in VDMScanFilter
                                         ;* END NOTE
    Mov    AL, NumPadAccum               ;* Get the accumulation value
    Mov    [SI].Key.XChar, AL            ;*  Put it in the Keypacket
    Pop    AX                            ;* Restore AX
    Mov    [SI].DDFlags, 0               ;*  Clear DDFlags
    Mov    NumPadAccum, 0                ;* clear value
    Jmp    TwoPackets                    ;*  Go pass packet again.
 .Endif                                  ;* Endif
  Pop AX                                 ;*  Restore AX



Public Spurious
Spurious:        ;* Jumps to here when unexpected shift key break code seen.
                 ;* or a MultiMake is seen

      ;* Near end of processing.  We check to see IF Kbd LEDs need updating.
      ;* IF it is, then we will start the Update LED command here.
      ;* IF not, we must queue the request.

   Mov    DH,ES_DI                       ;* Tell PhysToVirt where to put it.
   Push   DI                             ;* Save PSG pointer
   Call   AccessKCB                      ;* Go get access to this SG's KCB
   Mov    BX,DI                          ;* Put KCB offset in BX
   Pop    DI                             ;* Restore PSG pointer
   Mov    AX,[DI].ShiftFlags             ;* Get PSG ShiftFlags
   Push   AX                             ;*             Save shift flags
   Mov    ES:[BX].KCBShift,AX            ;* Put them in the KCB
                                         ;*
    ;*
    ;*  Send VKBD the scan code
    ;*

   Mov   AX,CurSG                        ;* Setup for next test and call.
 .If <AX ge sgidFirstVDM>                ;* Check if current SG is a VDM
    and IntFlags, NOT Up_LEDs            ;* JC Do not update LEDs for a VDM SG

   .If <bit AIMFlags z ConsumeScan> AND  ;* AIM If we are not supposed to consume
                                         ;* AIM  this scan for sticky keys, AND

   .If <bit IntFlags z Not_VScan>        ;*            If the scan code
                                         ;* can be sent to the VKBD.
      Mov  BL,-1                         ;* Indicate an Activated SG check.
      Call SGActivation                  ;*            Check to see if we have
                                         ;* received a VDMCreated call for
                                         ;* the current VDM session.
     .If <c>                             ;* if it is active,(recieved a
                                         ;*  VDD/PDD Created call for the SG.)
        Xor   AH,AH                         ;* Not needed, SC is put in low nib
        Mov   AL,Byte Ptr [SI].KPacketLen+1 ;* Get scan code
        Mov   PDDtoVDDSCPkt.kint_chScan,AX  ;*  Pkt at XLateRetry
        Mov   BX,CurSG                      ;* Get screen group ID
        Mov   PDDtoVDDSCPkt.kint_usSGID,BX  ;*  Put SGID code in VDDs packet
        Call  SendVDDSC                  ;* Send the scan code to the VDD
     .Else                               ;* Otherwise, buffer up the scan codes
        Call  PutInVDMQ                  ;* in the VDMQ until we get the Created
     .Endif                              ;* call in the VDD/PDD interface.
   .Endif                                ;* Endif scan not to be sent to VKBD
    Pop    AX                            ;*           
    Jmp    Only_Exit                     ;* prepare to exit int handler for
 .Endif                                  ;* VDM sessions.
   Pop    AX                             ;* Restore shift flags
                                         ;*            - Begin
                                         ;* Restore KCB address of KCB w/
                                         ;* current focus
   Push    DI                            ;* Save PSG pointer for SG that
                                         ;* interrupt belongs to.
   Mov     DI,StkPSG                     ;* Get PSG pointer for SG that
                                         ;* interrupt was received in
   Mov     BX,Word Ptr KCBFocusAddress   ;* Get physical address saved
   Mov     Word Ptr [DI].KCBAddress,BX   ;* Put it back where it goes
   Mov     BX,Word Ptr KCBFocusAddress+2 ;* Get physical address saved
   Mov     Word Ptr [DI].KCBAddress+2,BX ;* Put it back where it goes
   Pop     DI                            ;* Restore PSG pointer for SG that
                                         ;* interrupt belongs to.
                                         ;*            - End

   Mov     DL,DevHlp_UnPhysToVirt        ;* Specify DevHlp function
   Call    [DeviceHelp]                  ;* Call Device Help

Public Only_Exit
Only_Exit:
 Test MiscFlags,BeepSpeaker              ;* Check if need to beep speaker.
 .If <nz>
    KbdBeep 3,1000,13
    And MiscFlags, NOT BeepSpeaker       ;* Turn bit off
 .Endif
  And IntFlags, Not Not_VScan         ;*            Turn off bit for VKBD scans.

  Push    AX                             ;* AIM
  Mov     AL, Byte Ptr [SI].KPacketLen+1 ;* AIM
  Test    AL, BreakBit                   ;* AIM
 .If <nz>                                ;* AIM
    And   AIMFlags, NOT ConsumeScan      ;* AIM Clear bit for consuming breaks.
 .Endif                                  ;* AIM
  Pop     AX                             ;* AIM

;* start ptr AK02182 problem with Scroll LED toggel on and off with Pad arrow key

 .If<bit IntFlagArea.XKeyFlags nz SecPrefix >  ;* if just saw E0 then 182
       And IntFlags, NOT Up_LEDs               ;* Turn off UP_LEDs Full Screen flag
 .Endif
                            

  Ret
ProcessScanCode endp

Public   ConsInpFilter
ConsInpFilter Proc ;******/

;/***************************************************************************
;*
;* FUNCTION NAME = ConsInpFilter
;*
;* DESCRIPTION   = Keyboard Interrupt Handler Console Input Filter
;*
;*                  This routine processes the DDFlags of the Monitor
;*                  Key Packet. It checks for Accent, Ctrl-Break, Ctrl-C
;*                  Shift-Prtsc, Ctrl-PrtSc and Ctrl-P Keys and issues
;*                  the appropriate DevHlp Send_Event.
;*
;*
;*
;*
;* INPUT         = DI = Per Session Data Area Address
;*                 SI = Key Packet Address
;*
;* OUTPUT        = AX, BX, CX, DX, BP registers, carry flag changed.
;*
;*
;* RETURN-NORMAL = Carry set = throw key away
;*                 Carry clear = keep key
;*
;* RETURN-ERROR  = NONE
;*
;*
;**************************************************************************/



     Push   BP                           ;* Save our stack frame pointer
     Mov    DH,ES_DI                     ;* Tell PhysToVirt where to put result
     Push   DI                           ;* Save PSG pointer
     Call   AccessKCB                    ;* Go get access to this SG's KCB
     Mov    BX,DI                        ;* Put KCB offset in BX
     Pop    DI                           ;* Restore PSG pointer
     Mov    CX,[SI].DDFlags              ;* Get the device driver flagword.
     Test   [SI].Key.Status,1            ;* If inputmode is
 .If <z> NEAR                            ;* ShiftReport
                                         ;*            Begin
       Mov    CX,[SI].DDFlags            ;* Get the device driver flagword.
       Push   CX                         ;* save the flag word
       Test   CX,KeyBreak                ;* Check for a break
    .If <nz> AND                         ;* If it is BUT
     And    CX,KeyTypeMask               ;* Isolate the key type field.
    .If <CX ne SysReqKey>                ;* its not the break of SysReq
       Pop    CX                         ;* Restore the flag word
       Stc                               ;* throw the key away
    .Else NEAR
       Pop    CX
                                         ;*            End
       Mov    BP,CX                      ;* Put flags in an index reg.
       And    BP,KeyTypeMask             ;* Isolate the key type field.
      .If <z>                            ;* If zero we always keep it
         clc                             ;* return with carry clear
      .Elseif <BP b 8>                   ;* Is this a System key or
                                         ;* special keyboard code?
         StC                             ;* Yes, so throw it away now.
      .ElseIf <BP ae 30h>                ;* Is this a non-keyboard generated key?
        .If <BP eq 31h>                  ;* But is this a "written" key?
           ClC                           ;* Yes, so we always keep it.
        .Else                            ;* Else, not a character.
           StC                           ;* So indicate to throw it away.
        .Endif
      .Else NEAR                         ;* Otherwise, the key is in the range
                                         ;* we need to check out.
         Sub  BP,8                       ;* Normalize key type number.
        .If <BP b MaxCIFKeyType> NEAR    ;* If this key type in range
            And   CH,3Fh                 ;* Clear high bits of DD flags
                                         ;* (we don't use'm anyway).
            Mov   BH,ES:[BX].KCBInpMode  ;* Get input mode.
            And   BH,INPUTMODE           ;* Clear possible other bits.
            Or    CH,BH                  ;* Put input mode in high bit.
            Mov   DL,DevHlp_UnPhysToVirt ;* Specify DevHlp function
            Call  [DeviceHelp]           ;* Call Device Help
            Xor   BX,BX                  ;* Clear event reg for
                                         ;* following SendEvents.
            Mov   DL,DevHlp_SendEvent    ;* Set DevHlp function for SendEvents.
            Shl   BP,1                   ;* Make Key Type number an index.
            Add   BP,Offset KbdCode:CIFTable ;* Index into case table for
                                         ;*  the Console Input Filter.
            Jmp   CS:[BP]                ;* Go process the key.
      ;*
      ;* Following is a case table for the Console Input Filter checks.
      ;* Control will merge again at the label "CIFKeyCheckEnd" below.
      ;*

Public  PauseChk,      PSPauseChk,      WakeUpChk
Public  AccentKeyChk,  BreakKeyChk,     PsBreakKeyChk,  PrtScrKeyChk
Public  PrtEchoKeyChk, PsPrtEchoKeyChk, PrtFlushKeyChk, SysReqKeyChk

Even
CIFTable Label Word      ;* Beginning of ConsInpFilter checks case table.
              dw  PauseChk               ;* 8 = Ctrl-NumLock key.
              dw  PsPauseChk             ;* 9 = Pseudo Ctrl-NumLock (Ctrl-S) key.
              dw  WakeUpChk              ;* A = Key following 8 or 9.
              dw  ReservedType           ;* B = Reserved key type (throw away)
              dw  ReservedType           ;* C = Reserved key type (throw away)
              dw  ReservedType           ;* D = Reserved key type (throw away)
              dw  ReservedType           ;* E = Reserved key type (throw away)
              dw  ReservedType           ;* F = Reserved key type (throw away)
              dw  AccentKeyChk           ;* 10 = Accent key.
              dw  BreakKeyChk            ;* 11 = Ctrl-Break key.
              dw  PsBreakKeyChk          ;* 12 = Pseudo Ctrl-Break (Ctrl-C) key.
              dw  PrtScrKeyChk           ;* 13 = Shift-PrtScr key.
              dw  PrtEchoKeyChk          ;* 14 = Ctrl-PrtScr key.
              dw  PsPrtEchoKeyChk        ;* 15 = Pseudo Ctrl-PrtScr (Ctrl-P) key.
              dw  PrtFlushKeyChk         ;* 16 = Flush Print Buffer (Ctrl-Alt-PrtScr) key.
              dw  SysReqKeyChk           ;* 17 = Sys Request Key (PTM 4990)
MaxCIFKeyType Equ ($-CIFTable)/2

PauseChk:                                ;* Ctrl-NumLock key.
PsPauseChk:                              ;* Pseudo Ctrl-NumLock (Ctrl-S) key.
             .If <bit [SI].DDFlags z KeyBreak> AND NEAR ;* If not a key break and
             .If <bit [DI].PSGFlags z NowPaused> AND NEAR   ;* Not already paused
             .If <bit [DI].PSGFlags z SQMODE> ;*            Event must not
                                              ;* occur in SQMODE.
                Mov   AH,event_CtrlScrLk      ;* No, set event to send.
                Mov   BX,[DI].PSGNum          
                Mov   DL,DevHlp_SendEvent     ;* Set DevHlp function.
                Call  [DeviceHelp]            ;* Go send it.
                Or    [DI].PSGFlags,NowPaused ;* Indicate now paused.
                Or    IntFlagArea.XlateFlags,SGPaused ;* used for UnPauseChk
             .Endif
              Stc                        ;* Throw the key away
              Jmp CIFKeyCheckEnd         ;* Go to bottom of case table.

WakeUpChk:                               ;* Key following PauseKey or
                                         ;* PseudoPause.
             .If <bit [DI].PSGFlags z SQMODE> ;*            Event must not
                                              ;* occur in SQMODE.
                Mov   AH,event_CtrlScrLk      ;* Set event to send.
                Mov   BX,[DI].PSGNum          ;* Put SG # in parm reg (P6165)
                Mov   DL,DevHlp_SendEvent     ;* Set DevHlp function.
                Call  [DeviceHelp]            ;* Go send it.
                And   [DI].PSGFlags,Not NowPaused ;* Clear paused indication.
                And   IntFlagArea.XlateFlags,Not SGPaused ;* ditto
                Stc                           ;* Throw the key away
                Jmp   CIFKeyCheckEnd          ;* Go to bottom of case table.
             .Endif                           ;*

AccentKeyChk:                            ;* Accent key.
              Test    CX,AccentedKey     ;* Check if this an accent Character to keep.
             .If <z>                     ;* Is it?
                StC                      ;* Throw this one away.
             .Endif
              Jmp     CIFKeyCheckEnd     ;* Merge at bottom of case table.

BreakKeyChk:                             ;* Ctrl-Break key.
              ;*
              ;* If we are paused, we want to now signal that we
              ;* aren't paused because the break takes higher precedence
              ;* than the pause wake-up.
              ;*

             .If <bit [DI].PSGFlags nz NowPaused> AND ;* Check if paused
             .If <bit [DI].PSGFlags z SQMODE>     ;*            Event must not
                                                  ;* occur in SQMODE.
                 Mov  AH,event_CtrlScrLk          ;* Set event to send.
                 Mov  BX,[DI].PSGNum              ;* Put SG # in parm reg (P6165)
                 Mov  DL,DevHlp_SendEvent         ;* Set DevHlp function.
                 Call [DeviceHelp]                ;* Go send it.
                 And  [DI].PSGFlags,Not NowPaused ;* Clear paused indication.
                 And  IntFlagArea.XlateFlags,Not SGPaused ;* ditto
             .Endif

                                         ;*            MonBlockCheck blocks the
              Call MonBlockCheck         ;* thread as long as thread's session
                                         ;* is not the active session.  This
                                         ;* used to be YieldCheck which would
                                         ;* yield if not active session.
                Push   AX                ;*             Begin, Save AX
                Xor    AX,AX             ;* Indicate to Access the KCB
                Call   PurgeKIB          ;* Now purge KIB.
                Pop    AX                ;*            End, Restore AX
              Xor    BX,BX               ;* Clear parm reg.
              Or     CH,CH               ;* Check if in Raw Mode.
             .If <s>                     ;* Are we?
                Mov   AH,event_CtrlBrk   ;* Yes, so set event to send.
                Call  [DeviceHelp]       ;* Go send it.
                ClC                      ;* Keep the key.
             .Else                       ;* Else cooked mode.
                Mov    AH,event_CtrlC    ;* Set event to send.
                Call   [DeviceHelp]      ;* Go send it.
                StC                      ;* Discard key.
             .Endif
              Jmp    CIFKeyCheckEnd      ;*  Merge at bottom of case table.

PsBreakKeyChk:                           ;*  Pseudo Ctrl-Break (Ctrl-C) key.
              ;*
              ;* If we are paused, we want to now signal that we
              ;* aren't paused because the break takes higher precedence
              ;* than the pause wake-up.
              ;*

             .If <bit [DI].PSGFlags nz NowPaused> AND ; Check if paused
             .If <bit [DI].PSGFlags z SQMODE> ;*            Event must not
                                              ;* be sent in SQMODE.
                 Mov   AH,event_CtrlScrLk     ;* Set event to send.
                 Mov   BX,[DI].PSGNum         
                 Mov   DL,DevHlp_SendEvent    ;* Set DevHlp function.
                 Call  [DeviceHelp]           ;*Go send it.
                 And   [DI].PSGFlags,Not NowPaused  ;* Clear paused indication.
                 And   IntFlagArea.XlateFlags,Not SGPaused ;* ditto
             .Endif
              Test CH,0C0h              ;* Check if in Raw Mode or in 3xBox.
             .If <z>                    ;* Are we?
                                        ;*            MonBlockCheck blocks the
                Call  MonBlockCheck     ;* thread as long as thread's session
                                        ;* is not the active session.  This
                                        ;* used to be YieldCheck which would
                                        ;* yield if not active session.


                Mov   AH,event_CtrlC          ;* Set event to send.
                Call  [DeviceHelp]            ;* Go send it.
                StC                           ;* Discard key.
             .Endif
              Jmp Short CIFKeyCheckEnd        ;*  Merge at bottom of case table.

PrtScrKeyChk:                                 ;* Shift-PrtScr key.
             .If <bit [DI].PSGFlags z SQMODE> ;*            Event must not
                                              ;* occur in SQMODE.
                Mov  AH,event_ShftPrtSc       ;* Set event to send.
                Call [DeviceHelp]             ;* Go send it.
                StC                           ;* Throw away the key.
                Jmp  Short CIFKeyCheckEnd     ;* Merge at bottom of case table.
             .Endif                           ;*

PrtEchoKeyChk:                         ;* Ctrl-PrtScr key.
PsPrtEchoKeyChk:                       ;* Pseudo Ctrl-PrtScr (Ctrl-P) key.
              Test   CH,0C0h           ;* Check if in Raw Mode or in 3xBox.
             .If <z>                   ;* Are we?
                                       ;*  MonBlockCheck blocks the           
                Call MonBlockCheck     ;* thread as long as thread's session
                                       ;* is not the active session.  This
                                       ;* used to be YieldCheck which would
                                       ;* yield if not active session.
               .If <bit [DI].PSGFlags z SQMODE>;*             Event must not
                                               ;* Event must not occur in SQMODE.
                  Mov   AH,event_CtrlPrtSc     ;* Set event to send.
                  Call  [DeviceHelp]           ;* Go send it.
                  Stc                          ;* Discard key.
               .Endif
             .Endif
              Jmp Short CIFKeyCheckEnd     ;* Merge at bottom of case table.

PrtFlushKeyChk:                            ;* Flush Print buffer to printer
              Jmp Short CIFKeyCheckEnd     ;* Merge at bottom of case table.

SysReqKeyChk:                              ;* System Request key
              Stc                          
                                           ;* Alway throw SYSREQ away
              Jmp Short CIFKeyCheckEnd     ;* Merge at bottom of case table.

ReservedType:                              ;* Reserved key type
              Stc                           ;* throw it away


CIFKeyCheckEnd:      ;* End of Console Input Filter key checks case table.

        .Else        ;* Else keytype is undefined.
            StC      ;* So indicate throwaway.
        .Endif       ;* End of "undefined value within filtered keytypes" check.
      .Endif         ;* End of KeyType category checks.
    .Endif           ;* Endif KeyBreak or not check
 .Endif              ;* Endif this is a shift report key or not check
  Pop BP             ;* Restore our stack frame pointer
  Ret

ConsInpFilter Endp

Code Ends
     End
