/*
*   IBM Confidential
*
*   OCO Source Materials
*
*   (c) Copyright IBM Corp. 1994, 1998
*
*   The source code for this program is not published or otherwise divested of its
*   tradesecrets, irrespective of what has been deposited with the U.S. Copyright Office.
*/

/****************************************************************************/
/*                                                                           */
/* SOURCE FILE NAME = KBDINIT.C                                              */
/*                                                                           */
/* DESCRIPTIVE NAME = Physical Keyboard Device Dependent Initialization      */
/*                                                                           */
/* 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.2                                                         */
/*                                                                           */
/* DATE         01/11/94                                                     */
/*                                                                           */
/* DESCRIPTION  Initialization for Device Dependent Driver.                  */
/*                                                                           */
/* FUNCTIONS    void Init(void)                                              */
/*                                                                           */
/* NOTES       DEPENDENCIES:  Controller or keyboard must be set to the      */
/*                            PC compatible scan code set.                   */
/*             RESTRICTIONS:  Machine must be a 386 or compatible with       */
/*                            a 386.                                         */
/*                                                                           */
/* STRUCTURES   PRPH                                                         */
/*              AttachDDStr                                                  */
/*                                                                           */
/* EXTERNAL REFERENCES                                                       */
/*                                                                           */
/*              NONE                                                         */
/*                                                                           */
/* EXTERNAL FUNCTIONS                                                        */
/*                                                                           */
/*              NONE                                                         */
/*                                                                           */
/*   CHANGE ACTIVITY =                                                       */
/*     DATE      FLAG        APAR   CHANGE DESCRIPTION                       */
/*     --------  ----------  -----  ----------------------------------       */
/*     07/08/97   CN181212          Added InitTime flag                      */
/*     01/30/98   HCT D192860       Check kbderr to exit infinite loop       */
/*                                  while waiting for kbd IDs                */
/*     03/12/98   HCT D193257       Add IO delay and adjust timming loop     */
/*     06/20/98   LR_USB            Modified to support USB Keyboard Client. */
/*                                                                           */
/*****************************************************************************/

/*-----------------------------*/
/*   Include files             */
/*-----------------------------*/

 #include "os2.h"
 #include "bseerr.h"
 #include "devcmd.h"
 #include "strat2.h"
 #include "reqpkt.h"
 #include "dhcalls.h"
 #include "kbd.h"
 #include "kbddd.h"
 #include "kbdrm.h"
 #include "cmdphdr.h"
 #include "kbdusb.h"    //LR_USB

USHORT NEAR ParseCmdLine( PSZ pInitArgs );
VOID   NEAR TTYWrite( PSZ Buf );

/*-----------------------------*/
/*   Define files              */
/*-----------------------------*/

 #define FP_OFF(ptr) ((USHORT)((ULONG)(ptr)&0xFFFF))

/*-----------------------------*/
/*     External Variables      */
/*-----------------------------*/

 extern  int  endvariable;
 extern  int  DummyEnd;            //LR_USB

 extern  PRPH    pRPH;             /* Pointer to RPH (Request Packet Header) */
 extern  PFN     Device_Help;
 extern  PFN     KbdDI_Entry;
 extern  AttachDDStr KbdDI;

 extern  USHORT  Offset_Int_Handler;
 extern  USHORT  Offset_IDC_Handler;
 extern  USHORT  Offset_Timer_Handler;
 extern  USHORT  Offset_BTTimer_Handler;        //SM148922
 extern  USHORT  Keycount;

extern BYTE PrevState;

 extern  BYTE    DataByte1;
 extern  BYTE    DataByte2;
 extern  BYTE    Current_State;
 extern  BYTE    KbdResend;
 extern  BYTE    KbdError;
 extern  BYTE    AsyncInterruptTime;
 extern  BYTE    SyncInterruptTime;
 extern  BYTE    TIMERFLAG;
 extern  BYTE    BTTIMERFLAG;                   //SM148922
 extern  BYTE    Type_Rate;
 extern  BYTE    InitTime;                      //CN181212
 extern  BYTE    KbdIsLocked;                   // AP 1998-06-29

/*****************************************************************************/
/*                                                                           */
/* FUNCTION NAME  : Init                                                     */
/*                 "IBM Unique Code"                                         */
/*                                                                           */
/* DESCRIPTION    : Initialization function for the keyboard device dependent*/
/*                  driver.  If device independent driver is not installed   */
/*                  yet, or can not get IRQ 1 then it won't install itself.  */
/*                                                                           */
/*****************************************************************************/

void Init (void)
{
  PRPINITIN  pRPI = (PRPINITIN)  pRPH;
  PRPINITOUT pRPO = (PRPINITOUT) pRPH;
//LR_USB  int i, j, k;

//LR_USB begin
#ifdef DEBUG
dsPrint (DBG_HLVLFLOW, "IBMKBD: Init\r\n");
#endif
//LR_USB end

  KbdError = TURNOFF;                       /* Reset Error flag.             */
  KbdResend = 0;                            /* Reset Resend flag.            */
  AsyncInterruptTime = 0;                   /* Reset Interrupt flag.         */
  SyncInterruptTime = 0;                    /* Reset Interrupt flag.         */
  InitTime = 1;                             //CN181212
  TIMERFLAG = TURNOFF;                      /* Reset Timer flag.             */
  BTTIMERFLAG = TURNOFF;                    //SM148922: Reset block thread timer flag
  Type_Rate = Fast_Type_Rate;               /* Default type rate and delay.  */
  Device_Help =  pRPI->DevHlpEP;            /* Load Device Help pointer.     */

  if (ParseCmdLine (pRPI->InitArgs)) TTYWrite (ParmErrMsg);

        /* First we must get the address of the independent keyboard driver. */

  if (DevHelp_AttachDD ("KBD$    ", (NPBYTE)&KbdDI)) { /* Attach to KBDDI.   */
    KbdError = TURNON;
  }
  else  {
    KbdDI_Entry = (PFN)KbdDI.Pmode; /* Load pointer to driver. */

    if ( RM_KBD_CreateDriver()      /* Resource Manager Setup. */
      || RM_KBD_AllocIRQ (KBD_IRQ)  /* Reserve IRQ.            */
      || RM_KBD_AllocPortBuffer()   /* Reserve Port 64.        */
      || RM_KBD_AllocPortCmd()      /* Reserve Port 64.        */
      || RM_KBD_CreateAdapter()) {  /* Create Adapter.         */
      KbdError = TURNON;
      goto KbdFail;
    }
    Disable_Keyboard();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();
    IODelay();

          /* Now we must install our handy-dandy keyboard interrupt handler. */

    Offset_Int_Handler = FP_OFF (&Kbd_Interrupt);
    if (DevHelp_SetIRQ ((NPFN) Offset_Int_Handler, (USHORT)KBD_IRQ, 0)) {
        KbdError = TURNON;
    }
  }
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  Enable_Keyboard();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();
  IODelay();

KbdFail:

  if (KbdError) {
    pRPO->CodeEnd = (USHORT)0;              /* Init failed.                  */
    pRPO->DataEnd = (USHORT)0;
    pRPH->Status = STATUS_DONE | STERR | STATUS_ERR_UNKCMD;

    RM_KBD_DestroyDriver();                 /* Delete from Resource Manager. */
  }
  else  {                                   /* Init complete successfully.   */
    pRPO->CodeEnd = (USHORT)&DummyEnd;      //LR_USB &Init;
    pRPO->DataEnd = (USHORT)&endvariable;
    pRPH->Status = STATUS_DONE;

    Offset_IDC_Handler = FP_OFF(&IDC_Entry_Point);
    Offset_Timer_Handler = FP_OFF(&KbdTimerHandler);
//SM148922: Offset for block thread time handler
    Offset_BTTimer_Handler = FP_OFF(&KbdBTTimerHandler);

    DevHelp_TickCount ((NPFN)Offset_Timer_Handler, MAX_Tick); /* Create timer*/
//SM148922: Create timer for block thread
    DevHelp_TickCount ((NPFN)Offset_BTTimer_Handler, MAX_Tick);

//LR_USB begin
   if (DevHelp_AllocateCtxHook ((NPFN)FP_OFF(HookHandler), &gHookHandle)) {
#ifdef DEBUG
dsPrint (DBG_CRITICAL, "IBMKBD: Init, AllocateCtxHook ERROR\r\n");
#endif
    }
//LR_USB end

    STI;
    Current_State = S_HOTPLGPG;
    HotPlgPg (CMD_SELFTEST);                  /* Start hotplug/init routine. */

//LR_USB    i = (DataByte1 == 0 && DataByte2 == 0); // ready to receive ID bytes
    // HCT 01/30/98 D192860
    // While we expect keyboard IDs here, they may never come if
    // customer/bank unplug the keyboard (YES!!! they do on ATM machines)
    // In that case, by checking for KbdError, we will be able to
    // get out of this infinite loop.
//LR_USB begin
/*
    k = 0;
    while (!KbdIsLocked && i && !KbdError) { // AP --- Add "!KbdIsLocked &&"
      for (j = 0; j < 1000; j++) {}
      CLI;
      i = (DataByte1 == 0 && DataByte2 == 0);
      STI;
    }
*/
    while (Current_State > S_SENTSCSD);
//LR_USB end

    RM_KBD_CreateDevice (Keycount);          /* Resource Manager Setup.      */
    { // AP-198827 --------------------
    extern USHORT KbdDI_Handle;                 /* Handle to KBDDI.     */
    extern USHORT KbdCS;
    extern USHORT KbdDS;

    // Open the DI kbd if is was not already opened to prevent system hang later
    if (KbdDI_Handle == -1) {
       _asm {
          mov KbdCS, cs                 /* Save the code segment value. */
          mov KbdDS, ds                 /* Save the data segment value. */
       }                                        /* Register with KBDDI. */
       KbdDI_Handle = KbdDI_Entry(CMD_Open, Offset_IDC_Handler, KbdDS, KbdCS);
    }
    } // AP-198827 --------------------

//LR_USB begin
#ifdef DEBUG
dsPrint (DBG_HLVLFLOW, "IBMKBD: Init = OK\r\n");
#endif
//LR_USB end

  }
  InitTime = 0;                               //CN181212
}

/*****************************************************************************/

USHORT NEAR ParseCmdLine (PSZ pInitArgs)
{
  CC     cc;
  PBYTE  pOutBuf;       //LR_USB NPSZ   pOutBuf;
  USHORT Flags = 0;
  USHORT rc = 0;
  USHORT Length;

  pOutBuf = poutbuf;

  cc = Command_Parser( (PSZ)          pInitArgs,
                       (POPTIONTABLE) &opttable,
                       (PBYTE)        pOutBuf,
                       (USHORT)       outbuf_len );

  if ( cc.ret_code == NO_ERR )
  {
    while ( !rc && pOutBuf[1] != (UCHAR) TOK_ID_END )
    {

      Length = pOutBuf[0];

      switch ( pOutBuf[1] )
      {

        /*-------------------------------------------*/
        /* No Keyboard Mode - /none                  */
        /*                                           */
        /*-------------------------------------------*/

        case TOK_ID_NONE:

          FakeKbd = 1;
          break;


        /*-------------------------------------------*/
        /* Numlock - /NumOn /NumOff                  */
        /*                                           */
        /* Check for if numlock on or off            */
        /*-------------------------------------------*/

        case TOK_ID_NUMLOCK_ON:

          NumLock = 1;
          break;

        case TOK_ID_NUMLOCK_OFF:

          NumLock = 0;
          break;


        /*-------------------------------------------*/
        /* Unknown Switch                            */
        /*                                           */
        /*-------------------------------------------*/

        default:

          rc = 1;
          break;
      }

      if ( !rc ) pOutBuf += Length;

    }
  }
  else if ( cc.ret_code != NO_OPTIONS_FND_ERR )
  {
    rc = 1;
  }

  return( rc );
}

VOID NEAR TTYWrite( PSZ Buf )
{
  InitMsg.MsgStrings[0] = Buf;

  DevHelp_Save_Message( (NPBYTE) &InitMsg );
}

