; SCCSID = src/dev/kbd/kbdbase.ssc/kbdscan.asm, kbd, c.basedd 98/01/16
    Page  58,132
    Title   KBDSCAN - Kbd Device Driver Scan Code Processor
    Name    KBDSCAN

;/*************************************************************************
;*
;* SOURCE FILE NAME = KBDSCAN.ASM
;*
;* DESCRIPTIVE NAME = PKBD Scan Code Processor
;*
;* 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         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
;*             @V2.0XXX01  B730591
;*             @V2.0XXX02  B724802
;*             @V2.0WCH01  46491
;*             @V2.0XXX03  DCR 652
;*             @V2.OXXX04  PTM 5625
;*             @V2.0XXX05  DCR 1131
;*             @V2.0XXX06  PTM 5992
;*             @V2.0XXX07  PTM 2382
;*             @V2.0XXX08  B785763
;*             @V2.0XXX09  700700
;*             @V2.0XXX10  DCR 408
;*             @V2.0XXX11  B786969
;*             @V2.0XXX12  B724802
;*             @V2.0XXX13  DCR 513
;*             @V2.0XXX14  DCR 8
;*             @V2.0XXX15  B787171
;*             @V2.0XXX16  PTMs 3090/3497
;*             @V2.0XXX17  B733926
;*             @V2.0XXX18  DCR 549
;*             @V2.0XXX19  B786686
;*             @V2.0XXX20  B787292
;*             @V2.0XXX21  PTM 4990
;*             @V2.0XXX22  B711290
;*             @V2.OXXX23  PTM 6810
;*             @V2.OXXX24  B789221
;*   06/08/95  121142      PJ18302  No longer rely on stack vars (StkKCBS &
;*             StkKCBO) for kcb addr -> these are being invalidated by
;*             devHelp calls &/or blocks/yields in certain situations
;*             (these values are obtained through a devHelp PhysToVirt;
;*             PhysToVirt values are no longer valid after another devHelp
;*             or a block/yield).
;*
;*   10/27/97  @V3.0RV01 121081    Check for UsetwoAcc before setting
;*                                 beep flag.
;*
;*   UNKNOWN   J-DBCS001          DBCS enabling (J-001)
;*   UNKNOWN   J-DBCS002          DBCS enabling (ms001)
;*   UNKNOWN   JS03022            PTR JS03022/JC20 (ss0016)     (S.Sakamoto)
;*   10/27/94  J-DBCSWARP         Base code change for WARP         (H.Mori)
;*   06/14/95  JS07091    PJ15809 Keyboard hung with many key stroke(H.Mori)
;*   10/03/96  J-1223             Alt+Home in DOS sess cause shift bit problem (H.Mori)
;*   10/07/96  J-1053             Beep sounds when switching screens(H.Mori)
;*   07/28/97  2901j-             Incorrect CapsLock state if a Monitor is in SG0 (K.Ueda)
;*   10/2/97   D184790            Fix incorrect CAP LOCK LED state
;*   09/30/97  Skip Nizinski      Process dump enhancements  F180062.
;*   11/14/98  kwb                Change test for monitor special events
;**************************************************************************


.286p
.sall
.xcref
.xlist
  Include   mvdm.inc       ;*
  Include   osmaca.inc     ;*  Added for @V2.0XXX03, 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      ;* @V2.OXXX04  - 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

;;****************** - Security Begin

  __KBDDDREQ__ EQU  1          ; 180062 Exclude StartSesReqPkt from secure.inc
  Include   secure.inc   ;* Security dev_help structure
  Include   secure2.inc  ;* Security dev_help parameter

;;****************** - Security End
.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       ;* @V2.0XXX05
  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       ;* @V2.0XXX01
  Extrn    NumPadAccum       :Byte       ;*
  Extrn    KcbBlockId        :Word       ;* @V2.0XXX02
  Extrn    IntCount          :DWord      ;* PEN SUPPORT
  Extrn    CallBack          :Byte       ;* PEN SUPPORT
  Extrn    IDC_Write         :Word       ;* PEN SUPPORT
  Extrn    Keystroke2        :Byte
ifdef DBCSKBD
  Extrn    Keystroke         :BYTE       ;@IBM J-DBCSWARP(A)

  Extrn DIDD_Name            :Byte       ;@IBM J-DBCS002(A)
  Extrn DIDD_Exist           :Byte       ;@IBM J-DBCS002(A)
  Extrn DIDD_pDS             :Word       ;@IBM J-DBCS002(A)
  Extrn DIDD_pEntry          :DWord      ;@IBM J-DBCS002(A)
  Extrn KbdHWIDs             :Word       ;@IBM J-DBCS002(A)
endif ;DBCSKBD

  StkFrameVars

;;****************** - Security Begin

  Extrn    Security_DS       :WORD
  Extrn    Security_Off      :DWORD
  Extrn    Security_Enable   :BYTE
  Extrn    Security_Open     :WORD
  Extrn    TrustedPath       :WORD
  Extrn    Reboot_Rejected   :BYTE       ; 123036
  Extrn    GlobalRebootFlag  :WORD       ; cn 7/25/95

;;****************** - Security End

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
;*
;*************************************************************************/

ifdef DBCSKBD
ifdef kbd101                                                      ;J-DCR287  @IBM J-DBCSWARP(A)
   mov Keystroke,  al                 ; Store first scan code     ;J-DCR287  @IBM J-DBCSWARP(A)
   mov Keystroke2, bl                 ; Store second scan code    ;J-DCR287  @IBM J-DBCSWARP(A)
endif                                                             ;J-DCR287  @IBM J-DBCSWARP(A)
endif ;DBCSKBD

   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

;;****************** - Security Begin

 .if <Security_Enable eq 1>
    push ds
    mov esi, Security_Off           ; Point to data offset
    mov ds, Security_DS             ; Load Security's DS
    Inc Dword Ptr [esi]             ; Increment for activity
    pop ds
    .if < al eq Scan_Ctrl >         ; cn 7/25/95 added for reboot
       or GlobalRebootFlag,CtlFlag  ; so that secure os/2 will
      .elseif <al eq Scan_Ctrl+BreakBit > ; not reboot for an ioctl
         and GlobalRebootFlag,not CtlFlag ; only for actual key
        .elseif < al eq Scan_Alt >      ; cn 7/25/94
           or GlobalRebootFlag,AltFlag  ; cn 7/25/94
          .elseif <al eq Scan_Alt+BreakBit >  ; cn 7/25/94
             and GlobalRebootFlag,not AltFlag ; cn 7/25/94
    .endif                          ; cn 7/25/94
 .endif

;;****************** - Security End

.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                    ;* @V2.0WCH01 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
                                         ;* @V2.0XXX06 End
; --  Do not rely on stack variables - get kcb address ourselves        ;121142
;121142 LES       BX, Dword Ptr StkKCBO         ;* Get the KCB address from stack
  Push DX                               ;save regs                      ;121142
  Push DI                               ;                               ;121142
  Mov DH,ES_DI                          ;retn kcb slctr/offset in es/di ;121142
  CALL AccessKCB                        ;get  kcb address               ;121142
  Mov BX,DI                             ;put offset in bx               ;121142
  Pop DI                                ;                               ;121142
  Pop DX                                ;restore regs                   ;121142

ifdef DBCSKBD
;;-----------------------------------------------------------------------;@IBM J-DBCS002(A)
;;  KeyMapping                                                           ;@IBM J-DBCS002(A)
;;-----------------------------------------------------------------------;@IBM J-DBCS002(A)
                                                                         ;@IBM J-DBCS002(A)
 .If <DIDD_Exist ne 0> AND                                               ;@IBM J-DBCS002(A)
 .If <KbdHWIDs eq 83ABh > OR                                             ;@IBM J-DBCS002(A)
 .If <KbdHWIDs eq 41ABh > OR                                             ;@IBM J-DBCS002(A)
 .If <KbdHWIDs eq 84ABh > OR                                             ;@IBM J-DBCS002(A)
 .If <KbdHWIDs eq 54ABh >                                                ;@IBM J-DBCS002(A)
    Push DS                                                              ;@IBM J-DBCS002(A)
    Push ES                                                              ;@IBM J-DBCS002(A)
    Push DS                                                              ;@IBM J-DBCS002(A)
    Pop  ES                                                              ;@IBM J-DBCS002(A)
                                       ; AL     ; H/W scan code          ;@IBM J-DBCS002(A)
                                       ; ES:BX  ; KCB address            ;@IBM J-DBCS002(A)
    Mov  DL, IntFlagArea.XlateFlags    ; XlateFlags                      ;@IBM J-DBCS002(A)
    Mov  DS, DIDD_pDS                  ; DS of DI D/D                    ;@IBM J-DBCS002(A)
    Mov  AH, 0                         ; Command                         ;@IBM J-DBCS002(A)
    Call ES:DIDD_pEntry                                                  ;@IBM J-DBCS002(A)
    Pop  ES                                                              ;@IBM J-DBCS002(A)
    Pop  DS                                                              ;@IBM J-DBCS002(A)
                                                                         ;@IBM J-DBCS002(A)
    Mov IntFlagArea.XlateFlags, DL     ; XlateFlags                      ;@IBM J-DBCS002(A)
 .Endif                                                                  ;@IBM J-DBCS002(A)
                                                                         ;@IBM J-DBCS002(A)
;;-----------------------------------------------------------------------;@IBM J-DBCS002(A)
endif ;DBCSKBD


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.
ifdef DBCSKBD
  Or       [SI].Key.Status,DefaultDBCS   ;* Set fainal bit              ;@IBM J-DBCS001(A)
 ;*Clear not only shift report bit but also extended code bit.          ;@IBM J-DBCS001(A)
  And      [SI].Key.Status,Not EXTENDEDCODE+SHIFTREPORT                 ;@IBM J-DBCS001(A)
  Mov      [DI].DBCSFlags,DL             ;* Put copy in PSG             ;@IBM J-DBCS001(A)
endif ;DBCSKBD
  Mov      DL,ES:[BX].KCBDBCSSh          ;* Get DBCS shift status from KCB.
  Mov      [SI].Key.DShift,DL            ;* Put in Key CharData rec.
ifdef DBCSKBD
  Mov      [DI].DBCSShift,DL             ;* Put copy in PSG             ;@IBM J-DBCS001(A)
endif ;DBCSKBD
  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             ;* @V2.0XXX07 Save Shift Flags, we need them
                                    ;* when creating packet for E0 scan code.
ifdef DBCSKBD
IFDEF  KLFX103                                                          ;@IBM K-JI001
                                                                        ;@IBM K-JI001
 ;;;;  103 keyborad Hangeul/Hanja keyboard support.                     ;@IBM K-JI001
 ;;;;  clear down_hangeul/alpha or down_hanja information.              ;@IBM K-JI001
 ;;;;  103 KBD send key-up(break key) information only from keyboard,   ;@IBM K-JI001
 ;;;;  when Hangeul/Hanja key is pressed.                               ;@IBM K-JI001
                                                                        ;@IBM K-JI001
   .If <AL eq 0F2H>                     ; Hangeul Key?                  ;@IBM K-JI001
    And  AL, 7FH                      ;                bit              ;@IBM K-JI001
   .Endif                                                               ;@IBM K-JI001
                                                                        ;@IBM K-JI001
    .If <AL eq 0F0H>                     ; Hangeul Key? (5561/5580)     ;@IBM K-JI001
      And  AL, 7FH                      ; then, clear break bit         ;@IBM K-JI001
    .Endif                                                              ;@IBM K-JI001
                                                                        ;@IBM K-JI001
   .If <AL eq 0F1H>                     ; Hanja   Key?                  ;@IBM K-JI001
     And  AL, 7FH                      ; then, clear break bit          ;@IBM K-JI001
   .Endif                                                               ;@IBM K-JI001
                                                                        ;@IBM K-JI001
                                                                        ;@IBM K-JI001
   .If <Al eq 72H>                       ;Hangeul                       ;@IBM K-JI001
     And ES:[BX].KCBRes1,not (down_hangeul+down_alpha+down_jamo+down_hanja_25+down_hanja_csr);clear down information   ;@IBM K-JI001
   .Endif                                                               ;@IBM K-JI001
    .If <Al eq 70H>                       ;Hangeul/5561-5580(PS/55)     ;@IBM K-JI001
     And ES:[BX].KCBRes1,not (down_hangeul+down_alpha+down_jamo+down_hanja_25+down_hanja_csr);clear down information   ;@IBM K-JI001
    .Endif                                                              ;@IBM K-JI001
   .If <Al eq 71H>                       ;Hanja                         ;@IBM K-JI001
     And ES:[BX].KCBRes1,not (down_hangeul+down_alpha+down_jamo+down_hanja_25+down_hanja_csr);clear down information   ;@IBM K-JI001
   .Endif                                                               ;@IBM K-JI001
                                                                        ;@IBM K-JI001
ENDIF                                                                   ;@IBM K-JI001

 Mov DL,ES:[BX].KCBRes1             ;* Get Jshift down info.            ;@IBM J-DBCS001(A)
 Mov [DI].DshiftDown,DL             ;* Set to current PSG area          ;@IBM J-DBCS001(A)
endif ;DBCSKBD

                                         ;* @V2.0XXX08 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
                                         ;* @V2.0XXX08 end

 .If <AL eq OtherKey> NEAR               ;* Enhanced keyboard secondary key prefix
    Or IntFlagArea.XKeyFlags, SecPrefix  ;* Indicate for next scan code.
    Jmp Spurious                  ;*  @V2.0XXX07 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                           ;* @V2.0XXX09 save SG number.
ifdef DBCSKBD
    ;@IBM Are these lines really necessary ?     Hirosawa 4/29            ;@IBM J-DBCS001(A)
    Mov AH, [DI].DshiftDown               ;* Get flags from specified PSG.;@IBM J-DBCS001(A)
    Mov [SI].XDshiftDown,AH               ;* Save in Flag Area.           ;@IBM J-DBCS001(A)
endif ;DBCSKBD
;;*    Mov      CX, DI                 ;* @V2.0XXX10 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
;;*                                          ;* @V2.0XXX10Begin
;;*       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].
;;*
;;*       ;*@IBM *******************BIDI_011293 - Start****DEFECT 60356*************
;;*       ;**
;;*       ;** 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
;;*       ;**
;;*       ;*@IBM ********************BIDI_011293 - End ***************************
;;*
;;*         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.

       ;* @V2.0XXX17 Removed the above code and added next line instead. @IBM

         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                          ;* @V2.0XXX09 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.

ifdef DBCSKBD
    Mov    BL,[DI].XDshiftDown                                        ;@IBM J-DBCS001(A)
endif ;DBCSKBD
    Pop    DI                          ;* Restore PSG pointer.
ifdef DBCSKBD
    Mov    [DI].DshiftDown,BL                                         ;@IBM J-DBCS001(A)
endif ;DBCSKBD
    Mov    BX,[SI].Key.Shift           ;* Get shift flags from CDR
    Mov    [DI].ShiftFlags,BX          ;* And put them in PSG data area
ifdef DBCSKBD
    Mov    BL,[SI].Key.DShift          ;* Get DShift flags from CDR    ;@IBM J-DBCS001(A)
    Mov    [DI].DBCSShift,BL           ;* And put them in PSG data area;@IBM J-DBCS001(A)
    Mov    BL,[SI].Key.Status          ;* Get DBCS status  from CDR    ;@IBM J-DBCS001(A)
    Mov    [DI].DBCSFlags,BL           ;* And put them in PSG data area;@IBM J-DBCS001(A)
endif ;DBCSKBD

 ;* Gutted code for retranslation ,  @V2.0XXX11

 .Endif                                  ;* Endif special scan code or not

  Pusha                              ;* Start of procrun for @V2.0XXX12
  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 @V2.0XXX12

   ;* 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 = Bad accent/char combo, beep only
MaxSysKeyType Equ ($-SysKeyChecks)/2


RebootKeyChk:                        ;* Last key of the Reboot sequence.
 .If <Security_Enable eq 1>
   .If <Reboot_Rejected eq 0>        ;* This reboot already rejected?  123036
.386p
     Mov    EAX, DHSEC_TRUSTEDPATH
.286p
     Mov    DL, DEVHLP_SECURITY
     Call   [DeviceHelp]
     .If  <AX ne 0>
       ;* If the devhlp rejects the reboot, set the Reboot_Rejected byte
       ;* so that we don't invoke the callout again for any repeating key
       ;* sequence (i.e. the user is holding down the Ctl-Alt-Del too
       ;* long). Reboot_Rejected gets reset in KbdXlate when we detect
       ;* the next KeyBreak.                                           123036
         Mov Reboot_Rejected, 1      ;* Remember it was rejected.      123036
         Jmp SysKeyCheckEnd
     .Endif
   .Else                             ;* Repeating key.                 123036
      Jmp SysKeyCheckEnd             ;* Reject this reboot too.        123036
   .Endif
 .Endif
 .if <Security_Enable eq 1>          ; cn 7/25/95
    xor ah,ah                        ; force zero to set cn 7/25/95
 .else                               ; cn 7/25/95
    Test LockupFlags,Lockup          ;* @V2.0XXX05 If Desktop's Lockup
 .endif                              ; cn 7/25/95
 .If <nz>                            ;* @V2.0XXX05 is on, do not reboot
     Jmp SysKeyCheckEnd              ;* @V2.0XXX05 the system.
 .Endif                              ;* @V2.0XXX05
                                     ;* @V2.0XXX13: 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.
                                     ;* @V2.0XXX13 END

DumpKeyChk:                          ;* Last key of Stand Alone dump sequence.
 ;* 180062 Moved security test below since process dump hotkey needs
 ;*        the same check for KeyBreak.
 ;* 180062.If <Security_Enable eq 1>
   ;* The following test is needed to avoid calling the DevHelp twice.
   ;* This code is first entered when the second NUMLOCK key in the sequence
   ;* is pressed (make). The second time through is when the key is released
   ;* After the break, we need to reset the DumpKeyOnce flag.          121218
     Test   [SI].DDFlags, KeyBreak   ;* Was key released?
     .If <z>
         Jmp     SysKeyCheckEnd      ;* No. Avoid DevHelp call.        121218
     .Endif
 .If <Security_Enable eq 1>
.386p
     Mov    EAX, DHSEC_TRUSTEDPATH
.286p
     Mov    DL, DEVHLP_SECURITY
     Call   [DeviceHelp]
     .If  <AX ne 0>
         And IntFlagArea.XKeyFlags, NOT DumpKeyOnce ;* Cancel dump sequence.121218
         Jmp SysKeyCheckEnd
     .Endif
 .Endif
    Test LockupFlags,Lockup          ;* @V2.0XXX05 If Desktop's Lockup
   .If <nz>  OR                      ;* @V2.0XXX05 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            ;* @V2.0XXX05 the system.
   .Endif                            ;* @V2.0XXX05
                                     ;*
    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
; With process dump enhancements, the hotkey sequence may take a process dump
;  and leave the system up and running.                                  180062
;;; 180062   Jmp    [SADump]                  ;* Go to Stand Alone Dump.
    Call     [SADump]                ;* Call dump routine                180062
    And IntFlagArea.XKeyFlags, NOT DumpKeyOnce ;* Cancel dump sequence.  180062
    ; fall through to SysKeyCheckEnd                                     180062
                                     ;*
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:                         ;* Bad accent/char combo, beep only
                                     ;* @V2.0XXX14 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
                                     ;* @V2.0XXX14 END
    Jmp Short SysKeyCheckEnd         ;* Go to bottom of case table.

Public SecPrefixCodeChk
SecPrefixCodeChk:                    ;* E0,E1 prefix from the keyboard
                                     ;* @V2.0XXX14   BEGIN
                                     ;* PTR SM03760  commented this out @IBM
;*   Or [SI].DDFlags,NotSQPacket     ;* Flag as not a SQ packet
                                     ;* @V2.0XXX14   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>  AND          ;* If mons registered try to pass
   .if <TrustedPath eq 0>                      ;;** Security - trusted path

;/* HCT D184790
ifdef DBCSKBD
      .If <bit [DI].PSGFlags nz SQMODE> AND ;* Check for Single Queue mode.      ;2901j-
      .If <bit [SI].DDFlags z NotSQPacket>  ;* If packet should go in SQ buffer  ;2901j-
         And IntFlags, NOT Up_LEDs          ;* Turn off UP_LEDs Full Screen flag ;2901j-
      .Endif                                                                     ;2901j-
endif ;DBCSKBD
                                               ;;** turns monitors off or on.
      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.
      Test [DI].PSGFlags, SQMODE         ;* Check for Single Queue mode.   ;@IBM J-1223(A)
     .If < nz >                          ;* If we're in SQ mode, AND       ;@IBM J-1223(A)
        Call [DeviceHelp]                ;* Go pass Key to monitor         ;@IBM J-1223(A)
     .Else                               ;*                                ;@IBM J-1223(A)
       .If <bit [DI].PSGFlags nz ActiveSG> AND ;* If this session is active, ;@IBM JS07091(A)
       .If <bit [DI].PSGFlags z Flushing>  ;* If MonFlush is not processing. ;@IBM JS07091(A)
          Call [DeviceHelp]                ;* Go pass Key to monitor
;@IBM J-1053(D) .Else                      ;* If not active,                 ;@IBM JS07091(A)
;@IBM J-1053(D)    STC                     ;*   set carry flag               ;@IBM JS07091(A)
       .Endif                              ;*                                ;@IBM JS07091(A)
     .Endif                              ;*                                ;@IBM J-1223(A)
     .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>        ;* @V2.0XXX01 ,If nonzero
          Call PutInSQB                    ;* Call SingleQ DD with Hot Key Info
       .Endif                              ;* Endif
        Pop   BX
        Pop   SI
        Call PutInSQB
     .Endif

                                         ;* @V2.0XXX15 No VDM call to ConsInpfilter.
     .If <CurSG lt sgidFirstVDM>         ;* Not a VDM SG (PTR B708198) @IBM

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

           .If <bit [DI].PSGFlags z ActiveSG>  ;* Is this session active ?    ;@IBM JS07091(A)
                 Or  MiscFlags,BeepSpeaker     ;* No.  Beep speaker.          ;@IBM JS07091(A)
                 Jmp IgnoreKey                 ;*                             ;@IBM JS07091(A)
           .Endif                              ;*                             ;@IBM JS07091(A)
            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
IgnoreKey:                               ;*                                   ;@IBM JS07091(A)

           ;* @V2.0XXX16 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     ;* PTR B722320   @IBM
          .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
                               ;* @V2.0XXX14 Not in Single Queue Mode.
     .Endif                    ;* @V2.0XXX15 Endif NOT VDM session.
   .Endif                      ;* End of "monitors installed or not" check.
                               ;* End of "no read yet" check.
                               ;* @IBM PTR AR08988
 .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> AND
    Test Byte Ptr IntFlagArea.XSpecFlags, UseTwoAcc
                                              ;* Check to see if we are passing
                                              ;* an Accent char. @V3.0RV01
   .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                             ;* @V2.0XXX01
  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
ifdef DBCSKBD
    Mov    [SI].Key.Scan, 0              ;* @IBM Clear Xlated Scan     ;@IBM JS03022(A)
    And    [SI].Key.Status, NOT 1        ;* Clear ShiftReport Flag     ;@IBM JS03022(A)
endif ;DBCSKBD
    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                             ;* @V2.0XXX18  Save shift flags
   Mov    ES:[BX].KCBShift,AX            ;* Put them in the KCB
ifdef DBCSKBD
   Mov    AL,[DI].DBCSFlags              ;* Get PSG DBCSFlags           ;@IBM J-DBCS001(A)
   Mov    ES:[BX].KCBDBCSFl,AL           ;* Put them in the KCB         ;@IBM J-DBCS001(A)
   Mov    AL,[DI].DBCSShift              ;* Get PSG DBCSShift           ;@IBM J-DBCS001(A)
   Mov    ES:[BX].KCBDBCSSh,AL           ;* Put them in the KCB         ;@IBM J-DBCS001(A)
   Mov    AL,[DI].DshiftDown             ;* Get PSG DBCS Down info.     ;@IBM J-DBCS001(A)
   Mov    ES:[BX].KCBRes1,AL             ;* Put them in the KCB         ;@IBM J-DBCS001(A)
endif ;DBCSKBD
                                         ;*
    ;*
    ;*  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>        ;* @V2.0XXX19 If the scan code
                                         ;* can be sent to the VKBD.
      Mov  BL,-1                         ;* Indicate an Activated SG check.
      Call SGActivation                  ;* @V2.0XXX18 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                            ;* @V2.0XXX18
    Jmp    Only_Exit                     ;* prepare to exit int handler for
 .Endif                                  ;* VDM sessions.
   Pop    AX                             ;* Restore shift flags
                                         ;* @V2.0XXX06 - 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.
                                         ;* @V2.0XXX06 - 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         ;* @V2.0XXX20 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
                            ;* end AK02182          @IBM

  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.

;ifndef DBCSKBD                           @kwb
;  Test   [SI].Key.Status,1            ;* If inputmode is
; .If <z> NEAR                            ;* ShiftReport
;else ;DBCSKBD
;  ;@IBM I don't know if the following adaptations are necessary. Hirosawa 4/29
  Test ES:[BX].KCBInpMode,SHIFTREPORT                                   ;@IBM J-DBCS001(A)
 .If <nz> AND                                                           ;@IBM J-DBCS001(A)
 .If <CX eq ShiftMask> OR                                               ;@IBM J-DBCS001(A)
 .If <CX eq ShiftMask+KeyBreak> OR                                      ;@IBM J-DBCS001(A)
 .If <CX eq ShiftMask+SecondaryKey> OR                                  ;@IBM J-DBCS001(A)
 .If <CX eq ShiftMask+KeyBreak+SecondaryKey>                            ;@IBM J-DBCS001(A)
  ;  Clc                          ;Keep the shift key                   ;@IBM J-DBCS001(A)
                                  ;Carry is cleared by Test instruction ;@IBM J-DBCS001(A)
 .Else NEAR                                                             ;@IBM J-DBCS001(A)
;endif ;DBCSKBD                           @kwb
                                         ;* @V2.0XXX21 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
                                         ;* @V2.0XXX21 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> ;* @V2.0XXX22 Event must not
                                              ;* occur in SQMODE.
                Mov   AH,event_CtrlScrLk      ;* No, set event to send.
                Mov   BX,[DI].PSGNum          ;* Put SG # in parm reg ;*(P6165) @IBM
                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.
ifdef DBCSKBD
        ; PAUSE --> press two keys at the same time --> hang up         ;@IBM J-DBCS001(A)
        ; NOWPaused bit is set during pause, and this bit is cleared    ;@IBM J-DBCS001(A)
        ; in the consinputfilter that is called in mondispentry when    ;@IBM J-DBCS001(A)
        ; monitor is installed. Therefor it takes time to clear         ;@IBM J-DBCS001(A)
        ; NOWPaused bit after WakeUpKey(DDFlags : 0A) is sent to        ;@IBM J-DBCS001(A)
        ; monitor. When next key is pressed before NOWPaused bit        ;@IBM J-DBCS001(A)
        ; is cleared, the second WakeUpKey is sent to monitor.          ;@IBM J-DBCS001(A)
        ; Then DevHlp_SendEvent is called TWO TIMES, then system        ;@IBM J-DBCS001(A)
        ; goes to mad.                                                  ;@IBM J-DBCS001(A)

;@IBM J-DBCS001(D)   .If <bit [DI].PSGFlags z SQMODE> ;* @V2.0XXX22 Event must not
;@IBM J-DBCS001(D)                                    ;* occur in SQMODE.
             .If <bit [DI].PSGFlags z SQMODE> AND                       ;@IBM J-DBCS001(A)
              Test [DI].PSGFlags,NowPaused     ;Is KBD actually paused. ;@IBM J-DBCS001(A)
             .If <nz>                                                   ;@IBM J-DBCS001(A)
else
             .If <bit [DI].PSGFlags z SQMODE> ;* @V2.0XXX22 Event must not
                                              ;* occur in SQMODE.
endif ;DBCSKBD
                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>     ;* @V2.0XXX22 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

                                         ;* @V2.OXXX23 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                ;* @V2.OXXX24  Begin, Save AX
                Xor    AX,AX             ;* Indicate to Access the KCB
                Call   PurgeKIB          ;* Now purge KIB.
                Pop    AX                ;* @V2.OXXX24 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> ;* @V2.0XXX22 Event must not
                                              ;* be sent in SQMODE.
                 Mov   AH,event_CtrlScrLk     ;* Set event to send.
                 Mov   BX,[DI].PSGNum         ;* Put SG # in parm reg  @IBM (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
              Test CH,0C0h              ;* Check if in Raw Mode or in 3xBox.
             .If <z>                    ;* Are we?
                                        ;* @V2.OXXX23 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> ;* @V2.0XXX22 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 @V2.0XXX23
                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>;* @V2.0XXX22  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                          ;*  @IBM PTM 7606
                                           ;* 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
