/* SCCSID = "src/dev/usb/COM/COMIOCTL.C, usb, c.basedd 98/10/26" */
/*
*   Licensed Material -- Property of IBM
*
*   (c) Copyright IBM Corp. 1998  All Rights Reserved
*/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  COMIOCTL.C                                            */
/*                                                                            */
/*   DESCRIPTIVE NAME:  USB Communication Device Class Driver IOCtl routines  */
/*                                                                            */
/*   FUNCTION: These routines handle the task time IOCtl commands to          */
/*             the USB Communication Device Class Driver.                     */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             COMIOCtl                                                       */
/*             FuncError                                                      */
/*             SetBitRate                                                     */
/*             SetLine                                                        */
/*             SetBitRateExt                                                  */
/*             TransmitImm                                                    */
/*             SetBreakOff                                                    */
/*             SetMdmCtrl                                                     */
/*             StopTransmit                                                   */
/*             StartTransmit                                                  */
/*             SetBreakOn                                                     */
/*             SetDCB                                                         */
/*             GetBitRate                                                     */
/*             GetLine                                                        */
/*             GetBitRateExt                                                  */
/*             GetStatus                                                      */
/*             GetTxStatus                                                    */
/*             GetModemOutput                                                 */
/*             GetModemInput                                                  */
/*             GetInQueue                                                     */
/*             GetOutQueue                                                    */
/*             GetError                                                       */
/*             GetEvent                                                       */
/*             GetDCB                                                         */
/*             GetEnhMode                                                     */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          98/10/26  LR                                                      */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include "usbcom.h"
#include <bsedev.h>

static USHORT VerifyData (PRP_GENIOCTL pRPIOCtl, USHORT datalength);
static USHORT VerifyParam (PRP_GENIOCTL pRPIOCtl, USHORT packetlength);

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  COMIOCtl                                         */
/*                                                                    */
/* DESCRIPTIVE NAME: IOCtl entry point                                */
/*                   for the USB Communication Device Class Driver    */
/*                                                                    */
/* FUNCTION:   The function of this routine is to call appropriate    */
/*             worker routine to process the IOCtl command.           */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  COMIOCtl                                             */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  es:bx -> kernel request packet                             */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  FuncError                                    */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void COMIOCtl (PRPH pRP)
{
   UCHAR function = ((PRP_GENIOCTL)pRP)->Function;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: IOCtl F = 0x%x\r\n", function);
#endif

   if (((PRP_GENIOCTL)pRP)->Category != COM_IOCTL_CAT)
   {
      ((PRP_GENIOCTL)pRP)->rph.Status = STDON | STERR | ERROR_I24_BAD_COMMAND;

#ifdef DEBUG
      dsPrint1 (DBG_CRITICAL, "USBCOM: Unknown IOCtl Category = 0x%x\r\n",
                ((PRP_GENIOCTL)pRP)->Category);
#endif
   }
   else
   {
      if (function < MIN_IOCTL_FUNC || function > MAX_IOCTL_FUNC) FuncError ((PRP_GENIOCTL)pRP);
      else (*gFuncList[function-MIN_IOCTL_FUNC])((PRP_GENIOCTL)pRP);
   }
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  FuncError                                        */
/*                                                                    */
/* DESCRIPTIVE NAME:  IOCtl Function not supported in the driver      */
/*                                                                    */
/* FUNCTION:  The function of this routine is to return               */
/*            IOCtl function not supported for the request.           */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  FuncError                                            */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void FuncError (PRP_GENIOCTL pRPIOCtl)
{
#ifdef DEBUG
   dsPrint1 (DBG_CRITICAL, "USBCOM: Unknown IOCtl Function = 0x%x\r\n",
             pRPIOCtl->Function);
#endif

   pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_BAD_COMMAND;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetBitRate                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set bit rate                                    */
/*                                                                    */
/* FUNCTION:  This function sets the bit rate.                        */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetBitRate                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SetLineCoding                                */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetBitRate (PRP_GENIOCTL pRPIOCtl)
{
   USHORT bitrate;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, sizeof(USHORT)) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   bitrate = *(PUSHORT)pRPIOCtl->ParmPacket;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: SetBitRate = %d\r\n", bitrate);
#endif

   if ((ULONG)bitrate < gCOM.dwMinDTERate ||
       (ULONG)bitrate > gCOM.dwMaxDTERate ||
       bitrate > MAX_BITRATE_WORD)
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      return;
   }
   if (gCOM.line.dwDTERate != bitrate)
   {
      if (gCOM.bMSR & MSR_DCD) pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      else
      {
         gCOM.prevline.dwDTERate = gCOM.line.dwDTERate;
         gCOM.line.dwDTERate = bitrate;
         if (gCOM.iModem < MAX_MDMS)
         {
            SetLineCoding();
            if (DevHelp_ProcBlock ((ULONG)(PUCHAR)&gCOM.line, SET_LINE_CODING_TO,
                                   WAIT_IS_INTERRUPTABLE) == WAIT_TIMED_OUT)
               gCOM.line.dwDTERate = gCOM.prevline.dwDTERate;
         }
      }
   }
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetLine                                          */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set line characteristics                        */
/*                                                                    */
/* FUNCTION:  This function sets the line characteristics.            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetLine                                              */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SetLineCoding                                */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetLine (PRP_GENIOCTL pRPIOCtl)
{
   PLINECONTROL pLine;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 3) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pLine = (PLINECONTROL)pRPIOCtl->ParmPacket;

#ifdef DEBUG
   dsPrint3 (DBG_HLVLFLOW, "USBCOM: SetLine Bits = %d, Parity = %d, Stop = %d\r\n",
             pLine->bDataBits, pLine->bParity, pLine->bStopBits);
#endif
   if (!gCOM.bValidLineInit ||
       !gCOM.bValidLine[pLine->bStopBits][pLine->bParity][pLine->bDataBits-MIN_DATABITS])
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      return;
   }
   if (gCOM.line.bDataBits   != pLine->bDataBits ||
       gCOM.line.bParityType != pLine->bParity   ||
       gCOM.line.bCharFormat != pLine->bStopBits)
   {
      if (gCOM.bMSR & MSR_DCD) pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      else
      {
         gCOM.prevline.bDataBits   = gCOM.line.bDataBits;
         gCOM.prevline.bParityType = gCOM.line.bParityType;
         gCOM.prevline.bCharFormat = gCOM.line.bCharFormat;
         gCOM.line.bDataBits   = pLine->bDataBits;
         gCOM.line.bParityType = pLine->bParity;
         gCOM.line.bCharFormat = pLine->bStopBits;
         if (gCOM.iModem < MAX_MDMS)
         {
            SetLineCoding();
            if (DevHelp_ProcBlock ((ULONG)(PUCHAR)&gCOM.line, SET_LINE_CODING_TO,
                                   WAIT_IS_INTERRUPTABLE) == WAIT_TIMED_OUT)
            {
               gCOM.line.bDataBits   = gCOM.prevline.bDataBits;
               gCOM.line.bParityType = gCOM.prevline.bParityType;
               gCOM.line.bCharFormat = gCOM.prevline.bCharFormat;
            }
         }
      }
   }
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetBitRateExt                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Extended set bit rate                           */
/*                                                                    */
/* FUNCTION:  This function sets the bit rate in doubleword.          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetBitRateExt                                        */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SetLineCoding                                */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetBitRateExt (PRP_GENIOCTL pRPIOCtl)
{
   ULONG bitrate;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, sizeof(ULONG)) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   bitrate = *(PULONG)pRPIOCtl->ParmPacket;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: SetBitRateExt = %ld\r\n", bitrate);
#endif

   if (bitrate < gCOM.dwMinDTERate || bitrate > gCOM.dwMaxDTERate)
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      return;
   }
   if (gCOM.line.dwDTERate != bitrate)
   {
      if (gCOM.bMSR & MSR_DCD) pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
      else
      {
         gCOM.prevline.dwDTERate = gCOM.line.dwDTERate;
         gCOM.line.dwDTERate = bitrate;  
         if (gCOM.iModem < MAX_MDMS)
         {
            SetLineCoding();
            if (DevHelp_ProcBlock ((ULONG)(PUCHAR)&gCOM.line, SET_LINE_CODING_TO,
                                   WAIT_IS_INTERRUPTABLE) == WAIT_TIMED_OUT)
               gCOM.line.dwDTERate = gCOM.prevline.dwDTERate;
         }
      }
   }
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  TransmitImm                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Transmit byte immediate                         */
/*                                                                    */
/* FUNCTION:  This function tansmits byte immediate.                  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  TransmitImm                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SendByte                                     */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void TransmitImm (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (gCOM.iModem >= MAX_MDMS)
   {
      pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_NOT_READY;
      return;
   }
   if (VerifyParam (pRPIOCtl, sizeof(UCHAR)) || VerifyData (pRPIOCtl, 0) ||
       gCOM.bTxBreak || gCOM.wDataToggle & SEND_BYTE_INPROGRESS)
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   gCOM.bTxImm = *(PUCHAR)pRPIOCtl->ParmPacket;
   gCOM.wDataToggle |= SEND_BYTE_INPROGRESS;
   if (!(gCOM.wDataToggle & SEND_DATA_INPROGRESS)) SendByte (&gCOM.bTxImm, COM_IRQ_SENDBYTE);

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: TransmitImm = 0x%x\r\n", gCOM.bTxImm);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetBreakOff                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set break off                                   */
/*                                                                    */
/* FUNCTION:  This function sets the break off.                       */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetBreakOff                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SendBreak                                    */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetBreakOff (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (gCOM.iModem >= MAX_MDMS)
   {
      pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_NOT_READY;
      return;
   }
   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(USHORT)) ||
       !(gMDM[gCOM.iModem].acmCapabilities & SEND_BREAK_SUPPORT))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: SetBreakOff\r\n");
#endif

   gCOM.bTxBreak = TURNOFF;
   SendBreak (SEND_BREAK_OFF, COM_IRQ_BREAKOFF);

   *(PUSHORT)pRPIOCtl->DataPacket = gCOM.wError;
   // This function does not reset any bits in the Error word
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetMdmCtrl                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set modem control signals                       */
/*                                                                    */
/* FUNCTION:  This function sets the modem control signals.           */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetMdmCtrl                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SetSignals                                   */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetMdmCtrl (PRP_GENIOCTL pRPIOCtl)
{
   PMODEMSTATUS pMask;
   UCHAR        signals;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, sizeof(MODEMSTATUS)) || VerifyData (pRPIOCtl, sizeof(USHORT)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pMask = (PMODEMSTATUS)pRPIOCtl->ParmPacket;

#ifdef DEBUG
   dsPrint2 (DBG_HLVLFLOW, "USBCOM: SetMdmCtrl = 0x%x, 0x%x\r\n",
             pMask->fbModemOn, pMask->fbModemOff);
#endif
/*
   The setting of bit 0 affects DTR and the setting of bit 1 affects RTS.
   Ones in the "on mask" specifies which of the two signals are to be turned on, and
   zeros in the "off mask" specify which of the two signals are to be turned off.
*/
   signals = (UCHAR)(~pMask->fbModemOff | pMask->fbModemOn);
   if ((signals & ~(MCR_DTR | MCR_RTS)) || // trying to set reserved fields
       (signals & MCR_DTR && (gCOM.dcb.bmF1 & F1_DTR_MASK) == F1_DTR_FLOW) || // DTR input handshaking
       (signals & MCR_RTS &&
        ((gCOM.dcb.bmF2 & F2_RTS_MASK) == F2_RTS_FLOW) || // RTS input handshaking
         (gCOM.dcb.bmF2 & F2_RTS_MASK) == F2_RTS_TOGGLE)) // RTS toggling on transmit
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   gCOM.bMCR = gCOM.bMCR & pMask->fbModemOff | pMask->fbModemOn;
   if (gCOM.iModem < MAX_MDMS) SetSignals();

   *(PUSHORT)pRPIOCtl->DataPacket = gCOM.wError;
   // This function does not reset any bits in the Error word
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  StopTransmit                                     */
/*                                                                    */
/* DESCRIPTIVE NAME:  Stop transmit                                   */
/*                                                                    */
/* FUNCTION:  This function stops transmitting (behaves as if an XOFF */
/*            was received).                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  StopTransmit                                         */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void StopTransmit (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (gCOM.iModem >= MAX_MDMS)
   {
      pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_NOT_READY;
      return;
   }
   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: StopTransmit\r\n");
#endif

   gCOM.wDataToggle |= STOP_TRANSMIT;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  StartTransmit                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Start transmit                                  */
/*                                                                    */
/* FUNCTION:  This function starts transmitting (behaves as if an XON */
/*            was received).                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  StartTransmit                                         */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SendData                                     */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void StartTransmit (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (gCOM.iModem >= MAX_MDMS)
   {
      pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_NOT_READY;
      return;
   }
   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: StartTransmit\r\n");
#endif
   
   gCOM.wDataToggle &= ~STOP_TRANSMIT;
   SendData();
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetBreakOn                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set break on                                    */
/*                                                                    */
/* FUNCTION:  This function sets the break on.                        */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetBreakOn                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SendBreak                                    */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetBreakOn (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (gCOM.iModem >= MAX_MDMS)
   {
      pRPIOCtl->rph.Status = STDON | STERR | ERROR_I24_NOT_READY;
      return;
   }
   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(USHORT)) ||
       !(gMDM[gCOM.iModem].acmCapabilities & SEND_BREAK_SUPPORT))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: SetBreakOn\r\n");
#endif

   gCOM.bTxBreak = TURNON;
   SendBreak (SEND_BREAK_ON, COM_IRQ_BREAKON);

   *(PUSHORT)pRPIOCtl->DataPacket = gCOM.wError;
   // This function does not reset any bits in the Error word
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  SetDCB                                           */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set Device Control Block                        */
/*                                                                    */
/* FUNCTION:  This function sets the Device Control Block.            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  SetDCB                                               */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void SetDCB (PRP_GENIOCTL pRPIOCtl)
{
   PCOMDCB pDCB;

#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: Set DCB\r\n");
#endif

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, sizeof(DCBINFO)) || VerifyData (pRPIOCtl, 0))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pDCB = (PCOMDCB)pRPIOCtl->ParmPacket;
   /*
      Check for invalid values in the DCB request
   */
   if (pDCB->bmF1 & F1_RESERVED ||                     // reserved bits on
       (pDCB->bmF1 & F1_DTR_MASK) == F1_DTR_INVALID || // invalid DTR control mode
       !(pDCB->bmF3 & F3_READ_TO_MASK))                // invalid read timeout processing
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   movmem ((PSZ)&gCOM.dcb, (PSZ)pDCB, sizeof(COMDCB));

#ifdef DEBUG
   dsPrint2 (DBG_DETAILED, "USBCOM: DCB Timeouts = %d, %d 1/100 secs\r\n",
             gCOM.dcb.wWriteTO, gCOM.dcb.wReadTO);
   dsPrint3 (DBG_DETAILED, "USBCOM: DCB Flags = 0x%x, 0x%x, 0x%x\r\n",
             gCOM.dcb.bmF1, gCOM.dcb.bmF2, gCOM.dcb.bmF3);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetBitRate                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query bit rate                                  */
/*                                                                    */
/* FUNCTION:  This function returns the current bit rate in word.     */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetBitRate                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  SetLineCoding                                */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetBitRate (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(USHORT)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   if (gCOM.line.dwDTERate > MAX_BITRATE_WORD)
   {
      if (gCOM.bMSR & MSR_DCD)
      {
         pRPIOCtl->rph.Status |= STERR | ERROR_INVALID_PARAMETER;
         return;
      }
      else
      {
         gCOM.prevline.dwDTERate = gCOM.line.dwDTERate;
         gCOM.line.dwDTERate = MAX_BITRATE_WORD;
         if (gCOM.iModem < MAX_MDMS)
         {
            SetLineCoding();
            if (DevHelp_ProcBlock ((ULONG)(PUCHAR)&gCOM.line, SET_LINE_CODING_TO,
                                   WAIT_IS_INTERRUPTABLE) == WAIT_TIMED_OUT)
               gCOM.line.dwDTERate = gCOM.prevline.dwDTERate;
         }
      }
   }
   *(PUSHORT)pRPIOCtl->DataPacket = (USHORT)gCOM.line.dwDTERate;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetBitRate = %d\r\n", *(PUSHORT)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetLine                                          */
/*                                                                    */
/* DESCRIPTIVE NAME:  Get line characteristics                        */
/*                                                                    */
/* FUNCTION:  This function returns the current line characteristics. */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetLine                                              */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetLine (PRP_GENIOCTL pRPIOCtl)
{
   PLINECONTROL pLine = (PLINECONTROL)pRPIOCtl->DataPacket;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(LINECONTROL)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pLine->bDataBits   = gCOM.line.bDataBits;
   pLine->bParity     = gCOM.line.bParityType;
   pLine->bStopBits   = gCOM.line.bCharFormat;
   pLine->fTransBreak = gCOM.bTxBreak;

#ifdef DEBUG
   dsPrint4 (DBG_HLVLFLOW, "USBCOM: GetLine Bits = %d, Parity = %d, Stop = %d, Break = %d\r\n",
             pLine->bDataBits, pLine->bParity, pLine->bStopBits, pLine->fTransBreak);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetBitRateExt                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Extended query bit rate                         */
/*                                                                    */
/* FUNCTION:  This function returns the extended query bit rate       */
/*            in doublewords.                                         */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetBitRateExt                                        */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetBitRateExt (PRP_GENIOCTL pRPIOCtl)
{
   PBITRATE pBitRate = (PBITRATE)pRPIOCtl->DataPacket;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(BITRATE)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pBitRate->dwBitRate  = gCOM.line.dwDTERate;
   pBitRate->bBitRate   = 0;
   pBitRate->dwMin      = gCOM.dwMinDTERate;
   pBitRate->bMin       = 0;
   pBitRate->dwMax      = gCOM.dwMaxDTERate;
   pBitRate->bMax       = 0;

#ifdef DEBUG
   dsPrint3 (DBG_HLVLFLOW, "USBCOM: GetBitRateExt = %ld, Min = %ld, Max = %ld\r\n",
             pBitRate->dwBitRate, pBitRate->dwMin, pBitRate->dwMax);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetStatus                                        */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query status                                    */
/*                                                                    */
/* FUNCTION:  This function returns the status.                       */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetStatus                                            */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetStatus (PRP_GENIOCTL pRPIOCtl)
{
   PUCHAR pStatus;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(UCHAR)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pStatus = pRPIOCtl->DataPacket;
   *pStatus = 0;
   if (~gCOM.bMSR & MSR_CTS)
      if ((gCOM.dcb.bmF1 & F1_OUT_FLOW) == F1_OUT_CTS_FLOW) *pStatus |= COMSTATUS_CTS;
   if (~gCOM.bMSR & MSR_DSR)
   {
      if ((gCOM.dcb.bmF1 & F1_OUT_FLOW) == F1_OUT_DSR_FLOW) *pStatus |= COMSTATUS_DSR_TR;
      if (gCOM.dcb.bmF1 & F1_IN_DSR_SENSE)                  *pStatus |= COMSTATUS_DSR_REC;
   }
   if (~gCOM.bMSR & MSR_DCD)
      if ((gCOM.dcb.bmF1 & F1_OUT_FLOW) == F1_OUT_DCD_FLOW) *pStatus |= COMSTATUS_DCD;
   if (gCOM.wDataToggle & SEND_BYTE_INPROGRESS)             *pStatus |= COMSTATUS_TRIMM;
   if (gCOM.wDataToggle & STOP_TRANSMIT &&
       !(gCOM.wDataToggle & XOFF_SENT))                     *pStatus |= COMSTATUS_XOFF_REC;
   if (gCOM.wDataToggle & STOP_TRANSMIT &&
       gCOM.wDataToggle & XOFF_SENT)                        *pStatus |= COMSTATUS_XOFF_TR;
   if (gCOM.bTxBreak)                                       *pStatus |= COMSTATUS_BREAK;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetStatus = 0x%x\r\n", *pStatus);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetTxStatus                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query transmit data status                      */
/*                                                                    */
/* FUNCTION:  This function returns the transmit data status.         */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetTxStatus                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetTxStatus (PRP_GENIOCTL pRPIOCtl)
{
   PUCHAR pTxStatus;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(UCHAR)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pTxStatus = pRPIOCtl->DataPacket;
   *pTxStatus = 0;
   if (gCOM.pRPWrite[CURRENT] != NULL)          *pTxStatus |= WRITE_REQUEST_QUEUED;
   if (gCOM.outq.wCount != 0)                   *pTxStatus |= DATA_IN_TX_QUE;
   if (gCOM.wDataToggle & SEND_DATA_INPROGRESS) *pTxStatus |= HARDWARE_TRANSMITTING;
   if (gCOM.wDataToggle & SEND_BYTE_INPROGRESS) *pTxStatus |= CHAR_READY_TO_SEND_IMM;
   if (gCOM.wDataToggle & SEND_BYTE_INPROGRESS &&
       gCOM.bTxImm == gCOM.dcb.bXON)            *pTxStatus |= WAITING_TO_SEND_XON;
   if (gCOM.wDataToggle & SEND_BYTE_INPROGRESS &&
       gCOM.bTxImm == gCOM.dcb.bXOFF)           *pTxStatus |= WAITING_TO_SEND_XOFF;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetTxStatus = 0x%x\r\n", *pTxStatus);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetModemOutput                                   */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query modem control output signals              */
/*                                                                    */
/* FUNCTION:  This function returns the modem control output signals. */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetModemOutput                                       */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetModemOutput (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(UCHAR)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   *(PUCHAR)pRPIOCtl->DataPacket = gCOM.bMCR;   // Modem Control Register

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetModemOutput = MCR = 0x%x\r\n",
             *(PUCHAR)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetModemInput                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query modem input signals                       */
/*                                                                    */
/* FUNCTION:  This function returns the modem input signals.          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetModemInput                                        */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetModemInput (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(UCHAR)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   *(PUCHAR)pRPIOCtl->DataPacket = gCOM.bMSR;   // Modem Status Register

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetModemInput = MSR = 0x%x\r\n",
             *(PUCHAR)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetInQueue                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query number of bytes in receive queue          */
/*                                                                    */
/* FUNCTION:  This function returns the number of bytes queued and    */
/*            size of receive queue.                                  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetInQueue                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetInQueue (PRP_GENIOCTL pRPIOCtl)
{
   PRXQUEUE pQueueBytes;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(RXQUEUE)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pQueueBytes = (PRXQUEUE)pRPIOCtl->DataPacket;
   pQueueBytes->cch = gCOM.inq.wCount;
   pQueueBytes->cb = sizeof(gCOM.inq.bBuffer);

#ifdef DEBUG
   dsPrint2 (DBG_HLVLFLOW, "USBCOM: GetInQueue = %d, %d\r\n",
             pQueueBytes->cch, pQueueBytes->cb);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetOutQueue                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query number of bytes in transmit queue         */
/*                                                                    */
/* FUNCTION:  This function returns the number of bytes queued and    */
/*            size of transmit queue.                                 */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetOutQueue                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetOutQueue (PRP_GENIOCTL pRPIOCtl)
{
   PRXQUEUE pQueueBytes;

   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(RXQUEUE)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   pQueueBytes = (PRXQUEUE)pRPIOCtl->DataPacket;
   pQueueBytes->cch = gCOM.outq.wCount;
   pQueueBytes->cb = sizeof(gCOM.outq.bBuffer);

#ifdef DEBUG
   dsPrint2 (DBG_HLVLFLOW, "USBCOM: GetOutQueue = %d, %d\r\n",
             pQueueBytes->cch, pQueueBytes->cb);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetError                                         */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query error information                         */
/*                                                                    */
/* FUNCTION:  This function retrieves and clears the error word.      */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetError                                             */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetError (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(USHORT)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   *(PUSHORT)pRPIOCtl->DataPacket = gCOM.wError;
   gCOM.wError = 0;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetError = 0x%x\r\n",
             *(PUSHORT)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetEvent                                         */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query event information                         */
/*                                                                    */
/* FUNCTION:  This function retrieves and clears the event word.      */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetEvent                                             */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetEvent (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(USHORT)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   *(PUSHORT)pRPIOCtl->DataPacket = gCOM.wEvent;
   gCOM.wEvent = 0;

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetEvent = 0x%x\r\n",
             *(PUSHORT)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetDCB                                           */
/*                                                                    */
/* DESCRIPTIVE NAME:  Get Device Control Block information            */
/*                                                                    */
/* FUNCTION:  This function returns Device Control Block information. */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetDCB                                               */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetDCB (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

#ifdef DEBUG
   dsPrint (DBG_HLVLFLOW, "USBCOM: GetDCB\r\n");
#endif

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(DCBINFO)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   movmem (pRPIOCtl->DataPacket, (PSZ)&gCOM.dcb, sizeof(COMDCB));

#ifdef DEBUG
   dsPrint2 (DBG_DETAILED, "USBCOM: DCB Timeouts = %d, %d 1/100 secs\r\n",
             gCOM.dcb.wWriteTO, gCOM.dcb.wReadTO);
   dsPrint3 (DBG_DETAILED, "USBCOM: DCB Flags = 0x%x, 0x%x, 0x%x\r\n",
             gCOM.dcb.bmF1, gCOM.dcb.bmF2, gCOM.dcb.bmF3);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  GetEnhMode                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Query enhanced mode parameters                  */
/*                                                                    */
/* FUNCTION:  This function returns the enhanced mode parasmeters.    */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  GetEnhMode                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: pRPIOCtl->rph.Status                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  VerifyParam                                  */
/*                       VerifyData                                   */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void GetEnhMode (PRP_GENIOCTL pRPIOCtl)
{
   pRPIOCtl->rph.Status = STDON;

   if (VerifyParam (pRPIOCtl, 0) || VerifyData (pRPIOCtl, sizeof(UCHAR) + sizeof(ULONG)))
   {
      pRPIOCtl->rph.Status |= STERR | ERROR_I24_GEN_FAILURE;
      return;
   }
   *(PUCHAR)pRPIOCtl->DataPacket = 0;   // Enhanced Flags1

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "USBCOM: GetEnhMode = 0x%x\r\n",
             *(PUCHAR)pRPIOCtl->DataPacket);
#endif
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VerifyData                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Verify access to data packet                    */
/*                                                                    */
/* FUNCTION:  This function is used to verify access to data packet.  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  VerifyData                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*         USHORT datalength                                          */
/*                                                                    */
/* EXIT-NORMAL: 0 if access is verified                               */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

static USHORT VerifyData (PRP_GENIOCTL pRPIOCtl, USHORT datalength)
{
   if (datalength) return (DevHelp_VerifyAccess (SELECTOROF (pRPIOCtl->DataPacket),
                                                 datalength, 
                                                 OFFSETOF(pRPIOCtl->DataPacket),
                                                 VERIFY_READWRITE));
   else return (OFFSETOF (pRPIOCtl->DataPacket) &&
                (SELECTOROF (pRPIOCtl->DataPacket) & SELECTOR_MASK));
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VerifyParam                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Verify access to parameter packet               */
/*                                                                    */
/* FUNCTION:  This function is used to verify access to parameter     */
/*            packet.                                                 */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  VerifyParam                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PRP_GENIOCTL pRPIOCtl                                      */
/*         USHORT packetlength                                        */
/*                                                                    */
/* EXIT-NORMAL: 0 if access is verified                               */
/*                                                                    */
/* EXIT-ERROR:                                                        */
/*                                                                    */
/* EFFECTS: None                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

static USHORT VerifyParam (PRP_GENIOCTL pRPIOCtl, USHORT packetlength)
{
   if (packetlength) return (DevHelp_VerifyAccess (SELECTOROF (pRPIOCtl->ParmPacket),
                                                   packetlength, 
                                                   OFFSETOF(pRPIOCtl->ParmPacket),
                                                   VERIFY_READONLY));
   else return (OFFSETOF (pRPIOCtl->ParmPacket) &&
                (SELECTOROF (pRPIOCtl->ParmPacket) & SELECTOR_MASK));
}

