/*static char *SCCSID = "@(#)vlptlo.c   6.7 92/01/30";*/
#pragma linesize(132)
#pragma pagesize(60)
#pragma title("VLPTLO.C")
/****************************************************************************/
/*                                                                          */
/*                       IBM/Microsoft Confidential                         */
/*                                                                          */
/*                 Copyright (c) IBM Corporation  1987, 1990                */
/*                 Copyright (c) Microsoft Corp.  1987, 1990                */
/*                           All Rights Reserved                            */
/*                                                                          */
/****************************************************************************/
/************************** START OF SPECIFICATIONS **********************/
/*                                                                       */
/*   SOURCE FILE NAME:  VLPTLO.C                                         */
/*                                                                       */
/*   DESCRIPTIVE NAME:  Private VLPT service subroutines                 */
/*                                                                       */
/*   FUNCTION: These subroutines are responsible for error handling,     */
/*             maintaining the print stream buffer. They are also        */
/*             responsible for issuing the VDH calls to OPEN, WRITE to,  */
/*             and CLOSE the spool file handles.                         */
/*                                                                       */
/*   NOTES:                                                              */
/*      DEPENDENCIES: Spooler is running                                 */
/*      RESTRICTIONS: None                                               */
/*                                                                       */
/*   ENTRY POINTS:                                                       */
/*             dopopup     - popup message handler                       */
/*             reseterrors - reset error bits                            */
/*             seterrors   - set error bits                              */
/*             proc_error  - process VDH service errors                  */
/*                                                                       */
/*   EXTERNAL REFERENCES:                                                */
/*       VDHPopup    - Display popup and return user response            */
/*       VDHKillVDM  - Put mark on the wall to kill VDM at next dispatch */
/*       VDHWaitEventSem - Wait on an event semaphore                    */
/*       VDHOpen     - Open LPT device                                   */
/*       VDHWrite    - Write to LPT device                               */
/*       VDHClose    - Close LPT device                                  */
/*       VDHAllocMem - Allocate 32:32 fixed memory                       */
/*       VDHGetError - Get error from VDH call                           */
/*                                                                       */
/*                                                                       */
/**************************** END OF SPECIFICATIONS **********************/

#include <mvdm.h>                           /* VDH services, etc.        */
#include <error.h>                          /* OS/2 error codes          */
#include "vlptp.h"                          /* VLPT data defines         */
#include "vlptdata.h"                       /* VLPT external data        */

#pragma BEGIN_SWAP_CODE
/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  DOPOPUP                                             */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle message popups                               */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Set do type error bit                                             */
/*  2) Set busy bit for this port id.                                    */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  DOPOPUP                                                 */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*       vlptinst - ptr to offset portid of per VDM data area            */
/*       table_ptr -     pointer to error processing table               */
/*       errortype -     0=open, 1=flush, 2=close, 3=allocmem,           */
/*                       4=directmode                                    */
/*                                                                       */
/* EXIT-NORMAL: resp_val - response from VDHPOPUP                        */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Perform popups and perform function from user responses     */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*       get_direct_access - request direct I/O access                   */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*       VDHPopup    - Display popup and return user response            */
/*       VDHKillVDM  - Put mark on the wall to kill VDM at next dispatch */
/*       VDHWaitEventSem - Wait on an event semaphore                    */
/*       VDHOpen     - Open LPT device                                   */
/*       VDHWrite    - Write to LPT device                               */
/*       VDHClose    - Close LPT device                                  */
/*       VDHAllocMem - Allocate 32:32 fixed memory                       */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
UINT PRIVENTRY dopopup(vlptinst,table_ptr,errortype)
PVLPTINST vlptinst;
struct error_table_record *table_ptr;
UINT errortype;
 {
  BOOL       vrc;                       /* VDHPopup return code    */
  ULONG      retry;                     /* retry value             */
  ULONG      actiontaken;

  vrc = 1;

  /*---------------------------------------------------------------*/
  /*- Set the response value equal to the default response value  -*/
  /*- for the error table that was passed in.                     -*/
  /*---------------------------------------------------------------*/
  resp_val = table_ptr->def_res;

  /*---------------------------------------------------------------*/
  /*- Call VDHPopup to notify the user of the error               -*/
  /*---------------------------------------------------------------*/
  VDHPopup(
           (PSZZ)table_ptr->sub_str,
           (ULONG)table_ptr->num_sub_str,
           (ULONG)table_ptr->m_err_code,
           (PULONG)&resp_val,
           (ULONG)table_ptr->valid_res,
           (PSZ)NULL);

  /*---------------------------------------------------------------*/
  /*- Evaluate the user response to VDHPopup.                     -*/
  /*---------------------------------------------------------------*/
  switch (resp_val)
    {
  /*---------------------------------------------------------------*/
  /*- If the user response was to ABORT the VDM then call         -*/
  /*- VDHKillVDM.                                                 -*/
  /*---------------------------------------------------------------*/
     case ABORT:
  /*---------------------------------------------------------------*/
  /*- Set the data stream character count to zero.  36857         -*/
  /*---------------------------------------------------------------*/
             vlptinst->bufcount = 0;
             VDHKillVDM(CURRENT_VDM);
             break;
  /*---------------------------------------------------------------*/
  /*- If the user response was to IGNORE the error, then do not   -*/
  /*- do anything special.                                        -*/
  /*---------------------------------------------------------------*/
     case IGNORE:
             break;
  /*---------------------------------------------------------------*/
  /*- If the user response was RTN_ERR_PGM then do not do         -*/
  /*- anything special.                                           -*/
  /*---------------------------------------------------------------*/
     case RTN_ERR_PGM:
             break;
  /*---------------------------------------------------------------*/
  /*- If the user response was to RETRY then set up for a retry.  -*/
  /*---------------------------------------------------------------*/
     case RETRY:
             retry = table_ptr->retry;      /* get retry count     */

  /*---------------------------------------------------------------*/
  /*- Keep trying the retry until the count is decremented to zero-*/
  /*---------------------------------------------------------------*/
             while (retry != 0)
               {

  /*---------------------------------------------------------------*/
  /*- If the timeout value is not zero then call VDHWaitEventSem  -*/
  /*- to delay for the length of time in timeout.                 -*/
  /*---------------------------------------------------------------*/
                 if (table_ptr->timeout != 0)
                   {
                    VDHWaitEventSem(
                                    (HVDHSEM)vlpt_sem_handle,
                                    (ULONG)table_ptr->timeout);
                   } /* endif */

  /*---------------------------------------------------------------*/
  /*- Decide which VDH service to retry by evaluating errortype.  -*/
  /*---------------------------------------------------------------*/
                 switch (errortype)
                    {
  /*---------------------------------------------------------------*/
  /*- If the errortype is OPEN_TYPE then retry VDHOpen.           -*/
  /*---------------------------------------------------------------*/
                     case   OPEN_TYPE:
                            lptname[3] = PORTS[vlptinst->lptportid];
                            if (!(VDHOpen((PSZ)lptname,
                                          (PHFILE)&vlptinst->fshandle,
                                          SSToDS(&actiontaken),
                                          (ULONG)NULL,
                                          VDHOPEN_FILE_NORMAL,
                                          VDHOPEN_ACTION_OPEN_IF_EXISTS,
                                          VDHOPEN_FLAGS_FAIL_ON_ERROR+VDHOPEN_ACCESS_READWRITE+VDHOPEN_SHARE_DENYNONE+VDHOPEN_FLAGS_NOINHERIT,
                                          (PVOID)NULL)))
                              {
                               vrc = 0;
                              } else {
                               vrc = 1;
                              } /* endif */
                            break;

  /*---------------------------------------------------------------*/
  /*- If the errortype is FLUSH_TYPE then retry VDHWrite.         -*/
  /*---------------------------------------------------------------*/
                     case   FLUSH_TYPE:
                            if ((VDHWrite(
                                   (HFILE)vlptinst->fshandle,
                                   (PVOID)vlptinst->stream,
                                   (ULONG)vlptinst->bufcount)) == WRITE_ERROR)
                              {
                               vrc = 0;
                              } else {
                               vrc = 1;
                              } /* endif */
                            break;

  /*---------------------------------------------------------------*/
  /*- If the errortype is ALLOC_TYPE then retry VDHAllocMem.      -*/
  /*---------------------------------------------------------------*/
                     case   ALLOC_TYPE:
                            if ((vlptinst->stream = VDHAllocMem(
                                      (ULONG)ulbuffersize[vlptinst->lptportid],
                                      (ULONG)VDHAM_SWAPPABLE)) == 0)
                              {
                               vrc = 0;
                              } else {
                               vrc = 1;
                              } /* endif */
                            break;

  /*---------------------------------------------------------------*/
  /*- If the errortype is DIRECT_TYPE then call get_direct_access -*/
  /*- to get direct I/O access for the port associated with       -*/
  /*- vlptinst.                                                   -*/
  /*---------------------------------------------------------------*/
                     case   DIRECT_TYPE:
                            if ((get_direct_access(vlptinst)) != 0) {
                                vrc = 0;
                            } else {
                                vrc = 1;
                            } /* endif */
                            break;

                    } /* endswitch */

  /*---------------------------------------------------------------*/
  /*- Check VDH service error to see if retry was successful. If  -*/
  /*- it was not successful then decrement retry counter.         -*/
  /*---------------------------------------------------------------*/
                 if (vrc == 0)
                   {
                    retry--;
                   } /* endif */

  /*---------------------------------------------------------------*/
  /*- If the retry was successful then set the response value to  -*/
  /*- zero, and set the retry count to zero to end the retry loop.-*/
  /*---------------------------------------------------------------*/
                 else
                   {
                    resp_val = 0;
                    retry = 0;

                   } /* endif */

               } /* endwhile */

             break;

    } /* endswitch */

  return(resp_val);

 }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  RESETERRORS                                         */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle resetting of error bits for do type routines */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Reset do type error bit                                           */
/*  2) Reset status port for this port id.                               */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  RESETERRORS                                             */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*       vlptinst - ptr to offset portid of per VDM data area            */
/*       dotype - 0=open, 1=flush, 2=close                               */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Resets do type error bit and virtual status port            */
/*                                                                       */
/* INTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/* EXTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY reseterrors(vlptinst,dotype)
  PVLPTINST vlptinst;
  UINT dotype;
 {

  register BYTE doflag;                 /* temporary flag variable */

  /*---------------------------------------------------------------*/
  /*- If dotype is egual to an OPEN_TYPE then set doflag to an    -*/
  /*- OPEN ERROR FLAG.                                            -*/
  /*---------------------------------------------------------------*/
  if (dotype == OPEN_TYPE)
    {
     doflag = OPEN_ERROR_FLAG;
    }
  else
    {

  /*---------------------------------------------------------------*/
  /*- Else doflag is set to FLUSH ERROR FLAG.                     -*/
  /*---------------------------------------------------------------*/
     doflag = FLUSH_ERROR_FLAG;

    } /* endif */

  /*---------------------------------------------------------------*/
  /*- Now that the type of error flag is known, reset that flag.  -*/
  /*---------------------------------------------------------------*/
  vlptinst->flags  &= ~(UCHAR)doflag;

  /*---------------------------------------------------------------*/
  /*- Reset the virtual status port to its POWER_ON_STATUS.       -*/
  /*---------------------------------------------------------------*/
   vlptinst->status = POWER_ON_STATUS;

  return;
 }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  SETERRORS                                           */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle setting of error bits for do type routines   */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Set do type error bit                                             */
/*  2) Set busy bit for this port id.                                    */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  SETERRORS                                               */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*       vlptinst - ptr to offset portid of per VDM data area            */
/*       dotype - 0=open, 1=flush, 2=close                               */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Sets do type error bit and busy bit                         */
/*                                                                       */
/* INTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/* EXTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY seterrors(vlptinst,dotype)
  PVLPTINST vlptinst;
  UINT dotype;
 {

  register BYTE doflag;                 /* temporary flag variable */

  /*---------------------------------------------------------------*/
  /*- If dotype is egual to an OPEN_TYPE then set doflag to an    -*/
  /*- OPEN ERROR FLAG.                                            -*/
  /*---------------------------------------------------------------*/
  if (dotype == OPEN_TYPE)
    {
     doflag = OPEN_ERROR_FLAG;
    }
  else
    {

  /*---------------------------------------------------------------*/
  /*- Else set doflag to a FLUSH ERROR FLAG.                      -*/
  /*---------------------------------------------------------------*/
     doflag = FLUSH_ERROR_FLAG;

    } /* endif */

  /*---------------------------------------------------------------*/
  /*- Now that the type of error flag is known, set that flag.    -*/
  /*---------------------------------------------------------------*/
  vlptinst->flags  |=  (UCHAR)doflag;

  /*---------------------------------------------------------------*/
  /*- Set the BUSY bit.                                           -*/
  /*---------------------------------------------------------------*/
  vlptinst->status &= ~(UCHAR)BUSY_BIT;

  return;
 }


/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  PROC_ERROR                                          */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle processing of errors from VDH called rtns    */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Get error from VDH call.                                          */
/*  2) Call popup with error from VDH call.                              */
/*  3) Retry steps 1 and 2 if response from popup is RETRY               */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  PROC_ERROR                                              */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*           vlptinst - ptr to offset portid of per VDM data area        */
/*           table_ptr - pointer to error processing table               */
/*           errortype - 0=open, 1=flush, 2=close, 3=allocmem            */
/*                                                                       */
/* EXIT-NORMAL: resp_val - response from VDHPOPUP                        */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Causes retry on errors and popups to be displayed           */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*       dopopup     - Perform message popup logic                       */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*       VDHGETERROR - Get error from VDH call                           */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
UINT PRIVENTRY proc_error(vlptinst,table_ptr,errortype)
PVLPTINST vlptinst;
struct error_table_record table_ptr[];
UINT errortype;
 {
  UINT          i;              /* loop counter                    */
  ULONG         ret_err;        /* error returned from VDHGetError */

  resp_val = RETRY;             /* set response value to default   */

  /*---------------------------------------------------------------*/
  /*- Set up loop to continue until the response is not RETRY.    -*/
  /*---------------------------------------------------------------*/
  while (resp_val == RETRY)
    {
     i = 0;                                 /* initialize counter  */

  /*---------------------------------------------------------------*/
  /*- Get the error code from the previous VDH service call.      -*/
  /*---------------------------------------------------------------*/
     ret_err = VDHGetError();

  /*---------------------------------------------------------------*/
  /*- Loop through the error table looking for an error code that -*/
  /*- matches the one returned by VDHGetError. If a match is not  -*/
  /*- found then a default error table entry is used.             -*/
  /*---------------------------------------------------------------*/
     while ((table_ptr[i].err_code != ret_err)
            && (table_ptr[i].err_code != NULL))
       {
        ++i;
       } /* endwhile */

  /*---------------------------------------------------------------*/
  /*- If the error table entry currently pointed to does not      -*/
  /*- require that an error popup be presented to the user then   -*/
  /*- return RTN_ERR_PGM.                                         -*/
  /*-                                                             -*/
  /*- ERROR_INTERRUPT states the process will die once it exits   -*/
  /*- kernel mode.  Proc_error returns a good return code, no     -*/
  /*- popup will be displayed, and the buffer count zeroed so     -*/
  /*- terminate VDM will not resend this buffer to the kernel dd. -*/
  /*---------------------------------------------------------------*/
     if (table_ptr[i].popup == NO_POPUP)
       {
        if (ret_err == ERROR_INTERRUPT)
          {
           resp_val = 0;
           return(resp_val);
          }
          else
          {
           return(RTN_ERR_PGM);
          } /* endif */
       } /* endif */

  /*---------------------------------------------------------------*/
  /*- If the error table entry currently pointed to does require  -*/
  /*- that a popup be presented to the user then call dopopup.    -*/
  /*---------------------------------------------------------------*/
     else
       {
        lptname[3] = PORTS[vlptinst->lptportid]; /* create subst str   */
        table_ptr[i].sub_str = (PSZZ)lptname; /* save subst string     */
        table_ptr[i].num_sub_str = 1;       /* save # of subst strings */

        resp_val = dopopup(
                           vlptinst,
                           &table_ptr[i],
                           errortype);
       } /* endif */

    } /* endwhile */

  /*---------------------------------------------------------------*/
  /*- Return response value from the popup.                       -*/
  /*---------------------------------------------------------------*/
  return(resp_val);

 }


#pragma END_SWAP_CODE
