mirror of https://github.com/lianthony/NT4.0
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.
631 lines
17 KiB
631 lines
17 KiB
/*****************************************************************************
|
|
|
|
Copyright (c) 1993 Media Vision Inc. All Rights Reserved
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code configuration code for the initialization phase
|
|
of the MVAUDIO device driver.
|
|
|
|
Author:
|
|
|
|
EPA 03-09-93
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
#include "sound.h"
|
|
|
|
//
|
|
// Internal routines
|
|
//
|
|
NTSTATUS
|
|
SoundInitIoPort(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PPAS_CONFIG_DATA ConfigData
|
|
);
|
|
NTSTATUS
|
|
SoundPortValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Port
|
|
);
|
|
NTSTATUS
|
|
SoundInitDmaChannel(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG DmaChannel,
|
|
IN ULONG DmaBufferSize
|
|
);
|
|
NTSTATUS
|
|
SoundDmaChannelValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG DmaChannel
|
|
);
|
|
NTSTATUS
|
|
SoundInitInterrupt(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
);
|
|
NTSTATUS
|
|
SoundInterruptValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
);
|
|
VOID
|
|
SoundSetVersion(
|
|
IN PGLOBAL_DEVICE_INFO pGlobalInfo,
|
|
IN ULONG DSPVersion
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,SoundSetVersion)
|
|
#pragma alloc_text(INIT,SoundInitHardwareConfig)
|
|
#pragma alloc_text(INIT,SoundInitIoPort)
|
|
#pragma alloc_text(INIT,SoundInitDmaChannel)
|
|
#pragma alloc_text(INIT,SoundInitInterrupt)
|
|
#pragma alloc_text(INIT,SoundSaveConfig)
|
|
#pragma alloc_text(INIT,SoundReadConfiguration)
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
/*****************************************************************************
|
|
|
|
NOT USED ANYMORE
|
|
Routine Description :
|
|
|
|
Sets a version DWORD into the registry as a pseudo return code
|
|
to sndblst.drv
|
|
|
|
As a side effect the key to the registry entry is closed.
|
|
|
|
Arguments :
|
|
|
|
pGlobalInfo - Our driver global info
|
|
|
|
DSPVersion - the version number we want to set
|
|
|
|
Return Value :
|
|
|
|
None
|
|
|
|
*****************************************************************************/
|
|
VOID SoundSetVersion( IN PGLOBAL_DEVICE_INFO pGlobalInfo,
|
|
IN ULONG DSPVersion )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
UNICODE_STRING VersionString;
|
|
|
|
/***** Start *****/
|
|
|
|
RtlInitUnicodeString(&VersionString,
|
|
L"DSP Version");
|
|
|
|
if ( pGlobalInfo->RegistryPathName )
|
|
{
|
|
NTSTATUS SetStatus;
|
|
|
|
SetStatus = SoundWriteRegistryDWORD( pGlobalInfo->RegistryPathName,
|
|
L"DSP Version",
|
|
DSPVersion );
|
|
|
|
if (!NT_SUCCESS(SetStatus))
|
|
{
|
|
dprintf1(("ERROR: SoundSetVersion(): Failed to write version - status %XH", SetStatus));
|
|
}
|
|
} // End IF (pGlobalInfo->RegistryPathName)
|
|
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
SoundInitHardwareConfig()
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundInitHardwareConfig( IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN PPAS_CONFIG_DATA ConfigData )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
NTSTATUS Status;
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf4(("SoundInitHardwareConfig(): Start"));
|
|
|
|
//
|
|
// Check the input source
|
|
//
|
|
if ( ConfigData->InputSource > INPUT_OUTPUT)
|
|
{
|
|
dprintf1(("ERROR: SoundInitHardwareConfig(): Invalid Input Source = %u",
|
|
ConfigData->InputSource));
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
pGDI->Hw.InputSource = (UCHAR) ConfigData->InputSource;
|
|
|
|
//
|
|
// Find the Base Port and Wake up the PAS Hardware
|
|
//
|
|
Status = SoundInitIoPort( pGDI,
|
|
ConfigData );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
dprintf1(("ERROR: SoundInitHardwareConfig(): SoundInitIoPort() Failed with Status = %u",
|
|
Status));
|
|
|
|
SoundWriteRegistryDWORD( pGDI->RegistryPathName,
|
|
REG_VALUENAME_DRIVER_STATUS,
|
|
ERROR_NO_HW_FOUND );
|
|
|
|
return Status;
|
|
} // End IF (!NT_SUCCESS(Status))
|
|
|
|
//
|
|
// Find interrupt
|
|
//
|
|
Status = SoundInitInterrupt( pGDI,
|
|
&ConfigData->InterruptNumber );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
dprintf1(("ERROR: SoundInitHardwareConfig(): SoundInitInterrupt() Failed with Status = %u",
|
|
Status));
|
|
SoundWriteRegistryDWORD( pGDI->RegistryPathName,
|
|
REG_VALUENAME_DRIVER_STATUS,
|
|
ERROR_INT_CONFLICT );
|
|
return Status;
|
|
} // End IF (!NT_SUCCESS(Status))
|
|
|
|
//
|
|
// Find DMA channel
|
|
//
|
|
Status = SoundInitDmaChannel( pGDI,
|
|
&ConfigData->DmaChannel,
|
|
ConfigData->DmaBufferSize);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
dprintf1(("ERROR: SoundInitHardwareConfig(): SoundInitDmaChannel() Failed with Status = %u",
|
|
Status));
|
|
SoundWriteRegistryDWORD( pGDI->RegistryPathName,
|
|
REG_VALUENAME_DRIVER_STATUS,
|
|
ERROR_DMA_CONFLICT );
|
|
return Status;
|
|
} // End IF (!NT_SUCCESS(Status))
|
|
|
|
//
|
|
// Initialize the ProAudio hardware registers
|
|
//
|
|
HwInitPAS( pGDI );
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // End SoundInitHardwareConfig()
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
SoundInitIoPort()
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundInitIoPort( IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PPAS_CONFIG_DATA ConfigData )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
// NTSTATUS Status;
|
|
NTSTATUS PasStatus;
|
|
|
|
/***** Start *****/
|
|
|
|
//
|
|
// Find where our device is mapped
|
|
//
|
|
|
|
dprintf4(("SoundInitIoPort(): Start"));
|
|
|
|
#if 0
|
|
// Do this in FindPasHardware instead!!
|
|
pGDI->Hw.PortBase = SoundMapPortAddress( pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
ConfigData->Port,
|
|
NUMBER_OF_PAS_PORTS,
|
|
&pGDI->MemType);
|
|
#else
|
|
pGDI->Hw.PortBase = (PUCHAR) &pGDI->PASInfo.ProPort;
|
|
#endif // 0
|
|
|
|
//
|
|
// Try to Locate any ProAudio Spectrums
|
|
//
|
|
PasStatus = FindPasHardware( pGDI,
|
|
ConfigData );
|
|
|
|
if ( !NT_SUCCESS(PasStatus) )
|
|
{
|
|
dprintf1(("ERROR: SoundInitIoPort(): FindPasHardware() Failed with Status = %XH",
|
|
PasStatus));
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
} // End IF (!NT_SUCCESS(PasStatus))
|
|
|
|
pGDI->ProAudioSpectrum = TRUE;
|
|
pGDI->Hw.ThunderBoard = FALSE;
|
|
|
|
InitPasAndMixer( pGDI,
|
|
&pGDI->PASInfo,
|
|
ConfigData );
|
|
|
|
//
|
|
// Setup Min & Max values
|
|
//
|
|
pGDI->MinHz = MIN_SAMPLE_RATE;
|
|
pGDI->MaxInHz = MAX_SAMPLE_RATE;
|
|
pGDI->MaxOutHz = MAX_SAMPLE_RATE;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // End SoundInitIoPort()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
SoundInitDmaChannel()
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundInitDmaChannel( IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG DmaChannel,
|
|
IN ULONG DmaBufferSize )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
DEVICE_DESCRIPTION DeviceDescription; // DMA adapter object
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf3(("SoundInitDmaChannel(): Start"));
|
|
dprintf4((" SoundInitDmaChannel(): DMA Channel = %u", *DmaChannel));
|
|
dprintf4((" SoundInitDmaChannel(): DMA Buffer Size = %XH", DmaBufferSize));
|
|
|
|
//
|
|
// See if we can get this channel
|
|
//
|
|
|
|
//
|
|
// Zero the device description structure.
|
|
//
|
|
|
|
RtlZeroMemory(&DeviceDescription,
|
|
sizeof(DEVICE_DESCRIPTION));
|
|
|
|
//
|
|
// Get the adapter object for this card.
|
|
//
|
|
|
|
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
|
|
DeviceDescription.AutoInitialize = TRUE;
|
|
DeviceDescription.ScatterGather = FALSE;
|
|
DeviceDescription.DmaChannel = *DmaChannel;
|
|
DeviceDescription.InterfaceType = Isa; // Must use Isa DMA
|
|
DeviceDescription.DmaSpeed = Compatible;
|
|
DeviceDescription.MaximumLength = DmaBufferSize;
|
|
DeviceDescription.BusNumber = pGDI->BusNumber;
|
|
|
|
//
|
|
// Check the DMA Channel to set the DMA width
|
|
//
|
|
if ( *DmaChannel > 4 )
|
|
{
|
|
// 16 Bit DMA
|
|
DeviceDescription.DmaWidth = Width16Bits;
|
|
}
|
|
else
|
|
{
|
|
// 8 Bit DMA
|
|
DeviceDescription.DmaWidth = Width8Bits;
|
|
}
|
|
|
|
return SoundGetCommonBuffer(&DeviceDescription, &pGDI->WaveInfo.DMABuf);
|
|
|
|
} // End SoundInitDmaChannel()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
SoundInitInterrupt()
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundInitInterrupt( IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
NTSTATUS Status;
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf4(("SoundInitInterrupt(): Start"));
|
|
|
|
//
|
|
// See if we can get this interrupt
|
|
//
|
|
|
|
Status = SoundConnectInterrupt(*Interrupt,
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
SoundISR,
|
|
(PVOID)pGDI,
|
|
INTERRUPT_MODE,
|
|
IRQ_SHARABLE,
|
|
&pGDI->WaveInfo.Interrupt );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
dprintf1(("ERROR: SoundInitInterrupt(): SoundConnectInterrupt() Failed with Status = %XH",
|
|
Status));
|
|
return Status;
|
|
} // End IF (!NT_SUCCESS(Status))
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // End SoundInitInterrupt()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
Routine Description :
|
|
|
|
Saves the drivers configuration information for our device
|
|
|
|
Arguments :
|
|
|
|
Registry Key values
|
|
|
|
Return Value :
|
|
|
|
NT status code - STATUS_SUCCESS if no problems
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundSaveConfig( IN PWSTR DeviceKey,
|
|
IN ULONG Port,
|
|
IN ULONG DmaChannel,
|
|
IN ULONG Interrupt,
|
|
IN ULONG InputSource )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
NTSTATUS Status;
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf4(("SoundSaveConfig(): Start"));
|
|
|
|
//
|
|
// Port
|
|
//
|
|
Status = SoundWriteRegistryDWORD( DeviceKey,
|
|
SOUND_REG_PORT,
|
|
Port );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// DmaChannel
|
|
//
|
|
Status = SoundWriteRegistryDWORD( DeviceKey,
|
|
SOUND_REG_DMACHANNEL,
|
|
DmaChannel );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Interrupt
|
|
//
|
|
Status = SoundWriteRegistryDWORD( DeviceKey,
|
|
SOUND_REG_INTERRUPT,
|
|
Interrupt );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Input Source
|
|
//
|
|
Status = SoundWriteRegistryDWORD( DeviceKey,
|
|
SOUND_REG_INPUTSOURCE,
|
|
InputSource );
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Make sure the config routine sees the data
|
|
//
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
} // End SoundSaveConfig()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
Routine Description :
|
|
|
|
Saves the drivers Volume configuration information for our device
|
|
|
|
Arguments :
|
|
|
|
PGLOBAL_DEVICE_INFO pGDI
|
|
|
|
Return Value :
|
|
|
|
NT status code - STATUS_SUCCESS if no problems
|
|
|
|
*****************************************************************************/
|
|
VOID SoundSaveVolume( PGLOBAL_DEVICE_INFO pGDI )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
int i;
|
|
PLOCAL_DEVICE_INFO pLDI;
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf4(("SoundSaveVolume(): Start"));
|
|
|
|
//
|
|
// Write out left and right volume settings for each device
|
|
//
|
|
|
|
for (i = 0; i < NumberOfDevices; i++) {
|
|
if ( pGDI->DeviceObject[i] ) {
|
|
pLDI = (PLOCAL_DEVICE_INFO)pGDI->DeviceObject[i]->DeviceExtension;
|
|
SoundSaveDeviceVolume( pLDI, pGDI->RegistryPathName );
|
|
}
|
|
|
|
} // End FOR (i < NumberOfDevices)
|
|
|
|
} // End SoundSaveVolume()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
Routine Description :
|
|
|
|
Return configuration information for our device
|
|
|
|
Arguments :
|
|
|
|
ConfigData - where to store the result
|
|
|
|
Return Value :
|
|
|
|
NT status code - STATUS_SUCCESS if no problems
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SoundReadConfiguration( IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext )
|
|
{
|
|
/***** Local Variables *****/
|
|
|
|
PPAS_CONFIG_DATA ConfigData;
|
|
|
|
/***** Start *****/
|
|
|
|
dprintf4(("SoundReadConfiguration(): Start"));
|
|
|
|
ConfigData = Context;
|
|
|
|
if ( ValueType == REG_DWORD )
|
|
{
|
|
// Base I/O Port
|
|
if ( _wcsicmp(ValueName, SOUND_REG_PORT) == 0 )
|
|
{
|
|
ConfigData->Port = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration(): Read Port Base = %XH",
|
|
ConfigData->Port));
|
|
}
|
|
|
|
// Interrupt
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_INTERRUPT) == 0 )
|
|
{
|
|
ConfigData->InterruptNumber = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration(): Read Interrupt = %u",
|
|
ConfigData->InterruptNumber));
|
|
}
|
|
|
|
// DMA Channel
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_DMACHANNEL) == 0 )
|
|
{
|
|
ConfigData->DmaChannel = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration(): Read DMA Channel = %u",
|
|
ConfigData->DmaChannel));
|
|
}
|
|
|
|
// DMA Buffer Size
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_DMABUFFERSIZE ) == 0 )
|
|
{
|
|
ConfigData->DmaBufferSize = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration(): Read DMA Buffer Size = %XH",
|
|
ConfigData->DmaBufferSize));
|
|
}
|
|
|
|
// FM Clock Override
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_FM_CLK_OVRID) == 0 )
|
|
{
|
|
ConfigData->FMClockOverride = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration(): Read FMClockOverride = %u",
|
|
ConfigData->FMClockOverride));
|
|
}
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_ALLOWMICLINEINTOLINEOUT) == 0 )
|
|
{
|
|
ConfigData->AllowMicOrLineInToLineOut = (BOOLEAN)(*(PULONG)ValueData != 0);
|
|
dprintf3((" SoundReadConfiguration(): Read FMClockOverride = %u",
|
|
ConfigData->FMClockOverride));
|
|
}
|
|
|
|
// Input Source
|
|
else if ( _wcsicmp(ValueName, SOUND_REG_INPUTSOURCE) == 0 )
|
|
{
|
|
ConfigData->InputSource = *(PULONG)ValueData;
|
|
dprintf3((" SoundReadConfiguration() Read Input Source = %s",
|
|
ConfigData->InputSource == INPUT_LINEIN ? "Line in" :
|
|
ConfigData->InputSource == INPUT_AUX ? "Aux" :
|
|
ConfigData->InputSource == INPUT_MIC ? "Microphone" :
|
|
ConfigData->InputSource == INPUT_OUTPUT ? "Output" :
|
|
"Invalid input source" ));
|
|
}
|
|
} // End IF (ValueType == REG_DWORD)
|
|
else {
|
|
if (ValueType == REG_BINARY &&
|
|
_wcsicmp(ValueName, SOUND_MIXER_SETTINGS_NAME) == 0) {
|
|
ASSERTMSG("Mixer data wrong length!",
|
|
ValueLength == sizeof(ConfigData->MixerSettings));
|
|
|
|
dprintf3(("Mixer settings"));
|
|
RtlCopyMemory((PVOID)ConfigData->MixerSettings,
|
|
ValueData,
|
|
ValueLength);
|
|
ConfigData->MixerSettingsFound = TRUE;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
/************************************ END ***********************************/
|
|
|