/******************************************************************************\
*                                                                              *
*      ADAPTER.C  -     Adapter control related code.                          *
*                                                                              *
*      Copyright (c) C-Cube Microsystems 1996 - 1999                                 *
*      All Rights Reserved.                                                    *
*                                                                              *
*      Use of C-Cube Microsystems code is governed by terms and conditions     *
*      stated in the accompanying licensing statement.                         *
*                                                                              *
\******************************************************************************/


#include "Headers.h"

#pragma hdrstop
#include "vidstrm.h"
#include "audstrm.h"
#include "sbpstrm.h"
#include "ccaption.h"

#ifdef ENCORE
#include "avwinwdm.h"
#include "anlgstrm.h"
#else
#include "vpestrm.h"
#include "dataXfer.h"
#endif

#include "zivaguid.h"
#include "boardio.h"
#include "bmaster.h"
#include "cl6100.h"

#include "Hwif.h"

static VOID HwInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID HwUninitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID AdapterOpenStream( PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID AdapterCloseStream( PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID AdapterStreamInfo( PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID AdapterGetDataIntersection( PHW_STREAM_REQUEST_BLOCK pSrb );

static VOID BeginHwInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID HighPriorityInit( IN PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID PassiveInit( IN PHW_STREAM_REQUEST_BLOCK pSrb );
static VOID HighPriorityInit( IN PHW_STREAM_REQUEST_BLOCK pSrb );

VOID STREAMAPI AdapterReleaseCurrentSrb( PHW_STREAM_REQUEST_BLOCK pSrb );

#pragma alloc_text( page, HwInitialize )
#pragma alloc_text( page, HwUninitialize )


#if 0
static void STREAMAPI CreateFile(PHW_STREAM_REQUEST_BLOCK pSrb );
OBJECT_ATTRIBUTES	InitializedAttributes;
IO_STATUS_BLOCK		IOStatusBlock;
HANDLE	Handle;
WCHAR		wPath[] = L"ohm.dat";
UNICODE_STRING		pathUnicodeString;
LARGE_INTEGER		AllocSize ;
long dwCountTotal=0;
#endif

PHW_DEVICE_EXTENSION pDevEx;


/******************************************************************************

                   Adapter Based Request Handling Routines

******************************************************************************/

/*
** AdapterReceivePacket()
**
**   Main entry point for receiving adapter based request SRBs.  This routine
**   will always be called at High Priority.
**
**   Note: This is an asyncronous entry point.  The request does not complete
**         on return from this function, the request only completes when a
**         StreamClassDeviceNotification on this request block, of type
**         DeviceRequestComplete, is issued.
**
** Arguments:
**
**   pSrb - Pointer to the STREAM_REQUEST_BLOCK
**        pSrb->HwDeviceExtension - will be the hardware device extension for
**                                  as initialised in HwInitialise
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReceivePacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{	
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->CommandData.ConfigInfo->HwDeviceExtension;
	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin AdapterReceivePacket->" ));

#ifdef DEBUG
	if( KeGetCurrentIrql() <= DISPATCH_LEVEL )
	{
		DebugPrint(( DebugLevelError, "IRQL is screwed!\n" ));
		ASSERT( FALSE );
		MonoOutSetBlink( TRUE );
		MonoOutStr( "IRQL" );
		MonoOutSetBlink( FALSE );
	}
#endif

	switch( pSrb->Command )
	{
	case SRB_INITIALIZE_DEVICE:
		DebugPrint(( DebugLevelVerbose, "SRB_INITIALIZE_DEVICE\n" ));
	
//		HwInitialize( pSrb );
//		break;
		BeginHwInitialize( pSrb ); //MS update
		return;


	case SRB_UNINITIALIZE_DEVICE:
		DebugPrint(( DebugLevelVerbose, "SRB_UNINITIALIZE_DEVICE\n" ));
		HwUninitialize( pSrb );
		break;

	case SRB_OPEN_STREAM:
		DebugPrint(( DebugLevelVerbose, "SRB_OPEN_STREAM\n" ));
		AdapterOpenStream( pSrb );
		break;

	case SRB_CLOSE_STREAM:
		DebugPrint(( DebugLevelVerbose, "SRB_CLOSE_STREAM\n" ));
		AdapterCloseStream( pSrb );
		break;

	case SRB_GET_STREAM_INFO:
		DebugPrint(( DebugLevelVerbose, "SRB_GET_STREAM_INFO\n" ));
		AdapterStreamInfo( pSrb );
		break;

	case SRB_GET_DATA_INTERSECTION:
		DebugPrint(( DebugLevelVerbose, "SRB_GET_DATA_INTERSECTION\n" ));
		AdapterGetDataIntersection( pSrb );
		break;


	case SRB_GET_DEVICE_PROPERTY:
		AdapterGetProperty( pSrb );
		MonoOutStr("SRB_GET_DEVICE_PROPERTY");
		break;

	case SRB_SET_DEVICE_PROPERTY:
		AdapterSetProperty( pSrb );
		MonoOutStr("SRB_SET_DEVICE_PROPERTY");
		break;



	case SRB_CHANGE_POWER_STATE:
		DebugPrint(( DebugLevelVerbose, "SRB_CHANGE_POWER_STATE\n" ));
#if defined(DECODER_DVDPC)
    if (pSrb->CommandData.DeviceState == PowerDeviceD0)
    {
        //
        // bugbug - need to turn power back on here.
        //
		// Vinod.
//sri		ZivaHw_Initialize(pHwDevExt);
//		Commented for bug fix on GateWay Chameleon

    }
    else
    {
        //
        // bugbug - need to turn power off here, as well as disabling
        // interrupts.
        //
        //DisableIT();
    }
#endif
		pSrb->Status = STATUS_SUCCESS;
		break;

	case SRB_PAGING_OUT_DRIVER:
		DebugPrint(( DebugLevelVerbose, "SRB_PAGING_OUT_DRIVER\n" ));
		//TRAP
		//DisableIT();
		pSrb->Status = STATUS_SUCCESS;
		break;


	default:
		DebugPrint(( DebugLevelInfo, "!!!! UNKNOWN COMMAND !!!! :::> %X\n", pSrb->Command ));
		// This is a request that we do not understand. Indicate invalid
		// command and complete the request
		pSrb->Status = STATUS_NOT_IMPLEMENTED;
	}
	
	AdapterReleaseRequest( pSrb );
	DebugPrint(( DebugLevelVerbose, "ZiVA: End AdapterReceivePacket\n" ));
}

/******************************************************************************/
/*******************  Adapter Initialization Section  *************************/
/******************************************************************************/



/*
** BeginHwInitialize()
**
** Stub for the init sequence
**
** Arguments:
**
**   pSRB - pointer to the request packet for the initialise command
**
**    ->ConfigInfo - provides the I/O port, memory windows, IRQ, and DMA levels
**                that should be used to access this instance of the device
**
** Returns:
**
**
**
** Side Effects:  none
*/
static VOID BeginHwInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;

	DebugPrint(( DebugLevelVerbose, "ZiVA: BeginHwInitialize()\n" ));
   StreamClassCallAtNewPriority(NULL, pHwDevExt, Low, PassiveInit, pSrb);
	return;
   
}
/*
** PassiveInit()
**
** Passive level callback for the init sequence
**
** Arguments:
**
**   pSRB - pointer to the request packet for the initialise command
**
**    ->ConfigInfo - provides the I/O port, memory windows, IRQ, and DMA levels
**                that should be used to access this instance of the device
**
** Returns:
**
**
**
** Side Effects:  none
*/
static VOID PassiveInit( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;

	InitializeHost(pSrb);
   StreamClassCallAtNewPriority(NULL, pHwDevExt, LowToHigh, HighPriorityInit, pSrb);
   return;
}


/*
** HighPriorityInit()
**
** High priority callback for the init sequence
**
** Arguments:
**
**   pSRB - pointer to the request packet for the initialise command
**
**    ->ConfigInfo - provides the I/O port, memory windows, IRQ, and DMA levels
**                that should be used to access this instance of the device
**
** Returns:
**
**
**
** Side Effects:  none
*/
static VOID HighPriorityInit( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{

   HwInitialize(pSrb);
   
	AdapterReleaseRequest( pSrb );
}




/*
** HwInitialize()
**
**   Initializes an adapter accessed through the information provided in the
**   ConfigInfo structure
**
** Arguments:
**
**   pSRB - pointer to the request packet for the initialise command
**
**    ->ConfigInfo - provides the I/O port, memory windows, IRQ, and DMA levels
**                that should be used to access this instance of the device
**
** Returns:
**
**       STATUS_SUCCESS - if the card initializes correctly
**       STATUS_NO_SUCH_DEVICE - or other if the card is not found, or does
**                               not initialize correctly.
**
**
** Side Effects:  none
*/
static VOID HwInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
	ULONG dwSize;

	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin HwInitialize()\n" ));
	
//	InitializeHost(pSrb);

	pHwDevExt->bVideoStreamOpened			= FALSE;
	pHwDevExt->bAudioStreamOpened			= FALSE;
	pHwDevExt->bSubPictureStreamOpened		= FALSE;
	pHwDevExt->bOverlayInitialized			= FALSE;
	pHwDevExt->nAnalogStreamOpened			= 0;
	pHwDevExt->iTotalOpenedStreams			= 0;

	pHwDevExt->bVideoCanAuthenticate		= FALSE;
	pHwDevExt->bAudioCanAuthenticate		= FALSE;
	pHwDevExt->bSubPictureCanAuthenticate	= FALSE;
	pHwDevExt->iStreamToAuthenticateOn		= -1;

	pHwDevExt->bValidSPU					= FALSE;
	pHwDevExt->hli.StartPTM					= 0;

	pHwDevExt->pCurrentVideoSrb				= NULL;
	pHwDevExt->dwCurrentVideoSample			= 0;
	pHwDevExt->pCurrentAudioSrb				= NULL;
	pHwDevExt->dwCurrentAudioSample			= 0;
	pHwDevExt->pCurrentSubPictureSrb		= NULL;
	pHwDevExt->dwCurrentSubPictureSample	= 0;
	pHwDevExt->CurrentlySentStream			= ZivaNumberOfStreams;	// Just make sure it is none of them
	pHwDevExt->wNextSrbOrderNumber			= 0;
	pHwDevExt->bInterruptPending			= FALSE;
	pHwDevExt->bPlayCommandPending			= FALSE;
	pHwDevExt->bScanCommandPending			= FALSE;
	pHwDevExt->bSlowCommandPending			= FALSE;

	pHwDevExt->nStopCount					= 0;
	pHwDevExt->nPauseCount					= 0;
	pHwDevExt->nPlayCount					= 0;
	pHwDevExt->nTimeoutCount				= AUTHENTICATION_TIMEOUT_COUNT;

	pHwDevExt->NewRate						= 10000;
	pHwDevExt->bToBeDiscontinued			= FALSE;
	pHwDevExt->bDiscontinued				= FALSE;
	pHwDevExt->bAbortAtPause				= FALSE;
	pHwDevExt->bRateChangeFromSlowMotion	= FALSE;
	pHwDevExt->dwVideoDataUsed				=0;
	pHwDevExt->dwAudioDataUsed				=0;
	pHwDevExt->dwSubPictureDataUsed			=0;
	
	pHwDevExt->bEndFlush					= FALSE;
	pHwDevExt->bTimerScheduled				= FALSE;
	
	pHwDevExt->dwCurrentVideoPage			= 0;
	pHwDevExt->dwCurrentAudioPage			= 0;
	pHwDevExt->dwCurrentSubPicturePage		= 0;

	pHwDevExt->bStreamNumberCouldBeChanged	= FALSE;
	pHwDevExt->wCurrentStreamNumber			= -1;

	pHwDevExt->bSwitchDecryptionOn			= FALSE;
	pHwDevExt->zInitialState				= ZIVA_STATE_STOP;
	
	pHwDevExt->bHliPending					= FALSE;
		

	pHwDevExt->gdwCount						= 0;

	pHwDevExt->dwFirstVideoOrdNum			= -1;
	pHwDevExt->dwFirstAudioOrdNum			= -1;
	pHwDevExt->dwFirstSbpOrdNum				= -1;

	pHwDevExt->dwVSyncCount					=0;
	pHwDevExt->nApsMode						= -1;
	pHwDevExt->VidSystem					= -1;
	pHwDevExt->ulLevel						=0;
	pHwDevExt->fAtleastOne					= TRUE;
	
	pHwDevExt->dwPrevSTC					= 0;
	pHwDevExt->bTrickModeToPlay				=FALSE;
	pHwDevExt->prevStrm						=0;
	pHwDevExt->fFirstSTC					= FALSE;


	pHwDevExt->cCCRec=0;
	pHwDevExt->cCCDeq=0;
	pHwDevExt->cCCCB=0;
	pHwDevExt->cCCQ=0;
	pHwDevExt->pstroCC = NULL;
   
	
	pHwDevExt->dwUserDataSize=0;
	pHwDevExt->fReSync = FALSE;

	pHwDevExt->bInitialized = TRUE;

	pDevEx = pHwDevExt ;

	

	pHwDevExt->pPhysicalDeviceObj			= ConfigInfo->PhysicalDeviceObject;
	pHwDevExt->pDiscKeyBufferLinear			= (PUCHAR)StreamClassGetDmaBuffer( pHwDevExt );
	pHwDevExt->pDiscKeyBufferPhysical		= StreamClassGetPhysicalAddress(
															pHwDevExt,
															NULL,
															pHwDevExt->pDiscKeyBufferLinear,
															DmaBuffer,
															&dwSize );

	// Indicate the size of the structure necessary to describe all streams
	// that are supported by this hardware
	ConfigInfo->StreamDescriptorSize = sizeof( HW_STREAM_HEADER )+	// Stream header and
			ZivaNumberOfStreams * sizeof( HW_STREAM_INFORMATION );	// stream descriptors

	
	pHwDevExt->pCCDevEx = pHwDevExt;
	pSrb->Status = STATUS_SUCCESS;
#if defined (LOAD_UCODE_FROM_FILE)
	// Do nothing.
#else
	if( !ZivaHw_Initialize( pHwDevExt ) || !InitializeOutputStream( pSrb ))
		pSrb->Status = STATUS_IO_DEVICE_ERROR;
#endif

	DebugPrint(( DebugLevelVerbose, "ZiVA: End HwInitialize()\n" ));
}


/*
** HwUninitialize()
**
**   Release all resources and clean up the hardware
**
** Arguments:
**
**      DeviceExtension - pointer to the deviceextension structure for the
**                       the device to be free'd
**
** Returns:
**
** Side Effects:  none
*/
static VOID HwUninitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin HwUninitialize()\n" ));
#ifdef ENCORE
	AnalogUninitialize( pSrb );
#else
	pSrb->Status = STATUS_SUCCESS;
#endif
	DebugPrint(( DebugLevelVerbose, "ZiVA: End HwUninitialize()\n" ));
}

/*
** AdapterOpenStream()
**
**   This routine is called when an OpenStream SRB request is received
**
** Arguments:
**
**   pSrb - pointer to stream request block for the Open command
**
** Returns:
**
** Side Effects:  none
*/
static VOID AdapterOpenStream( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	int i;
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;

	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin AdapterOpenStream\n" ));
	pSrb->Status = STATUS_TOO_MANY_NODES;

	for( i = 0; i < SIZEOF_ARRAY( infoStreams ); i++ )
	{
		if( infoStreams[i].hwStreamObject.StreamNumber == pSrb->StreamObject->StreamNumber )
		{	// This is the stream we're interested in.
			// Then copy stream object structure into passed buffer
			PVOID pHwStreamExtension = pSrb->StreamObject->HwStreamExtension;
			*(pSrb->StreamObject) = infoStreams[i].hwStreamObject;
			pSrb->StreamObject->HwStreamExtension = pHwStreamExtension;
			pSrb->StreamObject->HwDeviceExtension = pHwDevExt;
			pSrb->Status = STATUS_SUCCESS;
			break;
		}
	}

	if( pSrb->Status == STATUS_SUCCESS )
	{
		++pHwDevExt->iTotalOpenedStreams;
		++pHwDevExt->nStopCount;
		++pHwDevExt->nPauseCount;
		++pHwDevExt->nPlayCount;
		
		switch( pSrb->StreamObject->StreamNumber )
		{
		case ZivaVideo:
			pHwDevExt->bVideoStreamOpened = TRUE;
#if defined(DECODER_DVDPC) || defined(EZDVD)
			ProcessVideoFormat( pSrb->CommandData.OpenFormat, pHwDevExt );
#endif
			
			
			break;

		case ZivaAudio:
			pHwDevExt->bAudioStreamOpened = TRUE;
			pHwDevExt->pstroAud = pSrb->StreamObject;
			break;

		case ZivaSubpicture:
			pHwDevExt->bSubPictureStreamOpened = TRUE;
			break;

#ifdef ENCORE
		case ZivaAnalog:
			++pHwDevExt->nAnalogStreamOpened;
			AnalogOpenStream( pSrb );

			break;
#endif			

#if defined(DECODER_DVDPC) || defined(EZDVD)
		case ZivaYUV:
			pHwDevExt->pstroYUV = pSrb->StreamObject;
			pSrb->StreamObject->HwEventRoutine = (PHW_EVENT_ROUTINE) CycEvent;
			break;
#endif

		case ZivaCCOut:
			pHwDevExt->pstroCC = pSrb->StreamObject;
			break;

		default:
			ASSERT( FALSE );
		}
	}
	else
		DebugPrint(( DebugLevelWarning, "ZiVA: !!! Strange Stream Number\n" ));
	
	if ( pHwDevExt->iTotalOpenedStreams == 1 )
	{
		pHwDevExt->dwVideoDataUsed				= 0;
		pHwDevExt->dwAudioDataUsed				= 0;
		pHwDevExt->dwSubPictureDataUsed			= 0;
		pHwDevExt->bStreamNumberCouldBeChanged	= FALSE;
		pHwDevExt->wCurrentStreamNumber			= -1;
		pHwDevExt->bSwitchDecryptionOn			= FALSE;
		pHwDevExt->zInitialState				= ZIVA_STATE_STOP;
	
		
		pHwDevExt->bEndFlush					= FALSE;
		pHwDevExt->bTimerScheduled = FALSE;

		if ( !ZivaHw_Initialize( pHwDevExt ) )
		{
			DebugPrint((DebugLevelFatal,"ZiVA: Could not Initialize the HW on first Stream Open\n"));
			pSrb->Status = STATUS_NOT_IMPLEMENTED;
		}
		
	 }


	DebugPrint(( DebugLevelVerbose, "ZiVA: End AdapterOpenStream\n" ));
}


/*
** AdapterCloseStream()
**
**   Close the requested data stream
**
** Arguments:
**
**   pSrb the request block requesting to close the stream
**
** Returns:
**
** Side Effects:  none
*/

static VOID AdapterCloseStream( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;

	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin AdapterCloseStream\n" ));
	pSrb->Status = STATUS_SUCCESS;

	ASSERT( pHwDevExt->nStopCount == pHwDevExt->iTotalOpenedStreams );
	ASSERT( pHwDevExt->nPauseCount == pHwDevExt->iTotalOpenedStreams );
	ASSERT( pHwDevExt->nPlayCount == pHwDevExt->iTotalOpenedStreams );
	--pHwDevExt->iTotalOpenedStreams;
	--pHwDevExt->nStopCount;
	--pHwDevExt->nPauseCount;
	--pHwDevExt->nPlayCount;
	// Determine which stream number is being closed. This number indicates
	// the offset into the array of streaminfo structures that was filled out
	// in the AdapterStreamInfo call.
	switch( pSrb->StreamObject->StreamNumber )
	{
	case ZivaVideo:
		pHwDevExt->bVideoStreamOpened = FALSE;
		break;

	case ZivaAudio:
		pHwDevExt->bAudioStreamOpened = FALSE;
		pHwDevExt->pstroAud = NULL;
		break;

	case ZivaSubpicture:
		pHwDevExt->bSubPictureStreamOpened = FALSE;
		break;
#ifdef ENCORE
	case ZivaAnalog:
		--pHwDevExt->nAnalogStreamOpened;
		AnalogCloseStream( pSrb );
		break;
#endif
#if defined(DECODER_DVDPC) || defined(EZDVD)
	case ZivaYUV:
		pHwDevExt->pstroYUV = NULL;
        pHwDevExt->VideoPort = 0;   // Disable
		break;
#endif


	case ZivaCCOut:
		CleanCCQueue(pHwDevExt);
		pHwDevExt->pstroCC = NULL;

		break;

	default:
		++pHwDevExt->iTotalOpenedStreams;
		++pHwDevExt->nStopCount;
		++pHwDevExt->nPauseCount;
		++pHwDevExt->nPlayCount;
		DebugPrint(( DebugLevelWarning, "ZiVA: !!! Strange Stream Number\n" ));
		ASSERT( FALSE );
		pSrb->Status = STATUS_NOT_IMPLEMENTED;
		//TRAP
	}

	//
	// Reset the Authenticated Stream if anyone is being closed
	//
	pHwDevExt->iStreamToAuthenticateOn = -1;

	//
	// Reset the HW on last Stream Close
	//
	if( pHwDevExt->iTotalOpenedStreams == 0 )
	{
		pHwDevExt->wNextSrbOrderNumber = 0;
		// Make sure next Authentication request will be postponed
		// until "last packet" flag has come on each stream.
		AdapterClearAuthenticationStatus( pHwDevExt );


		// Clean up the hardware
		if( !ZivaHw_Reset() )
		{
			DebugPrint(( DebugLevelError, "ZiVA: Could not Reset the HW on last Stream Closed\n" ));
			pSrb->Status = STATUS_IO_DEVICE_ERROR;
		}
#if defined(ENCORE)
		else
			AnalogCloseStream( pSrb );
#endif
	}
#ifdef DEBUG
	if( pHwDevExt->iTotalOpenedStreams < 0 )
		DebugPrint(( DebugLevelWarning, "ZiVA: !!!!!!!!!!!!!!!!!! Open/Close streams mismatch !!!!!!!!!!!!!!!!\n" ));
#endif

	DebugPrint(( DebugLevelVerbose, "ZiVA: End AdapterCloseStream\n" ));
}

void AdapterInitLocals(PHW_DEVICE_EXTENSION pHwDevExt)
{
	pHwDevExt->pCurrentVideoSrb				= NULL;
	pHwDevExt->dwCurrentVideoSample			= 0;

	pHwDevExt->pCurrentAudioSrb				= NULL;
	pHwDevExt->dwCurrentAudioSample			= 0;

	pHwDevExt->pCurrentSubPictureSrb		= NULL;
	pHwDevExt->dwCurrentSubPictureSample	= 0;
	pHwDevExt->CurrentlySentStream			= ZivaNumberOfStreams;  // Just make sure it is none of them
	pHwDevExt->bInterruptPending			= FALSE;
	pHwDevExt->bPlayCommandPending			= FALSE;
	pHwDevExt->bScanCommandPending			= FALSE;
	pHwDevExt->bSlowCommandPending			= FALSE;
	pHwDevExt->bHliPending					= FALSE;
	pHwDevExt->NewRate						= 10000;

	pHwDevExt->dwVideoDataUsed				= 0;

	pHwDevExt->dwCurrentVideoPage			= 0;
	pHwDevExt->dwCurrentAudioPage			= 0;
	pHwDevExt->dwCurrentSubPicturePage		= 0;

	pHwDevExt->dwAudioDataUsed				= 0;
	pHwDevExt->dwSubPictureDataUsed			= 0;

	pHwDevExt->bToBeDiscontinued			= FALSE;
	pHwDevExt->bDiscontinued				= FALSE;
	pHwDevExt->bAbortAtPause				= FALSE;
	pHwDevExt->bRateChangeFromSlowMotion	= FALSE;

	pHwDevExt->gdwCount = 0;
	pHwDevExt->dwFirstVideoOrdNum			= -1;
	pHwDevExt->dwFirstAudioOrdNum			= -1;
	pHwDevExt->dwFirstSbpOrdNum				= -1;
	pHwDevExt->dwVSyncCount					=0;
	pHwDevExt->nApsMode						= -1;
	pHwDevExt->VidSystem					= -1;
	pHwDevExt->ulLevel						=0;
	pHwDevExt->fAtleastOne					= TRUE;

//temp 	pHwDevExt->dwPrevSTC					= 0;
	pHwDevExt->bTrickModeToPlay				=FALSE;
	pHwDevExt->prevStrm						=0;
	pHwDevExt->fFirstSTC					= TRUE;

	pHwDevExt->cCCRec=0;
	pHwDevExt->cCCDeq=0;
	pHwDevExt->cCCCB=0;
	pHwDevExt->cCCQ=0;
   
//	pHwDevExt->pstroCC = NULL;
//	pHwDevExt->dwUserDataBuffer[]={0};
	pHwDevExt->dwUserDataSize=0;
	pHwDevExt->fReSync = FALSE;
	CleanCCQueue(pHwDevExt);


#ifdef EZDVD
	ZivaHw_Initialize(pHwDevExt);
#endif

}



/*
** AdapterStreamInfo()
**
**   Returns the information of all streams that are supported by the
**   mini-driver
**
** Arguments:
**
**   pSrb - Pointer to the STREAM_REQUEST_BLOCK
**   pSrb->HwDeviceExtension - will be the hardware device extension for
**                                  as initialised in HwInitialise
**
** Returns:
**
** Side Effects:  none
*/
static VOID AdapterStreamInfo( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	int i;
	PHW_DEVICE_EXTENSION pdevext = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
	PHW_STREAM_HEADER pStrHdr = &(pSrb->CommandData.StreamBuffer->StreamHeader);
	PHW_STREAM_INFORMATION pstrinfo = &(pSrb->CommandData.StreamBuffer->StreamInfo);

	DebugPrint(( DebugLevelVerbose, "ZiVA: Begin AdapterStreamInfo\n" ));

	// Fill stream header structure
	pStrHdr->NumberOfStreams = ZivaNumberOfStreams;
	pStrHdr->SizeOfHwStreamInformation = sizeof( HW_STREAM_INFORMATION );
	pStrHdr->Topology = (PKSTOPOLOGY)&Topology;
#ifdef ENCORE
	pStrHdr->NumDevPropArrayEntries	= SIZEOF_ARRAY( psEncore );
	pStrHdr->DevicePropertiesArray	= (PKSPROPERTY_SET)psEncore;
#else
	pStrHdr->NumDevPropArrayEntries	= 0;
	pStrHdr->DevicePropertiesArray	= NULL;
#endif

	for( i = 0; i < SIZEOF_ARRAY( infoStreams ); i++, pstrinfo++ )
	{	// Copy stream information structure into passed buffer
		*pstrinfo = infoStreams[i].hwStreamInfo;
	}

	pSrb->Status = STATUS_SUCCESS;
	DebugPrint(( DebugLevelVerbose, "ZiVA: End AdapterStreamInfo\n" ));

}





/*
** AdapterGetDataIntersection()
**
**
**
** Arguments:
**
**
**
** Returns:
**
** Side Effects:
*/
static VOID AdapterGetDataIntersection( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PSTREAM_DATA_INTERSECT_INFO	IntersectInfo = pSrb->CommandData.IntersectInfo;
	PKSDATARANGE				DataRange = IntersectInfo->DataRange;
	PKSDATAFORMAT*				pFormat;
	ULONG						i, formatSize;

	if( IntersectInfo->StreamNumber >= ZivaNumberOfStreams )
	{	// Incorrect stream number
		pSrb->Status = STATUS_NOT_IMPLEMENTED;
		return;
	}

	pSrb->Status = STATUS_NO_MATCH;
#if defined (ENCORE)
	if( IntersectInfo->StreamNumber == ZivaAnalog )
	{
		PKSDATAFORMAT pFrmt = (PKSDATAFORMAT)&ZivaFormatAnalogOverlayOut;
		pFormat = &pFrmt;
	}



/*	else if(IntersectInfo->StreamNumber == ZivaCCOut)
	{
//		*pFormat = &hwfmtiCCOut;
//		formatSize = sizeof hwfmtiCCOut;
		MonoOutStr("CCOut");
		pFormat = infoStreams[IntersectInfo->StreamNumber].hwStreamInfo.StreamFormatsArray;
	}*/
	else
#endif
		pFormat = infoStreams[IntersectInfo->StreamNumber].hwStreamInfo.StreamFormatsArray;

	for( i = 0; i < infoStreams[IntersectInfo->StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
			pFormat++, i++ )
	{	// Check format
		formatSize = (*pFormat)->FormatSize;
#if defined (ENCORE)
		if( IntersectInfo->StreamNumber != ZivaAnalog && DataRange->FormatSize != formatSize )
			continue;
#endif
		if( IsEqualGUID( &DataRange->MajorFormat, &((*pFormat)->MajorFormat) ) &&
			IsEqualGUID( &DataRange->SubFormat, &((*pFormat)->SubFormat) ) &&
			IsEqualGUID( &DataRange->Specifier, &((*pFormat)->Specifier) ) )
		{
			pSrb->Status = STATUS_SUCCESS;
			break;
		}
	}
	if( pSrb->Status != STATUS_SUCCESS )
		return;

	// Check to see if the size of the passed in buffer is a ULONG.
	// if so, this indicates that we are to return only the size
	// needed, and not return the actual data.
	if( IntersectInfo->SizeOfDataFormatBuffer != sizeof( ULONG ) )
	{	//
		// we are to copy the data, not just return the size
		//
		if( IntersectInfo->SizeOfDataFormatBuffer < formatSize )
			pSrb->Status = STATUS_BUFFER_TOO_SMALL;
		else
		{
			RtlCopyMemory( IntersectInfo->DataFormatBuffer,  *pFormat, formatSize );
			pSrb->ActualBytesTransferred = formatSize;
			pSrb->Status = STATUS_SUCCESS;
		}
	}
	else	// if sizeof ULONG specified
	{
		// Caller wants just the size of the buffer. Get that.
		*(PULONG)IntersectInfo->DataFormatBuffer = formatSize;
		pSrb->ActualBytesTransferred = sizeof( ULONG );
	}	// if sizeof ULONG
}


VOID STREAMAPI adapterUpdateNextSrbOrderNumberOnDiscardSrb( PHW_STREAM_REQUEST_BLOCK pSrb )
{
  PHW_DEVICE_EXTENSION  pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
  ULONG  ulSample;
  KSSTREAM_HEADER * pHeader;
  WORD wMaxDiscardedOrderNumber = 0;

  for( ulSample = 0; ulSample < pSrb->NumberOfBuffers; ulSample++ )
  {
    pHeader    = ((PKSSTREAM_HEADER)pSrb->CommandData.DataBufferArray) + ulSample;
    wMaxDiscardedOrderNumber = max( (WORD)((pHeader->TypeSpecificFlags) >> 16), wMaxDiscardedOrderNumber );
  }

  if ( wMaxDiscardedOrderNumber >= pHwDevExt->wNextSrbOrderNumber )
  {
    pHwDevExt->wNextSrbOrderNumber = wMaxDiscardedOrderNumber + 1;
    MonoOutStr( "<<< Updating NextSrbOrderNumber to " );
    MonoOutULong( pHwDevExt->wNextSrbOrderNumber );
    MonoOutStr( " >>>" );
  }

  return ;
}


/*
** MoveToNextSample()
**
**  This routine is being called when there is a need to move
**  to the next Sample(buffer) in the current Srb.
**
** Arguments:
**    pSrb - the request block to advance Sample Number.
**
** Returns:
**    TRUE  - Successfuly moved to next Sample
**    FALSE - There was no more samples and current Srb was released
**
** Side Effects:  unknown
*/
BOOLEAN STREAMAPI MoveToNextSample( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
	DWORD* pdwCurrentSrbSample;
	DWORD* pdwCurrentSrbPage;

	switch( pSrb->StreamObject->StreamNumber )
	{
	case ZivaVideo:
		pdwCurrentSrbSample = &pHwDevExt->dwCurrentVideoSample;
		pdwCurrentSrbPage = &pHwDevExt->dwCurrentVideoPage;
		break;
	case ZivaAudio:
		pdwCurrentSrbSample = &pHwDevExt->dwCurrentAudioSample;
		pdwCurrentSrbPage = &pHwDevExt->dwCurrentAudioPage;
		break;
	case ZivaSubpicture:
		pdwCurrentSrbSample = &pHwDevExt->dwCurrentSubPictureSample;
		pdwCurrentSrbPage = &pHwDevExt->dwCurrentSubPicturePage;
		break;
	default:
		MonoOutStr( "!!!!!!!!!!!!!!!!!!! WRONG STREAM # IN MoveToNextSample ROUTINE !!!!!!!!!!!!!!!!!!!!!!!!!!!" );
		return FALSE;
	}
//	if(dwDataUsed == 0)
//	{
		(*pdwCurrentSrbSample)++;
//		pHwDevExt->wNextSrbOrderNumber++;
//	}
	(*pdwCurrentSrbPage)++;
	if( *pdwCurrentSrbSample >= pSrb->NumberOfBuffers)
	{
		if( *pdwCurrentSrbSample > pSrb->NumberOfBuffers )
		{
			MonoOutSetBlink( TRUE );
			MonoOutStr( "<<< Current sample number is higher than the number of buffers >>>" );
			MonoOutSetBlink( FALSE );
		}
//		MonoOutStr("MoveToNextSample()::RSRB");
		AdapterReleaseCurrentSrb( pSrb );
		return FALSE;
	}

	return TRUE;
}




VOID CancelPacket( PHW_STREAM_REQUEST_BLOCK pSrb, BOOL bCancel )
{
	PHW_DEVICE_EXTENSION	pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
	ULONG					ulSample;
	PKSSTREAM_HEADER		pHeader;
	WORD					wMaxOrder = 0, wMinOrder = 0xFFFF;
#ifdef DEBUG
	LPSTR					pszFuncString, pszPacketString = NULL;

	pszFuncString = bCancel ? "Cancel" : "Timeout";
	DebugPrint(( DebugLevelVerbose,"ZiVA: Adapter%sPacket ->", pszFuncString ));
	MonoOutSetUnderscore( TRUE );
	MonoOutChar( ' ' );
	MonoOutStr( pszFuncString );
	MonoOutStr( "->" );
#endif

	if( !(pSrb->Flags & SRB_HW_FLAGS_DATA_TRANSFER) )
	{
		DebugPrint(( DebugLevelVerbose," As a Control\n" ));
		MonoOutStr( "(Control or Device)" );
		AdapterReleaseRequest( pSrb );
		return;
	}


	// We need to find this packet, pull it off our queues, and cancel it
	// Try to find this Srb in the Pending List. If it's there just
	// empty the slot
	if(bCancel)
	{
		if( pHwDevExt->pCurrentVideoSrb == pSrb )
		{
#ifdef DEBUG
			pszPacketString = "Video";
#endif
			pHwDevExt->pCurrentVideoSrb = NULL;
			pHwDevExt->dwCurrentVideoSample = 0;
			pHwDevExt->dwCurrentVideoPage = 0;
			pHwDevExt->dwVideoDataUsed	=0;
		}
		else if( pHwDevExt->pCurrentAudioSrb == pSrb )
		{
#ifdef DEBUG
			pszPacketString = "Audio";
#endif
			pHwDevExt->pCurrentAudioSrb = NULL;
			pHwDevExt->dwCurrentAudioSample = 0;
			pHwDevExt->dwCurrentAudioPage = 0;
			pHwDevExt->dwAudioDataUsed = 0;
		
		
		}
		else if( pHwDevExt->pCurrentSubPictureSrb == pSrb )
		{
#ifdef DEBUG
			pszPacketString = "Subpicture";
#endif
			pHwDevExt->pCurrentSubPictureSrb = NULL;
			pHwDevExt->dwCurrentSubPictureSample = 0;
			pHwDevExt->dwCurrentSubPicturePage = 0;
			pHwDevExt->dwSubPictureDataUsed = 0;
		}
	}
	else	//added 11/6/98
	{
		if( pHwDevExt->bInterruptPending )
			MoveToNextSample( pSrb );
	}

#ifdef DEBUG
	if( pszPacketString )
	{
		DebugPrint(( DebugLevelVerbose, pszPacketString ));
		MonoOutStr( pszPacketString );
	}
#endif

	// Reset the HW if it was the currently sending Srb.
	// It usually means that hardware messed up so we'll schedule "play",
	// "slow motion" or "scan" commands if one of them was in effect, reset
	// hardware and cancel this packet

	if( pHwDevExt->CurrentlySentStream == (ZIVA_STREAM)pSrb->StreamObject->StreamNumber )
	{
		ZIVA_STATE zState;

		DebugPrint(( DebugLevelVerbose, "Current" ));
		MonoOutStr( " Current Strm# " );
		MonoOutInt( pSrb->StreamObject->StreamNumber );

		// This request is in a middle of a Bus Master transferring and most likely
		// that the interrupt is pending. If so we have to reset the
		// Bus Master device.
		if( pHwDevExt->bInterruptPending )
		{
			pHwDevExt->bInterruptPending = FALSE;
			MonoOutStr( " Cancel pending interrupt" );
		}

		// Lets do a clean start (Abort->Play) for the upcoming stream
		zState = ZivaHw_GetState();
		if( zState != ZIVA_STATE_STOP )
		{
			MonoOutStr( " Aborting" );
			
			if( !ZivaHw_Abort() )
				ZivaHw_Reset();
			
			pHwDevExt->bInterruptPending = FALSE;

			pHwDevExt->bScanCommandPending = TRUE;
			
		}

		// Clean the CurrentlySentStream
		pHwDevExt->CurrentlySentStream = ZivaNumberOfStreams;
	}




	if(bCancel)
		pSrb->Status = STATUS_CANCELLED;
	
	// It is necessary to call the request back correctly.  Determine which type of
	// command it is and then find all stream commands, and do stream notifications
	switch( pSrb->Flags & (SRB_HW_FLAGS_DATA_TRANSFER | SRB_HW_FLAGS_STREAM_REQUEST) )
	{
	case SRB_HW_FLAGS_STREAM_REQUEST | SRB_HW_FLAGS_DATA_TRANSFER:
		DebugPrint(( DebugLevelVerbose," As a Data\n" ));
		MonoOutStr( "(Data)" );

		// Find the smallest and the biggest discarded order number in this packet
		for( ulSample = 0; ulSample < pSrb->NumberOfBuffers; ulSample++ )
		{
			pHeader = (PKSSTREAM_HEADER)pSrb->CommandData.DataBufferArray + ulSample;
			wMaxOrder = max( (WORD)(pHeader->TypeSpecificFlags >> 16), wMaxOrder );
			wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
		}
		MonoOutStr( " Min:" );
		MonoOutInt( wMinOrder );
		MonoOutStr( " Max:" );
		MonoOutInt( wMaxOrder );
		MonoOutStr( " Curr:" );
		MonoOutInt( pHwDevExt->wNextSrbOrderNumber );
		if(bCancel)
		{
			if( /*wMinOrder <= pHwDevExt->wNextSrbOrderNumber &&*/
				wMaxOrder >= pHwDevExt->wNextSrbOrderNumber )
			{
				pHwDevExt->wNextSrbOrderNumber = wMaxOrder + 1;
				MonoOutStr( "<<< Updating NextSrbOrderNumber to " );
				MonoOutULong( pHwDevExt->wNextSrbOrderNumber );
				MonoOutStr( " >>>" );
			}
			else
				MonoOutChar( ' ' );
			MonoOutStr("Cancel::ARR");
			AdapterReleaseRequest( pSrb );
		}
		else
		{

			if(pHwDevExt->pCurrentSubPictureSrb)
			{
				pHeader = (PKSSTREAM_HEADER)pHwDevExt->pCurrentSubPictureSrb->CommandData.DataBufferArray ;
				pHeader += pHwDevExt->dwCurrentSubPictureSample;
				wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
			}
			if(pHwDevExt->pCurrentVideoSrb)
			{
				pHeader = (PKSSTREAM_HEADER)pHwDevExt->pCurrentVideoSrb->CommandData.DataBufferArray ;
				pHeader += pHwDevExt->dwCurrentVideoSample;
				wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
			}
			if(pHwDevExt->pCurrentAudioSrb)
			{
				pHeader = (PKSSTREAM_HEADER)pHwDevExt->pCurrentAudioSrb->CommandData.DataBufferArray ;
				pHeader += pHwDevExt->dwCurrentAudioSample;
				wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
			}

			pHwDevExt->wNextSrbOrderNumber = wMinOrder ;
			AdapterSendData(pHwDevExt);
		}


		MonoOutStr( "(Current->" );
		if( pHwDevExt->pCurrentVideoSrb )
			MonoOutStr( "V" );
		if( pHwDevExt->pCurrentAudioSrb )
			MonoOutStr( "A" );
		if( pHwDevExt->pCurrentSubPictureSrb )
			MonoOutStr( "S" );
		if( !pHwDevExt->pCurrentVideoSrb && !pHwDevExt->pCurrentAudioSrb && !pHwDevExt->pCurrentSubPictureSrb )
			MonoOutStr( "Queue empty" );
		MonoOutStr( ")" );


		break;

	case SRB_HW_FLAGS_STREAM_REQUEST:
		DebugPrint(( DebugLevelVerbose," As a Control\n" ));
		MonoOutStr( "(Control)" );
		AdapterReleaseRequest( pSrb );
		break;

	default:
		// this must be a device request.  Use device notifications
		DebugPrint(( DebugLevelVerbose," As a Device\n" ));
		MonoOutStr( "(Device)" );
		AdapterReleaseRequest( pSrb );
	}
	
	MonoOutSetUnderscore( FALSE );
	DebugPrint(( DebugLevelVerbose, "ZiVA: End Adapter%sPacket\n", pszFuncString ));
}


/*** AdapterCancelPacket()
**
**   Request to cancel a packet that is currently in process in the minidriver
**
** Arguments:
**
**   pSrb - pointer to request packet to cancel
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterCancelPacket( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	CancelPacket( pSrb, TRUE );
}

/*
** AdapterTimeoutPacket()
**
**   This routine is called when a packet has been in the minidriver for
**   too long.  The adapter must decide what to do with the packet
**
** Arguments:
**
**   pSrb - pointer to the request packet that timed out
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterTimeoutPacket( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;

	// If this is a data request, and the device is paused (we probably have run out of
	// data buffer) or busy with overlay calibration we need more time, so just reset the
	// timer, and let the packet continue
	if( ZivaHw_GetState() == ZIVA_STATE_PAUSE 
#ifdef ENCORE
		|| pHwDevExt->nVGAMode != AP_KNOWNMODE
#endif
		)
	{
		DebugPrint(( DebugLevelVerbose, "Timeout: Stream is PAUSED\n" ));

				// reset the timeout counter, and continue
		pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
		return;
	}

	CleanCCQueue(pHwDevExt);	

	CancelPacket( pSrb, FALSE );
}

void FinishCurrentPacketAndSendNextOne( PHW_DEVICE_EXTENSION pHwDevExt )
{
	DWORD dwSample;
	PHW_STREAM_REQUEST_BLOCK pSrb = NULL;
	DWORD dwCurBuf=0;
	
	switch( pHwDevExt->CurrentlySentStream )
	{
	case ZivaVideo:
		pSrb = pHwDevExt->pCurrentVideoSrb;
		++pHwDevExt->dwCurrentVideoPage;
		if(pHwDevExt->dwVideoDataUsed <= 0)
		{
			pHwDevExt->wNextSrbOrderNumber++;
			++pHwDevExt->dwCurrentVideoSample;
			dwCurBuf = pHwDevExt->dwCurrentVideoSample;

		}
		dwSample = pHwDevExt->dwCurrentVideoPage;
		break;

	case ZivaAudio:
		pSrb = pHwDevExt->pCurrentAudioSrb;
		++pHwDevExt->dwCurrentAudioPage;
		if(pHwDevExt->dwAudioDataUsed <= 0)
		{
			pHwDevExt->wNextSrbOrderNumber++;
			++pHwDevExt->dwCurrentAudioSample;
			dwCurBuf = pHwDevExt->dwCurrentAudioSample;
		}
		dwSample = pHwDevExt->dwCurrentAudioPage;

		
		break;

	case ZivaSubpicture:
		pSrb = pHwDevExt->pCurrentSubPictureSrb;
		++pHwDevExt->dwCurrentSubPicturePage;
		if(pHwDevExt->dwSubPictureDataUsed <= 0)
		{
			pHwDevExt->wNextSrbOrderNumber++;
			++pHwDevExt->dwCurrentSubPictureSample;
			dwCurBuf = pHwDevExt->dwCurrentSubPictureSample;
		}
		
		dwSample = pHwDevExt->dwCurrentSubPicturePage;
		
		break;
	}
	if( pSrb )
	{
		if( ( dwSample >= pSrb->NumberOfPhysicalPages) || (dwCurBuf >= pSrb->NumberOfBuffers))
		{
			if( dwSample > pSrb->NumberOfPhysicalPages)
			{
				MonoOutSetBlink( TRUE );
				MonoOutStr( "<<< Current sample number is higher than the number of buffers >>>" );
				MonoOutSetBlink( FALSE );
			}

//tmp			MonoOutStr("RSRB");
			AdapterReleaseCurrentSrb( pSrb );
		}
		// Clean the CurrentlySentStream
		pHwDevExt->CurrentlySentStream = ZivaNumberOfStreams;
		// Send next chunk of data
		AdapterSendData( pHwDevExt );
	}
}


UINT AdapterPrepareDataForSending( PHW_DEVICE_EXTENSION pHwDevExt,
									PHW_STREAM_REQUEST_BLOCK pCurrentStreamSrb,
									DWORD dwCurrentStreamSample,
									PHW_STREAM_REQUEST_BLOCK* ppSrb, DWORD* pdwSample,
									DWORD* dwCurrentSample,DWORD dwCurrentPage,
									LONG* pdwDataUsed)
{
	PKSSTREAM_HEADER pHeader;
	static DWORD wPrevOrderNumber=0xfff;

	// Check if this guy has any data to send
	pHeader = (PKSSTREAM_HEADER)pCurrentStreamSrb->CommandData.DataBufferArray+dwCurrentStreamSample;

	if(pHeader == NULL)
	{
		MonoOutStr("PHeader NULL");
		MoveToNextSample( pCurrentStreamSrb );
		pHwDevExt->wNextSrbOrderNumber++;
		// Sorry, but we have to start all over again...
		return TRUE;
	}


	if( pHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED )
	{
		MonoOutStr( "!!!! Skipping TYPECHANGED buffer !!!!" );
		MoveToNextSample( pCurrentStreamSrb );
		// Sorry, but we have to start all over again...
		return TRUE;
	}
	if( (WORD)(pHeader->TypeSpecificFlags >> 16) == pHwDevExt->wNextSrbOrderNumber )
	{
		
		if( !pHeader->DataUsed )
		{
			MonoOutStr( "!!!! DataUsed is 0 !!!!" );
			MoveToNextSample( pCurrentStreamSrb );
			pHwDevExt->wNextSrbOrderNumber++;
			// Sorry, but we have to start all over again...
			return TRUE;
		}
		// Found our SRB
		if((*pdwDataUsed <= 0))
		{
			*pdwDataUsed += pHeader->DataUsed;
			if(*pdwDataUsed == 0)
			{
				MoveToNextSample(pCurrentStreamSrb);
				pHwDevExt->wNextSrbOrderNumber++;
				return TRUE;
			}
		}
		if(pHeader->PresentationTime.Time)
			pHwDevExt->VideoSTC = pHeader->PresentationTime.Time;
		*ppSrb		= pCurrentStreamSrb;
		*pdwSample	= dwCurrentPage;
		*dwCurrentSample = dwCurrentStreamSample;
	}

	return FALSE;
}

UpdateOrdinalNumber(IN PHW_DEVICE_EXTENSION pHwDevExt)
{
	if(( (pHwDevExt->pCurrentVideoSrb) || (pHwDevExt->pCurrentAudioSrb) || (pHwDevExt->pCurrentSubPictureSrb)) )
	{
		PKSSTREAM_HEADER pHeader;
		WORD wMinOrder = 0xFFFF;
		if( pHwDevExt->pCurrentVideoSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentVideoSrb->CommandData.DataBufferArray)+
			pHwDevExt->dwCurrentVideoSample;
			wMinOrder = (WORD)(pHeader->TypeSpecificFlags >> 16);
		}
		if( pHwDevExt->pCurrentAudioSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentAudioSrb->CommandData.DataBufferArray)+
			pHwDevExt->dwCurrentAudioSample;
			wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
		}
		if( pHwDevExt->pCurrentSubPictureSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentSubPictureSrb->CommandData.DataBufferArray)+
			pHwDevExt->dwCurrentSubPictureSample;
			wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
		}	

		ASSERT( wMinOrder != 0xFFFF );
		pHwDevExt->wNextSrbOrderNumber = wMinOrder;
		MonoOutSetBlink( TRUE );
		MonoOutStr( "<<< Self recovering NextSrbOrderNumber to " );
		MonoOutULong( pHwDevExt->wNextSrbOrderNumber );
		MonoOutStr( " >>>" );
		MonoOutSetBlink( FALSE );
		
	}
	
}
BOOLEAN  CanUpdateOrdinalNumber(IN PHW_DEVICE_EXTENSION pHwDevExt)
{
	BOOLEAN bReturn = FALSE;	
	if(pHwDevExt->bScanCommandPending)
	{
		if((pHwDevExt->NewRate == 10000) ||  (pHwDevExt->bRateChangeFromSlowMotion) )
		{

			pHwDevExt->bRateChangeFromSlowMotion = FALSE;
			if(pHwDevExt->bDiscontinued)
			{
				pHwDevExt->bDiscontinued = FALSE;
				UpdateOrdinalNumber(pHwDevExt);
				bReturn = TRUE;
			}
		}
	}
	return bReturn;
}
void IssuePendingCommands(PHW_DEVICE_EXTENSION pHwDevExt)
{
	pHwDevExt->bEndFlush = FALSE;
	pHwDevExt->bTimerScheduled = FALSE;
	DisableThresholdInt();
	if( pHwDevExt->bPlayCommandPending == TRUE )
	{	// If "Play" command is pending - it's time to fire it
		pHwDevExt->bPlayCommandPending = FALSE;
		ZivaHw_FlushBuffers( );
		pHwDevExt->bInterruptPending = FALSE;
		if( !ZivaHw_Play() )
			DebugPrint(( DebugLevelInfo, "ZiVA: !!!!!!!!! Play command did not succeed !!!!!!!!!\n" ));
	}
	if( pHwDevExt->bScanCommandPending == TRUE )
	{
		pHwDevExt->bScanCommandPending = FALSE;
		if(pHwDevExt->NewRate == 10000)
		{
			ZivaHw_Abort();//sri
			pHwDevExt->bInterruptPending = FALSE;
			ZivaHw_Play();
		}
		else if(pHwDevExt->NewRate < 10000)
		{
			ZivaHw_Abort();//sri
			pHwDevExt->bInterruptPending = FALSE;
			ZivaHw_Scan();
		}
		else
		{
		
			ZivaHw_Abort();//sri
			pHwDevExt->bInterruptPending = FALSE;
			ZivaHw_SlowMotion( 8 );
		}
	}

}


void CallAdapterSendAtALaterTime( PHW_DEVICE_EXTENSION pHwDevExt )
{

//	UpdateOrdinalNumber(pHwDevExt);
	MonoOutStr("CallAdapterSendAtALaterTime");
	if(pHwDevExt->bTimerScheduled)
	{
		pHwDevExt->bTimerScheduled = FALSE;
		MonoOutStr("CallAdapterSend");
		UpdateOrdinalNumber(pHwDevExt);
		AdapterSendData(pHwDevExt);
	}

}


BOOL UpdateOrdNum_MinOfAllThree(PHW_DEVICE_EXTENSION pHwDevExt)
{
	if( ((!pHwDevExt->bVideoStreamOpened || pHwDevExt->pCurrentVideoSrb) &&
		(!pHwDevExt->bAudioStreamOpened || pHwDevExt->pCurrentAudioSrb) &&
		(!pHwDevExt->bSubPictureStreamOpened || pHwDevExt->pCurrentSubPictureSrb))
		 )
	{
		PKSSTREAM_HEADER pHeader;
		WORD wMinOrder = 0xFFFF;
		
		
		if( pHwDevExt->pCurrentVideoSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentVideoSrb->CommandData.DataBufferArray)+
						pHwDevExt->dwCurrentVideoSample;
			wMinOrder = (WORD)(pHeader->TypeSpecificFlags >> 16);
		}
		if( pHwDevExt->pCurrentAudioSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentAudioSrb->CommandData.DataBufferArray)+
						pHwDevExt->dwCurrentAudioSample;
			wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
		}
		if( pHwDevExt->pCurrentSubPictureSrb )
		{
			pHeader = (PKSSTREAM_HEADER)(pHwDevExt->pCurrentSubPictureSrb->CommandData.DataBufferArray)+
						pHwDevExt->dwCurrentSubPictureSample;
			wMinOrder = min( (WORD)(pHeader->TypeSpecificFlags >> 16), wMinOrder );
		}

		ASSERT( wMinOrder != 0xFFFF );
		pHwDevExt->wNextSrbOrderNumber = wMinOrder;
		MonoOutSetBlink( TRUE );
		MonoOutStr( "<<< Self recovering NextSrbOrderNumber to " );
		MonoOutULong( pHwDevExt->wNextSrbOrderNumber );
		MonoOutStr( " >>>" );
		MonoOutSetBlink( FALSE );
		return TRUE;
	}
	else
		return FALSE;
}


/*BOOL StartUpDiscontinue(PHW_DEVICE_EXTENSION pHwDevExt)
{
	if(pHwDevExt->dwFirstVideoOrdNum != -1)
		wMinOrder = min( (WORD)pHwDevExt->dwFirstVideoOrdNum, wMinOrder );
	if(pHwDevExt->dwFirstAudioOrdNum != -1)
		wMinOrder = min( (WORD)pHwDevExt->dwFirstAudioOrdNum, wMinOrder );
	if(pHwDevExt->dwFirstSbpOrdNum != -1)
		wMinOrder = min( (WORD)pHwDevExt->dwFirstSbpOrdNum, wMinOrder );
	if((wMinOrder != -1) && (wMinOrder > pHwDevExt->wNextSrbOrderNumber) )
	{
		pHwDevExt->wNextSrbOrderNumber = wMinOrder ;
		return TRUE;
	}
	else
		return FALSE;
}*/

/*
** AdapterSendData()
**
**  This routine is being scheduled by the either one of the input
**  streams when it receives data or by the ISR when sending of the
**  previos block is completed and there still Srbs pending.
**
** Arguments:
**
**  pHwDevExt - the hardware device extension.
**
** Returns: none
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterSendData( IN PHW_DEVICE_EXTENSION pHwDevExt )
{
	PHW_STREAM_REQUEST_BLOCK	pSrb;
	DWORD						dwPageToSend;
	DWORD						dwCurrentSample;
#ifndef DECODER_DVDPC
	if(pHwDevExt->bAbortAtPause)
		return;
#endif
	// Check if HW is not busy and there is something to send
	if( pHwDevExt->bInterruptPending ||
		(pHwDevExt->pCurrentVideoSrb == NULL &&
		 pHwDevExt->pCurrentAudioSrb == NULL && pHwDevExt->pCurrentSubPictureSrb == NULL) )
		return;

	// Find the next Sample by the order number
	for( ;; )
	{
		pSrb = NULL;

		if( pHwDevExt->pCurrentVideoSrb &&
			AdapterPrepareDataForSending( pHwDevExt, pHwDevExt->pCurrentVideoSrb,
							pHwDevExt->dwCurrentVideoSample, &pSrb, &dwPageToSend,&dwCurrentSample,
							pHwDevExt->dwCurrentVideoPage,&pHwDevExt->dwVideoDataUsed) )
			continue;
		if( pHwDevExt->pCurrentAudioSrb && pSrb == NULL &&
			AdapterPrepareDataForSending( pHwDevExt, pHwDevExt->pCurrentAudioSrb,
							pHwDevExt->dwCurrentAudioSample, &pSrb, &dwPageToSend,&dwCurrentSample,
							pHwDevExt->dwCurrentAudioPage,&pHwDevExt->dwAudioDataUsed) )
			continue;
		if( pHwDevExt->pCurrentSubPictureSrb && pSrb == NULL &&
			AdapterPrepareDataForSending( pHwDevExt, pHwDevExt->pCurrentSubPictureSrb,
							pHwDevExt->dwCurrentSubPictureSample, &pSrb, &dwPageToSend,&dwCurrentSample,
							pHwDevExt->dwCurrentSubPicturePage,&pHwDevExt->dwSubPictureDataUsed) )
			continue;

		if( pSrb != NULL )		// Found the right SRB
		{
			pHwDevExt->CurrentlySentStream = pSrb->StreamObject->StreamNumber;
			break;
		}

		if(CanUpdateOrdinalNumber(pHwDevExt))
		{
			UpdateOrdinalNumber(pHwDevExt);
			continue;
		}
    
		if(pHwDevExt->bEndFlush)
		{
			pHwDevExt->bEndFlush = FALSE;
			MonoOutStr("Timer Scheduled for AdapterSendData");
			StreamClassScheduleTimer( NULL, pHwDevExt,
                                400000,
                                (PHW_TIMER_ROUTINE)CallAdapterSendAtALaterTime,
                                pHwDevExt );
			pHwDevExt->bTimerScheduled = TRUE;

			
		}
		
		if(UpdateOrdNum_MinOfAllThree(pHwDevExt))
			continue;
//		if(StartUpDiscontinue(pHwDevExt))
//			continue;

		MonoOutStr( "!! CD !!" );
		//MonoOutStr( "!!!!!!!!!!!!!!! COUNTER DISCONTINUITY !!!!!!!!!!!!!!!!!!!" );

		// Clean the CurrentlySentStream
		pHwDevExt->CurrentlySentStream = ZivaNumberOfStreams;
		
		return;
	}
	
	XferData(pSrb,pHwDevExt,dwPageToSend,dwCurrentSample);
}




/*
** AdapterReleaseCurrentSrb()
**
**   This routine is called by the AdapterSendData() and HWInterrupt() functions
**   when there is no more data in the Currently processing Srb.
**
** Arguments:
**
**  pSrb - the request block to release.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReleaseCurrentSrb( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
	PKSSTREAM_HEADER pHeader;

	pSrb->Status = STATUS_SUCCESS;

	// Clear the CurrentSrb and Sample count for this Srb
	switch( pSrb->StreamObject->StreamNumber )
	{
	case ZivaVideo:
		pHwDevExt->pCurrentVideoSrb = NULL;
		pHwDevExt->dwCurrentVideoSample = 0;
		pHwDevExt->dwCurrentVideoPage = 0;
		pHwDevExt->dwVideoDataUsed=0;
		break;
	case ZivaAudio:
		pHwDevExt->pCurrentAudioSrb = NULL;
		pHwDevExt->dwCurrentAudioSample = 0;
		pHwDevExt->dwCurrentAudioPage = 0;
		pHwDevExt->dwAudioDataUsed=0;
		break;
	case ZivaSubpicture:
		pHwDevExt->pCurrentSubPictureSrb = NULL;
		pHwDevExt->dwCurrentSubPictureSample = 0;
		pHwDevExt->dwCurrentSubPicturePage = 0;
		pHwDevExt->dwSubPictureDataUsed=0;
		break;
	default:
		MonoOutStr( "!!!!!!!! Releasing Srb for UNKNOWN stream !!!!!!!!" );
	}

	// Check if this is the last Srb for current title
	pHeader = (PKSSTREAM_HEADER)pSrb->CommandData.DataBufferArray+pSrb->NumberOfBuffers-1;
	if( pHeader->TypeSpecificFlags & KS_AM_UseNewCSSKey )
	{
		switch( pSrb->StreamObject->StreamNumber )
		{
		case ZivaVideo:
			MonoOutStr( "!!! Last video Srb !!!" );
			pHwDevExt->bVideoCanAuthenticate = TRUE;
			break;

		case ZivaAudio:
			MonoOutStr( "!!! Last audio Srb !!!" );
			pHwDevExt->bAudioCanAuthenticate = TRUE;
			break;

		case ZivaSubpicture:
			MonoOutStr( "!!! Last SP Srb !!!" );
			pHwDevExt->bSubPictureCanAuthenticate = TRUE;
			break;

		default:
			MonoOutStr( "!!!!!!!! Last Srb for UNKNOWN stream !!!!!!!!" );
		}
	}
	
	AdapterReleaseRequest( pSrb );
}


/*
** AdapterReleaseRequest()
**
**   This routine is called when any of the open pins (streams) wants
**   to dispose an used request block.
**
** Arguments:
**
**  pSrb - the request block to release.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReleaseRequest( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	if( pSrb->Status == STATUS_PENDING )
		MonoOutStr( " !!! Srb is PENDING - not releasing !!! " );
	else
	{
		if( pSrb->Flags & SRB_HW_FLAGS_STREAM_REQUEST )
		{
			if( pSrb->Flags & SRB_HW_FLAGS_DATA_TRANSFER )
			{
				StreamClassStreamNotification( ReadyForNextStreamDataRequest, pSrb->StreamObject );
//				MonoOutStr(" Release D");
			}
			else
			{
				StreamClassStreamNotification( ReadyForNextStreamControlRequest, pSrb->StreamObject );
//				MonoOutStr(" Release C");
			}
			StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb );
		}
		else
		{
			StreamClassDeviceNotification( ReadyForNextDeviceRequest, pSrb->HwDeviceExtension );
			StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb );
		}
	}
}


/*
** AdapterCanAuthenticateNow()
**
**   This routine is called when Authentication request was made by the
**   Class Driver.
**
** Arguments:
**
**  pHwDevExt - hardware device extension.
**
** Returns:
**
**   TRUE if Authentication is allowed at this moment, FALSE otherwise.
**
** Side Effects:  none
*/
BOOL STREAMAPI AdapterCanAuthenticateNow( IN PHW_DEVICE_EXTENSION pHwDevExt )
{
	if( (pHwDevExt->bVideoStreamOpened == FALSE ||
		 (pHwDevExt->bVideoStreamOpened == TRUE && pHwDevExt->bVideoCanAuthenticate == TRUE)) &&
		(pHwDevExt->bAudioStreamOpened == FALSE ||
		 (pHwDevExt->bAudioStreamOpened == TRUE && pHwDevExt->bAudioCanAuthenticate == TRUE)) &&
		(pHwDevExt->bSubPictureStreamOpened == FALSE ||
		 (pHwDevExt->bSubPictureStreamOpened == TRUE && pHwDevExt->bSubPictureCanAuthenticate == TRUE)) )
		return TRUE;

	return FALSE;
}

/*
** AdapterClearAuthenticationStatus()
**
**   This routine is called when Authentication and key exchange was
**   completed.
**
** Arguments:
**
**  pHwDevExt - hardware device extension.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterClearAuthenticationStatus( IN PHW_DEVICE_EXTENSION pHwDevExt )
{
	pHwDevExt->bVideoCanAuthenticate		= FALSE;
	pHwDevExt->bAudioCanAuthenticate		= FALSE;
	pHwDevExt->bSubPictureCanAuthenticate	= FALSE;
}


/*
** AdapterSetState()
**
**    Sets the current state
**
** Arguments:
**
**    pSrb - pointer to the stream request block for properties
**
** Returns:
**
** Side Effects:  none
*/
BOOL AdapterSetState( PHW_STREAM_REQUEST_BLOCK pSrb )
{
	PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
	PHW_STREAM_EXTENSION pStreamExt = (PHW_STREAM_EXTENSION)pSrb->StreamObject->HwStreamExtension;

	DebugPrint(( DebugLevelVerbose, "ZiVA: AdapterSetState() -> " ));
	pSrb->Status = STATUS_SUCCESS;

	// Execute appropriate command only when it comes for every stream
	switch( pSrb->CommandData.StreamState )
	{
	case KSSTATE_STOP:
		pStreamExt->ksState = pSrb->CommandData.StreamState;
#ifdef ENCORE
		if( pSrb->StreamObject->StreamNumber == ZivaAnalog && pHwDevExt->nAnalogStreamOpened > 1 )
			pHwDevExt->nStopCount -= pHwDevExt->nAnalogStreamOpened-1;
#endif
		if( --pHwDevExt->nStopCount == 0 )
		{
//			ZwClose(Handle);
			pHwDevExt->nStopCount = pHwDevExt->iTotalOpenedStreams;
			DebugPrint(( DebugLevelVerbose, "Stop" ));
			if( !ZivaHw_Abort() )
				pSrb->Status = STATUS_IO_DEVICE_ERROR;
			else
				pHwDevExt->bInterruptPending = FALSE;
			AdapterInitLocals(pHwDevExt);
		}
		break;

	case KSSTATE_PAUSE:
		pStreamExt->ksState = pSrb->CommandData.StreamState;
		pStreamExt->bCanBeRun = TRUE;
		if( (ZivaHw_GetState( ) == ZIVA_STATE_SCAN) || (ZivaHw_GetState( ) ==ZIVA_STATE_SLOWMOTION) )//sri
			pHwDevExt->bAbortAtPause = TRUE;

#ifdef ENCORE
		if( pSrb->StreamObject->StreamNumber == ZivaAnalog && pHwDevExt->nAnalogStreamOpened > 1 )
			pHwDevExt->nPauseCount -= pHwDevExt->nAnalogStreamOpened-1;
#endif
		if( --pHwDevExt->nPauseCount == 0 )
		{

			pHwDevExt->nPauseCount = pHwDevExt->iTotalOpenedStreams;
			DebugPrint(( DebugLevelVerbose, "Pause" ));
			
			if( !ZivaHw_Pause() )
			{
				MonoOutStr("Pause Failed");
				pSrb->Status = STATUS_IO_DEVICE_ERROR;
			}
			
		}
		break;

	case KSSTATE_RUN:
		pStreamExt->ksState = pSrb->CommandData.StreamState;
#ifdef ENCORE
		if( pSrb->StreamObject->StreamNumber == ZivaAnalog && pHwDevExt->nAnalogStreamOpened > 1 )
			pHwDevExt->nPlayCount -= pHwDevExt->nAnalogStreamOpened-1;
#endif
		if( --pHwDevExt->nPlayCount == 0 )
		{

			pHwDevExt->nPlayCount = pHwDevExt->iTotalOpenedStreams;
			DebugPrint(( DebugLevelVerbose, "Run" ));
			// We could be resuming playback here after Pause mode
			if(pHwDevExt->bAbortAtPause)
			{
				pHwDevExt->bAbortAtPause = FALSE;

				ZivaHw_Abort();

#ifdef DECODER_DVDPC
				
				if( !ZivaHw_Play() )			// Just run the hardware
					pSrb->Status = STATUS_IO_DEVICE_ERROR;
//				pHwDevExt->bPlayCommandPending = TRUE;
//				AdapterSendData(pHwDevExt);
#endif

#ifndef DECODER_DVDPC
				pHwDevExt->bInterruptPending = FALSE;
				pHwDevExt->bPlayCommandPending = TRUE;
				FinishCurrentPacketAndSendNextOne( pHwDevExt );
				AdapterSendData(pHwDevExt);
#endif
				

			}
			else
			{

				if( pHwDevExt->bInterruptPending )
				{
					if( !ZivaHw_Play() )			// Just run the hardware
						pSrb->Status = STATUS_IO_DEVICE_ERROR;
				}
				else
				{
				// Since Authentication and Key Exchange comes in between
				// "Run" command and actual data sending and ZiVA Microcode
				// cannot sustain it - postpone issuing Play command to ZiVA
				// until first packet of the data arrives.
					pHwDevExt->bPlayCommandPending = TRUE;
				// Kick the Adapter to start transferring data
					AdapterSendData( pHwDevExt );
				}
			}

			EnableVideo(pSrb);
		}
		break;
	}

	DebugPrint(( DebugLevelVerbose, "\nZiVA: End AdapterSetState()\n" ));

        return TRUE;
}

/*
** AdapterReleaseControlRequest()
**
**   This routine is called when any of the open pins (streams) wants
**   to dispose an used control request block.
**
** Arguments:
**
**  pSrb - the request block to release.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReleaseControlRequest( PHW_STREAM_REQUEST_BLOCK pSrb )
{
  if ( pSrb->Status == STATUS_PENDING )
  {
    MonoOutStr( " !!! Srb is PENDING - not releasing !!! " );
  }
  else
  {
    StreamClassStreamNotification( ReadyForNextStreamControlRequest,
                                   pSrb->StreamObject);

    StreamClassStreamNotification( StreamRequestComplete,
                                   pSrb->StreamObject,
                                   pSrb);
//	MonoOutStr(" Release ");
  }
}

/*
** AdapterReleaseDataRequest()
**
**   This routine is called when any of the open pins (streams) wants
**   to dispose an used data request block.
**
** Arguments:
**
**  pSrb - the request block to release.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReleaseDataRequest( PHW_STREAM_REQUEST_BLOCK pSrb )
{
  if ( pSrb->Status == STATUS_PENDING )
  {
    MonoOutStr( " !!! Srb is PENDING - not releasing !!! " );
  }
  else
  {
    StreamClassStreamNotification( ReadyForNextStreamDataRequest,
                                   pSrb->StreamObject);

    StreamClassStreamNotification( StreamRequestComplete,
                                   pSrb->StreamObject,
                                   pSrb);
//	MonoOutStr(" ReleaseData ");
  }
}

/*
** AdapterReleaseDeviceRequest()
**
**   This routine is called when any of the open pins (streams) wants
**   to dispose an used device request block.
**
** Arguments:
**
**  pSrb - the request block to release.
**
** Returns:
**
** Side Effects:  none
*/
VOID STREAMAPI AdapterReleaseDeviceRequest( PHW_STREAM_REQUEST_BLOCK pSrb )
{
  StreamClassDeviceNotification( ReadyForNextDeviceRequest,
                                 pSrb->HwDeviceExtension);

  StreamClassDeviceNotification( DeviceRequestComplete,
                                 pSrb->HwDeviceExtension,
                                 pSrb);
}

VOID STREAMAPI AdapterReleaseCtrlDataSrb( PHW_STREAM_REQUEST_BLOCK pSrb )
 {
  PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  KSSTREAM_HEADER *pHeader;

  //
  // Clear the CurrentSrb and Sample count for this Srb
  //


  

  
  pSrb->Status = STATUS_SUCCESS;

  //
  // Check if this is the last Srb for current title
  //

  pHeader = ((KSSTREAM_HEADER *)(pSrb->CommandData.DataBufferArray)) ;

  if ( pHeader->TypeSpecificFlags & KS_AM_UseNewCSSKey )
  {
     switch ( pSrb->StreamObject->StreamNumber )
    {
		case ZivaVideo:
			pHwDevExt->bVideoCanAuthenticate = TRUE;
			break;

		case ZivaAudio:
		  pHwDevExt->bAudioCanAuthenticate = TRUE;
		  break;

		case ZivaSubpicture:
			pHwDevExt->bSubPictureCanAuthenticate = TRUE;
			break;

		default:
			MonoOutStr( "!!!!!!!! Last Srb for UNKNOWN stream !!!!!!!!" );
    }
  }

  AdapterReleaseDataRequest( pSrb );
}


BOOL CheckAndReleaseIfCtrlPkt(PHW_STREAM_REQUEST_BLOCK pSrb)
{
	KSSTREAM_HEADER *pHeader;
    pHeader    = ((PKSSTREAM_HEADER)pSrb->CommandData.DataBufferArray);

	if (pHeader->TypeSpecificFlags & KS_AM_UseNewCSSKey)
	{
		if (pSrb->NumberOfBuffers == 0)
		{
			AdapterReleaseCtrlDataSrb(pSrb);
			return TRUE;
		}
		else if (pSrb->NumberOfBuffers == 1)
		{
			BYTE   *pData;
			DWORD  dwDataUsed;

			pData      = pHeader->Data;
			dwDataUsed = pHeader->DataUsed;

			if ((dwDataUsed == 0) ||
				(pData &&  *((DWORD*)pData) != 0xBA010000)) 
			{
				AdapterReleaseCtrlDataSrb(pSrb);
				return TRUE;;
			}

		}
		
	}

	return FALSE;
}



#if 0
static void STREAMAPI CreateFile(PHW_STREAM_REQUEST_BLOCK pSrb )
{

	NTSTATUS ntStatus;

	ASSERT( pSrb->Status == STATUS_PENDING );
			
	RtlInitUnicodeString (&pathUnicodeString,wPath);
                              


	InitializeObjectAttributes(&InitializedAttributes,&pathUnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
//	InitializedAttributes.Length = 2048;
//	AllocSize.QuadPart=0xffff;
//	ntStatus = ZwCreateFile(&Handle,FILE_WRITE_DATA,
//										&InitializedAttributes,&IOStatusBlock,
//										0,FILE_ATTRIBUTE_NORMAL,0,FILE_SUPERSEDE,
//										FILE_NO_INTERMEDIATE_BUFFERING,NULL,0);
	ntStatus = ZwCreateFile( &Handle,
                             GENERIC_WRITE,
                            &InitializedAttributes,
                            &IOStatusBlock,
                            NULL,                          // alloc size = none
                            FILE_ATTRIBUTE_NORMAL,
                            0,
                            FILE_CREATE,
                            FILE_WRITE_THROUGH,
                            NULL,  // eabuffer
                            0 );   // ealength

	if(NT_SUCCESS(ntStatus))
		MonoOutStr("File Creation success");
	
	MonoOutULong(IOStatusBlock.Information);
	
	if( (IOStatusBlock.Information == FILE_CREATED) || (IOStatusBlock.Information == FILE_OPENED) )
		MonoOutStr("File Creation success");
	else
		MonoOutStr("File Creation failed");

	pSrb->Status = STATUS_SUCCESS;

	StreamClassCallAtNewPriority( pSrb->StreamObject, pSrb->HwDeviceExtension, LowToHigh,
									(PHW_PRIORITY_ROUTINE)AdapterReleaseRequest, pSrb );
}

#endif



/*WriteFile()
{
	if(STATUS_SUCCESS != ZwWriteFile(Handle,NULL,NULL,NULL,&IOStatusBlock,pdwPhysAddress ,dwCount,NULL,NULL))
			MonoOutStr("WriteOperationFailed");
}*/