/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/*static char *SCCSID = "@(#)vlpti17.c  6.1 90/11/19";*/
/* static char *SCCSID = "@(#) @(#)vlpti17.c  6.8 90/01/24"; */
#pragma linesize(132)
#pragma pagesize(60)
#pragma title("VLPTI17.C")
/****************************************************************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  VLPTI17.C                                             */
/*                                                                            */
/*   DESCRIPTIVE NAME:  VDM interrupt 17H handler                             */
/*                                                                            */
/*   FUNCTION: These routines service the VDM software interrupt 17H.         */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: Spooler is running                                      */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             VLPTInt17    - VDM interrupt 17H handler                       */
/*             VLPTI17Print - Interrupt 17H print function subroutine         */
/*             VLPTI17Init  - Interrupt 17H initialize function subroutine    */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*             VDHPopInt - Remove interrupt frame from client's stack         */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

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


#pragma BEGIN_SWAP_CODE

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTINT17                                        */
/*                                                                    */
/* DESCRIPTIVE NAME:  Virtual LPT Interrupt 17H Handler               */
/*                                                                    */
/* FUNCTION:  The function of this routine is to service the VDM      */
/*            software interrupt 17h. This routine validates the input*/
/*            parameters and calls the appropriate routine to handle  */
/*            the request.                                            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTInt17                                            */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  (PARAMETERS)  (passed on the stack)                        */
/*         pcrf     -    client register frame pointer                */
/*                                                                    */
/* EXIT-NORMAL:  returns TRUE for no VDD chaining                     */
/*               virtual status put in AH of client register frame    */
/*                                                                    */
/* EXIT-ERROR:  returns TRUE for no VDD chaining                      */
/*              AH of client register frame unchanged                 */
/*                                                                    */
/* EFFECTS: AH of CRF will equal status if successful                 */
/*                                                                    */
/* INTERNAL REFERENCES:  VLPTI17Print                                 */
/*                       VLPTI17Init                                  */
/*                       doCheck                                      */
/*                       chk_offset                                   */
/*                       fixup_status                                 */
/*                                                                    */
/* EXTERNAL REFERENCES:  VDHPopInt                                    */
/*                       VDHArmTimerHook                              */
/*                       VDHDisarmTimerHook                           */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL HOOKENTRY VLPTInt17(pcrf)
PCRF pcrf;
{
    UINT port_id;                  /* port id                        */
    INT penderror;                 /* pending error flag             */
    INT rc;                        /* return code                    */

    rc = TRUE;               /* set return code for no VDD chaining  */
    penderror = 1;           /* initialize pending error to error    */
    port_id = DX(pcrf);      /* make working copy of port id,        */
                             /* port id is passed in DX of CRF       */

#ifdef DEBUG
   vdhInt3();
#endif
    /*---------------------------------------------------------------*/
    /*- If the passed in port id is 0, 1, or 2 then continue        -*/
    /*- servicing the interrupt, otherwise return with return code  -*/
    /*- for no VDD chaining.                                        -*/
    /*---------------------------------------------------------------*/
        if ( port_id <= 2 ) {

    /*---------------------------------------------------------------*/
    /*- Make sure that port_id is still the offset of the correct   -*/
    /*- port address. This check is done by calling chk_offset. If  -*/
    /*- for some reason the user has changed the order of the       -*/
    /*- parallel port addresses in the VDMs 40:08 area then         -*/
    /*- chk_offset will return the correct offset into the VLPT     -*/
    /*- port address table.                                         -*/
    /*---------------------------------------------------------------*/
            if ((port_id = chk_offset(port_id))<(MAXPRTS+1)) {

    /*---------------------------------------------------------------*/
    /*- If the OPEN error, CLOSE error, or FLUSH error are not set  -*/
    /*- then set pending error to no error. Else, call doCheck to   -*/
    /*- clear the pending error.                                    -*/
    /*---------------------------------------------------------------*/
                if (!(pvd_area[port_id].flags & (BYTE)OP_CL_FL_MASK)) {
                    penderror = 0;             /* set pending error  */
                } else {                       /*  to no error       */
                    doCheck(&pvd_area[port_id]); /* call doCheck     */

    /*---------------------------------------------------------------*/
    /*- If the OPEN error, CLOSE error, or FLUSH error are not set  -*/
    /*- then set pending error to no error.                         -*/
    /*---------------------------------------------------------------*/
                    if (!(pvd_area[port_id].flags & (BYTE)OP_CL_FL_MASK)) {
                        penderror = 0;         /* set pending error  */
                    } /* endif */              /*  to no error       */

                } /* endif */

    /*---------------------------------------------------------------*/
    /*- Evaluate the function passed with the interrupt and take the-*/
    /*- correct action. If the function passed is not valid then    -*/
    /*- return with return code set for no VDD chaining.            -*/
    /*---------------------------------------------------------------*/
                    switch ( AH(pcrf) ) {       /* get the function  */
                                                /*  number from CRF  */
                    case (UINT)0:               /* send character    */
                        if ( penderror == 0 )   /* if no error       */
                            VLPTI17Print(&pvd_area[port_id], pcrf);

                        AH(pcrf) = (fixup_status(pvd_area[port_id].status));

                        if ((pvd_area[port_id].flags & (BYTE)OP_CL_FL_MASK) != 0)
                            AH(pcrf) |= TIME_OUT;
                        break;

                    case (UINT)1:               /* initialize device */
                        if ( penderror == 0 )   /* if no error       */
                            VLPTI17Init(&pvd_area[port_id]);

                        AH(pcrf) = (fixup_status(pvd_area[port_id].status));
                        break;

                    case (UINT)2:               /* return status     */
                        if (pvd_area[port_id].hhookLptEventContext)
                          VDHDisarmTimerHook(pvd_area[port_id].hhookLptEventContext);

                        AH(pcrf) = (fixup_status(pvd_area[port_id].status));

                        if (nmsLptTimeout != 0)
                           VDHArmTimerHook(pvd_area[port_id].hhookLptEventContext,nmsLptTimeout,this_VDM);

                        break;

                    default:               /* function out of range  */
                        break;

                    } /* endswitch */

            } /* endif */          /* no match found                 */

        } /* endif */              /* port id out of range           */

    /*---------------------------------------------------------------*/
    /*- Cause the Int 17 ROM routine not to be executed upon return.-*/
    /*---------------------------------------------------------------*/
        VDHPopInt();

return (rc);                       /* return with no VDD chaining    */
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  fixup_status                                     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to mask off bits in the */
/*            status flags and flip some bits. This is done to be     */
/*            compatible with CBIOS INT17 code.                       */
/*                                                                    */
/* INPUT:  inflag - byte of status flags                              */
/*                                                                    */
/* OUTPUT: inflag - fixed up byte of status flags                     */
/*                                                                    */
/* SIDE EFFECTS: NONE                                                 */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BYTE PRIVENTRY fixup_status(inflag)
BYTE inflag;                       /* flag manipulation area         */
{
    /*---------------------------------------------------------------*/
    /*- Mask off unused bits of input byte                          -*/
    /*---------------------------------------------------------------*/
    inflag &= STATUS_MASK;

    /*---------------------------------------------------------------*/
    /*- Flip the BUSY and SLCT bits of input byte                   -*/
    /*---------------------------------------------------------------*/
    inflag ^= STATUS_REV;

    return(inflag);                /* return processed input byte    */
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  chk_offset                                       */
/*                                                                    */
/* FUNCTION:  The function of this routine is to compare a parallel   */
/*            port address from the VDMs 40:08 with the addresses in  */
/*            the VLPT port address table. This comparison in done    */
/*            to make up for an application that might have changed   */
/*            the parallel port addresses in the local bios data area.*/
/*                                                                    */
/* INPUT:  portoffset - the offset of the port address in question    */
/*                                                                    */
/* OUTPUT: portoffset - the offset of the port address in the VLPT    */
/*                      port address table, if an address match is    */
/*                      not found then the maximum number of parallel */
/*                      ports plus one will be returned.              */
/*                                                                    */
/* SIDE EFFECTS: NONE                                                 */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
UINT PRIVENTRY chk_offset(portoffset)
UINT portoffset;             /* port offset of parallel port address */
{
    USHORT offset_address;   /* port offset address holding area     */
    UINT k;                  /* counter                              */
    INT found;               /* found flag                           */

    /*---------------------------------------------------------------*/
    /*- Copy the base printer port address in the current VDMs bios -*/
    /*- data area at an offset of portoffset into offset_address.   -*/
    /*---------------------------------------------------------------*/
    offset_address = VDMBase.rb_awLPT[portoffset];
    found = FALSE;                 /* set found to not found         */
    k = 0;                         /* initialize counter             */

    /*---------------------------------------------------------------*/
    /*- Loop through the VLPT port address table looking for an     -*/
    /*- address that matches the one from the VDM bios data area.   -*/
    /*- This is done to make sure the correct device is used even   -*/
    /*- if the application has changed the addresses in the VDMs    -*/
    /*- bios data area.                                             -*/
    /*---------------------------------------------------------------*/
    while ( (k<=2) && (found == FALSE )) {

    /*---------------------------------------------------------------*/
    /*- If an address match is found then set the found flag,       -*/
    /*- otherwise increment the counter to look at the next entry.  -*/
    /*---------------------------------------------------------------*/
        if ( offset_address == vpa_table[k].data ) {

            found = TRUE;  /* set found to not found         */

        } else {

            ++k;         /* increment to next entry in table */

        } /* endif */

    } /* endwhile */

    /*---------------------------------------------------------------*/
    /*- If a port address match was found then set up the return to -*/
    /*- be the offset that the matching address was found at.       -*/
    /*- Otherwise, return the matching address not found value of   -*/
    /*- MAXPRTS plus one.                                           -*/
    /*---------------------------------------------------------------*/
    if ( found == TRUE ) {

        portoffset = k;

    } else {

        portoffset = MAXPRTS + 1;

    } /* endif */

    return(portoffset);       /* port offset of parallel port address */
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTI17PRINT                                     */
/*                                                                    */
/* DESCRIPTIVE NAME:  Virtual LPT Interrupt 17H Print Routine         */
/*                                                                    */
/* FUNCTION:  The function of this routine is to service the VDM      */
/*            software interrupt 17h print requests.                  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTI17PRINT                                         */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  (PARAMETERS)  (passed on the stack)                        */
/*         vlptinst - ptr to offset portid of the per VDM data area   */
/*         pcrf     - client register frame pointer                   */
/*                                                                    */
/* Client's Registers VLPTI17PRINT is interested in:                  */
/*                                                                    */
/*     AL = character to write                                        */
/*                                                                    */
/* EXIT-NORMAL:  NONE                                                 */
/*                                                                    */
/* EXIT-ERROR:  NONE                                                  */
/*                                                                    */
/* EFFECTS:  Virtual data port.                                       */
/*                                                                    */
/* INTERNAL REFERENCES:  doCloseSpool                                 */
/*                       doOpenSpool                                  */
/*                       doWrite                                      */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID PRIVENTRY VLPTI17Print(vlptinst, pcrf)
PVLPTINST vlptinst;
PCRF pcrf;
{
    /*---------------------------------------------------------------*/
    /*- If the device is not open then open it                      -*/
    /*---------------------------------------------------------------*/
    if (!(vlptinst->flags & OPEN_FLAG)) {
        doOpenSpool(vlptinst);     /* call doOpenSpool               */

    /*---------------------------------------------------------------*/
    /*- If the device is already open then check to see if the      -*/
    /*- PDB associated with the device is the same as the current   -*/
    /*- PDB. If they are not the same then close the device and     -*/
    /*- reopen it under the current PDB. This close and open is     -*/
    /*- done if PRINT_SEPARATE_OUTPUT is set(default).              -*/
    /*---------------------------------------------------------------*/
    } else {
       if (VLPTFlags & LPTINT17SEP) {
         if (pdbCurrent != (vlptinst->pdb_spool)) {
             doCloseSpool(vlptinst);
             doOpenSpool(vlptinst);
         } /* endif */
       } /* endif */
    } /* endif */

    /*---------------------------------------------------------------*/
    /*- If an open error does not exist for the passed device, then -*/
    /*- put the byte to print into the virtual data port and call   -*/
    /*- doWrite to put it in the device print stream.               -*/
    /*---------------------------------------------------------------*/
    if (!(vlptinst->flags & (BYTE)OPEN_ERROR_FLAG)) {
        vlptinst->data = AL(pcrf);
        doWrite(vlptinst);
    } /* endif */

    return ;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTI17INIT                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Virtual LPT Interrupt 17H Initialize Routine    */
/*                                                                    */
/* FUNCTION:  The function of this routine is to service the VDM      */
/*            software interrupt 17h initialize port requests.        */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTI17INIT                                          */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  (PARAMETERS)  (passed on the stack)                        */
/*         vlptinst - ptr to offset portid of the per VDM data area   */
/*                                                                    */
/* EXIT-NORMAL:  NONE                                                 */
/*                                                                    */
/* EXIT-ERROR:  NONE                                                  */
/*                                                                    */
/* EFFECTS:  init flag in the per VDM data area                       */
/*                                                                    */
/* INTERNAL REFERENCES:  doCloseSpool                                 */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID PRIVENTRY VLPTI17Init(vlptinst)
PVLPTINST vlptinst;
{
    /*---------------------------------------------------------------*/
    /*- Set the INIT flag in per VDM data area flags so VLPT can    -*/
    /*- tell where the doCloseSpool comes from.                     -*/
    /*---------------------------------------------------------------*/
    vlptinst->flags |= INIT_FLAG;

    doCloseSpool(vlptinst); /* call doCloseSpool to initialize device*/

    return ;
}


#pragma END_SWAP_CODE
