/*static char *SCCSID = "@(#)util.c     6.11 92/06/08";*/
/****************************************************************************/
/*                                                                          */
/*                       IBM/Microsoft Confidential                         */
/*                                                                          */
/*                 Copyright (c) IBM Corporation  1987, 1991                */
/*                 Copyright (c) Microsoft Corp.  1987, 1991                */
/*                           All Rights Reserved                            */
/*                                                                          */
/****************************************************************************/

/*********************** START OF SPECIFICATIONS *****************************/
/*                                                                           */
/* Source File Name: UTIL.C                                                  */
/*                                                                           */
/* Descriptive Name: Mouse/Keyboard Utility Routines                         */
/*                                                                           */
/* Status: OS/2 Release 2.00                                                 */
/*                                                                           */
/* Function: This module does the grunt work for Keyboard and Mouse API's    */
/*           and routes the call to an appropriate subsystem. See the        */
/*           specs attached to each routine for more detail and Public API's */
/*           are referenced in OS/2 1.3 Programmers Toolkit Control Program  */
/*           Reference manual, S91f-9260-00.  They are NOT referenced in any */
/*           OS/2 2.0 documentation.                                         */
/*                                                                           */
/* Internal Entry Points: GlobalInit()                                       */
/*                        SessionInit()                                      */
/*                        KbdGetSemaphore()                                  */
/*                        MouGetSemaphore()                                  */
/*                        KbdClearSemaphore()                                */
/*                        MouClearSemaphore()                                */
/*                        KbdCheckProcType()                                 */
/*                        MouCheckProcType()                                 */
/*                        CheckRegisterParms()                               */
/*                        MMIOtrace()                                        */
/*                                                                           */
/* External Entry Points: RoutProcessInit()                                  */
/*                        RoutExitList()                                     */
/*                                                                           */
/* Data: Refer to Instance and common data declarations in ROUTER.C,         */
/*       CHARROUT.H and SUBSYS.ASM                                           */
/*                                                                           */
/* Notes:                                                                    */
/*   Dependencies: 0 must be an invalid selector.                            */
/*                 0 must be an invalid current process PID.                 */
/*                 most instance data variables are maintained by VIOCALLS   */
/*                                                                           */
/*   Restrictions: This source file must be compiled with the instance data, */
/*                 _DATA, as the default data segment which is done in       */
/*                 SUBSYS.ASM.  The MAKEFILE must have the flag that         */
/*                 sets the Common or Global data segment to CDATA active.   */
/*                                                                           */
/*********************** END OF SPECIFICATIONS *******************************/

/*****************************************************************************/
/*******   C H A N G E       H I S T O R Y   *********************************/
/*****************************************************************************/
/* @GDW  - 08/29/91 - PTR B726157 - Combine KIO and MIO into MKIO router     */
/* @GDW  - 09/11/91 - PTR B726826 - MMIOPH Table for KBD in wrong order.     */
/* @GDW  - 10/19/91 - PTR B728410 - Both Base Subsystem address' needs to    */
/*                                  have DosLoadModule and DosGetProcAddr    */
/*                                  API's called for each process.           */
/* @GDW  - 11/13/91 - PTR B728906 - KbdOpen not allowing multiple opens.     */
/* @GDW  - 11/21/91 - PTR B728981 - KbdRegister failing when process that    */
/*                                  called it dies. Remove KbdDeRegister call*/
/*                                  in RoutExitList() per process cleanup.   */
/* @GDW  - 01/21/92 - PTR B731619 - KbdSynch API reenabled. Was NO-OP.       */
/*                                  MouSynch API reenabled. Was NO-OP.       */
/* @GDW  - 02/06/92 - PTR B732368 - Move call to DosLoadModule for AKS and   */
/*                                  AMS to RoutProcessInit in UTIL.C from    */
/*                                  Router.  This fixes problem where the    */
/*                                  Router was getting the address for all   */
/*                                  Keyboard API's except KbdGetFocus and    */
/*                                  KbdFreeFocus routed to AKS.              */
/* @GDW  - 02/28/92 - PTR B733895 - RoutExitList is TRAP D when a application*/
/*                                  exits due to AKS_Addr being invalid.     */
/* @GDW  - 06/08/92 - PTR B736408 - MouOpen fails the second time from the   */
/*                                  same session.                            */
/* @GDW  - 11/21/92 - DEF 060116  - KbdCharIn not returning when wait flag   */
/*                                  is set to NOWAIT.                        */
/* @Paul - 12/28/92 - DEF XXXXXXX - Forwarding mechanism moucalls kbdcalls   */
/*                                  viocalls has circular reference. This    */
/*                                  kills performance and is not how the     */
/*                                  forwarding was designed to work.         */
/* @GDW  - 01/21/93 - DEF 059591  - <CONTL BREAK> causing deadlock.          */
/* @GDW  - 02/02/93 - DEF 061231  - KbdCharIn() MMIO wrong output.           */
/* @GDW  - 02/09/93 - DEF 061793  - <CTRL C> in OS/2 Window causes deadlock  */
/*                                  added wait parm to KbdGetSemaphore and   */
/*                                  moved check for <CTRL C> into function   */
/*                                  KbdGetSemaphore.                         */
/* @GDW  - 02/22/93 - DEF 062082  - An application generated VIOPopUp that   */
/*                                  runs in SG3 can grab a semaphore and not */
/*                                  clear it because RoutExitList was not    */
/*                                  being registered correctly.              */
/* @GDW  - 03/02/93 - DEF 063131  - An application using KbdRegister cannot  */
/*                                  use the registered API's from a different*/
/*                                  process.                                 */
/* @GDW  - 03/23/93 - DEF 063946  - "TYPE CONFIG.SYS | MORE" causes keyboard */
/*                                  focus to be lost.                        */
/* @GDW  - 03/31/93 - DEF 065384  - Regression caused by use of              */
/*                                  SGCB->KBD_FocusHandle when it wasn't     */
/*                                  being initialized correctly.             */
/* @GDW  - 04/02/93 - DEF 065582  - Regression caused by use of              */
/*                                  SGCB->KBD_FocusHandle when it wasn't     */
/*                                  being initialized correctly still not    */
/*                                  fixed.                                   */
/* @GDW  - 08/30/93 - DEF 072823  - Cleanup routine ROUTEXITLIST called      */
/*                                  KbdDeRegister causing CUE.EXE to work    */
/*                                  incorrectly.

/*****************************************************************************/
/*******   Defines for inclusion of required typedefs, etc... ****************/
/*****************************************************************************/

#define INCL_ERRORS
#define INCL_DOSSEMAPHORES
#define INCL_DOSPROCESS
#define INCL_DOSINFOSEG
#define INCL_DOSMODULEMGR
#define INCL_KBD
#define INCL_MOU

#include <os2.h>
#include <dos.h>
#include <infoseg.h>
#include <string.h>
#include "smrsgcb.h"
#include "router.h"

/* @Paul ... Translate back to the original names to allow internal  */
/* resolution instead of a forwarder circular reference.             */
/* Note for post Borg this will be redesigned to resolve the general */
/* problem.                                                          */
#undef MouDeRegister
#undef KbdDeRegister
#undef KbdSetCp
#undef KbdFreeFocus
APIRET APIENTRY MouDeRegister(void);
APIRET APIENTRY KbdDeRegister(void);
APIRET APIENTRY KbdSetCp(USHORT usReserved, USHORT pidCP, HKBD hdbd);
APIRET APIENTRY KbdFreeFocus(HKBD hkbd);
/* @Paul ... End of added section. */

extern USHORT APIENTRY BKSMAIN(void);                                /* MDLL */
extern USHORT APIENTRY BMSMAIN(void);                                /* MDLL */

/*****************************************************************************/
/* External Common data declarations - Global Variables                      */
/*****************************************************************************/

extern USHORT (APIENTRY *BMS_Addr)(VOID);  /* BMS entry address              */
extern USHORT (APIENTRY *BKS_Addr)(VOID);  /* BKS entry address              */
extern USHORT APIENTRY DOSSMFREEMEM(PALTCB); /* Frees ALTCB for session      */
extern CHAR      moudd_name[];          /* Mouse Device Driver name          */
extern CHAR      kbddd_name[];          /* Keyboard Device Driver name       */
/* MDLL extern CHAR      bms_entrypoint[];      /* Base Mouse Subsystem entry name   */
extern CHAR      bms_modname[];         /* Base Mouse Subsystem DLL name     */
/* MDLL extern CHAR      bks_entrypoint[];      /* Base Keyboard Subsystem entry name*/
extern CHAR      bks_modname[];         /* Base Keyboard Subsystem DLL name  */
extern USHORT    moudd_exists;          /* Mouse Device Driver exists flag   */
extern USHORT    sesmgr_pid;            /* Session Manager process ID        */
extern USHORT    global_initflag;       /* Global Initialization Flag        */
extern PGDTINFOS global_info;           /* Global information address        */
extern USHORT    InitFlag;              /* BKSMAIN and BMSMAIN init flag     */
                                        /* Bit 3 set means BMSMAIN is loaded */
                                        /* Bit 4 set means BKSMAIN is loaded */
#ifdef MMIOPH
  extern  SEL    mmio_sel;              /* Memory Mapped I/O selector        */
  extern  USHORT mou_mmio_codes[];      /* PRE MMIO trace hooks array        */
  extern  USHORT kbd_mmio_codes[];      /* PRE MMIO trace hooks array        */
  extern  USHORT FAR *mmio_buffer;      /* Addr. of memory mapped I/O buffer */
#endif

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                        ******************************    */
/*  SUBROUTINE NAME:  KbdGetSemaphore     ***  UNPUBLISHED  ROUTINE  ***    */
/*                                        ******************************    */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Get semaphore to serialize API's through router      */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemRequest() to own semaphore or wait until    */
/*             semaphore is clear.                                          */
/*                                                                          */
/*  ENTRY POINT:  KbdGetSemaphore                                           */
/*      LINKAGE:  CALL NEAR (from Router, KbdCharin, KbdStringIn,           */
/*                           KbdGetFocus and KbdFreeFocus)                  */
/*                                                                          */
/*  INPUT:  IOWait    1 = Don't wait for a keystroke                        */
/*                    0 = Wait until a keystroke is availible.              */
/*                                                                          */
/*  EXIT-NORMAL: none                                                       */
/*                                                                          */
/*  EXIT-ERROR: Error Code from DosFSRamSemRequest API                      */
/*                                                                          */
/*  EFFECTS: Sets the Semaphore SGData->KBD_SynchSem ownership.             */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: none                                                    */
/*     COMMON data: none                                                    */
/*                                                                          */
/*        ROUTINES: none                                                    */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*    LOCAL info: none                                                      */
/*   GLOBAL info: none                                                      */
/*      ROUTINES: DosFSRamSemRequest()                                      */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

USHORT KbdGetSemaphore(ULONG WaitFlag) {

  USHORT RC = NO_ERROR;

/* 063946 */
/****************************************************************************/
/*  Maintain the semaphore count, (cUsage field), so that it never gets     */
/*  above ONE for the thread that owns the semaphore.  The semaphore that   */
/*  is owned by a thread that has called the KbdCharIn or KbdStringIn       */
/*  API's with the WaitFlag set to wait for a keystroke, is cleared when    */
/*  the API returns from the device driver when a keystroke becomes         */
/*  availible.  If a user hits <CNTL-C> or <CNTL-BREAK>, while the thread   */
/*  is blocked at the device driver, the semaphore of the calling thread    */
/*  is not cleared and the next time the thread calls KbdCharIn or          */
/*  KbdStringIn, a semaphore deadlock will occur.  CMD.EXE calls KbdCharIn  */
/*  API with the wait option and while the thread is blocked at the device  */
/*  driver, a user could <CNTL-C> or <CNTL-BREAK> causing the thread to     */
/*  return to CMD.EXE without clearing the in use semaphore.  This is now   */
/*  fixed with the following semaphore count logic.                         */
/****************************************************************************/

  if (SGData->KBD_SynchSem.tid != LocalInfo->LIS_CurThrdID)    /* 063946 */
    do
      RC = DosFSRamSemRequest((PDOSFSRSEM)&SGData->KBD_SynchSem, WaitFlag);
    while (RC == ERROR_INTERRUPT);

  if (RC == ERROR_SEM_TIMEOUT)
    RC = ERROR_KBD_KEYBOARD_BUSY;
  else
    if (RC == ERROR_SEM_OWNER_DIED)
      RC = NO_ERROR;

  return(RC);

}

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                        ******************************    */
/*  SUBROUTINE NAME:  MouGetSemaphore     ***  UNPUBLISHED  ROUTINE  ***    */
/*                                        ******************************    */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Get semaphore to serialize API's.                    */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemRequest() to own semaphore or wait until    */
/*             semaphore is clear.                                          */
/*                                                                          */
/*  ENTRY POINT:  MouGetSemaphore                                           */
/*      LINKAGE:  CALL NEAR (from Router(), MouSynch, MouRegister and       */
/*                           MouDeRegister API's)                           */
/*                                                                          */
/*  INPUT:  RoutCode - Function Code of API being processed                 */
/*                                                                          */
/*  EXIT-NORMAL: none                                                       */
/*                                                                          */
/*  EXIT-ERROR: Error Code from DosFSRamSemRequest API                      */
/*                                                                          */
/*  EFFECTS: Sets the Semaphore SGData->MOU_SynchSem ownership.             */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: none                                                    */
/*     COMMON data: none                                                    */
/*                                                                          */
/*        ROUTINES: none                                                    */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*    LOCAL info: none                                                      */
/*   GLOBAL info: none                                                      */
/*      ROUTINES: DosFSRamSemRequest()                                      */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

USHORT MouGetSemaphore(USHORT RoutCode) {

  USHORT RC = NO_ERROR;

  if (RoutCode == FC_MOUREADEVENTQUE) {
    do
      RC = DosFSRamSemRequest((PDOSFSRSEM)&SGData->MOU_SynchSem,
                                                   SEM_IMMEDIATE_RETURN);
    while (RC == ERROR_INTERRUPT);

    if (RC == ERROR_SEM_OWNER_DIED)
      RC = NO_ERROR;
  }

  return(RC);

}

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                        ******************************    */
/*  SUBROUTINE NAME:  KbdClearSemaphore   ***  UNPUBLISHED  ROUTINE  ***    */
/*                                        ******************************    */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Clear semaphore to let API's waiting get control     */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemClear() to clear the owned semaphore.       */
/*                                                                          */
/*  ENTRY POINT:  KbdClearSemaphore                                         */
/*      LINKAGE:  CALL NEAR (from Router)                                   */
/*                                                                          */
/*  INPUT:  none                                                            */
/*                                                                          */
/*  EXIT-NORMAL: none                                                       */
/*                                                                          */
/*  EXIT-ERROR: Error Code from DosFSRamSemClear API                        */
/*                                                                          */
/*  EFFECTS: Clears the Semaphore Screen Group Data.                        */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: none                                                    */
/*     COMMON data: none                                                    */
/*                                                                          */
/*        ROUTINES: none                                                    */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*    LOCAL info: none                                                      */
/*   GLOBAL info: none                                                      */
/*      ROUTINES: DosFSRamSemClear() - clear the semaphore                  */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

VOID KbdClearSemaphore(VOID) {

  USHORT RC;

  do
    RC = DosFSRamSemClear((PDOSFSRSEM)&SGData->KBD_SynchSem);
  while (RC == ERROR_INTERRUPT);

  return;

}

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                        ******************************    */
/*  SUBROUTINE NAME:  MouClearSemaphore   ***  UNPUBLISHED  ROUTINE  ***    */
/*                                        ******************************    */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Clear semaphore to let API's waiting into router     */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemClear() to clear the owned semaphore.       */
/*                                                                          */
/*  ENTRY POINT:  MouClearSemaphore                                         */
/*      LINKAGE:  CALL NEAR (from Router)                                   */
/*                                                                          */
/*  INPUT:  RoutCode   - Function Code of API being processed               */
/*                                                                          */
/*  EXIT-NORMAL: none                                                       */
/*                                                                          */
/*  EXIT-ERROR: none                                                        */
/*                                                                          */
/*  EFFECTS: Clears the Semaphore in Screen Group Data.                     */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: none                                                    */
/*     COMMON data: none                                                    */
/*                                                                          */
/*        ROUTINES: none                                                    */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*    LOCAL info: none                                                      */
/*   GLOBAL info: none                                                      */
/*      ROUTINES: DosFSRamSemClear() - clear the semaphore                  */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

VOID MouClearSemaphore(USHORT RoutCode) {

  USHORT RC = NO_ERROR;

  if (RoutCode == FC_MOUREADEVENTQUE)
    do
      RC = DosFSRamSemClear((PDOSFSRSEM)&SGData->MOU_SynchSem);
    while (RC == ERROR_INTERRUPT);

  return;

}

/*********************** START OF SPECIFICATIONS *****************************/
/*                                                                           */
/*                                     ******************************        */
/* SUBROUTINE NAMES:  RoutExitList     ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/* DESCRIPTIVE NAMES: Mouse/Keyboard router exit list procedure              */
/*                                                                           */
/* FUNCTIONS:  Clear all process related semaphores because this process     */
/*             is dying.                                                     */
/*                                                                           */
/* NOTES:  This routine is called from DosExitList which has a list of       */
/*         registered routines that will be called when a process is dying.  */
/*                                                                           */
/* ENTRY POINTS:  RoutExitList                                               */
/*     LINKAGES:  CALL FAR from DosExitList();                               */
/*                                                                           */
/* INPUT: none                                                               */
/*                                                                           */
/* EXIT-NORMAL:  always                                                      */
/*                                                                           */
/* EXIT-ERROR:   none                                                        */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*   INSTANCE data: KBDProcessSem - Just as the name suggests.               */
/*                  MOUProcessSem - Just as the name suggests.               */
/*     COMMON data: none                                                     */
/*        ROUTINES: none                                                     */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*    LOCAL info: none                                                       */
/*   GLOBAL info: none                                                       */
/*      ROUTINES: KbdFreeFocus() - Frees the bond to the logical keyboard    */
/*                KbdDeRegister() - Unloads the registered sub system        */
/*                MouDeRegister() - Unloads the registered sub system        */
/*                DosFSRamSemClear() - Clears the owned fastsafe semaphore   */
/*                                                                           */
/* SIDE EFFECTS: Control passes to the next exit list procedure. This        */
/*               process no longer exists as far as the router is concerned, */
/*               at least until it starts up again.  There is no return like */
/*               other routines because the control is passed via the call   */
/*               to DosExitList() which will call the next registered        */
/*               routine on its list.                                        */
/*                                                                           */
/*               The call to DosFSRamSemRequest() while in the DosExitList() */
/*               routine has a different behavior.  It checks the PID field  */
/*               of the semaphore's structure and if it is the same as the   */
/*               current PID, the TID field is changed to the current TID to */
/*               get ownership of the semaphore for DosFSRamSemClear() to    */
/*               work correctly.                                             */
/*                                                                           */
/*********************** END OF SPECIFICATIONS *******************************/

VOID APIENTRY RoutExitList(VOID) {

  USHORT RC;

  /*****************************************************/
  /* Force a TRAP D if the SGData variable is not set. */
  /*****************************************************/
  if (SGData) {
    if (SGData->KBD_FocusHandle != -1)
      if (SGData->KBD_FocusPID == CurrentPID)
        KbdFreeFocus(SGData->KBD_FocusHandle);

    /**************************************************************/
    /* Only allow PID that started the current Screen Group to    */
    /* issue the DeRegister calls because we need to clean up for */
    /* applications that issue Register calls without calling a   */
    /* DeRegister.                                                */
    /**************************************************************/
    if (SGData->SGCB_PID == CurrentPID) {               /* 072823 */
      if (SGData->KBD_AKSCB != 0L)
        KbdDeRegister();

      if (SGData->MOU_AMSCB != 0L)
        MouDeRegister();
    }

    if (SGData->KBD_SynchSem.pid == CurrentPID) {             /* B731619 */
      do
        RC = DosFSRamSemRequest((PDOSFSRSEM)&SGData->KBD_SynchSem,
                                             SEM_IMMEDIATE_RETURN);
      while (RC == ERROR_INTERRUPT);

      if (RC == NO_ERROR || RC == ERROR_SEM_OWNER_DIED) {
        do
          RC = DosFSRamSemClear((PDOSFSRSEM)&SGData->KBD_SynchSem);
        while (RC == ERROR_INTERRUPT);
      }
    }

    /********************************************************/
    /* Does current PID own the Router Mouse API semaphore? */
    /********************************************************/
    if (SGData->MOU_SynchSem.pid == CurrentPID) {           /* B731619 */
      do
        RC = DosFSRamSemRequest((PDOSFSRSEM)&SGData->MOU_SynchSem,
                                             SEM_IMMEDIATE_RETURN);
      while (RC == ERROR_INTERRUPT);

      if (RC == NO_ERROR || RC == ERROR_SEM_OWNER_DIED) {
        do
          RC = DosFSRamSemClear((PDOSFSRSEM)&SGData->MOU_SynchSem);
        while (RC == ERROR_INTERRUPT);
      }
    }

  } /* endif */

  /**************************************************/
  /* Transfer control to next exit list procedure.  */
  /**************************************************/
  DosExitList(EXLST_EXIT, (PFNEXITLIST)RoutExitList);

} /* END RoutExitList */

/******************* START OF SPECIFICATIONS *********************************/
/*                                                                           */
/*                                     ******************************        */
/* SUBROUTINE NAME:  GlobalInit        ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/* DESCRIPTIVE NAME:  Global initialization routine                          */
/*                                                                           */
/* FUNCTION:  One time only processing.  MMIO initializations are the        */
/*            only ones that are being done now.                             */
/*                                                                           */
/* ENTRY POINT:  GlobalInit                                                  */
/*     LINKAGE:  CALL NEAR (from SessionInit() routine)                      */
/*                                                                           */
/* INPUT:  None.                                                             */
/*                                                                           */
/* EXIT-NORMAL:  NO_ERROR                                                    */
/*                                                                           */
/* EXIT-ERROR: None                                                          */
/*                                                                           */
/* EFFECTS:                                                                  */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*   INSTANCE data: none                                                     */
/*     COMMON data: global_initflag = TRUE after GlobalInit() success.       */
/*                                                                           */
/*        ROUTINES: none                                                     */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*    LOCAL info: none                                                       */
/*   GLOBAL info: none                                                       */
/*                                                                           */
/*      ROUTINES: None                                                       */
/*                                                                           */
/******************* END  OF  SPECIFICATIONS *********************************/
USHORT GlobalInit(VOID) {

  #ifdef MMIOPH
    mmio_sel = global_info->SIS_MMIOBase;
    mmio_buffer = MAKEP(mmio_sel,4);
  #endif

  global_initflag = TRUE;

  return(NO_ERROR);

} /* END GlobalInit */

/*********************** START OF SPECIFICATIONS *****************************/
/*                                                                           */
/*                                     ******************************        */
/* SUBROUTINE NAME: SessionInit        ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/* DESCRIPTIVE NAME: Screen Group initializaton routine.                     */
/*                                                                           */
/* FUNCTION: Call GlobalInit() and KbdSetCP()                                */
/*                                                                           */
/* ENTRY POINT: SessionInit                                                  */
/*     LINKAGE: CALL NEAR  from RoutProcessInit()                            */
/*                                                                           */
/* INPUT: None                                                               */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*            SGData->ROUT_InitFlag = Screen Group data init flag            */
/*                                                                           */
/* EXIT-NORMAL: AX = NO_ERROR                                                */
/*                                                                           */
/* EXIT-ERROR: Error from GlobalInit()                                       */
/*             Error from KbdSetCp()                                         */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*                                                                           */
/*    LOCAL info: None                                                       */
/*   SESSION data: ROUT_InitFlag - Session Initialization Flag               */
/*                 KBD_SynchSem.cb    - Semaphore Structure Size field       */
/*                 MOU_SynchSem.cb    - Semaphore Structure Size field       */
/*                 KBD_FocusHandle    - Handle of thread that owns focus     */
/*                                                                           */
/*   GLOBAL info: ProcCodePage = is LABEL aligned with the variable loaded   */
/*                               by call to DosGetCP() in VIOINIT.ASM and is */
/*                               in instance data, _DATA segment.            */
/*        ROUTINES: KbdSetCp() - ProcCodePage is loaded in VIOINIT routine.  */
/*                                                                           */
/*********************** END OF SPECIFICATIONS *******************************/

USHORT SessionInit(VOID) {

  USHORT  RC = NO_ERROR;

  SGData->ROUT_InitFlag = TRUE;
  SGData->KBD_SynchSem.cb = sizeof(SGData->KBD_SynchSem);     /* B731619 */
  SGData->MOU_SynchSem.cb = sizeof(SGData->MOU_SynchSem);     /* B731619 */
  SGData->KBD_FocusHandle = -1;

  if (!global_initflag)
    RC = GlobalInit();

  if (RC == NO_ERROR)
    /*********************************************************************/
    /* The return code is NOT checked here because this call is just to  */
    /* force the loading of country support in BKSCALLS.DLL.  If there   */
    /* is no country support loaded in the config.sys, an error would be */
    /* returned but the function would have been completed correctly in  */
    /* BKSCALLS, so we ignore the return code.                           */
    /*********************************************************************/
    KbdSetCp(RESERVED, ProcCodePage, HANDLE);

  if (RC != NO_ERROR)
    SGData->ROUT_InitFlag = FALSE;

  return(RC);

} /* END SessionInit */

/******************* START OF SPECIFICATIONS *********************************/
/*                                                                           */
/*                                     ******************************        */
/*  SUBROUTINE NAME:  RoutProcessInit  ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/*  DESCRIPTIVE NAME:  Per-process (DYN-LINK) initialization routine         */
/*                     for KBDCALLS and MOUCALLS.                            */
/*                                                                           */
/*  FUNCTION: Add the exitlist routine and initialize session control block. */
/*            Load the Base Keyboard Subsystem, BKSCALLS.DLL and the         */
/*            Base Mouse Subsystem, BMSCALLS.DLL.  This routine is called    */
/*            from OS2CHAR.DLL                                               */
/*                                                                           */
/*  ENTRY POINT:  RoutProcessInit                                            */
/*      LINKAGE:  CALL FAR (from "process starter")                          */
/*  INPUT:  None.                                                            */
/*                                                                           */
/*  EXIT-NORMAL:  RC = NO_ERROR                                              */
/*                                                                           */
/*  EXIT-ERROR:   RC = ERROR returned from DosExitList or SessionInit.       */
/*                RC = ERROR returned from DOSLOADMODULE(),                  */
/*                RC = ERROR returned from DOSGETPROCADDR()                  */
/*                                                                           */
/*  EFFECTS: BKSCALLS.DLL is loaded and its address obtained.                */
/*           BMSCALLS.DLL is loaded and its address obtained.                */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*  INSTANCE data: ProcessInitFlag - indicates ProcessInit complete          */
/*    COMMON data: mmio_buffer     - Memory-Mapped-IO buffer address         */
/*                 BMS_Addr     - address of BMSCALLS.DLL's entry procedure. */
/*                 BKS_Addr     - address of BKSCALLS.DLL's entry procedure. */
/*       ROUTINES: RoutExitList()  - process-termination cleanup routine     */
/*                 SessionInit()   - Initialize current Session if needed    */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*  INSTANCE data: CurrentTYPE   - assigned in VioProcessInit                */
/*                 LocalInfo     - assigned in VioProcessInit                */
/*                 ProcessInitFlag - Obvious                                 */
/*   SESSION data: ROUT_InitFlag - Session Initialization Flag               */
/*    GLOBAL data: global_info   - Global Information Segment Structure      */
/*       ROUTINES: DosExitList() - manage exitlist routine                   */
/*                 DosGetInfoSeg() - Get global and local information segs.  */
/*                 DosLoadModule() - Load the associated module name.        */
/*                 DosGetProcAddr() - Get the address of the associated DLL. */
/*                 DosFreeModule() - Free module name on ERROR.              */
/*                                                                           */
/******************* END  OF  SPECIFICATIONS *********************************/

USHORT pascal far _saveregs _loadds RoutProcessInit() {

  SEL    localsel;              /* Temporary selector  */
  SEL    globalsel;             /* Temporary selector  */
  USHORT handle;                /* Temporary handle    */
  USHORT RC = NO_ERROR;
                             /* 065384 */
  DosEnterCritSec();         /* Stop all other threads until init complete */

  DosGetInfoSeg(&globalsel, &localsel);
  global_info = MAKEP(globalsel,INFOSEG_OFFSET);
  LocalInfo = MAKEP(localsel,0);

  /************************************************************************/
  /* Add the RoutExitList routine for resource clearing PRIOR to an app   */
  /* getting called.  This is done via the EARLYEXITFCODE equate which is */
  /* defined in ROUTER.H.  The second call adds a RoutExitList routine    */
  /* for resource clearing AFTER applications get their exitlist routines */
  /* processed.  This stops an app from deadlocking on a semaphore when   */
  /* calling a Kbd or Mou API from the applications exitlist routine.     */
  /************************************************************************/
  RC = DosExitList(EARLYEXITFCODE, (PFNEXITLIST)RoutExitList); /* 062082  */
  if (RC == NO_ERROR) {                                        /* B728410 */
    RC = DosExitList(LATEEXITFCODE, (PFNEXITLIST)RoutExitList);/* 062082  */
    if (RC == NO_ERROR) {
      if (!(InitFlag & 0x010)) { /* BKS is forwarded to DOSCALL1? */ /* MDLL */

        /************************************************************************/
        /* Reload Base Keyboard Subsystem, (BKS), entry point address for this  */
        /* process.  The address becomes invalid and needs to be reattached for */
        /* each running process.                                                */
        /************************************************************************/
        RC = DosLoadModule(NAMEBUFFER, BUFFERLENGTH, bks_modname, &handle);
        if (RC == NO_ERROR) {
          RC = DosGetProcAddr(handle, (PSZ) 1, (PFN FAR *)&BKS_Addr);  /* MDLL */
          if (RC != NO_ERROR)
            DosFreeModule(handle);
          else {                                                     /* MDLL */
            if ((ULONG *)BKS_Addr == &BKSMAIN) {                     /* MDLL */
              InitFlag |= 0x10;                                      /* MDLL */
              DosFreeModule(handle);                                 /* MDLL */
            }                                                        /* MDLL */
          }                                                          /* MDLL */
        }                                                         /* B728410 */
      }                                                              /* MDLL */
      if (RC == NO_ERROR) {                                     /* B728410 */
        if (!(InitFlag & 0x08)) {/* BMS is forwarded to DOSCALL1? */ /* MDLL */
          /**************************************/
          /* Reload Base Mouse Subsystem  (BMS) */
          /**************************************/
          RC = DosLoadModule(NAMEBUFFER, BUFFERLENGTH, bms_modname, &handle);

          if (RC == NO_ERROR) {
            RC = DosGetProcAddr(handle, (PSZ) 1, (PFN FAR *)&BMS_Addr);   /* MDLL */
            if (RC != NO_ERROR)
              DosFreeModule(handle);
            else {                                                   /* MDLL */
              if ((ULONG *)BMS_Addr == &BMSMAIN) {                   /* MDLL */
                InitFlag |= 0x08;                                    /* MDLL */
                DosFreeModule(handle);                               /* MDLL */
              }                                                      /* MDLL */
            }                                                        /* MDLL */
          }
        }                                                            /* MDLL */
      }                                                         /* B728410 */

      if (RC == NO_ERROR) {
        if (SGData->ROUT_InitFlag == FALSE)
          RC = SessionInit();
      }
    }
  }

  if (RC == ERROR_ALREADY_EXISTS)
    RC = NO_ERROR;

  if (RC == NO_ERROR)
    ProcessInitFlag = TRUE;

  DosExitCritSec();             /*  065384 Re-enable all other threads */

  return(RC);

} /* END RoutProcessInit() */

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                     ******************************       */
/*  SUBROUTINE NAME:  KbdCheckProcType  ***  UNPUBLISHED  ROUTINE  ***       */
/*                                     ******************************       */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Set semaphore for associated API.                    */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemRequest() to set API semaphore.             */
/*                                                                          */
/*  ENTRY POINT:  KbdCheckProcType                                           */
/*      LINKAGE:  CALL NEAR (Call near from Router())                       */
/*                                                                          */
/*  INPUT:  RoutCode   - Function Code of API being processed               */
/*                                                                          */
/*  EXIT-NORMAL:  RC = NO_ERROR                                             */
/*                                                                          */
/*  EXIT-ERROR: error code from DosFSRamSemRequest()                        */
/*              ERROR_KBD_REGISTER - caller is VIOPOPUP or VIOWindow        */
/*                                                                          */
/*  EFFECTS:  The appropriate semaphore is set according to the RoutCode    */
/*            and the screen group type is checked to validate whether      */
/*            the caller can make the associated API call.  ProcessInit()   */
/*            is also called if the flag has not yet been set.              */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: CurrentTYPE - the type of the callers process           */
/*                  CurrentSGID - the current Screen Group ID               */
/*                  KBDProcessSem - FSRamSemaphore structure for KBD API's  */
/*                                                                          */
/*     COMMON data: ProcessInitFlag - checked for process init complete.    */
/*                                                                          */
/*        ROUTINES: ProcessInit() - Should only need to be called when a    */
/*                                  process is dying and a API is called    */
/*                                  from somewhere in the DosExitList       */
/*                                  group of routines after our exitlist    */
/*                                  is complete.                            */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*      ROUTINES: DosFSRamSemRequest() - request FSRamSemaphore.            */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

USHORT KbdCheckProcType(VOID) {

  USHORT RC = NO_ERROR;

  if (!ProcessInitFlag)
    RC = RoutProcessInit();

  if (RC == NO_ERROR) {
    if (!SGData->ROUT_InitFlag)                               /* 065582 */
      RC = SessionInit();

    if (RC == NO_ERROR) {
      if (CurrentTYPE == LIS_PT_DETACHED)
        RC = ERROR_KBD_DETACHED;
      else {
        if (CurrentTYPE != LIS_PT_FULLSCRN && CurrentTYPE != LIS_PT_VIOWIN)
          RC = ERROR_KBD_EXTENDED_SG;
        else {
          if (SGData->KBD_FocusHandle != -1 &&
              SGData->KBD_FocusPID != CurrentPID) {           /* 063946 */
            RC = ERROR_KBD_KEYBOARD_BUSY;
          }
        }
      }
    }
  }

  return(RC);

}

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                     ******************************       */
/*  SUBROUTINE NAME:  MouCheckProcType  ***  UNPUBLISHED  ROUTINE  ***      */
/*                                     ******************************       */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Set semaphore for associated API.                    */
/*                                                                          */
/*  FUNCTION:  Calls DosFSRamSemRequest() to set API semaphore.             */
/*                                                                          */
/*  ENTRY POINT:  MouCheckProcType                                          */
/*      LINKAGE:  CALL NEAR (Call near from Router())                       */
/*                                                                          */
/*  INPUT:  RoutCode   - Function Code of API being processed               */
/*                                                                          */
/*  EXIT-NORMAL:  RC = NO_ERROR                                             */
/*                                                                          */
/*  EXIT-ERROR: error code from DosFSRamSemRequest()                        */
/*              ERROR_MOU_EXTENDED - caller is PM or MVDM screen group      */
/*              ERROR_MOUSE_REGISTER - caller is VIOPOPUP or VIOWindow      */
/*                                                                          */
/*  EFFECTS:  The appropriate semaphore is set according to the RoutCode    */
/*            and the screen group type is checked to validate whether      */
/*            the caller can make the associated API call.  ProcessInit()   */
/*            is also called if the flag has not yet been set.              */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: CurrentTYPE - the type of the callers process           */
/*                  CurrentSGID - the current Screen Group ID               */
/*                                                                          */
/*     COMMON data: ProcessInitFlag - checked for process init complete.    */
/*                                                                          */
/*        ROUTINES: ProcessInit() - Should only need to be called when a    */
/*                                  process is dying and a API is called    */
/*                                  from somewhere in the DosExitList       */
/*                                  group of routines after our exitlist    */
/*                                  is complete.                            */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*      ROUTINES: DosFSRamSemRequest() - request FSRamSemaphore.            */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

USHORT MouCheckProcType(VOID) {

  USHORT RC = NO_ERROR;

  if (!ProcessInitFlag)
    RC = RoutProcessInit();

  if (RC == NO_ERROR) {
    if (moudd_exists != TRUE)
      RC = ERROR_MOUSE_NO_DEVICE;
    else {
      if (CurrentTYPE == LIS_PT_DETACHED)
        RC = ERROR_MOU_DETACHED;
      else {
        if (CurrentTYPE != LIS_PT_FULLSCRN && CurrentTYPE != LIS_PT_VIOWIN)
          RC = ERROR_MOU_EXTENDED_SG;
      }
    }
  }

  return(RC);

}

/******************* START OF SPECIFICATIONS ********************************/
/*                                                                          */
/*                                        ******************************    */
/*  SUBROUTINE NAME:  CheckRegisterParms  ***  UNPUBLISHED  ROUTINE  ***    */
/*                                        ******************************    */
/*                                                                          */
/*  DESCRIPTIVE NAME:  Validate ASCIIZ strings and mask parameters          */
/*                                                                          */
/*  FUNCTION:  Compare the string lengths against the allowable limits and  */
/*             check the mask against its limits.                           */
/*                                                                          */
/*  ENTRY POINT:  CheckRegisterParms                                        */
/*      LINKAGE:  CALL NEAR                                                 */
/*                                                                          */
/*  INPUT:  ModuleName - Name of the DLL being processed                    */
/*          EntryPoint - Procedure name of DLL entry point.                 */
/*          Mask       - Mask indicating Keyboard API's being registered.   */
/*                                                                          */
/*  EXIT-NORMAL:  RC = NO_ERROR                                             */
/*                                                                          */
/*  EXIT-ERROR: ERROR_KBD_INVALID_MASK - Mask invalid                       */
/*              ERROR_KBD_INVALID_ASCIIZ - Modulename/EntryPoint Invalid    */
/*              ERROR_KBD_REGISTER - Previous KbdRegister outstanding in    */
/*                                   current Screen Group.                  */
/*                                                                          */
/*  EFFECTS:  none                                                          */
/*                                                                          */
/* INTERNAL REFERENCES:                                                     */
/*   INSTANCE data: none                                                    */
/*                                                                          */
/*     COMMON data: none                                                    */
/*                                                                          */
/*        ROUTINES: none                                                    */
/*                                                                          */
/* EXTERNAL REFERENCES:                                                     */
/*      ROUTINES: none                                                      */
/*                                                                          */
/******************* END  OF  SPECIFICATIONS ********************************/

USHORT CheckRegisterParms(PSZ ModuleName, PSZ EntryPoint, ULONG Mask) {

  USHORT RC = NO_ERROR;
  USHORT Length;

  if ((Length = _fstrlen(ModuleName)) && Length <= MAXIMUM_MOD_LENGTH) {
    if ((Length = _fstrlen(EntryPoint)) && Length <= MAXIMUM_EP_LENGTH) {
      if ((Mask == NO_MASK) || (Mask > MAXIMUM_MASK_SIZE))
        RC = REG_MASK_ERROR;
    }
    else
      RC = REG_STRING_ERROR;
  }
  else
    RC = REG_STRING_ERROR;

  return(RC);

}

/******************* START OF SPECIFICATIONS *********************************/
/*                                                                           */
/*                                       ******************************      */
/*  SUBROUTINE NAME:  KbdReloadAltSubSys ***  UNPUBLISHED  ROUTINE  ***      */
/*                                       ******************************      */
/*                                                                           */
/*  DESCRIPTIVE NAME:  Reload the address of the entry point to a Registered */
/*                     Keybord Sub System.                                   */
/*                                                                           */
/*  FUNCTION: When a process switch occurs, the address of a registered    . */
/*            subsystems entry point is no longer valid.  The calls to       */
/*            DosGetProcAddr and DosLoadModule are done to reload the        */
/*            address for the current process.                               */
/*                                                                           */
/*  ENTRY POINT:  KbdReloadAltSubSys                                         */
/*      LINKAGE:  CALL NEAR (from Router KbdGetFocus and KbdFreeFocus)       */
/*  INPUT:  None.                                                            */
/*                                                                           */
/*  EXIT-NORMAL:  RC = NO_ERROR                                              */
/*                                                                           */
/*  EXIT-ERROR:   RC = ERROR returned from DOSLOADMODULE(),                  */
/*                RC = ERROR returned from DOSGETPROCADDR()                  */
/*                                                                           */
/*  EFFECTS: AKS_Addr has address of Alternate SubSystem entry point.        */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*  INSTANCE data: NONE                                                      */
/*                                                                           */
/*    COMMON data: AKS_Addr  - address of Alternate DLL's entry procedure.   */
/*                 SgData    - address of current Screen Group Control Block */
/*                                                                           */
/*       ROUTINES: NONE                                                      */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*  INSTANCE data: NONE                                                      */
/*                                                                           */
/*       ROUTINES: DosLoadModule() - Load the associated module name.        */
/*                 DosGetProcAddr() - Get the address of the associated DLL. */
/*                 DosFreeModule() - Free module name on ERROR.              */
/*                                                                           */
/******************* END  OF  SPECIFICATIONS *********************************/
USHORT KbdReloadAltSubSys(VOID) {                                 /* B733895 */

  USHORT RC = NO_ERROR;

  if (SGData->KBD_Mask) {
    if (!AKS_Addr) {
      RC = DosLoadModule(NAMEBUFFER,
                         BUFFERLENGTH,
                         SGData->KBD_AKSCB->ModuleName,
                         &SGData->KBD_AKSCB->Handle);

      if (RC == NO_ERROR) {
        RC = DosGetProcAddr(SGData->KBD_AKSCB->Handle,
                            SGData->KBD_AKSCB->EntryPoint,
                            (PFN FAR *)&AKS_Addr);            /* 063131 */

        if (RC != NO_ERROR)
          DosFreeModule(SGData->KBD_AKSCB->Handle);
      }
    }
  }

  return(RC);

}

/******************* START OF SPECIFICATIONS *********************************/
/*                                                                           */
/*                                       ******************************      */
/*  SUBROUTINE NAME:  MouReloadAltSubSys ***  UNPUBLISHED  ROUTINE  ***      */
/*                                       ******************************      */
/*                                                                           */
/*  DESCRIPTIVE NAME:  Reload the address of the entry point to a Registered */
/*                     Mouse Sub System.                                     */
/*                                                                           */
/*  FUNCTION: When a process switch occurs, the address of a registered    . */
/*            subsystems entry point is no longer valid.  The calls to       */
/*            DosGetProcAddr and DosLoadModule are done to reload the        */
/*            address for the current process.                               */
/*                                                                           */
/*  ENTRY POINT:  MouReloadAltSubSys                                         */
/*      LINKAGE:  CALL NEAR (from Router)                                    */
/*  INPUT:  None.                                                            */
/*                                                                           */
/*  EXIT-NORMAL:  RC = NO_ERROR                                              */
/*                                                                           */
/*  EXIT-ERROR:   RC = ERROR returned from DOSLOADMODULE(),                  */
/*                RC = ERROR returned from DOSGETPROCADDR()                  */
/*                                                                           */
/*  EFFECTS: AMS_Addr has address of Alternate SubSystem entry point.        */
/*                                                                           */
/* INTERNAL REFERENCES:                                                      */
/*  INSTANCE data: NONE                                                      */
/*                                                                           */
/*    COMMON data: AMS_Addr  - address of Alternate DLL's entry procedure.   */
/*                 SgData    - address of current Screen Group Control Block */
/*                                                                           */
/*       ROUTINES: NONE                                                      */
/*                                                                           */
/* EXTERNAL REFERENCES:                                                      */
/*  INSTANCE data: NONE                                                      */
/*                                                                           */
/*       ROUTINES: DosLoadModule() - Load the associated module name.        */
/*                 DosGetProcAddr() - Get the address of the associated DLL. */
/*                 DosFreeModule() - Free module name on ERROR.              */
/*                                                                           */
/******************* END  OF  SPECIFICATIONS *********************************/
USHORT MouReloadAltSubSys(VOID) {                                 /* B733895 */

  USHORT RC = NO_ERROR;

  /***************************************************************/
  /* Reload Alt Mouse Subsystem, (AMS), entry point address for  */
  /* this process.  The address becomes invalid and needs to be  */
  /* reattached for each running process.                        */
  /***************************************************************/
  if (SGData->MOU_Mask)
    if (!AMS_Addr) {
      RC = DosLoadModule(NAMEBUFFER,
                         BUFFERLENGTH,
                         SGData->MOU_AMSCB->ModuleName,
                         &SGData->MOU_AMSCB->Handle);

      if (RC == NO_ERROR) {
        RC = DosGetProcAddr(SGData->MOU_AMSCB->Handle,
                            SGData->MOU_AMSCB->EntryPoint,
                            (PFN FAR *)&AMS_Addr);            /* 063131 */

        if (RC != NO_ERROR)
          DosFreeModule(SGData->MOU_AMSCB->Handle);
      }
    }

  return(RC);

}

/*********************** START OF SPECIFICATIONS *****************************/
/*                                                                           */
/*                                     ******************************        */
/* SUBROUTINE NAME: MMIOKBDTrace       ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/* FUNCTION: Common memory mapped I/O trace point. Writes major/minor code   */
/*           to memory mapped I/O trace hardware buffer; (DEKKO Card).       */
/*                                                                           */
/* NOTES: Memory mapped I/O will not port to 32 bit flat model               */
/*                                                                           */
/* ENTRY POINT: MMIOKBDTrace(APIOrdinal,PreORPost)                           */
/*     LINKAGE: CALL NEAR                                                    */
/*                                                                           */
/* INPUT: RoutCode -   Current API function. Used as index into              */
/*                     major/minor code array.                               */
/*        PreORPost -  1 for pre-invocation, 2 for post-invocation           */
/*                     multiplied with PreORPost gives final index.          */
/*                                                                           */
/* EXIT-NORMAL: None                                                         */
/*                                                                           */
/* EXIT-ERROR: None                                                          */
/*                                                                           */
/* SIDE EFFECTS: None                                                        */
/*                                                                           */
/*********************** END OF SPECIFICATIONS *******************************/

#ifdef MMIOPH                /******* BEGIN MMIOPH performance routine *******/

#pragma optimize("",off)
VOID MMIOKBDTrace(USHORT RoutCode,USHORT PreORPost) {

   *mmio_buffer = kbd_mmio_codes[RoutCode+PreORPost];    /* 061231 */

   return;
}

#pragma optimize("",on)
#endif                       /*******  END  MMIOPH performance routine *******/

/*********************** START OF SPECIFICATIONS *****************************/
/*                                                                           */
/*                                     ******************************        */
/* SUBROUTINE NAME: MMIOMOUTrace       ***  UNPUBLISHED  ROUTINE  ***        */
/*                                     ******************************        */
/*                                                                           */
/* FUNCTION: Common memory mapped I/O trace point. Writes major/minor code   */
/*           to memory mapped I/O trace hardware buffer; (DEKKO Card).       */
/*                                                                           */
/* NOTES: Memory mapped I/O will not port to 32 bit flat model               */
/*                                                                           */
/* ENTRY POINT: MMIOMOUTrace(APIOrdinal,PreORPost)                           */
/*     LINKAGE: CALL NEAR                                                    */
/*                                                                           */
/* INPUT: RoutCode -   Current API function. Used as index into              */
/*                     major/minor code array.                               */
/*        PreORPost -  1 for pre-invocation, 2 for post-invocation           */
/*                     multiplied with PreORPost gives final index.          */
/*                                                                           */
/* EXIT-NORMAL: None                                                         */
/*                                                                           */
/* EXIT-ERROR: None                                                          */
/*                                                                           */
/* SIDE EFFECTS: None                                                        */
/*                                                                           */
/*********************** END OF SPECIFICATIONS *******************************/

#ifdef MMIOPH                /******* BEGIN MMIOPH performance routine *******/

VOID MMIOMOUTrace(USHORT RoutCode,USHORT PreORPost) {

   *mmio_buffer = mou_mmio_codes[RoutCode+PreORPost];

   return;

}

#endif                       /*******  END  MMIOPH performance routine *******/
