/*static char *SCCSID = "@(#)vlptdo.c 6.11 91/12/05";*/
#pragma linesize(132)
#pragma pagesize(60)
#pragma title("VLPTDO.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:  VLPTDO.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:                                                            */
/*             doCheck       - Check for pending errors                       */
/*             doOpenSpool   - Open a device                                  */
/*             doWrite       - Write a character to print stream              */
/*             doFlush       - Copy print stream to device                    */
/*             doCloseSpool  - Close a device                                 */
/*             doOpenDirect  - Open a device in direct mode                   */
/*             doCloseDirect - Close a device in direct mode                  */
/*             get_direct_access - get direct access to device                */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*             VDHAllocMem - Allocate memory                                  */
/*             VDHOpen     - Open device via MVDM mgr                         */
/*             VDHFreeMem  - Free memory                                      */
/*             VDHWrite    - Write data to device via MVDM mgr                */
/*             VDHClose    - Close device driver via MVDM mgr                 */
/*             VDHGetError - Query error from VDH services                    */
/*             PLPTPDDProc - VLPT-PLPT interface                              */
/*             VDHSetIOHookState - Enable/Disable I/O port hooking            */
/*                                                                            */
/**************************** 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:  DOCHECK                                             */
/*                                                                       */
/* DESCRIPTIVE NAME:  Check for previous errors that occurred during     */
/*                    doOpenSpool, doCloseSpool, or doWrite.             */
/*                                                                       */
/* FUNCTION:  The function of this routine is to check for errors        */
/*            that occurred during the previous call to VDHOpen,         */
/*            VDHClose, and VDHWrite. If an error is found then          */
/*            this routine, in an effort to clear the error, will        */
/*            call the routine that caused the error.                    */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doCheck                                                 */
/*    LINKAGE:  CALL NEAR 32                                             */
/*                                                                       */
/* INPUT: vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL:  NONE                                                    */
/*                                                                       */
/* EXIT-ERROR:  NONE                                                     */
/*                                                                       */
/* EFFECTS:  NONE                                                        */
/*                                                                       */
/* INTERNAL REFERENCES:  doOpenSpool                                     */
/*                       doWrite                                         */
/*                       doFlush                                         */
/*                                                                       */
/* EXTERNAL REFERENCES:  NONE                                            */
/*                                                                       */
/************************ END OF SPECIFICATIONS **************************/
VOID PRIVENTRY doCheck(vlptinst)
PVLPTINST vlptinst;
{
    /*---------------------------------------------------------------*/
    /*- If there is an OPEN error pending try to clear it by        -*/
    /*- calling doOpenSpool again.                                  -*/
    /*---------------------------------------------------------------*/
    if (vlptinst->flags & OPEN_ERROR_FLAG) {
        doOpenSpool(vlptinst);

    /*---------------------------------------------------------------*/
    /*- If the device is open then try to write the character       -*/
    /*- that is in the virtual data port. This character was not    -*/
    /*- written before because of the OPEN error just cleared.      -*/
    /*---------------------------------------------------------------*/
        if (vlptinst->flags & OPEN_FLAG) {
            doWrite(vlptinst);
        } /* endif */

    } else {

    /*---------------------------------------------------------------*/
    /*- If there is a FLUSH error pending try to clear it by        -*/
    /*- calling doFlush again if the device is open.                -*/
    /*---------------------------------------------------------------*/
        if (vlptinst->flags & FLUSH_ERROR_FLAG) {
            if (vlptinst->flags & OPEN_FLAG) {
                doFlush(vlptinst);
            } /* endif */
        } /* endif */
    } /* endif */

    return ;
}


/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doOpenSpool                                         */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle the opening of LPT device per VDM.           */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Open the device.                                                  */
/*  2) Initialize control variables.                                     */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doOpenSpool                                             */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Sets open bit and handle saved in PerVDMDataArea.           */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*    PROC_ERROR       - Processor for errors                            */
/*    SETERRORS        - Set   error bits for a do routine               */
/*    RESETERRORS      - Reset error bits for a do routine               */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*    VDHAllocMem      - Allocate memory                                 */
/*    VDHOpen          - Open device driver via MVDM mgr                 */
/*    VDHFreeMem       - Free memory                                     */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY doOpenSpool(vlptinst)
PVLPTINST vlptinst;
  {
  ULONG      actiontaken;

   /*---------------------------------------------------------------*/
   /*- Allocate memory for the per portid data stream.             -*/
   /*---------------------------------------------------------------*/
   if ((vlptinst->stream = VDHAllocMem(
                                       (ULONG)ulbuffersize[vlptinst->lptportid],
                                       (ULONG)VDHAM_SWAPPABLE)) == NULL)

   /*---------------------------------------------------------------*/
   /*- If the allocation failed then check to see if the OPEN ERROR-*/
   /*- FLAG is set. If it is set then return.                      -*/
   /*---------------------------------------------------------------*/
     {
      if (vlptinst->flags & (UCHAR)OPEN_ERROR_FLAG)
        {
         return;
        }

   /*---------------------------------------------------------------*/
   /*- If the OPEN ERROR FLAG is not set then call proc_error to   -*/
   /*- process the allocation error.                               -*/
   /*---------------------------------------------------------------*/
      else
        {
         if (proc_error(
                        vlptinst,
                        (struct error_table_record *)other_table,
                        (unsigned )ALLOC_TYPE)
             != 0)

   /*---------------------------------------------------------------*/
   /*- If proc_error returns an error then call seterrors to set   -*/
   /*- the OPEN ERROR FLAG and return.                             -*/
   /*---------------------------------------------------------------*/
           {
            seterrors(vlptinst,OPEN_TYPE);
            return;

           } /* endif */

        } /* endif */

     } /* endif */

   /*---------------------------------------------------------------*/
   /*- If the memory allocation was successful then create a       -*/
   /*- device name and then call VDHOpen    with the device name.  -*/
   /*---------------------------------------------------------------*/
   lptname[3] = PORTS[vlptinst->lptportid];

   /*---------------------------------------------------------------*/
   /*- If the VDHOpen    was not successful then check to see the  -*/
   /*- OPEN ERROR FLAG is set.                                     -*/
   /*---------------------------------------------------------------*/
   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)))
     {

   /*---------------------------------------------------------------*/
   /*- If the OPEN ERROR FLAG is set already, then free up the     -*/
   /*- memory allocated for the data stream and return.            -*/
   /*---------------------------------------------------------------*/
      if (vlptinst->flags & (UCHAR)OPEN_ERROR_FLAG)
        {
         if (vlptinst->stream != NULL)
         {
            VDHFreeMem((PVOID)vlptinst->stream);
            vlptinst->stream = NULL;
         }
         return;
        }

   /*---------------------------------------------------------------*/
   /*- If the OPEN ERROR FLAG is not set then call proc_error to   -*/
   /*- process the open error.                                     -*/
   /*---------------------------------------------------------------*/
      else
        {
         if (proc_error(
                        vlptinst,
                        (struct error_table_record *)other_table,
                        (unsigned )OPEN_TYPE)
            != 0)
           {

   /*---------------------------------------------------------------*/
   /*- If proc_error returns that there was an error then free the -*/
   /*- memory allocated for the data stream, call seterrors to set -*/
   /*- the OPEN ERROR FLAG in the per VDM data area for portid,    -*/
   /*- and return.                                                 -*/
   /*---------------------------------------------------------------*/
            if (vlptinst->stream != NULL)
            {
               VDHFreeMem((PVOID)vlptinst->stream);
               vlptinst->stream = NULL;
            }
            seterrors(vlptinst,OPEN_TYPE);
            return;

           } /* endif */

        } /* endif */

     } /* endif */

   /*---------------------------------------------------------------*/
   /*- Save current PDB in per VDM data area.                      -*/
   /*---------------------------------------------------------------*/
   vlptinst->pdb_spool = pdbCurrent;

   /*---------------------------------------------------------------*/
   /*- Call reseterrors to clear any open error condition.         -*/
   /*---------------------------------------------------------------*/
   reseterrors(vlptinst,OPEN_FLAG);

   /*---------------------------------------------------------------*/
   /*- Set the OPEN flag to indicate that the device is now open.  -*/
   /*---------------------------------------------------------------*/
   vlptinst->flags |= (UCHAR)OPEN_FLAG;

   /*---------------------------------------------------------------*/
   /*- Set the data stream character count to zero.                -*/
   /*---------------------------------------------------------------*/
   vlptinst->bufcount = 0;
   return;
  }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doWrite                                             */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle the logical writing of a data byte to a      */
/*                   logocal LPT device per VDM.                         */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Put byte from virtual data port in buffer for this device.        */
/*  2) If buffer filled then write to device.                            */
/*  3) update the update touched time so we can close spool file on      */
/*     time out                                                          */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doWrite                                                 */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Buffer and count in PerVDMDataArea updated                  */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*    doFlush          - Write data to device via MVDM mgr               */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*    VDHDisarmTimerHook                                                 */
/*    VDHArmTimerHook                                                    */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY doWrite(vlptinst)
PVLPTINST vlptinst;
  {

   /*---------------------------------------------------------------*/
   /*-Disarm timeout timer since we are about to write another byte-*/
   /*---------------------------------------------------------------*/
   if (vlptinst->hhookLptEventContext)
   {
     VDHDisarmTimerHook(vlptinst->hhookLptEventContext);
   }

   /*---------------------------------------------------------------*/
   /*- Move the byte of data from the virtual data port of portid  -*/
   /*- to the data stream for portid.                              -*/
   /*---------------------------------------------------------------*/
   vlptinst->stream[vlptinst->bufcount] = vlptinst->data;

   /*---------------------------------------------------------------*/
   /*- Increment the count of bytes in the data stream.            -*/
   /*---------------------------------------------------------------*/
   vlptinst->bufcount++;

   /*---------------------------------------------------------------*/
   /*- If the data stream(buffer) is now full then call doFlush to -*/
   /*- write the data stream.                                      -*/
   /*---------------------------------------------------------------*/
   if (vlptinst->bufcount == ulbuffersize[vlptinst->lptportid])
     {
      doFlush(vlptinst);
     } /* endif */

   /*---------------------------------------------------------------*/
   /*- If the user has specified a timeout then arm the hook       -*/
   /*- a Zero timeout means No timeout                             -*/
   /*---------------------------------------------------------------*/

   if (nmsLptTimeout != 0){
      VDHArmTimerHook(vlptinst->hhookLptEventContext,nmsLptTimeout,this_VDM);
   }

   return;
  }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doFlush                                             */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle the physical writing of data buffer to       */
/*                   LPT device per VDM                                  */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Write data to this device.                                        */
/*  2) Reset buffer count to zero.                                       */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doFlush                                                 */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS: Buffer flushed and count updated in PerVDMDataArea.          */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*    PROC_ERROR       - Processor for errors                            */
/*    SETERRORS        - Set   error bits for a do routine               */
/*    RESETERRORS      - Reset error bits for a do routine               */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*    VDHWrite         - Write data to device via MVDM mgr               */
/*    VDHGetError      - Query any VDHWrite error                        */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY doFlush(vlptinst)
PVLPTINST vlptinst;
  {
   ULONG    ret_err;             /* error returned from VDHGetError */

   /*---------------------------------------------------------------*/
   /*- Call VDHWrite    with the open file handle, data stream     -*/
   /*- pointer, and number of characters to write.                 -*/
   /*---------------------------------------------------------------*/
   if (VDHWrite(
                   (HFILE)vlptinst->fshandle,
                   (PVOID)vlptinst->stream,
                   (ULONG)vlptinst->bufcount) == WRITE_ERROR)
     {

   /*---------------------------------------------------------------*/
   /*- If the VDHWrite    was not successful then check to see if  -*/
   /*- the FLUSH ERROR FLAG is already set. If it is already set   -*/
   /*- then return.                                                -*/
   /*---------------------------------------------------------------*/
      if (vlptinst->flags & (UCHAR)FLUSH_ERROR_FLAG)
        {
         return;
        }

   /*---------------------------------------------------------------*/
   /*- If the FLUSH ERROR FLAG is not set then get the error and   -*/
   /*- set the appropriate error bits in the virtual status port.  -*/
   /*- Seterrors is called to set the FLUSH ERROR FLAG so the      -*/
   /*- buffer will be flushed on the next request and is called to -*/
   /*- set the busy bit in the virtual status port (flow control). -*/
   /*- Reseterrors clears the bits in the virtual status port.     -*/
   /*---------------------------------------------------------------*/
      else
        {
         ret_err = VDHGetError();

         switch (ret_err)
           {                                       /* virtual status port */
            case ERROR_WRITE_FAULT:                /* PE=0, SL=1, ER=0 */
                  vlptinst->status &= ~(UCHAR)PAPER_BIT;
                  vlptinst->status |= (UCHAR)SELECT_BIT;
                  break;

            case ERROR_OUT_OF_PAPER:               /* PE=1, SL=1, ER=0 */
                  vlptinst->status |= (UCHAR)(PAPER_BIT | SELECT_BIT);
                  break;

            case ERROR_BAD_UNIT:                   /* PE=1, SL=0, ER=0 */
                  vlptinst->status |= (UCHAR)PAPER_BIT;
                  vlptinst->status &= ~(UCHAR)SELECT_BIT;
                  break;

            default:
                  break;

           } /* endswitch */

         vlptinst->status &= ~(UCHAR)IOERROR_BIT;

         seterrors(vlptinst,FLUSH_TYPE);
         return;

        } /* endif */

     } /* endif */

   /*---------------------------------------------------------------*/
   /*- If the VDHWrite    was successful then set the count of     -*/
   /*- bytes in the data stream back to zero.                      -*/
   /*---------------------------------------------------------------*/
   vlptinst->bufcount = 0;

   /*---------------------------------------------------------------*/
   /*- Call reseterrors to clear any flush error condition.        -*/
   /*---------------------------------------------------------------*/
   reseterrors(vlptinst,FLUSH_TYPE);

   return;

  }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doCloseSpool                                        */
/*                                                                       */
/* DESCRIPTIVE NAME: Handle the closing of LPT device per VDM            */
/*                                                                       */
/* FUNCTION:                                                             */
/*  1) Flush the buffer for this device.                                 */
/*  2) Close the device.                                                 */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doCloseSpool                                            */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS: Sets close bit in PerVDMDataArea.                            */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*    doFlush          - Write buffer to device                          */
/*    PROC_ERROR       - Processor for errors                            */
/*    SETERRORS        - Set   error bits for a do routine               */
/*    RESETERRORS      - Reset error bits for a do routine               */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*    VDHClose         - Close device driver via MVDM mgr                */
/*    VDHFreeMem       - Free memory                                     */
/*    VDHDisarmTimerHook - Disarm PRINT_TIMEOUT event context hook       */
/*    VDHArmTimerHook  - Arm PRINT_TIMEOUT event context hook            */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY doCloseSpool(vlptinst)
PVLPTINST vlptinst;
  {
   /*---------------------------------------------------------------*/
   /*- Check to see if the OPEN FLAG is set.                       -*/
   /*---------------------------------------------------------------*/
   if (vlptinst->flags & (UCHAR)OPEN_FLAG)
     {

   /*---------------------------------------------------------------*/
   /*- Disarm timeout timer since we are closing the spool file    -*/
   /*---------------------------------------------------------------*/
      if (vlptinst->hhookLptEventContext)
      {
        VDHDisarmTimerHook(vlptinst->hhookLptEventContext);
      }

   /*---------------------------------------------------------------*/
   /*- If the OPEN FLAG is set then check to see if any bytes      -*/
   /*- remain in the data stream.                                  -*/
   /*---------------------------------------------------------------*/
      if (vlptinst->bufcount > 0)
        {

   /*---------------------------------------------------------------*/
   /*- Now try to flush the data stream by calling doFlush.        -*/
   /*---------------------------------------------------------------*/
         doFlush(vlptinst);

   /*---------------------------------------------------------------*/
   /*- If doFlush can not flush the data stream due to device      -*/
   /*- error and doCloseSpool called from PRINT_TIMEOUT event      -*/
   /*- context expiring then rearm timer and try again next event. -*/
   /*---------------------------------------------------------------*/

         if ((vlptinst->flags & (UCHAR)OP_CL_FL_MASK) &&
             (VLPTFlags & (FLAGS)TIMEOUT_IN_PROG) &&
             (nmsLptTimeout != 0))
           {
            VDHArmTimerHook(vlptinst->hhookLptEventContext,nmsLptTimeout,this_VDM);

            return;
           }
        } /* endif */

   /*---------------------------------------------------------------*/
   /*- The data stream is empty, call VDHClose    to close the     -*/
   /*- file handle.                                                -*/
   /*---------------------------------------------------------------*/
      VDHClose(vlptinst->fshandle);

   /*---------------------------------------------------------------*/
   /*- Clear out old PDB and old file handle                       -*/
   /*---------------------------------------------------------------*/
      vlptinst->pdb_spool = INVALID_PDB;
      vlptinst->fshandle = INVALID_HANDLE;

   /*---------------------------------------------------------------*/
   /*- The file handle is closed, now free the memory allocated    -*/
   /*- for the data stream.                                        -*/
   /*---------------------------------------------------------------*/
      if (vlptinst->stream != NULL)
      {
         VDHFreeMem((PVOID)vlptinst->stream);
         vlptinst->stream = NULL;
      }

     } /* endif - OPEN FLAG not set */

   /*---------------------------------------------------------------*/
   /*- Clear the OPEN FLAG for portid.                             -*/
   /*---------------------------------------------------------------*/
   vlptinst->flags &= ~(UCHAR)OPEN_FLAG;

   /*---------------------------------------------------------------*/
   /*- Clear any pending error conditions.                         -*/
   /*---------------------------------------------------------------*/
   vlptinst->flags &= ~(UCHAR)OP_CL_FL_MASK;

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

   return;

  }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doOpenDirect                                        */
/*                                                                       */
/* DESCRIPTIVE NAME: Request exclusive I/O access mode for a parallel    */
/*                   port controller                                     */
/*                                                                       */
/* FUNCTION: Call the VLPT-PLPT interface to request exclusive I/O       */
/*           access mode. If access is granted then disable I/O port     */
/*           trapping for the data/status/control ports. If access is    */
/*           denied then setup for displaying a collision popup to the   */
/*           user.                                                       */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doOpenDirect                                            */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: 0 - direct access granted                                */
/*                                                                       */
/* EXIT-ERROR: !0 - direct access not granted                            */
/*                                                                       */
/* EFFECTS:  Exclusive access flag in the per VDM data area.             */
/*           Direct PDB area of the per VDM data area.                   */
/*                                                                       */
/* INTERNAL REFERENCES:                                                  */
/*    get_direct_access - request direct I/O access                      */
/*    proc_error - processor for errors                                  */
/*                                                                       */
/* EXTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
BOOL PRIVENTRY doOpenDirect(vlptinst)
PVLPTINST vlptinst;
  {
   BOOL ret_code;                           /* return code            */

   /*---------------------------------------------------------------*/
   /*- Call get_direct_access to get direct I/O access for the     -*/
   /*- port associated with vlptinst.                              -*/
   /*---------------------------------------------------------------*/
   if ((get_direct_access(vlptinst)) == 0) {

       ret_code = 0;

   /*---------------------------------------------------------------*/
   /*- If direct I/O access is not granted then setup for          -*/
   /*- displaying a collision popup to the user. This popup        -*/
   /*- requires a substitution string that must be created.        -*/
   /*---------------------------------------------------------------*/
   } else {
       ret_code = (BOOL)proc_error(
                                   vlptinst,
                                   direct_table,
                                   DIRECT_TYPE);

   } /* endif */

   return(ret_code);
  }

/********************** START OF SPECIFICATIONS **************************/
/*                                                                       */
/* SUBROUTINE NAME:  doCloseDirect                                       */
/*                                                                       */
/* DESCRIPTIVE NAME: Release exclusive I/O access mode for a parallel    */
/*                   port controller                                     */
/*                                                                       */
/* FUNCTION: Call the VLPT-PLPT interface to release exclusive I/O       */
/*           access mode.                                                */
/*                                                                       */
/* NOTES:                                                                */
/*                                                                       */
/* CONTEXT: VDM task time                                                */
/*                                                                       */
/* ENTRY POINT:  doCloseDirect                                           */
/*    LINKAGE: CALL NEAR 32                                              */
/*                                                                       */
/* INPUT: (PARAMETERS)  (passed on the stack)                            */
/*        vlptinst - ptr to offset portid of per VDM data area           */
/*                                                                       */
/* EXIT-NORMAL: NONE                                                     */
/*                                                                       */
/* EXIT-ERROR: NONE                                                      */
/*                                                                       */
/* EFFECTS:  Exclusive access flag in the per VDM data area.             */
/*           Direct PDB area of the per VDM data area.                   */
/*                                                                       */
/* INTERNAL REFERENCES: NONE                                             */
/*                                                                       */
/* EXTERNAL REFERENCES:                                                  */
/*    PLPTPDDProc       - VLPT-PLPT interface                            */
/*    VDHSetIOHookState - Enable/Disable I/O port hooking                */
/*                                                                       */
/*********************** END OF SPECIFICATIONS ***************************/
VOID PRIVENTRY doCloseDirect(vlptinst)
PVLPTINST vlptinst;
  {
   /*---------------------------------------------------------------*/
   /*- If the port in question is in direct I/O access mode then   -*/
   /*- call the PDD and release direct I/O access for the port     -*/
   /*- associated with vlptinst. If the release is granted then    -*/
   /*- clear the direct mode flag, clear the direct mode PDB,      -*/
   /*- and enable port hooking for the data and status port.       -*/
   /*- If PLPT is not there then do not call it. Just process      -*/
   /*- the close. This allows direct I/O even when PLPT has been   -*/
   /*- de-installed.                                               -*/
   /*---------------------------------------------------------------*/
   if (vlptinst->flags & (UCHAR)DIRECT_MODE_FLAG) {

      if ((PLPTPDDProc == NULL) || (PLPTPDDProc((ULONG)PLPT_RELEASE_EXCLUSIVE,
                                   (F16PVOID)(ULONG)vlptinst->lptportid,
                                   F16PNULL)) == 0) {

        vlptinst->flags &= ((UCHAR)(~DIRECT_MODE_FLAG));

        vlptinst->pdb_direct = INVALID_PDB;

        VDHSetIOHookState(this_VDM,
                          vpa_table[vlptinst->lptportid].data,
                          1,
                          &v_ioh[((vlptinst->lptportid)*4)].iohtable,
                          (BOOL)TRUE);

        VDHSetIOHookState(this_VDM,
                          vpa_table[vlptinst->lptportid].status,
                          1,
                          &v_ioh[((vlptinst->lptportid)*4)+1].iohtable,
                          (BOOL)TRUE);

        VDHSetIOHookState(this_VDM,
                          vpa_table[vlptinst->lptportid].control,
                          1,
                          &v_ioh[((vlptinst->lptportid)*4)+2].iohtable,
                          (BOOL)TRUE);

      } /* endif */

   } /* endif */

   return;
  }

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  get_direct_access                                */
/*                                                                    */
/* FUNCTION:  Call the PDD and request direct I/O access for the port */
/*            associated with vlptinst. If access is granted then set */
/*            the direct mode flag, save the direct mode PDB, disable */
/*            port hooking for the data/status/control ports, and set */
/*            the return code to indicate a success. If PLPT has been */
/*            de-installed then direct I/O may be mixed with other    */
/*            I/O.                                                    */
/*                                                                    */
/* INPUT:  vlptinst - ptr to offset portid of per VDM data area       */
/*                                                                    */
/* OUTPUT:                                                            */
/*        EXIT-NORMAL: 0 - direct access granted                      */
/*                                                                    */
/*        EXIT-ERROR: !0 - direct access not granted                  */
/*                                                                    */
/* SIDE EFFECTS: Direct mode variables in the per VDM data area       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL PRIVENTRY get_direct_access(vlptinst)
PVLPTINST vlptinst;
  {
   BOOL ret_code;                           /* return code            */

   /*---------------------------------------------------------------*/
   /*- If the PLPT did not give VLPT an entry point to call then   -*/
   /*- direct access mode cannot be requested. Therefore direct    -*/
   /*- mode printing can be mixed with other printing because      -*/
   /*- PLPT is not there to serialize the parallel ports.          -*/
   /*- Call the PDD and request direct I/O access for the port     -*/
   /*- associated with vlptinst. If access is granted then set the -*/
   /*- direct mode flag, save the direct mode PDB, disable port    -*/
   /*- hooking for the data and status port, and set the return    -*/
   /*- code to indicate a success.                                 -*/
   /*---------------------------------------------------------------*/
     if ((PLPTPDDProc) && (PLPTPDDProc((ULONG)PLPT_REQUEST_EXCLUSIVE,
                          (F16PVOID)(ULONG)vlptinst->lptportid,
                           F16PNULL))) {

         ret_code = 1;

     } else {

         vlptinst->flags |= (UCHAR)DIRECT_MODE_FLAG;

         vlptinst->pdb_direct = pdbCurrent;

         VDHSetIOHookState(this_VDM,
                           vpa_table[vlptinst->lptportid].data,
                           1,
                           &v_ioh[((vlptinst->lptportid)*4)].iohtable,
                           (BOOL)FALSE);

         VDHSetIOHookState(this_VDM,
                           vpa_table[vlptinst->lptportid].status,
                           1,
                           &v_ioh[((vlptinst->lptportid)*4)+1].iohtable,
                           (BOOL)FALSE);

         VDHSetIOHookState(this_VDM,
                           vpa_table[vlptinst->lptportid].control,
                           1,
                           &v_ioh[((vlptinst->lptportid)*4)+2].iohtable,
                           (BOOL)FALSE);

         ret_code = 0;

     } /* endif */

   return(ret_code);
  }

#pragma END_SWAP_CODE
