/* SCCSID = "%W% %E%" */
/****************************************************************************/
/*                                                                          */
/*                           IBM Confidential                               */
/*                                                                          */
/*                 Copyright (c) IBM Corporation 1996                       */
/*                           All Rights Reserved                            */
/*                                                                          */
/****************************************************************************/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  PARUTIL.C                                             */
/*                                                                            */
/*   DESCRIPTIVE NAME:  PARALLEL port device driver miscellaneous service     */
/*                      routines.                                             */
/*                                                                            */
/*   FUNCTION: These routines handle the allocation and deallocation of       */
/*             the adapter instances, registration and deregistration of the  */
/*             instance timers, and calculation of the FIFO depth, and read   */
/*             and write thresholds.                                          */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             AllocateInstance                                               */
/*             AllocateInstancePool                                           */
/*             StartInstanceTimer                                             */
/*             DestroyInstance                                                */
/*             DeallocateInstance                                             */
/*             StopInstanceTimer                                              */
/*             DetermineFIFOThresholds                                        */
/*             DetermineFIFOWriteThresh                                       */
/*             DetermineFIFOReadThresh                                        */
/*             FillFIFOTest                                                   */
/*             EmptyFIFOTest                                                  */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          96/03/01  Frank Schroeder                                         */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include        "par.h"

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  AllocateInstance                                 */
/*                                                                    */
/* DESCRIPTIVE NAME:  Allocates an adapter instance.                  */
/*                                                                    */
/* FUNCTION:  The function of this routine is to allocate an adapter  */
/*            instance and maintain a linked list of allocated        */
/*            instances.                                              */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  AllocateInstance                                     */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  parInstance_t   pInst    - ptr to adapter instance   */
/* INPUT:  parInstance_t   pInst    - ptr to adapter instance         */
/*                                                                    */
/* EXIT-ERROR:  zero                                                  */
/*                                                                    */
/* EFFECTS:  cInstances, pFreeInstanceList, pInstanceHead,            */
/*           pInstanceFoot                                            */
/*                                                                    */
/* INTERNAL REFERENCES:  AllocateInstancePool                         */
/*                       StartInstanceTimer                           */
/*                                                                    */
/* EXTERNAL REFERENCES:  memset                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
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 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  AllocateInstancePool                             */
/*                                                                    */
/* DESCRIPTIVE NAME:  Allocates a pool of adapter instances.          */
/*                                                                    */
/* FUNCTION:  The function of this routine is to allocate a pool of   */
/*            adapter instances, initialize the adapter instances to  */
/*            zero and create a linked list of available instances.   */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  AllocateInstancePool                                 */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  pFreeInstanceList                                        */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  memset                                       */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
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 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  StartInstanceTimer                               */
/*                                                                    */
/* DESCRIPTIVE NAME:  Start the device driver periodic timer.         */
/*                                                                    */
/* FUNCTION:  The function of this routine is to start a periodic     */
/*            timer.                                                  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  StartInstanceTimer                                   */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  ZERO                                                 */
/*                                                                    */
/* EXIT-ERROR:  ONE                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  DevHelp_TickCount                            */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT StartInstanceTimer()
{

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

  return( 0 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  DestroyInstance                                  */
/*                                                                    */
/* DESCRIPTIVE NAME:  Deallocates the adapter instance pool.          */
/*                                                                    */
/* FUNCTION:  The function of this routine is to deallocate an        */
/*            adapter instance and release any resources allocated to */
/*            the instance. When no instances remain allocated, the   */
/*            memory is released and the device driver periodic       */
/*            timer is stopped.                                       */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  DestroyInstance                                      */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t   pInst    - ptr to adapter instance         */
/*                                                                    */
/* EXIT-NORMAL:  N/A                                                  */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void DestroyInstance( parInstance_t *pInst )
{
  /* Need to release IRQ */
  /* Need to call StopInstanceTimer */
  /* Need to decrement cInstances */

  DeallocateInstance( pInst );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  DeallocateInstance                               */
/*                                                                    */
/* DESCRIPTIVE NAME:  Deallocates an adapter instance.                */
/*                                                                    */
/* FUNCTION:  The function of this routine is to deallocate an        */
/*            adapter instance and maintain a linked list of          */
/*            allocated instances.                                    */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  DeallocateInstance                                   */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t   pInst    - ptr to adapter instance         */
/*                                                                    */
/* EXIT-NORMAL:  N/A                                                  */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  pInstanceHead, pInstanceFoot                             */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
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;
    }
  }
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  StopInstanceTimer                                */
/*                                                                    */
/* DESCRIPTIVE NAME:  Stop the device driver periodic timer.          */
/*                                                                    */
/* FUNCTION:  The function of this routine is to stop a periodic      */
/*            timer.                                                  */
/*                                                                    */
/* NOTES:  This function must be called when no active instances      */
/*         remain.                                                    */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  StopInstanceTimer                                    */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  ZERO                                                 */
/*                                                                    */
/* EXIT-ERROR:  ONE                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  DevHelp_ResetTimer                           */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT StopInstanceTimer()
{
  if ( DevHelp_ResetTimer( (NPFN) addTimerEventHandler ) )
  {
    return( 1 );
  }

  return( 0 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  DetermineFIFOThresholds                          */
/*                                                                    */
/* DESCRIPTIVE NAME:  Determine FIFO threadholds.                     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to determine the FIFO   */
/*            depth and the read and write interrupt thresholds for   */
/*            ECP capable chipsets.                                   */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  DetermineFIFOThresholds                              */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  N/A                                                  */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  IOWrite8                                     */
/*                       FillFIFOTest                                 */
/*                       DetermineFIFOReadThresh                      */
/*                       DetermineFIFOWriteThresh                     */
/*                       EmptyFIFOTest                                */
/*                       IODelay                                      */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void DetermineFIFOThresholds( parInstance_t *pInst )
{
  USHORT                ExtPortBase;
  UCHAR                 ExtControlReg;

   /*-------------------------------------------------------*/
   /* Set chipset in FIFO Test Mode                         */
   /*-------------------------------------------------------*/
   ExtControlReg         = pInst->ExtControlReg;
   pInst->ExtControlReg &= ~(EXT_CONTROL_MODE | EXT_CONTROL_FIFOIRQ);
   pInst->ExtControlReg |= EXT_CONTROL_MODE6;

   ExtPortBase = pInst->pIO[1];

   IOWrite8( ExtPortBase,
             EXT_CONTROL_REG,
             (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

   /*-------------------------------------------------------*/
   /* Empty then fill chipset FIFO to determine FIFO depth  */
   /*-------------------------------------------------------*/
   pInst->FIFODepth       = FillFIFOTest( pInst );

   /*--------------------------------------------------------*/
   /* Empty FIFO, set direction toward host (read), then     */
   /* fill FIFO until the chipset presents a FIFO service    */
   /* interrupt. This is the FIFO 'read' threshold.          */
   /*--------------------------------------------------------*/
   pInst->FIFOReadThresh  = DetermineFIFOReadThresh( pInst );

   /*--------------------------------------------------------*/
   /* Fill FIFO, set direction toward device (write), then   */
   /* empty FIFO until the chipset presents a FIFO service   */
   /* interrupt. This is the FIFO 'write' threshold.         */
   /*--------------------------------------------------------*/
   pInst->FIFOWriteThresh = DetermineFIFOWriteThresh( pInst );

   /*---------------------------------------*/
   /* Remove any residual data left in FIFO */
   /*---------------------------------------*/
   EmptyFIFOTest( pInst );

   /*---------------------------------------------*/
   /* Restore original chipset mode and direction */
   /*---------------------------------------------*/
   IOWrite8( pInst->pIO[0],
             SPP_CONTROL_REG,
             pInst->ControlReg );

   IODelay();
   IODelay();

   pInst->ExtControlReg = ExtControlReg;

   IOWrite8( ExtPortBase,
             EXT_CONTROL_REG,
             (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  DetermineFIFOWriteThresh                         */
/*                                                                    */
/* DESCRIPTIVE NAME:  Determine FIFO write threadhold.                */
/*                                                                    */
/* FUNCTION:  The function of this routine is to determine the FIFO   */
/*            write interrupt threshold for ECP capable chipsets.     */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  DetermineFIFOWriteThresh                             */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  write threshold value                                */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  FillFIFOTest                                 */
/*                       LockInstance                                 */
/*                       IOWrite8                                     */
/*                       IORead8                                      */
/*                       UnLockInstance                               */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT DetermineFIFOWriteThresh( parInstance_t *pInst )
{
  USHORT                i, ExtPortBase;
  UCHAR                 FIFOStatus;
  UCHAR                 ControlReg, databyte;

  /*-------------------*/
  /* Fill chipset FIFO */
  /*-------------------*/
  FillFIFOTest( pInst );

  /*--------------------------------------*/
  /* Set direction towards device (write) */
  /*--------------------------------------*/
  ControlReg = pInst->ControlReg & (UCHAR)~SPP_CONTROL_DIR;

  IOWrite8( pInst->pIO[0],
            SPP_CONTROL_REG,
            (UCHAR)(ControlReg ^ SPP_CONTROL_INVERT));


  /*-----------------------------------------------*/
  /* Disable interrupts and arm the FIFO interrupt */
  /*-----------------------------------------------*/
  LockInstance( pInst );

  pInst->ExtControlReg |= EXT_CONTROL_FIFOIRQ;

  ExtPortBase = pInst->pIO[1];

  IOWrite8( ExtPortBase,
            EXT_CONTROL_REG,
            (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

  /*---------------------------------------------------*/
  /* Empty the FIFO until the chipset presents an FIFO */
  /* service interrupt                                 */
  /*---------------------------------------------------*/
  for (i=0; i < pInst->FIFODepth; i++ )
  {
    FIFOStatus   = IORead8( ExtPortBase, EXT_CONTROL_REG );
    FIFOStatus  ^= EXT_CONTROL_INVERT;

    if ( !(FIFOStatus & EXT_CONTROL_FIFOIRQ) )
    {
      break;
    }

    databyte = IORead8( ExtPortBase, ECP_TFIFO_REG );
  }

  /*-------------------------------------*/
  /* Service the pending FIFO interrupt  */
  /*-------------------------------------*/
  pInst->ExtControlReg &= ~EXT_CONTROL_FIFOIRQ;

  IOWrite8( ExtPortBase,
            EXT_CONTROL_REG,
            (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

  /*------------------------*/
  /* Enable interrupts      */
  /*------------------------*/
  UnLockInstance( pInst );

  return( i );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  DetermineFIFOReadThresh                          */
/*                                                                    */
/* DESCRIPTIVE NAME:  Determine FIFO read threadhold.                 */
/*                                                                    */
/* FUNCTION:  The function of this routine is to determine the FIFO   */
/*            read interrupt threshold for ECP capable chipsets.      */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  DetermineFIFOReadThresh                              */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL:  read threshold value                                 */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  EmptyFIFOTest                                */
/*                       LockInstance                                 */
/*                       IOWrite8                                     */
/*                       IORead8                                      */
/*                       UnLockInstance                               */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT DetermineFIFOReadThresh( parInstance_t *pInst )
{
  USHORT                i, ExtPortBase;
  UCHAR                 FIFOStatus;
  UCHAR                 ControlReg;

  /*--------------------*/
  /* Empty chipset FIFO */
  /*--------------------*/
  EmptyFIFOTest( pInst );

  /*--------------------------------------*/
  /* Set direction towards host (read)    */
  /*--------------------------------------*/
  ControlReg = pInst->ControlReg | (UCHAR)SPP_CONTROL_DIR;

  IOWrite8( pInst->pIO[0],
            SPP_CONTROL_REG,
            (UCHAR)(ControlReg ^ SPP_CONTROL_INVERT));

  /*-----------------------------------------------*/
  /* Disable interrupts and arm the FIFO interrupt */
  /*-----------------------------------------------*/
  LockInstance( pInst );

  pInst->ExtControlReg |= EXT_CONTROL_FIFOIRQ;

  ExtPortBase = pInst->pIO[1];
  IOWrite8( ExtPortBase,
            EXT_CONTROL_REG,
            (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

  /*---------------------------------------------------*/
  /* Fill the FIFO until the chipset presents an FIFO  */
  /* service interrupt                                 */
  /*---------------------------------------------------*/
  for (i=0; i < pInst->FIFODepth; i++ )
  {
    FIFOStatus = IORead8( ExtPortBase, EXT_CONTROL_REG );
    FIFOStatus ^= EXT_CONTROL_INVERT;

    if ( !(FIFOStatus & EXT_CONTROL_FIFOIRQ) )
    {
      break;
    }

    IOWrite8( ExtPortBase, ECP_TFIFO_REG, 0 );
  }

  /*-------------------------------------*/
  /* Service the pending FIFO interrupt  */
  /*-------------------------------------*/
  pInst->ExtControlReg &= ~EXT_CONTROL_FIFOIRQ;

  IOWrite8( ExtPortBase,
            EXT_CONTROL_REG,
            (UCHAR)(pInst->ExtControlReg ^ EXT_CONTROL_INVERT));

  /*------------------------*/
  /* Enable interrupts      */
  /*------------------------*/
  UnLockInstance( pInst );

  return( i );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  FillFIFOTest                                     */
/*                                                                    */
/* DESCRIPTIVE NAME:  Fill the FIFO (Determine FIFO depth).           */
/*                                                                    */
/* FUNCTION:  The function of this routine is to determine the FIFO   */
/*            depth on ECP capable chipsets.                          */
/*                                                                    */
/* NOTES:  The FIFO is full on return.                                */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  FillFIFOTest                                         */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t   pInst    - ptr to adapter instance         */
/*                                                                    */
/* EXIT-NORMAL:  FIFO depth                                           */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  EmptyFIFOTest                                */
/*                       IORead8                                      */
/*                       IOWrite8                                     */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT FillFIFOTest( parInstance_t *pInst )
{
  USHORT               i, ExtPortBase;
  UCHAR                FIFOStatus;

  EmptyFIFOTest( pInst );

  ExtPortBase = pInst->pIO[1];

  for (i=0; i < MAX_FIFO_DEPTH; i++ )
  {

    FIFOStatus = IORead8( ExtPortBase, EXT_CONTROL_REG );
    FIFOStatus ^= EXT_CONTROL_INVERT;

    if ( FIFOStatus & EXT_CONTROL_FIFOFULL )
    {
      break;
    }

    IOWrite8( ExtPortBase, ECP_TFIFO_REG, 0 );
  }

  return( i );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  EmptyFIFOTest                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Empty the FIFO.                                 */
/*                                                                    */
/* FUNCTION:  The function of this routine is to empty the FIFO       */
/*            on ECP capable chipsets.                                */
/*                                                                    */
/* NOTES:  The FIFO is empty on return.                               */
/*                                                                    */
/* CONTEXT: Initialization time                                       */
/*                                                                    */
/* ENTRY POINT:  EmptyFIFOTest                                        */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t   pInst    - ptr to adapter instance         */
/*                                                                    */
/* EXIT-NORMAL:  N/A                                                  */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  IORead8                                      */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void EmptyFIFOTest( parInstance_t *pInst )
{
  USHORT                i, ExtPortBase;
  UCHAR                 databyte, FIFOStatus;

  ExtPortBase = pInst->pIO[1];

  for (i=0; i < MAX_FIFO_DEPTH; i++ )
  {
    FIFOStatus   = IORead8( ExtPortBase, EXT_CONTROL_REG );
    FIFOStatus  ^= EXT_CONTROL_INVERT;

    if ( FIFOStatus & EXT_CONTROL_FIFOEMPTY )
    {
      break;
    }

    databyte = IORead8( ExtPortBase, ECP_TFIFO_REG );
  }
}


