/******************************************************************************\ * * * 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"); }*/