/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Lexmark 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.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = PRDPSTRT
 *
 * DESCRIPTIVE NAME =
 *
 *
 * VERSION
 *
 * DATE
 *
 * DESCRIPTION
 *
 * FUNCTIONS   prdp_InitialiseCOMPort
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define INCL_32                        /* CON3201 */
#define INCL_DOSPROCESS                /* CON3201 */
#define INCL_DOSDEVICES
#define INCL_DOSSEMAPHORES
#define INCL_GREALL
#define INCL_GPIPRIMITIVES
#define INCL_WINHEAP
#define INCL_GPIBITMAPS
#define INCL_GPIERRORS
#define INCL_WINSHELLDATA
#define INCL_WINPOINTERS
#define INCL_SPL
#include <os2.h>
#undef INCL_DOSPROCESS                  /* CON3201 */
#undef INCL_DOSDEVICES
#undef INCL_DOSSEMAPHORES
#undef INCL_GREALL
#undef INCL_GPIPRIMITIVES
#undef INCL_WINHEAP
#undef INCL_GPIBITMAPS
#undef INCL_GPIERRORS
#undef INCL_WINSHELLDATA
#undef INCL_WINPOINTERS
#undef INCL_SPL

#define INCL_DDIBUNDLES
#define INCL_DDIFONTSTRUCS
#define INCL_DDIDEFS
#include <pmddi.h>
#undef INCL_DDIBUNDLES
#undef INCL_DDIFONTSTRUCS
#undef INCL_DDIDEFS

#define INCL_WINP_SELSERVER
#define INCL_WINP_SELECTIVE
#define INCL_WINP_SEI
#include <pmwinx.h>
#undef INCL_WINP_SELSERVER
#undef INCL_WINP_SELECTIVE
#undef INCL_WINP_SEI
#undef INCL_32                         /* CON3201 */

#include <prdconse.h>

#define PRDMTYPE_INCL
#define NO_CONSTANT_INCL
#include <prdinclt.h>
#undef NO_CONSTANT_INCL
#undef PRDMTYPE_INCL

#include <prdeextf.h>
#include <prdgextf.h>
#include <prdnextf.h>
#include <prdpextf.h>
#include <prdyextf.h>

extern HMODULE         prdd_ModHandle;




/**********************************************************************/
/*                                                                    */
/*   FUNCTION: prdp_InitialiseCOMPort                                 */
/*                                                                    */
/*   PARAMETERS:                                                      */
/*                                                                    */
/*   PSZ           LogicalAddress;     port logical address string    */
/*   unsigned      Handle;             printer handle from PrtOpen    */
/*                                                                    */
/*   DESCRIPTION:                                                     */
/*                                                                    */
/*   This function is called when output is to a serial printer       */
/*   attached to COM1, COM2, or COM3. The port options are read from  */
/*   os2.ini, converted to binary data and sent to the port device    */
/*   driver.                                                          */
/*   Format of an os2.ini entry for a COM port is                     */
/*   COMx=baud rate;parity;word length;stop bits;handshaking;         */
/**********************************************************************/
/* CON3201
USHORT  prdp_InitialiseCOMPort ( LogicalAddress,
                                     Handle )
*/
/* CON3203 CHANGED USHORT TO SHORT */
SHORT  prdp_InitialiseCOMPort ( PSZ        LogicalAddress,
                                HMODULE    Handle)




{
#define TFUNC "prdp_InitCOMPrt"

    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
/*  USHORT   IniSize;             Size of os2.ini entry   CON3201     */
    ULONG    IniSize;          /* Size of os2.ini entry               */
    /*USHORT   DosResult;         DOS return code         CON3201     */
    ULONG    DosResult;
    PBYTE    IniBuffer;        /* Copy of the OS2.INI entry for the   */
                               /* driver                              */
    USHORT   BitRate;          /* Bit rate parameter to PrtDevIOCtl   */
    BYTE     DataParityStop[3];/* Parameter to PrtDevIOCtl for        */
                               /* Setting data, parity and stop bits  */
    struct
    {
        USHORT WriteTimeout;
        USHORT ReadTimeout;
        BYTE Flags1;
        BYTE Flags2;
        BYTE Flags3;
        BYTE ErrorReplacementCharacter;
        BYTE BreakReplacementCharacter;
        BYTE XONCharacter;
        BYTE XOFFCharacter;
    }DeviceControlBlock;

    TRACE8(TFUNC, "Entry", FNULL, 0);

    /******************************************************************/
    /* Find out the size of the entry in OS2.INI for the spooler      */
    /* port data                                                      */
    /******************************************************************/
/* CON3201 ********************************************************************/
/* WinQueryProfileSize is no loner supported, use Prf call                    */
/*  if (TRUE)      @@@ use Win, not Prf call                                  */
/*  {                                                                         */
/*      if ( WinQueryProfileSize (  hab , (PSZ)"PM_SPOOLER_PORT" ,            */
/*                        LogicalAddress, (PUSHORT)&IniSize) )                */
/*         return(ERROR_NEG);                                                 */
/*  }                                                                         */
/*  else                                                                      */
/*  {                                                                         */
/*      if ( !PrfQueryProfileSize ( HINI_SYSTEMPROFILE,                       */
/*                                 (PSZ)"PM_SPOOLER_PORT" ,                   */
/*                                 LogicalAddress,                            */
/*                                 (PULONG)&IniSize) )                        */
/*          return(ERROR_NEG);                                                */
/*  }                                                                         */
/******************************************************************************/
/* CON3201 ********************************************************************/
/* WinQueryProfilSize is no longer supported so we will use the Prf function  */
/******************************************************************************/
        if ( !PrfQueryProfileSize ( HINI_SYSTEMPROFILE,
                                   (PSZ)"PM_SPOOLER_PORT" ,
                                   LogicalAddress,
                                   (PULONG)&IniSize) )
            return(ERROR_NEG);
    TRACE4(TFUNC, "Ini Port size", &IniSize, 1);

    /******************************************************************/
    /* Get hold of a segment to store our copy of the data from       */
    /* the OS2.INI file.                                              */
    /******************************************************************/
/*  OFFSETOF(IniBuffer) = NULL;      CON3201 */
/*  if ( (DosResult = SSALLOCSEG (IniSize, &SELECTOROF(IniBuffer), 0))      */
/*                                                           != DOS_OK )    */
    if ( (DosResult = SafeSSALLOCMEM (&IniBuffer, IniSize,  0))
                                                             != DOS_OK )
    {
        LOGDOSERR(TFUNC, "SSALLOCMEM Fail", &DosResult, 1, DosResult);
        return(ERROR_ZERO);
    }

    /******************************************************************/
    /* Read data from OS2.INI and store in the buffer.                */
    /******************************************************************/
/* CON3201 ************************************************************/
/* WinQeryProfileData is no longer supported, use the Prf call        */
/*  if (TRUE)      @@@ use Win, not Prf call                          */
/*  {                                                                 */
/*      if ( WinQueryProfileData( hab,                                */
/*                            (PSZ)"PM_SPOOLER_PORT",                 */
/*                            LogicalAddress,                         */
/*                            (PVOID)IniBuffer,                       */
/*                            (PUSHORT)&IniSize ) != OK )             */
/*      {                                                             */
/*          SSFREESEG(SELECTOROF(IniBuffer));                         */
/*          return(ERROR_NEG);                                        */
/*      }                                                             */
/*  }                                                                 */
/*  else                                                              */
/*  {                                                                 */
/*      if ( PrfQueryProfileData( HINI_SYSTEMPROFILE,                 */
/*                            (PSZ)"PM_SPOOLER_PORT",                 */
/*                            LogicalAddress,                         */
/*                            (PVOID)IniBuffer,                       */
/*                            (PULONG)&IniSize ) != OK )              */
/*      {                                                             */
/*          SSFREESEG(SELECTOROF(IniBuffer));                         */
/*          return(ERROR_NEG);                                        */
/*      }                                                             */
/*  }                                                                 */
/**********************************************************************/

        if ( PrfQueryProfileData( HINI_SYSTEMPROFILE,
                              (PSZ)"PM_SPOOLER_PORT",
                              LogicalAddress,
                              (PVOID)IniBuffer,
                              (PULONG)&IniSize ) != OK )
        {
            SSFREEMEM(IniBuffer);
            return(ERROR_NEG);
        }

    TRACE4(TFUNC, "Spool port data", IniBuffer, (IniSize / 4));

    /******************************************************************/
    /* if there is an entry for baud rate then convert it from ASCII  */
    /* to binary otherwise use the default of 1200                    */
    /* there is no entry if the next character in the buffer is a     */
    /* semicolon                                                      */
    /******************************************************************/
    if (*IniBuffer == ';')
        BitRate = 1200;
    else
        for (BitRate = 0;
             *IniBuffer != ';';
             BitRate = BitRate * 10 + *IniBuffer++ - '0');
    TRACE4(TFUNC, "Bit rate", FNULL, 0);

    /******************************************************************/
    /* issue PrtDevIOCtl category 1 function 0x41 to set the baud rate*/
    /******************************************************************/
    TRACE4(TFUNC, "Set baud rate", FNULL, 0);
    if ( (DosResult = PrtDevIOCtl(FNULL, (char *)&BitRate, 0x41, 1,
                                                     Handle)) != DOS_OK)
    {
        LOGDOSERR(TFUNC, "Fail Set BitRate", &DosResult, 1, DosResult);
     /* SSFREESEG(SELECTOROF(IniBuffer));                      CON3201 */
        SSFREEMEM(IniBuffer);
        return(ERROR_NEG);
    }


    /******************************************************************/
    /* if there is an entry for parity then convert it from           */
    /* ASCII to binary otherwise use the default of 0 (no parity)     */
    /* there is no entry if the next character in the buffer is a     */
    /* semicolon                                                      */
    /******************************************************************/
    if (*(++IniBuffer) == ';')
        DataParityStop[1] = 0;
    else
        DataParityStop[1] = *IniBuffer++ - '0';

    /******************************************************************/
    /* if there is an entry for word length then convert it from      */
    /* ASCII to binary otherwise use the default of 8                 */
    /* there is no entry if the next character in the buffer is a     */
    /* semicolon                                                      */
    /******************************************************************/
    if (*(++IniBuffer) == ';')
        *DataParityStop = 8;
    else
        *DataParityStop = *IniBuffer++ - '0';

    /******************************************************************/
    /* if there is an entry for stop bits then convert it from        */
    /* ASCII to binary otherwise use the default of 0 (1 stop bit)    */
    /* there is no entry if the next character in the buffer is a     */
    /* semicolon                                                      */
    /******************************************************************/
    if (*(++IniBuffer) == ';')
        DataParityStop[2] = 0;
    else
        /**************************************************************/
        /* stop bits entry may be 1, 1.5 or 2. To set these values,   */
        /* PrtDevIOCtl requires values of 0, 1 and 2 respectively     */
        /**************************************************************/
        if (IniBuffer[1] == '.')
        {
            DataParityStop[2] = 1;
            IniBuffer += 3;
        }
        else
            if (*IniBuffer++ == '1')
                DataParityStop[2] = 0;
            else
                DataParityStop[2] = 2;
    TRACE4(TFUNC, "Data par stop", DataParityStop, 1);

    /******************************************************************/
    /* issue PrtDevIOCtl category 1 function 0x42 to set the data     */
    /* bits, parity and stop bits                                     */
    /******************************************************************/
    if ( (DosResult = PrtDevIOCtl(FNULL, (char *)DataParityStop,
                                            0x42, 1, Handle)) != DOS_OK)
    {
        LOGDOSERR(TFUNC, "Fail DataParityStop", &DosResult, 1,
                                                             DosResult);
     /* SSFREESEG(SELECTOROF(IniBuffer));                     CON3201 */
        SSFREEMEM(IniBuffer);
        return(ERROR_NEG);
    }

    /******************************************************************/
    /* get the current Device Control Block via PrtDevIOCtl category  */
    /* 1 function 73                                                  */
    /******************************************************************/
    TRACE4(TFUNC, "Get DCB", FNULL, 0);
    if ( (DosResult = PrtDevIOCtl((char *)&DeviceControlBlock,
                                     FNULL, 0x73, 1, Handle)) != DOS_OK)
    {
        LOGDOSERR(TFUNC, "Fail Get DCB", &DosResult, 1, DosResult);
     /* SSFREESEG(SELECTOROF(IniBuffer));                      CON3201 */
        SSFREEMEM(IniBuffer);
        return(ERROR_NEG);
    }

    /******************************************************************/
    /* the output handshaking is controlled by bits 3, 4 and 5 of the */
    /* control block flags1, and bit 0 of flags2                      */
    /* there is no entry if the next character in the buffer is a     */
    /* semicolon                                                      */
    /* a 0 entry indicates no handshaking, 1 indicates hardware       */
    /* handshaking                                                    */
    /******************************************************************/
    if ( (*(++IniBuffer) == ';') || (*IniBuffer == '0') )
    {
        TRACE4(TFUNC, "No handshaking", FNULL, 0);
        DeviceControlBlock.Flags1 &= 0xc7;
        DeviceControlBlock.Flags2 |= 0x01;
    }
    else
    {
        TRACE4(TFUNC, "handshaking", FNULL, 0);
        DeviceControlBlock.Flags1 = (DeviceControlBlock.Flags1 & 0xdf) |
                                                                   0x18;
        DeviceControlBlock.Flags2 &= 0xfe;
    }

    /******************************************************************/
    /* free the inibuffer memory                                      */
    /******************************************************************/
/*  SSFREESEG(SELECTOROF(IniBuffer));                         CON3201 */
    SSFREEMEM(IniBuffer);

    /******************************************************************/
    /* having updated the flags1 field in the device control block,   */
    /* set this with PrtDevIOCtl category 1 function 53               */
    /******************************************************************/
    TRACE4(TFUNC, "Set DCB", FNULL, 0);
    if ( (DosResult = PrtDevIOCtl(FNULL,
           (char *)&DeviceControlBlock, 0x53, 1, Handle)) != DOS_OK)
    {
        LOGDOSERR(TFUNC, "Fail Set DCB", &DosResult, 1, DosResult);
        return(ERROR_NEG);
    }

    TRACE8(TFUNC, "Exit", FNULL, 0);
    return(OK);

} /* prdp_InitialiseCOMPort */

#undef TFUNC

