/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1992 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 source code is provided to you solely for       */
/*    the purpose of assisting you in your development of OS/2 device        */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Developer Connection Device Driver       */
/*    Source Kit for OS/2. This Copyright statement may not be removed.      */
/*                                                                           */
/*****************************************************************************/

#include        "par.h"
/*--------------------------------------------------------------------*/
/*                                                                    */
/*                                                                    */
/* parutil.c - Miscellaneous services                                 */
/*             Some of the routines could be placed into a throw away */
/*             segment for initialization only.                       */
/*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*/
/*                                                                    */
/* These routines updata the pInst->Flags bit mask field with         */
/* interrupts disabled.                                               */
/*                                                                    */
/*--------------------------------------------------------------------*/

void SetInstanceFlags( parInstance_t *pInst,
                       ULONG         Flags   )
{
  _asm
  {
     cli
  }
  pInst->Flags |= Flags;
  _asm
  {
     sti
  }
}

void ResetInstanceFlags( parInstance_t *pInst,
                         ULONG         Flags    )
{
  _asm
  {
     cli
  }
  pInst->Flags &= ~Flags;
  _asm
  {
     sti
  }
}

/*--------------------------------------------------------------------*/
/*                                                                    */
/* These routines insure non-interrupted access to the Parallel       */
/* ADD Instance structure.                                            */
/*                                                                    */
/*--------------------------------------------------------------------*/

void LockInstance( parInstance_t *pInst )
{
  _asm
  {
     cli
  }
}

void UnLockInstance( parInstance_t *pInst )
{
  _asm
  {
     sti
  }
}

/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine allocates a Parallel ADD instance structure.          */
/*                                                                    */
/* It also maintains a linked list of allocated instance structures.  */
/*                                                                    */
/*--------------------------------------------------------------------*/

parInstance_t *AllocateInstance()
{
  parInstance_t         *pInst;

  if ( !cInstances )
  {
    if ( AllocateInstancePool() )
    {
      return( 0 );
    }
    if ( StartInstanceTimer() )
    {
      return( 0 );
    }

  }

  if ( pInst = pFreeInstanceList )
  {
    pFreeInstanceList = pFreeInstanceList->pNextInst;

    memset( pInst, 0, sizeof(parInstance_t) );

    cInstances++;
  }

  if ( !pInstanceFoot )
  {
    pInstanceHead = pInst;
  }
  else
  {
    pInstanceFoot->pNextInst = pInst;
  }
  pInstanceFoot = pInst;

  return( pInst );
}

/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine allocates storage for Parallel ADD instances.         */
/*                                                                    */
/* Memory is statically allocated.                                    */
/*                                                                    */
/*--------------------------------------------------------------------*/

USHORT AllocateInstancePool()
{
  parInstance_t         *pInst;
  USHORT                i;


  memset( InstanceCBs, 0, sizeof(InstanceCBs) );

  pInst = pFreeInstanceList = InstanceCBs;

  for ( i=0; i < MAX_LPT-1; i++, pInst++ )
  {
    pInst->pNextInst = pInst+1;
  }

  return( 0 );
}
/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine starts a periodic timer used by the ADD's internal    */
/* timer services.                                                    */
/*                                                                    */
/*--------------------------------------------------------------------*/

USHORT StartInstanceTimer()
{

  if ( DevHelp_TickCount( (NPFN) addTimerEventHandler,
                          (USHORT) 1 )                  )
  {
    return( 1 );
  }

  return( 0 );
}

/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine releases a Parallel ADD instance structure.           */
/*                                                                    */
/* It also releases any resources that may have been allocated        */
/* to the instance and no instances left, it will release the         */
/* memory page used to store the ADD instance data.                   */
/*                                                                    */
/*--------------------------------------------------------------------*/


void DestroyInstance( parInstance_t *pInst )
{
  /* Need to release IRQ */
  /* Need to call StopInstanceTimer */
  /* Need to decrement cInstances */

  DeallocateInstance( pInst );
}


/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine release instance storage and removes the requested    */
/* Parallel instance from the list of active instances.               */
/*                                                                    */
/*--------------------------------------------------------------------*/

void DeallocateInstance( parInstance_t *pInst )
{
  parInstance_t         *pInstPrev;
  parInstance_t         *pInstCur;

  pInstPrev = 0;
  pInstCur  = pInstanceHead;

  while( pInstCur )
  {
    if ( pInstCur == pInst )
    {
      break;
    }
    pInstPrev = pInstCur;
    pInstCur  = pInstCur->pNextInst;
  }

  if ( !pInstCur )
  {
    return;
  }

  if ( pInstPrev )
  {
    if ( !(pInstPrev->pNextInst = pInst->pNextInst) )
    {
      pInstanceFoot = pInstPrev;
    }
  }
  else
  {
    if( !(pInstanceHead = pInst->pNextInst) )
    {
      pInstanceFoot = 0;
    }
  }
}


/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine stops the Parallel ADD periodic timer.                */
/*                                                                    */
/* It is called when no active instances remain.                      */
/*                                                                    */
/*--------------------------------------------------------------------*/

USHORT StopInstanceTimer()
{
  if ( DevHelp_ResetTimer( (NPFN) addTimerEventHandler ) )
  {
    return( 1 );
  }

  return( 0 );
}


/*--------------------------------------------------------------------*/
/*                                                                    */
/* This routine converts the ADD's internal error codes to ADD-32     */
/* request packet codes.                                              */
/*                                                                    */
/*--------------------------------------------------------------------*/

void SetRPErrorCode( parInstance_t *pInst )
{
  switch ( pInst->ReturnCode )
  {
    case RC_SUCCESS:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_TIMEOUT:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_CANCELLED:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_NOT_1284_DEVICE:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_INVALID_MODE:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_NO_MORE_DEVICES:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_DEVICE_IN_USE:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_INVALID_DEVICE_HANDLE:
      pInst->pRP->Status = 0x810C;
      break;
    case RC_INVALID_PARM:
      pInst->pRP->Status = 0x810C;
      break;
    default:
      pInst->pRP->Status = 0x810C;
  }
}

