Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

339 lines
12 KiB

//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
//
// ATITVSnd.CPP
// WDM TV Audio MiniDriver.
// AllInWonder/AllInWonderPro development platform.
// Main Source Module.
//
// $Date: 01 Apr 1998 13:29:14 $
// $Revision: 1.1 $
// $Author: KLEBANOV $
//
//==========================================================================;
extern "C"
{
#include "strmini.h"
#include "ksmedia.h"
#include "wdmdebug.h"
}
#include "atitvsnd.h"
#include "wdmdrv.h"
/*^^*
* DriverEntry()
* Purpose : Called when an SRB_INITIALIZE_DEVICE request is received
*
* Inputs : PVOID Arg1, PVOID Arg2
*
* Outputs : result of StreamClassregisterAdapter()
* Author : IKLEBANOV
*^^*/
extern "C"
ULONG DriverEntry ( IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
HW_INITIALIZATION_DATA HwInitData;
SetMiniDriverDebugLevel( pRegistryPath);
OutputDebugTrace(( "ATITVSnd: DriverEntry\n"));
RtlZeroMemory( &HwInitData, sizeof( HwInitData));
HwInitData.HwInitializationDataSize = sizeof(HwInitData);
// Entry points for Port Driver
HwInitData.HwInterrupt = NULL; // HwInterrupt;
HwInitData.HwReceivePacket = TVAudioReceivePacket;
HwInitData.HwCancelPacket = TVAudioCancelPacket;
HwInitData.HwRequestTimeoutHandler = TVAudioTimeoutPacket;
HwInitData.DeviceExtensionSize = sizeof( ADAPTER_DATA_EXTENSION);
HwInitData.PerRequestExtensionSize = sizeof( SRB_DATA_EXTENSION);
HwInitData.FilterInstanceExtensionSize = 0;
HwInitData.PerStreamExtensionSize = 0;
HwInitData.BusMasterDMA = FALSE;
HwInitData.Dma24BitAddresses = FALSE;
HwInitData.BufferAlignment = 3;
// HwInitData.TurnOffSynchronization = FALSE;
// we turn the synchronization ON. StreamClass is expected to call the MiniDriver
// at passive level only
HwInitData.TurnOffSynchronization = TRUE;
HwInitData.DmaBufferSize = 0;
OutputDebugTrace(( "ATITVSnd: StreamClassRegisterAdapter\n"));
return( StreamClassRegisterAdapter( pDriverObject, pRegistryPath, &HwInitData));
}
/*^^*
* TVAudioReceivePacket()
* Purpose : Main entry point for receiving adapter based request SRBs from the Class Driver.
* Will always be called at passive level, because the drivers
* turned the synchronization ON.
* Note : This is an asyncronous entry point. The request only completes when a
* StreamClassDeviceNotification on this SRB, of type DeviceRequestComplete,
* is issued. As soon we're running at passive level, we can do everything
* synchronously during the response to the SRBs with no worry
* to block somebody else for a long timer during I2C access
*
* Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb
*
* Outputs : none
* Author : IKLEBANOV
*^^*/
extern "C"
void STREAMAPI TVAudioReceivePacket( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb)
{
CWDMTVAudio * pCTVAudio;
KIRQL irqlCurrent;
PADAPTER_DATA_EXTENSION pPrivateData = ( PADAPTER_DATA_EXTENSION)( pSrb->HwDeviceExtension);
PSRB_DATA_EXTENSION pSrbPrivate = ( PSRB_DATA_EXTENSION)( pSrb->SRBExtension);
// check the device extension pointer
if(( pPrivateData == NULL) || ( pSrbPrivate == NULL))
{
TRAP;
pSrb->Status = STATUS_INVALID_PARAMETER;
StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
}
OutputDebugInfo(( "ATITVSnd: TVAudioReceivePacket() SRB = %x\n", pSrb));
if( pSrb->Command == SRB_INITIALIZE_DEVICE)
{
// this is the special case for SRB_INITIALIZE_DEVICE, because
// no Queue has been initialized yet. Everything we need later on
// is initialized during this SRB response
TVAudioAdapterInitialize( pSrb);
StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
return;
}
// the rest of the SRBs are coming after SpinLock and SRBQueue have been initialized
// during DRB_INITIALIZE_DEVICE SRB response.
// I'll insert the SRB in the Queue first of all. The processing SRB from the Queue
// can be triggered by finishing processing and SRB, or by the fact there is no SRB
// is in process down here
pSrbPrivate->pSrb = pSrb;
// Everything we're doing with the Queue has to be protected from being interrupted
KeAcquireSpinLock( &pPrivateData->adapterSpinLock, &irqlCurrent);
InsertTailList( &pPrivateData->adapterSrbQueueHead, &pSrbPrivate->srbListEntry);
if( pPrivateData->bSrbInProcess)
{
// there is another SRB being processed, and the new one will be picked up from
// the Queue when it's its turn.
KeReleaseSpinLock( &pPrivateData->adapterSpinLock, irqlCurrent);
return;
}
while( !IsListEmpty( &pPrivateData->adapterSrbQueueHead))
{
// turn on the semaphore for the others coming after
pPrivateData->bSrbInProcess = TRUE;
// be carefull here, if you've changed the place where srbListEntry is defined
// within the SRB_DATA_EXTENSION structure
pSrbPrivate = ( PSRB_DATA_EXTENSION)RemoveHeadList( &pPrivateData->adapterSrbQueueHead);
KeReleaseSpinLock( &pPrivateData->adapterSpinLock, irqlCurrent);
// here is the place to process the SRB we have retrieved from the Queue
pSrb = pSrbPrivate->pSrb;
pPrivateData = ( PADAPTER_DATA_EXTENSION)( pSrb->HwDeviceExtension);
pCTVAudio = &pPrivateData->CTVAudio;
ASSERT( pSrb->Status != STATUS_CANCELLED);
switch( pSrb->Command)
{
case SRB_INITIALIZATION_COMPLETE:
// StreamClass has completed the initialization
pSrb->Status = pCTVAudio->AdapterCompleteInitialization( pSrb);
break;
case SRB_UNINITIALIZE_DEVICE:
// close the device.
pCTVAudio->AdapterUnInitialize( pSrb);
break;
case SRB_OPEN_STREAM:
case SRB_CLOSE_STREAM:
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_GET_STREAM_INFO:
// return a block describing STREAM_INFO_HEADER and all the streams supported
pCTVAudio->AdapterGetStreamInfo( pSrb);
break;
case SRB_CHANGE_POWER_STATE:
pSrb->Status = pCTVAudio->AdapterSetPowerState( pSrb);
break;
case SRB_GET_DEVICE_PROPERTY:
if( pCTVAudio->AdapterGetProperty( pSrb))
pSrb->Status = STATUS_SUCCESS;
else
pSrb->Status = STATUS_INVALID_PARAMETER;
break;
case SRB_SET_DEVICE_PROPERTY:
if( pCTVAudio->AdapterSetProperty( pSrb))
pSrb->Status = STATUS_SUCCESS;
else
pSrb->Status = STATUS_INVALID_PARAMETER;
break;
// We should never get the following since this is a single instance device
case SRB_OPEN_DEVICE_INSTANCE:
case SRB_CLOSE_DEVICE_INSTANCE:
TRAP
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_UNKNOWN_DEVICE_COMMAND:
// we know we're getting some of these. Why should we?
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
default:
// TRAP
// this is a request that we do not understand. Indicate invalid command and complete the request
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
StreamClassDeviceNotification( DeviceRequestComplete, pPrivateData, pSrb);
KeAcquireSpinLock( &pPrivateData->adapterSpinLock, &irqlCurrent);
}
// turn off the semaphore to enable the others coming after
pPrivateData->bSrbInProcess = FALSE;
KeReleaseSpinLock( &pPrivateData->adapterSpinLock, irqlCurrent);
// there is no other SRB being processed at this time, let's start processing
}
extern "C"
void STREAMAPI TVAudioCancelPacket( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb)
{
pSrb->Status = STATUS_CANCELLED;
}
extern "C"
void STREAMAPI TVAudioTimeoutPacket( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb)
{
// not sure what to do here.
}
/*^^*
* TVAudioAdapterInitialize()
* Purpose : Called when SRB_INITIALIZE_DEVICE SRB is received.
* Performs checking of the hardware presence and I2C provider availability.
* Sets the hardware in an initial state.
* Note : The request does not completed unless we know everything
* about the hardware and we are sure it is capable to work in the current configuration.
* The hardware Caps are also aquised at this point. As soon this
* function is called at passive level, do everything synchronously
*
* Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb
*
* Outputs : none
* Author : IKLEBANOV
*^^*/
void TVAudioAdapterInitialize( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb)
{
PPORT_CONFIGURATION_INFORMATION pConfigInfo = pSrb->CommandData.ConfigInfo;
PADAPTER_DATA_EXTENSION pPrivateData = ( PADAPTER_DATA_EXTENSION)( pConfigInfo->HwDeviceExtension);
NTSTATUS ntStatus = STATUS_NO_SUCH_DEVICE;
CWDMTVAudio * pCTVAudio;
CI2CScript * pCScript = NULL;
UINT nErrorCode;
OutputDebugTrace(( "ATITVSnd: TVAudioAdapterInitialize()\n"));
ENSURE
{
if( pConfigInfo->NumberOfAccessRanges != 0)
{
OutputDebugError(( "ATITVSnd: illegal NumberOfAccessRanges = %lx\n", pConfigInfo->NumberOfAccessRanges));
FAIL;
}
// if we have I2CProvider implemented inside the MiniVDD, we have to
// get a pointer to I2CInterface from the Provider.
// There is an overloaded operator new provided for the CI2CScript Class.
pCScript = ( CI2CScript *)new(( PVOID)&pPrivateData->CScript)
CI2CScript( pConfigInfo, &nErrorCode);
if( nErrorCode != WDMMINI_NOERROR)
{
OutputDebugError(( "ATITVSnd: CI2CScript creation failure = %lx\n", nErrorCode));
FAIL;
}
// The CI2CScript object was created successfully.
// We'll try to allocate I2CProvider here for future possible I2C
// operations needed at Initialization time.
if( !pCScript->LockI2CProviderEx())
{
OutputDebugError(( "ATITVSnd: unable to lock I2CProvider"));
FAIL;
}
// we did lock the provider.
// There is an overloaded operator new provided for the CWDMTVAudio Class.
pCTVAudio = ( CWDMTVAudio *)new(( PVOID)&pPrivateData->CTVAudio) CWDMTVAudio( pConfigInfo, pCScript, &nErrorCode);
if( nErrorCode)
{
OutputDebugError(( "ATITVSnd: CWDMTVAudio constructor failure = %lx\n", nErrorCode));
FAIL;
}
InitializeListHead ( &pPrivateData->adapterSrbQueueHead);
KeInitializeSpinLock ( &pPrivateData->adapterSpinLock);
pPrivateData->PhysicalDeviceObject = pConfigInfo->RealPhysicalDeviceObject;
// no streams are supported
pConfigInfo->StreamDescriptorSize = sizeof( HW_STREAM_HEADER);
OutputDebugTrace(( "TVAudioAdapterInitialize(): exit\n"));
ntStatus = STATUS_SUCCESS;
} END_ENSURE;
if (pCScript)
pCScript->ReleaseI2CProvider();
pSrb->Status = ntStatus;
return;
}