//==========================================================================; // // WDMXBar.CPP // WDM Audio/Video CrossBar MiniDriver. // AIW Hardware platform. // CWDMAVXBar class implementation. // Copyright (c) 1996 - 1997 ATI Technologies Inc. All Rights Reserved. // //==========================================================================; extern "C" { #include "strmini.h" #include "ksmedia.h" #include "wdmdebug.h" } #include "atixbar.h" #include "wdmdrv.h" #include "aticonfg.h" /*^^* * AdapterCompleteInitialization() * Purpose : Called when SRB_COMPLETE_INITIALIZATION SRB is received. * * Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb * * Outputs : BOOL : returns TRUE * Author : IKLEBANOV *^^*/ NTSTATUS CWDMAVXBar::AdapterCompleteInitialization( PHW_STREAM_REQUEST_BLOCK pSrb) { PADAPTER_DATA_EXTENSION pPrivateData = ( PADAPTER_DATA_EXTENSION)( pSrb->HwDeviceExtension); NTSTATUS ntStatus; ULONG nPinsNumber; nPinsNumber = m_nNumberOfVideoInputs + m_nNumberOfAudioInputs + m_nNumberOfVideoOutputs + m_nNumberOfAudioOutputs; ENSURE { ntStatus = StreamClassRegisterFilterWithNoKSPins( \ pPrivateData->PhysicalDeviceObject, // IN PDEVICE_OBJECT DeviceObject, &KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID nPinsNumber, // IN ULONG PinCount, m_pXBarPinsDirectionInfo, // IN ULONG * Flags, m_pXBarPinsMediumInfo, // IN KSPIN_MEDIUM * MediumList, NULL); // IN GUID * CategoryList if( !NT_SUCCESS( ntStatus)) FAIL; OutputDebugTrace(( "CWDMAVXBar:AdapterCompleteInitialization() exit\n")); } END_ENSURE; if( !NT_SUCCESS( ntStatus)) OutputDebugError(( "CWDMAVXBar:AdapterCompleteInitialization() ntStatus=%x\n", ntStatus)); return( ntStatus); } /*^^* * AdapterUnInitialize() * Purpose : Called when SRB_UNINITIALIZE_DEVICE SRB is received. * * Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb * * Outputs : BOOL : returns TRUE * Author : IKLEBANOV *^^*/ BOOL CWDMAVXBar::AdapterUnInitialize( PHW_STREAM_REQUEST_BLOCK pSrb) { OutputDebugTrace(( "CWDMAVXBar:AdapterUnInitialize()\n")); if( m_pXBarInputPinsInfo != NULL) { ::ExFreePool( m_pXBarInputPinsInfo); m_pXBarInputPinsInfo = NULL; } if( m_pXBarPinsMediumInfo != NULL) { ::ExFreePool( m_pXBarPinsMediumInfo); m_pXBarPinsMediumInfo = NULL; } if( m_pXBarPinsDirectionInfo != NULL) { ::ExFreePool( m_pXBarPinsDirectionInfo); m_pXBarPinsDirectionInfo = NULL; } pSrb->Status = STATUS_SUCCESS; return( TRUE); } /*^^* * AdapterGetStreamInfo() * Purpose : Calles during StreamClass initialization procedure to get the information * about data streams exposed by the MiniDriver * * Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb * * Outputs : BOOL : returns TRUE * Author : IKLEBANOV *^^*/ BOOL CWDMAVXBar::AdapterGetStreamInfo( PHW_STREAM_REQUEST_BLOCK pSrb) { // pick up the pointer to the stream header data structure PHW_STREAM_HEADER pStreamHeader = ( PHW_STREAM_HEADER) \ &( pSrb->CommandData.StreamBuffer->StreamHeader); // pick up the pointer to the stream information data structure PHW_STREAM_INFORMATION pStreamInfo = ( PHW_STREAM_INFORMATION) \ &( pSrb->CommandData.StreamBuffer->StreamInfo); // no streams are supported DEBUG_ASSERT( pSrb->NumberOfBytesToTransfer >= sizeof( HW_STREAM_HEADER)); OutputDebugTrace(( "CWDMAVXBar:AdapterGetStreamInfo()\n")); m_wdmAVXBarStreamHeader.NumberOfStreams = 0; m_wdmAVXBarStreamHeader.SizeOfHwStreamInformation = sizeof( HW_STREAM_INFORMATION); m_wdmAVXBarStreamHeader.NumDevPropArrayEntries = KSPROPERTIES_AVXBAR_NUMBER_SET; m_wdmAVXBarStreamHeader.DevicePropertiesArray = m_wdmAVXBarPropertySet; m_wdmAVXBarStreamHeader.NumDevEventArrayEntries = 0; m_wdmAVXBarStreamHeader.DeviceEventsArray = NULL; m_wdmAVXBarStreamHeader.Topology = &m_wdmAVXBarTopology; * pStreamHeader = m_wdmAVXBarStreamHeader; pSrb->Status = STATUS_SUCCESS; return( TRUE); } /*^^* * AdapterQueryUnload() * Purpose : Called when the class driver is about to unload the MiniDriver * The MiniDriver checks if any open stream left. * * Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb * * Outputs : BOOL : returns TRUE * Author : IKLEBANOV *^^*/ BOOL CWDMAVXBar::AdapterQueryUnload( PHW_STREAM_REQUEST_BLOCK pSrb) { OutputDebugTrace(( "CWDMAVXBar:AdapterQueryUnload()\n")); pSrb->Status = STATUS_SUCCESS; return( TRUE); } /*^^* * operator new * Purpose : CWDMAVXBar class overloaded operator new. * Provides placement for a CWDMAVXBar class object from the PADAPTER_DEVICE_EXTENSION * allocated by the StreamClassDriver for the MiniDriver. * * Inputs : UINT size_t : size of the object to be placed * PVOID pAllocation : casted pointer to the CWDMAVXBar allocated data * * Outputs : PVOID : pointer of the CWDMAVXBar class object * Author : IKLEBANOV *^^*/ PVOID CWDMAVXBar::operator new( size_t size_t, PVOID pAllocation) { if( size_t != sizeof( CWDMAVXBar)) { OutputDebugTrace(( "CWDMAVXBar: operator new() fails\n")); return( NULL); } else return( pAllocation); } /*^^* * ~CWDMAVXBar() * Purpose : CWDMAVXBar class destructor. * Frees the allocated memory. * * Inputs : none * * Outputs : none * Author : IKLEBANOV *^^*/ CWDMAVXBar::~CWDMAVXBar() { OutputDebugTrace(( "CWDMAVXBar:~CWDMAVXBar() m_pXBarPinsInfo = %x\n", m_pXBarInputPinsInfo)); if( m_pXBarInputPinsInfo != NULL) { ::ExFreePool( m_pXBarInputPinsInfo); m_pXBarInputPinsInfo = NULL; } if( m_pXBarPinsMediumInfo != NULL) { ::ExFreePool( m_pXBarPinsMediumInfo); m_pXBarPinsMediumInfo = NULL; } if( m_pXBarPinsDirectionInfo != NULL) { ::ExFreePool( m_pXBarPinsDirectionInfo); m_pXBarPinsDirectionInfo = NULL; } } /*^^* * CWDMAVXBar() * Purpose : CWDMAVXBar class constructor. * Performs checking of the hardware presence. Sets the hardware in an initial state. * * Inputs : CI2CScript * pCScript : pointer to the I2CScript class object * PUINT puiError : pointer to return a completion error code * * Outputs : none * Author : IKLEBANOV *^^*/ CWDMAVXBar::CWDMAVXBar( PPORT_CONFIGURATION_INFORMATION pConfigInfo, CI2CScript * pCScript, PUINT puiErrorCode) :m_CATIConfiguration( pConfigInfo, pCScript, puiErrorCode) { UINT uiError; ULONG ulInstance; HANDLE hFolder = NULL; OutputDebugTrace(( "CWDMAVXBar:CWDMAVXBar() enter\n")); m_pXBarInputPinsInfo = m_pXBarOutputPinsInfo = NULL; m_pXBarPinsMediumInfo = NULL; m_pXBarPinsDirectionInfo = NULL; m_ulPowerState = PowerDeviceD0; // error code was caried over from ATIConfiguration class constructor uiError = * puiErrorCode; ENSURE { ULONG ulNumberOfPins, nPinIndex; UINT uiTunerId, nIndex; UCHAR uchTunerAddress; KSPIN_MEDIUM mediumKSPin; const KSPIN_MEDIUM * pMediumKSPin; if( uiError != WDMMINI_NOERROR) FAIL; if( pCScript == NULL) { uiError = WDMMINI_INVALIDPARAM; FAIL; } // first, find out whether any tuner type is installed. If not, we have only 2 video sources. m_CATIConfiguration.GetTunerConfiguration( &uiTunerId, &uchTunerAddress); m_nNumberOfVideoInputs = ( uchTunerAddress) ? 3 : 2; m_nNumberOfVideoOutputs = m_nNumberOfVideoInputs; m_CATIConfiguration.GetAudioProperties( &m_nNumberOfAudioInputs, &m_nNumberOfAudioOutputs); if( !uchTunerAddress) // if there is no tuner - no TVAudio input m_nNumberOfAudioInputs --; ulNumberOfPins = m_nNumberOfAudioInputs + m_nNumberOfVideoInputs + m_nNumberOfVideoOutputs + m_nNumberOfAudioOutputs; m_pXBarInputPinsInfo = ( PXBAR_PIN_INFORMATION) \ ::ExAllocatePool( NonPagedPool, sizeof( XBAR_PIN_INFORMATION) * ulNumberOfPins); if( m_pXBarInputPinsInfo == NULL) { uiError = WDMMINI_ERROR_MEMORYALLOCATION; FAIL; } m_pXBarPinsMediumInfo = ( PKSPIN_MEDIUM) \ ::ExAllocatePool( NonPagedPool, sizeof( KSPIN_MEDIUM) * ulNumberOfPins); if( m_pXBarPinsMediumInfo == NULL) { uiError = WDMMINI_ERROR_MEMORYALLOCATION; FAIL; } m_pXBarPinsDirectionInfo = ( PBOOL) \ ::ExAllocatePool( NonPagedPool, sizeof( BOOL) * ulNumberOfPins); if( m_pXBarPinsDirectionInfo == NULL) { uiError = WDMMINI_ERROR_MEMORYALLOCATION; FAIL; } m_pI2CScript = pCScript; m_pXBarOutputPinsInfo = &m_pXBarInputPinsInfo[m_nNumberOfAudioInputs + m_nNumberOfVideoInputs]; // Medium pin data has an Instance number inside ulInstance = ::GetDriverInstanceNumber( pConfigInfo->RealPhysicalDeviceObject); hFolder = ::OpenRegistryFolder( pConfigInfo->RealPhysicalDeviceObject, &UNICODE_WDM_REG_PIN_MEDIUMS); // initialize video input pins, TVTuner input is always the last one for( nIndex = 0; nIndex < m_nNumberOfVideoInputs; nIndex ++) { switch( nIndex) { case 0: // Composite m_pXBarInputPinsInfo[nIndex].AudioVideoPinType = KS_PhysConn_Video_Composite; // put the default value for the Medium first ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nIndex], &MEDIUM_WILDCARD, sizeof( KSPIN_MEDIUM)); // LineIn is always the first audio pin m_pXBarInputPinsInfo[nIndex].nRelatedPinNumber = m_nNumberOfVideoInputs; break; case 1: // SVideo m_pXBarInputPinsInfo[nIndex].AudioVideoPinType = KS_PhysConn_Video_SVideo; // put the default value for the Medium first ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nIndex], &MEDIUM_WILDCARD, sizeof( KSPIN_MEDIUM)); // LineIn is always the first audio pin m_pXBarInputPinsInfo[nIndex].nRelatedPinNumber = m_nNumberOfVideoInputs; break; case 2: // TVTuner m_pXBarInputPinsInfo[nIndex].AudioVideoPinType = KS_PhysConn_Video_Tuner; // put the default value for the Medium first ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nIndex], &ATIXBarVideoTunerInMedium, sizeof( KSPIN_MEDIUM)); // TVAudio is always the last audio pin m_pXBarInputPinsInfo[nIndex].nRelatedPinNumber = m_nNumberOfVideoInputs + m_nNumberOfAudioInputs - 1; break; default: TRAP; break; } // let's put another Medium value from the registry, if present if( ::ReadPinMediumFromRegistryFolder( hFolder, nIndex, &mediumKSPin)) ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nIndex], &mediumKSPin, sizeof( KSPIN_MEDIUM)); m_pXBarInputPinsInfo[nIndex].pMedium = &m_pXBarPinsMediumInfo[nIndex]; m_pXBarPinsMediumInfo[nIndex].Id = ulInstance; // all the pins here are inputs m_pXBarPinsDirectionInfo[nIndex] = FALSE; } // initialize audio input pins, TV Audio input is always the last one for( nIndex = 0; nIndex < m_nNumberOfAudioInputs; nIndex ++) { nPinIndex = nIndex + m_nNumberOfVideoInputs; switch( nIndex) { case 0: m_pXBarInputPinsInfo[nPinIndex].AudioVideoPinType = KS_PhysConn_Audio_Line; // put the default value for the Medium first ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &MEDIUM_WILDCARD, sizeof( KSPIN_MEDIUM)); m_pXBarInputPinsInfo[nPinIndex].nRelatedPinNumber = 0; break; case 1: m_pXBarInputPinsInfo[nPinIndex].AudioVideoPinType = KS_PhysConn_Audio_Tuner; // put the default value for the Medium first ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &ATIXBarAudioTunerInMedium, sizeof( KSPIN_MEDIUM)); m_pXBarInputPinsInfo[nPinIndex].nRelatedPinNumber = m_nNumberOfVideoInputs - 1; break; default: TRAP; break; } // let's put another Medium value from the registry, if present if( ::ReadPinMediumFromRegistryFolder( hFolder, nPinIndex, &mediumKSPin)) ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &mediumKSPin, sizeof( KSPIN_MEDIUM)); m_pXBarInputPinsInfo[nPinIndex].pMedium = &m_pXBarPinsMediumInfo[nPinIndex]; m_pXBarPinsMediumInfo[nPinIndex].Id = ulInstance; // all the pins here are inputs m_pXBarPinsDirectionInfo[nPinIndex] = FALSE; } // initialize outputs video pins, no X-connection for Video for( nIndex = 0; nIndex < m_nNumberOfVideoOutputs; nIndex ++) { nPinIndex = nIndex + m_nNumberOfVideoInputs + m_nNumberOfAudioInputs; m_pXBarOutputPinsInfo[nIndex].AudioVideoPinType = m_pXBarInputPinsInfo[nIndex].AudioVideoPinType; m_pXBarOutputPinsInfo[nIndex].nConnectedToPin = nIndex; m_pXBarOutputPinsInfo[nIndex].nRelatedPinNumber = m_nNumberOfVideoOutputs; // jaybo switch( m_pXBarOutputPinsInfo[nIndex].AudioVideoPinType) { case KS_PhysConn_Video_Tuner: pMediumKSPin = &ATIXBarVideoTunerOutMedium; break; case KS_PhysConn_Video_SVideo: pMediumKSPin = &ATIXBarVideoSVideoOutMedium; break; case KS_PhysConn_Video_Composite: pMediumKSPin = &ATIXBarVideoCompositeOutMedium; break; default: pMediumKSPin = &MEDIUM_WILDCARD; break; } ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], pMediumKSPin, sizeof( KSPIN_MEDIUM)); // let's put another Medium value from the registry, if present if( ::ReadPinMediumFromRegistryFolder( hFolder, nPinIndex, &mediumKSPin)) ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &mediumKSPin, sizeof( KSPIN_MEDIUM)); m_pXBarOutputPinsInfo[nIndex].pMedium = &m_pXBarPinsMediumInfo[nPinIndex]; m_pXBarPinsMediumInfo[nPinIndex].Id = ulInstance; // all the pins here are outputs m_pXBarPinsDirectionInfo[nPinIndex] = TRUE; } // initialize outputs audio pins for( nIndex = 0; nIndex < m_nNumberOfAudioOutputs; nIndex ++) { nPinIndex = nIndex + m_nNumberOfVideoInputs + m_nNumberOfAudioInputs + m_nNumberOfVideoOutputs; m_pXBarOutputPinsInfo[nIndex + m_nNumberOfVideoInputs].AudioVideoPinType = KS_PhysConn_Audio_AudioDecoder; // put the default value for the Medium first /* jaybo ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], ATIXBarAudioDecoderOutMedium, sizeof( KSPIN_MEDIUM)); */ ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &MEDIUM_WILDCARD, sizeof( KSPIN_MEDIUM)); // let's put another Medium value from the registry, if present if( ::ReadPinMediumFromRegistryFolder( hFolder, nPinIndex, &mediumKSPin)) ::RtlCopyMemory( &m_pXBarPinsMediumInfo[nPinIndex], &mediumKSPin, sizeof( KSPIN_MEDIUM)); m_pXBarOutputPinsInfo[nIndex + m_nNumberOfVideoInputs].nConnectedToPin = ( ULONG)-1; m_pXBarOutputPinsInfo[nIndex + m_nNumberOfVideoInputs].nRelatedPinNumber = (ULONG)-1; m_pXBarOutputPinsInfo[nIndex + m_nNumberOfVideoInputs].pMedium = &m_pXBarPinsMediumInfo[nPinIndex]; m_pXBarPinsMediumInfo[nPinIndex].Id = ulInstance; // all the pins here are outputs m_pXBarPinsDirectionInfo[nPinIndex] = TRUE; } if( hFolder != NULL) ::ZwClose( hFolder); // mute the audio as the default power-up behaviour m_CATIConfiguration.ConnectAudioSource( m_pI2CScript, AUDIOSOURCE_MUTE); // these two functions has to be called after the CWDMAVXBar class object was build on // on the stack and copied over into the DeviceExtension // This commant was true for the case, where the class object was build on the stack first. // There is an overloaded operator new provided for this class, and we can call it from here SetWDMAVXBarKSProperties(); SetWDMAVXBarKSTopology(); // Set run-time WDM properties at the last * puiErrorCode = WDMMINI_NOERROR; OutputDebugTrace(( "CWDMAVXBar:CWDMAVXBar() exit\n")); return; } END_ENSURE; * puiErrorCode = uiError; OutputDebugError(( "CWDMAVXBar:CWDMAVXBar() Error = %x\n", uiError)); } /*^^* * AdapterSetPowerState() * Purpose : Sets Power Management state for deviec * * Inputs : PHW_STREAM_REQUEST_BLOCK pSrb : pointer to the current Srb * * Outputs : NTSTATUS as the operation result * Author : TOM *^^*/ NTSTATUS CWDMAVXBar::AdapterSetPowerState( PHW_STREAM_REQUEST_BLOCK pSrb) { ULONG nAudioSource; ULONG nInputPin; NTSTATUS ntStatus; UINT nIndex; DEVICE_POWER_STATE nDeviceState = pSrb->CommandData.DeviceState; ntStatus = STATUS_ADAPTER_HARDWARE_ERROR; switch( nDeviceState) { case PowerDeviceD0: case PowerDeviceD3: if( nDeviceState != m_ulPowerState) { // if transition form D3 to D0 we have to restore audio connections if(( nDeviceState == PowerDeviceD0) && ( m_ulPowerState == PowerDeviceD3)) { for( nIndex = 0; nIndex < m_nNumberOfAudioOutputs; nIndex ++) { // we need to restore every audio output pin connection, // video output pins are hardwired nInputPin = m_pXBarOutputPinsInfo[nIndex + m_nNumberOfVideoOutputs].nConnectedToPin; switch( m_pXBarInputPinsInfo[nInputPin].AudioVideoPinType) { case KS_PhysConn_Audio_Line: nAudioSource = AUDIOSOURCE_LINEIN; break; case KS_PhysConn_Audio_Tuner: nAudioSource = AUDIOSOURCE_TVAUDIO; break; case 0xFFFFFFFF: nAudioSource = AUDIOSOURCE_MUTE; return( STATUS_SUCCESS); default: OutputDebugError(( "CWDMAVXBar:AdapterSetPowerState() Audio Pin type=%x\n", m_pXBarInputPinsInfo[nInputPin].AudioVideoPinType)); return STATUS_SUCCESS; } if( m_CATIConfiguration.ConnectAudioSource( m_pI2CScript, nAudioSource)) ntStatus = STATUS_SUCCESS; else { // error ntStatus = STATUS_ADAPTER_HARDWARE_ERROR; break; } } } else ntStatus = STATUS_SUCCESS; } else ntStatus = STATUS_SUCCESS; m_ulPowerState = nDeviceState; break; case PowerDeviceUnspecified: case PowerDeviceD1: case PowerDeviceD2: ntStatus = STATUS_SUCCESS; break; default: ntStatus = STATUS_INVALID_PARAMETER; break; } return( ntStatus); }