/* SCCSID = "%W% %E%" */
/****************************************************************************/
/*                                                                          */
/*                           IBM Confidential                               */
/*                                                                          */
/*                 Copyright (c) IBM Corporation 1996                       */
/*                           All Rights Reserved                            */
/*                                                                          */
/****************************************************************************/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  PARISR.C                                              */
/*                                                                            */
/*   DESCRIPTIVE NAME:  PARALLEL port device driver interrupt service         */
/*                      routines.                                             */
/*                                                                            */
/*   FUNCTION: These routines handle the servicing of hardware interrupts     */
/*             for the parallel port device driver.                           */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             parIRQEntry_0                                                  */
/*             parIRQEntry_1                                                  */
/*             parIRQEntry_2                                                  */
/*             parISR                                                         */
/*             addTimerEventHandler                                           */
/*             setDelayTimer                                                  */
/*             cancelDelayTimer                                               */
/*             cancelAllTimers                                                */
/*                                                                            */
/*   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:  parIRQEntry_0                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Service a parallel port hardware interrupt.     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to call the general     */
/*            purpose hardware interrupt handler with the appropriate */
/*            adapter instance index.                                 */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  parIRQEntry_0                                        */
/*    LINKAGE:  CALL FAR                                              */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: Clear the carry flag (interrupt was processed)        */
/*              Set the carry flag (interrupt was not processed)      */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  parISR                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT far parIRQEntry_0()
{
  return ( parISR( 0 ) >> 1 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  parIRQEntry_1                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Service a parallel port hardware interrupt.     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to call the general     */
/*            purpose hardware interrupt handler with the appropriate */
/*            adapter instance index.                                 */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  parIRQEntry_1                                        */
/*    LINKAGE:  CALL FAR                                              */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: Clear the carry flag (interrupt was processed)        */
/*              Set the carry flag (interrupt was not processed)      */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  parISR                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT far parIRQEntry_1()
{
  return ( parISR( 1 ) >> 1 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  parIRQEntry_2                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Service a parallel port hardware interrupt.     */
/*                                                                    */
/* FUNCTION:  The function of this routine is to call the general     */
/*            purpose hardware interrupt handler with the appropriate */
/*            adapter instance index.                                 */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  parIRQEntry_2                                        */
/*    LINKAGE:  CALL FAR                                              */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: Clear the carry flag (interrupt was processed)        */
/*              Set the carry flag (interrupt was not processed)      */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  parISR                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT far parIRQEntry_2()
{
  return ( parISR( 2 ) >> 1 );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  parISR                                           */
/*                                                                    */
/* DESCRIPTIVE NAME:  Interrupt Service Routine.                      */
/*                                                                    */
/* FUNCTION:  The function of this routine is to clear the hardware   */
/*            interrupt at the device, call the interrupt routine     */
/*            for the appropriate communication mode, issue the end   */
/*            of interrupt to the 8259 interrupt controller, and to   */
/*            inform the hardware interrupt manager whether the       */
/*            hardware interrupt was serviced.                        */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  parISR                                               */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: FALSE (interrupt was processed)                       */
/*              TRUE (interrupt was not processed)                    */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  IORead8                                      */
/*                       ResetInstanceFlags                           */
/*                       pInst->IRQRtn                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  DevHelp_EOI                                  */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
USHORT parISR( USHORT IRQIndex )
{
   parInstance_t        *pInst;

  pInst = IRQInfo[IRQIndex].pInst;
  /*------------------------------------------------------*/
  /* Read parallel port status reg to remove interrupt    */
  /* at the device.                                       */
  /*------------------------------------------------------*/
  IORead8( pInst->pIO[0], SPP_STATUS_REG );

  /*---------------------------------------------------------*/
  /* If the interrupt was 'expected' then call the currently */
  /* registered IRQ handler. Otherwise, the interrupt is     */
  /* ignored.                                                */
  /*---------------------------------------------------------*/
  if ( pInst->Flags & F_INTERRUPT_EXPECTED )
  {
    ResetInstanceFlags( pInst, F_INTERRUPT_EXPECTED );

    (pInst->IRQRtn)( pInst );
  }
  else
  {
     /* Could put some spurious interrupt code here. */
     return( TRUE );          /* not my interrupt - spurious? */
  }

  CLI();
  DevHelp_EOI( IRQInfo[IRQIndex].IRQLevel);  /* Kernel will enable ints. */
  return( FALSE );            /* my interrupt */
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  addTimerEventHandler                             */
/*                                                                    */
/* DESCRIPTIVE NAME:  Timer Event Handler.                            */
/*                                                                    */
/* FUNCTION:  The function of this routine is to loop through the     */
/*            active adapter instances when this routine is called    */
/*            and decrement each non-zero timer event counter.  When  */
/*            a timer event counter reaches zero, call the timer      */
/*            event handler to process the next event.                */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  addTimerEventHandler                                 */
/*    LINKAGE:  CALL FAR                                              */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  pInst->Timers[i].TimeoutRtn                  */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void far addTimerEventHandler()
{
  parInstance_t         *pInst;
  USHORT                i;

  pInst = pInstanceHead;

  /*----------------------------------------------*/
  /* Scan all active instances on each timer tick */
  /*----------------------------------------------*/
  while ( pInst )
  {
    /*--------------------------------------------*/
    /* Scan all internal timers for the instance  */
    /*--------------------------------------------*/
    for ( i = 0; i < TIMERS_PER_INSTANCE; i++ )
    {
      /*--------------------------------------------------*/
      /* If an instance timer made a 1->0 transition then */
      /* call the associated timeout routine              */
      /*--------------------------------------------------*/
      if ( pInst->Timers[i].TimerCount )
      {
        if ( !--(pInst->Timers[i].TimerCount) )
        {
          (pInst->Timers[i].TimeoutRtn)( pInst );
        }
      }
    }

    pInst = pInst->pNextInst;
  }
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  setDelayTimer                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Schedule an adapter instance timer              */
/*                                                                    */
/* FUNCTION:  The function of this routine is to register a timer     */
/*            event handler to be called when the timer expires.      */
/*                                                                    */
/* NOTES:  The granularity of the OS/2 timer services is 32 ms.       */
/*                                                                    */
/* CONTEXT: Task or interrupt time                                    */
/*                                                                    */
/* ENTRY POINT:  setDelayTimer                                        */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t  *pInst - ptr to adapter instance            */
/*         USHORT          TimerId - timer index                      */
/*                         &TimeoutRtn - timeout routine              */
/*         USHORT          TimeoutMS - time to wait in ms             */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  LockInstance                                 */
/*                       UnLockInstance                               */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void setDelayTimer( parInstance_t *pInst,
                    USHORT        TimerId,
                    void          (*TimeoutRtn)( parInstance_t *pInst ),
                    USHORT        TimeoutMS )
{

  LockInstance( pInst );
  pInst->Timers[TimerId].TimeoutRtn = TimeoutRtn;
  pInst->Timers[TimerId].TimerCount = TimeoutMS/MSPerTick;
  UnLockInstance( pInst );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  cancelDelayTimer                                 */
/*                                                                    */
/* DESCRIPTIVE NAME:  Cancel an adapter instance timer                */
/*                                                                    */
/* FUNCTION:  The function of this routine is to deregister a timer   */
/*            event handler by clearing the TimerCount field.         */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task or interrupt time                                    */
/*                                                                    */
/* ENTRY POINT:  cancelDelayTimer                                     */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t  *pInst - ptr to adapter instance            */
/*         USHORT          TimerId - timer index                      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  LockInstance                                 */
/*                       UnLockInstance                               */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void cancelDelayTimer( parInstance_t *pInst,
                       USHORT        TimerId )
{
  LockInstance( pInst );
  pInst->Timers[TimerId].TimerCount = 0;
  UnLockInstance( pInst );
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  cancelAllTimers                                  */
/*                                                                    */
/* DESCRIPTIVE NAME:  Cancel all adapter instance timers              */
/*                                                                    */
/* FUNCTION:  The function of this routine is to deregister all timer */
/*            event handlers by clearing all TimerCount fields.       */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task or interrupt time                                    */
/*                                                                    */
/* ENTRY POINT:  cancelAllTimers                                      */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  parInstance_t  *pInst - ptr to adapter instance            */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  LockInstance                                 */
/*                       UnLockInstance                               */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
void cancelAllTimers( parInstance_t *pInst )
{
  LockInstance( pInst );
  pInst->Timers[0].TimerCount = 0;
  pInst->Timers[1].TimerCount = 0;
  pInst->Timers[2].TimerCount = 0;
  UnLockInstance( pInst );
}


