/* SCCSID = "src/dev/usb/USBAUDIO/AUDINTR.C, usb, c.basedd 98/07/10" */
/*
*   Licensed Material -- Property of IBM
*
*   (c) Copyright IBM Corp. 1998  All Rights Reserved
*/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  AUDINTR.C                                             */
/*                                                                            */
/*   DESCRIPTIVE NAME:  USB Audio device driver interrupt handler             */
/*                                                                            */
/*                                                                            */
/*   FUNCTION:  Processes data stream and calls stream handler via            */
/*              IDC (Inter Device Communication) to get/give data buffers.    */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*                   ReportFreeBuffer                                         */
/*                   ReportEvent                                              */
/*                   TimerInterruptHandler                                    */
/*                                                                            */
/*                                                                            */
/*   EXTERNAL REFERENCES: NONE   										               */
/*				                                                                  */
/*                                                                            */
/* Change Log                                                                 */
/*                                                                            */
/*  Mark    yy/mm/dd  Programmer          Comment                             */
/*  ----    --------  ----------          -------                             */
/*          98/10/17  Vjacheslav Chibis   Original developer.                 */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#define  INCL_DOS
#define  INCL_DOSINFOSEG
#include "usbaud.h"  // USB Audio driver master include file
/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  ReportFreeBuffer                                 */
/*                                                                    */
/* DESCRIPTIVE NAME:  System timer interrupt handler                  */
/*                                                                    */
/* FUNCTION:  The function of this routine is to report free buffer   */
/*            back to stream manager                                  */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  ReportFreeBuffer                                     */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PSTREAM pStream - pointer to stream type data structure    */
/*                                                                    */
/* EXIT-NORMAL: ALWAYS                                                */
/*                                                                    */
/* EXIT-ERROR: N/A                                                    */
/*                                                                    */
/* EFFECTS: pStream->ucBuffers                                        */
/*                                                                    */
/* INTERNAL REFERENCES:  ReportEvent                                  */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID ReportFreeBuffer(PSTREAM pStream)
{
   SHD_REPORTINT   ShdInt;

   if( pStream==NULL )   // to prevent GPF
      return;

 #ifdef DEBUG
   dsPrint2(DBG_SPECIFIC, "USBAUD: ReportFreeBuffer \tindex=%d \tpBuffer=%lxh\r\n", pStream->usLastIOBuffIndex, (ULONG)pStream->IOBuff[pStream->usLastIOBuffIndex].pBuffer);
 #endif
 
 if (!pStream->ucBuffers) 
 {
    #ifdef DEBUG
    dsPrint(DBG_CRITICAL, "USBAUD : ReportFreeBuffer : No buffers! Exiting...\r\n");
    #endif
    return ;
 }
    
   pStream->IOBuff[pStream->usLastIOBuffIndex].bEmpty=TRUE;  //  shows that we can fill this buffer again

   // fills all required data structures to report free buffer to stream handler
   ShdInt.ulFlag         = SHD_WRITE_COMPLETE ;
   ShdInt.ulFunction     = SHD_REPORT_INT ;
   ShdInt.pBuffer        = pStream->IOBuff[pStream->usLastIOBuffIndex].pBuffer; /* pass back data buffer ptr */
   ShdInt.hStream        = pStream->hStream;
   ShdInt.ulStatus       = pStream->IOBuff[pStream->usLastIOBuffIndex].lCount; /* pass back # of bytes in data buffer */
   ShdInt.ulStreamTime   = pStream->ulCumTime;

   //  decremet number of fileed buffers
   if( pStream->ucBuffers )
      pStream->ucBuffers--;

   // IDC call to Stream Handler        
   ((PSHDFN)pStream->ADSHEntry)(&ShdInt);
}


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  ReportEvent                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Report event                                    */
/*                                                                    */
/* FUNCTION:  The function of this routine is to report stream time   */
/*            requseted by stream handler                             */
/*                                                                    */
/* NOTES:  none                                                       */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  ReportEvent                                          */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PSTREAM pStream  - pointer to stream type data structure   */
/*         BOOL bResetEvent - shows if we have to check time or bypass*/
/*                                checking and report anyway          */
/*                                                                    */
/* EXIT-NORMAL: ALWAYS                                                */
/*                                                                    */
/* EXIT-ERROR: N/A                                                    */
/*                                                                    */
/* EFFECTS:       pEvent->hEvent                                      */
/*                pEvent->ulCuePoint                                  */
/*                                                                    */
/* INTERNAL REFERENCES:  none                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  none                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/



VOID ReportEvent(PSTREAM pStream, BOOL bResetEvent)
{
   BOOL            bEventFound = FALSE;
   EVENT_QUEUE     *pEvent = pStream->pEventQueue;
   SHD_REPORTEVENT shdEvent;
   register USHORT i;


   //search for the event
   for( i = 0; i < MAX_EVENT_QUEUE; i++ )
   {
      if( pEvent->hEvent != (HEVENT)(-1) )
      {
         bEventFound = TRUE;
         break;
      }
      pEvent++;
   }

   // if no event pending or not found and not reset event mode, exit  or event time not expired //
   if( !bEventFound)
      return;

   if( !bResetEvent )
   {
      if( pStream->ulCumTime < pEvent->ulCuePoint ) // Event expired: notify stream handler //
         return;
   }

   //  first set up the parameter block  //
   shdEvent.ulFunction   = SHD_REPORT_EVENT;
   shdEvent.hStream      = pStream->hStream;
   shdEvent.hEvent       = pEvent->hEvent;
   shdEvent.ulStreamTime = bResetEvent?pStream->ulCumTime:pEvent->ulCuePoint;

   #ifdef DEBUG
   dsPrint2(DBG_SPECIFIC, "USBAUD: RepEvent=%lxh ulCuePoint=%lxh\r\n", pStream->ulCumTime, pEvent->ulCuePoint);
   #endif

   // Clean up the node //

   pEvent->hEvent = (HEVENT)(-1);
   pEvent->ulCuePoint = 0L;

   ((PSHDFN)pStream->ADSHEntry)(&shdEvent); // calls the stream handler //

}         


/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  TimerInterruptHandler                            */
/*                                                                    */
/* DESCRIPTIVE NAME:  System timer interrupt handler                  */
/*                                                                    */
/* FUNCTION:  The function of this routine is to handle system        */
/*            timer interrupt and calculate streaming time            */
/*                                                                    */
/* NOTES:  Stream time is incremented by the value of 32 ms           */
/*                                                                    */
/* CONTEXT: Interrupt time                                            */
/*                                                                    */
/* ENTRY POINT:  TimerInterruptHandler                                */
/*    LINKAGE:  CALL FAR                                              */
/*                                                                    */
/* INPUT:  None                                                       */
/*                                                                    */
/* EXIT-NORMAL: ALWAYS                                                */
/*                                                                    */
/* EXIT-ERROR: N/A                                                    */
/*                                                                    */
/* EFFECTS: GlobalTable.paStream->ulCumTime                           */
/*                                                                    */
/* INTERNAL REFERENCES:  ReportEvent                                  */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

VOID FAR TimerInterruptHandler(VOID)
{
   PSTREAM pStream = GlobalTable.paStream;

   if( (pStream->ulFlags&STREAM_STREAMING) && gNoOfActiveAudioDevices && gbActiveDeviceSupport )
   {
      pStream->ulCumTime+=gTicks;  // calculates stream time
      ReportEvent(pStream, FALSE); // report event t stream handler
   }
}
