/*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.      */
/*                                                                           */
/*****************************************************************************/
/* SCCSID = %W% %E% */
/**************************************************************************
 *
 * SOURCE FILE NAME = S506TIMR.C
 *
 * DESCRIPTIVE NAME = IBM1S506.ADD - Adapter Driver for ST506/IDE DASD
 *
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION : Adapter Driver timer driven entry points.
 *
 * Purpose:
 *
 *
 *
 *
 *
*/
 #define INCL_NOBASEAPI
 #define INCL_NOPMAPI
 #define INCL_NO_SCB
 #define INCL_INITRP_ONLY
 #define INCL_DOSERRORS
 #include "os2.h"
 #include "dos.h"
 #include "bseerr.h"
 #include "dskinit.h"
 #include <scb.h>
 #include <abios.h>

 #include "iorb.h"
 #include "reqpkt.h"
 #include "dhcalls.h"
 #include "addcalls.h"

 #include "s506cons.h"
 #include "s506type.h"
 #include "s506regs.h"
 #include "s506ext.h"
 #include "s506pro.h"
 #include "s506misc.h"


//
// IRQTimer()
// 
// Expected interrupt timeout routine.
//
VOID FAR IRQTimer( ULONG TimerHandle, PACB pACB, ULONG Unused  )
{
  if ( TimerHandle != pACB->IRQTimerHandle )
  {
    _asm { int 3 }
  }

  ADD_CancelTimer( TimerHandle );

  pACB->IRQTimerHandle  = 0;
  pACB->TimerFlags     |= ACBT_IRQ;
  pACB->Flags          &= ~ACBF_INTERRUPT;

  if( pACB->Flags & ACBF_WAITSTATE )
  {
     
     //
     // The device may be ready to transfer data but failed to interrupt.  If so
     // just continue.  This is known to happen on the Sony CDU76 CD-ROM for the 
     // ATAPI Identify command.
     PIORB_ADAPTER_PASSTHRU   pIORB        = (PIORB_ADAPTER_PASSTHRU)(pACB->pIORB);

     if( pIORB->iorbh.CommandCode == IOCC_ADAPTER_PASSTHRU &&
         pIORB->iorbh.CommandModifier == IOCM_EXECUTE_ATA &&
         pIORB->ControllerCmdLen == sizeof(PassThruATA) &&
         pIORB->pControllerCmd )
     {
        PPassThruATA             pPassThruATA = (PPassThruATA)(pIORB->pControllerCmd);

        if( pPassThruATA->TaskFileIn.Command == FX_ATAPI_IDENTIFY )
        {
           // WaitDRQ() sets pACB->State = ACBS_ERROR if no DRQ.  If the device is requesting
           // data transfer then the state is left alone and we proceed to read in the data.
           WaitDRQ( (NPACB)pACB );
        }
        else
        {
           pACB->State = ACBS_ERROR;
        }
     }
     else
     {
        pACB->State = ACBS_ERROR;
     }
     

     StartSM( (NPACB)pACB );                                        /*@V147576*/
  }
  else
  {
     _asm { int 3 }
  }

}

/*---------------------------------------------*/
/* DelayedRetry                                */
/* ------------                                */
/*                                             */
/*                                             */
/*                                             */
/*---------------------------------------------*/

VOID FAR DelayedRetry( ULONG hRetryTimer, PACB pACB, ULONG Unused )
{
  if ( pACB->RetryTimerHandle == hRetryTimer )
  {
    pACB->RetryTimerHandle = 0;
    ADD_CancelTimer( hRetryTimer );

    pACB->TimerFlags = 0;
    pACB->State = ACBS_RETRY;
    StartSM( (NPACB) pACB );                                        /*@V147576*/
  }
  else
  {
    _asm { int 3 }
  }

}

/*---------------------------------------------*/
/* DelayedReset                                */
/* ------------                                */
/*                                             */
/* This routine restarts the state machine to  */
/* determine if a reset has completed.         */
/*                                             */
/*---------------------------------------------*/

VOID FAR DelayedReset( ULONG hResetTimer, PACB pACB, ULONG Unused )
{
  if ( pACB->ResetTimerHandle == hResetTimer )
  {
    pACB->ResetTimerHandle = 0;
    ADD_CancelTimer( hResetTimer );

    pACB->State = ACBS_RESETCHECK;
    StartSM( (NPACB) pACB );                                        /*@V147576*/
  }
  else
  {
    _asm { int 3 }
  }

}

/*---------------------------------------------*/
/* ElapsedTimer                                */
/* ------------                                */
/*                                             */
/*                                             */
/*---------------------------------------------*/

VOID FAR ElapsedTimer( ULONG hElapsedTimer, ULONG Unused1, ULONG Unused2 )
{
  NPACB         npACB;
  USHORT        i;

  for ( i=0; i < MAX_ADAPTERS; i++ )
  {
    if ( npACB = ACBPtrs[i].npACB )
    {
      npACB->ElapsedTime += ELAPSED_TIMER_INTERVAL;
    }
  }
}

/*------------------------------------*/
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

VOID NEAR IODelay()
{
  ULONG   IODelayCtr = IODelayCount;

  while( IODelayCtr--)
    ;
}


