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.
829 lines
17 KiB
829 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code configuration code for the initialization phase
|
|
of the Microsoft Sound System device driver.
|
|
|
|
Author:
|
|
|
|
Robin Speed (RobinSp) 17-Oct-1992
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "sound.h"
|
|
#include <string.h>
|
|
|
|
//
|
|
// Internal routines
|
|
//
|
|
NTSTATUS
|
|
SoundInitIoPort(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Port
|
|
);
|
|
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,
|
|
IN ULONG DmaBufferSize
|
|
);
|
|
NTSTATUS
|
|
SoundInitInterrupt(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
);
|
|
NTSTATUS
|
|
SoundInterruptValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
);
|
|
BOOLEAN
|
|
InList(
|
|
IN CONST ULONG * List,
|
|
IN ULONG Value
|
|
);
|
|
NTSTATUS
|
|
SoundCheckCompaqBA(
|
|
PGLOBAL_DEVICE_INFO pGDI,
|
|
ULONG SoundPort
|
|
);
|
|
BOOLEAN
|
|
SoundTestTransfer(
|
|
IN PGLOBAL_DEVICE_INFO pGDI,
|
|
IN ULONG MajorFunction,
|
|
IN PDEVICE_OBJECT pDO,
|
|
IN PVOID DeviceData
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,SoundInitHardwareConfig)
|
|
#pragma alloc_text(INIT,SoundInitIoPort)
|
|
#pragma alloc_text(INIT,SoundPortValid)
|
|
#pragma alloc_text(INIT,SoundInitDmaChannel)
|
|
#pragma alloc_text(INIT,SoundDmaChannelValid)
|
|
#pragma alloc_text(INIT,SoundInitInterrupt)
|
|
#pragma alloc_text(INIT,SoundInterruptValid)
|
|
#pragma alloc_text(INIT,SoundSaveConfig)
|
|
#pragma alloc_text(INIT,SoundReadConfiguration)
|
|
#pragma alloc_text(INIT,SoundCheckCompaqBA)
|
|
#pragma alloc_text(INIT,InList)
|
|
#pragma alloc_text(INIT,SoundTestInterruptAndDMA)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
SoundInitHardwareConfig(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Port,
|
|
IN OUT PULONG InterruptNumber,
|
|
IN OUT PULONG DmaChannel,
|
|
IN ULONG DmaBufferSize
|
|
)
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Find port
|
|
//
|
|
|
|
Status = SoundInitIoPort(pGDI, Port);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Find interrupt
|
|
//
|
|
|
|
Status = SoundInitInterrupt(pGDI, InterruptNumber);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Find DMA channel
|
|
//
|
|
|
|
Status = SoundInitDmaChannel(pGDI, DmaChannel, DmaBufferSize);
|
|
pGDI->DmaChannel = *DmaChannel;
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Report all resources used
|
|
//
|
|
|
|
Status = SoundReportResourceUsage(pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
InterruptNumber,
|
|
INTERRUPT_MODE,
|
|
IRQ_SHARABLE,
|
|
DmaChannel,
|
|
Port,
|
|
NUMBER_OF_SOUND_PORTS);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Now we know all our data we can set up the real hardware
|
|
// The global device info now contains all device mappings etc
|
|
//
|
|
|
|
if (!HwInitialize(&pGDI->WaveInfo,
|
|
&pGDI->Hw,
|
|
*DmaChannel,
|
|
*InterruptNumber)) {
|
|
SoundSetErrorCode(pGDI->RegistryPathName, SOUND_CONFIG_BADCARD);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
InList(
|
|
IN CONST ULONG *List,
|
|
IN ULONG Value
|
|
)
|
|
{
|
|
for ( ; *List != 0xFFFF ; List++) { // 0xFFFF = end of list
|
|
if (Value == *List) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS
|
|
SoundInitIoPort(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Port
|
|
)
|
|
{
|
|
ULONG CurrentPort;
|
|
int i;
|
|
NTSTATUS Status;
|
|
static CONST ULONG PortChoices[] = VALID_IO_PORTS;
|
|
|
|
//
|
|
// Make sure the one given really is in the list
|
|
//
|
|
|
|
if (!InList(PortChoices, *Port)) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// First check the port we were given. If this is not OK look
|
|
// through them all in turn. 0xFFFF is an end marker in the array
|
|
//
|
|
|
|
|
|
for (i = 0, CurrentPort = *Port;
|
|
CurrentPort != 0xFFFF;
|
|
CurrentPort = PortChoices[i], i++) {
|
|
|
|
|
|
Status = SoundPortValid(pGDI, &CurrentPort);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
if (*Port != CurrentPort) {
|
|
dprintf2(("Changing port number to %4X", CurrentPort));
|
|
}
|
|
|
|
*Port = CurrentPort;
|
|
return Status;
|
|
}
|
|
|
|
if (Status != STATUS_DEVICE_CONFIGURATION_ERROR) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
dprintf2(("No valid IO port found"));
|
|
|
|
SoundSetErrorCode(pGDI->RegistryPathName, SOUND_CONFIG_NOCARD);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundCheckCompaqBA(PGLOBAL_DEVICE_INFO pGDI, ULONG SoundPort)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Port;
|
|
UCHAR CompaqPCR;
|
|
|
|
//
|
|
// Only 530 and 604 supported
|
|
//
|
|
|
|
if (SoundPort != 0x530 && SoundPort != 0x604) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
Port = 0xC44;
|
|
|
|
//
|
|
// Go and search at C44 - attach it to the wave in device so it will be
|
|
// overwritten later since we don't want to keep it
|
|
//
|
|
Status = SoundReportResourceUsage(
|
|
pGDI->DeviceObject[WaveInDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&Port,
|
|
1);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Find where our device is mapped and map 4 bytes to cover
|
|
// C44 and C47
|
|
//
|
|
|
|
pGDI->Hw.CompaqBA = SoundMapPortAddress(
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
Port,
|
|
4,
|
|
&pGDI->MemType);
|
|
|
|
//
|
|
// Read the peripheral Configuration Register (PCR)
|
|
//
|
|
|
|
CompaqPCR = READ_PORT_UCHAR(pGDI->Hw.CompaqBA);
|
|
|
|
//
|
|
// See if the PCR agress with where we think the hardware is
|
|
//
|
|
// 0x10 bit says sound enabled
|
|
// 0x20 bit says it's at 604 (rather than 530)
|
|
//
|
|
|
|
if (CompaqPCR != 0xFF &&
|
|
((CompaqPCR & 0x30) == 0x10 && SoundPort == 0x530 ||
|
|
(CompaqPCR & 0x30) == 0x30 && SoundPort == 0x604)) {
|
|
|
|
//
|
|
// Looks like the base address is really at C44. In
|
|
// this case we re-report so that we don't prevent others
|
|
// looking at the PCR since from now on we're only interested
|
|
// in 0xC47
|
|
//
|
|
|
|
Port += BOARD_ID;
|
|
|
|
Status = SoundReportResourceUsage(
|
|
pGDI->DeviceObject[WaveOutDevice],
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&Port,
|
|
1);
|
|
|
|
} else {
|
|
//
|
|
// Unmap - we don't need to unreport because our final declaration
|
|
// of what we use will overwrite our reporting of C44
|
|
//
|
|
|
|
if (pGDI->MemType == 0) {
|
|
MmUnmapIoSpace(pGDI->Hw.CompaqBA, 4);
|
|
}
|
|
pGDI->Hw.CompaqBA = NULL;
|
|
|
|
|
|
//
|
|
// It might be the old Compaq Business Audio 1
|
|
// The Red I (early Prolinea/I boxes) did not use the C44
|
|
// port but instaed used the actual ports, so lets try again
|
|
//
|
|
|
|
CompaqPCR = INPORT(&pGDI->Hw, BOARD_CONFIG);
|
|
|
|
if (CompaqPCR == 0xFF) {
|
|
//
|
|
// Must be one of the really old machines
|
|
// We'll test the interrupt and DMA later
|
|
//
|
|
|
|
pGDI->Hw.CompaqBA = pGDI->Hw.PortBase;
|
|
pGDI->Hw.NoPCR = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if ((CompaqPCR & 0x30) == 0x10 && SoundPort == 0x530 ||
|
|
(CompaqPCR & 0x30) == 0x30 && SoundPort == 0x604) {
|
|
|
|
pGDI->Hw.CompaqBA = pGDI->Hw.PortBase;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
} else {
|
|
Status = STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundPortValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Port
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Check we're going to be allowed to use this port or whether
|
|
// some other device thinks it owns this hardware
|
|
//
|
|
|
|
Status = SoundReportResourceUsage(
|
|
pGDI->DeviceObject[WaveInDevice], // As good as any device to own
|
|
// it
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
Port,
|
|
NUMBER_OF_SOUND_PORTS);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Find where our device is mapped
|
|
//
|
|
|
|
pGDI->Hw.PortBase = SoundMapPortAddress(
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
*Port,
|
|
NUMBER_OF_SOUND_PORTS,
|
|
&pGDI->MemType);
|
|
|
|
//
|
|
// Finally we can check and see if the hardware is happy
|
|
//
|
|
|
|
if (HwIsIoValid(&pGDI->Hw)) {
|
|
//
|
|
// Check if it's compaq Business Audio
|
|
//
|
|
|
|
#if !(_ON_PLANNAR_)
|
|
|
|
if ((INPORT(&pGDI->Hw, BOARD_ID) & 0x3F) != FH_PAL_PRODUCTREV_RQD) {
|
|
|
|
|
|
SoundCheckCompaqBA(pGDI, *Port);
|
|
}
|
|
#endif
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Free any resources. (note we don't have to do
|
|
// IoReportResourceUsage again because each one overwrites the
|
|
// previous).
|
|
//
|
|
|
|
if (pGDI->MemType == 0) {
|
|
MmUnmapIoSpace(pGDI->Hw.PortBase, NUMBER_OF_SOUND_PORTS);
|
|
}
|
|
pGDI->Hw.PortBase = NULL;
|
|
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
NTSTATUS
|
|
SoundInitDmaChannel(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG DmaChannel,
|
|
IN ULONG DmaBufferSize
|
|
)
|
|
{
|
|
ULONG CurrentDmaChannel;
|
|
NTSTATUS Status;
|
|
int i;
|
|
static CONST ULONG DmaChannelChoices[] = VALID_DMA_CHANNELS;
|
|
|
|
//
|
|
// Make sure the one given really is in the list
|
|
//
|
|
|
|
if (!InList(DmaChannelChoices, *DmaChannel)) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// First check the channel we were given if this fails
|
|
// try them all
|
|
//
|
|
|
|
for (i = 0, CurrentDmaChannel = *DmaChannel;
|
|
CurrentDmaChannel != 0xFFFF; // 0xFFFF is terminator
|
|
CurrentDmaChannel = DmaChannelChoices[i], i++) {
|
|
|
|
Status = SoundDmaChannelValid(pGDI, &CurrentDmaChannel, DmaBufferSize);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
if (*DmaChannel != CurrentDmaChannel) {
|
|
dprintf2(("Changing DMA channel to %u", CurrentDmaChannel));
|
|
}
|
|
|
|
*DmaChannel = CurrentDmaChannel;
|
|
return Status;
|
|
}
|
|
|
|
if (Status != STATUS_DEVICE_CONFIGURATION_ERROR) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
dprintf2(("No valid DMA channel found"));
|
|
|
|
SoundSetErrorCode(pGDI->RegistryPathName, SOUND_CONFIG_NODMA);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundDmaChannelValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG DmaChannel,
|
|
IN ULONG DmaBufferSize
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
DEVICE_DESCRIPTION DeviceDescription; // DMA adapter object
|
|
|
|
//
|
|
// See if the hardware is happy
|
|
//
|
|
|
|
if (!pGDI->Hw.NoPCR && !HwIsDMAValid(&pGDI->Hw, *DmaChannel)) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// Check we're going to be allowed to use this DmaChannel or whether
|
|
// some other device thinks it owns this hardware
|
|
//
|
|
|
|
Status = SoundReportResourceUsage(
|
|
pGDI->DeviceObject[WaveInDevice], // As good as any device to own
|
|
// it
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
DmaChannel,
|
|
NULL,
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// 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.DemandMode = !pGDI->SingleModeDMA;
|
|
DeviceDescription.ScatterGather = FALSE;
|
|
DeviceDescription.DmaChannel = *DmaChannel;
|
|
DeviceDescription.InterfaceType = (pGDI->BusType == MicroChannel) ?
|
|
MicroChannel : Isa;
|
|
DeviceDescription.DmaWidth = Width8Bits;
|
|
DeviceDescription.DmaSpeed = Compatible;
|
|
DeviceDescription.MaximumLength = DmaBufferSize;
|
|
DeviceDescription.BusNumber = pGDI->BusNumber;
|
|
|
|
return SoundGetCommonBuffer(&DeviceDescription, &pGDI->WaveInfo.DMABuf);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundInitInterrupt(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG CurrentInterrupt;
|
|
int i;
|
|
static CONST ULONG InterruptChoices[] = VALID_INTERRUPTS;
|
|
|
|
//
|
|
// Make sure the one given really is in the list
|
|
//
|
|
|
|
if (!InList(InterruptChoices, *Interrupt)) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// First check the interrupt we were given
|
|
// If this fails check them all
|
|
//
|
|
|
|
|
|
for (i = 0, CurrentInterrupt = *Interrupt;
|
|
CurrentInterrupt != 0xFFFF; // 0xFFFF is terminator
|
|
CurrentInterrupt = InterruptChoices[i], i++) {
|
|
|
|
|
|
Status = SoundInterruptValid(pGDI, &CurrentInterrupt);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
if (*Interrupt != CurrentInterrupt) {
|
|
dprintf2(("Changing interrupt to %u", CurrentInterrupt));
|
|
}
|
|
|
|
*Interrupt = CurrentInterrupt;
|
|
return Status;
|
|
}
|
|
|
|
if (Status != STATUS_DEVICE_CONFIGURATION_ERROR) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
dprintf2(("No valid Interrupt found"));
|
|
|
|
SoundSetErrorCode(pGDI->RegistryPathName, SOUND_CONFIG_NOINT);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundInterruptValid(
|
|
IN OUT PGLOBAL_DEVICE_INFO pGDI,
|
|
IN OUT PULONG Interrupt
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// See if the hardware is happy
|
|
//
|
|
|
|
if (!pGDI->Hw.NoPCR && !HwIsInterruptValid(&pGDI->Hw, *Interrupt)) {
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// Check we're going to be allowed to use this Interrupt or whether
|
|
// some other device thinks it owns this hardware
|
|
//
|
|
|
|
Status = SoundReportResourceUsage(
|
|
pGDI->DeviceObject[WaveInDevice], // As good as any device to own
|
|
// it
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
Interrupt,
|
|
INTERRUPT_MODE,
|
|
IRQ_SHARABLE,
|
|
NULL,
|
|
NULL,
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// See if we can get this interrupt
|
|
//
|
|
|
|
|
|
return SoundConnectInterrupt(
|
|
*Interrupt,
|
|
pGDI->BusType,
|
|
pGDI->BusNumber,
|
|
SoundISR,
|
|
(PVOID)pGDI,
|
|
INTERRUPT_MODE,
|
|
IRQ_SHARABLE,
|
|
&pGDI->WaveInfo.Interrupt);
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
SoundTestInterruptAndDMA(
|
|
IN PGLOBAL_DEVICE_INFO pGDI
|
|
)
|
|
//
|
|
// Check if the interrupt and DMA settings work with the card
|
|
// If not we beat a hasty retreat and hope we haven't broken anything!
|
|
//
|
|
{
|
|
int Error;
|
|
|
|
Error = SoundTestWaveDevice(pGDI->DeviceObject[WaveOutDevice]);
|
|
|
|
|
|
#if DBG
|
|
if (Error)
|
|
dprintf2(("SoundTestInterruptAndDMA: Error during SoundTestWaveDevice(WaveOut)."));
|
|
#endif
|
|
|
|
|
|
if (Error == 0) {
|
|
Error = SoundTestWaveDevice(pGDI->DeviceObject[WaveInDevice]);
|
|
|
|
|
|
#if DBG
|
|
if (Error)
|
|
dprintf2(("SoundTestInterruptAndDMA: Error during SoundTestWaveDevice(WaveIn)."));
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Make sure everything gets finished
|
|
//
|
|
|
|
HwSetWaveFormat(&pGDI->WaveInfo);
|
|
|
|
if (Error != 0) {
|
|
SoundSetErrorCode(pGDI->RegistryPathName,
|
|
Error == 1 ? SOUND_CONFIG_BADINT
|
|
: SOUND_CONFIG_BADDMA);
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
SoundSaveConfig(
|
|
IN PWSTR RegistryPath,
|
|
IN ULONG Port,
|
|
IN ULONG DmaChannel,
|
|
IN ULONG Interrupt
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = SoundWriteRegistryDWORD(RegistryPath, SOUND_REG_PORT, Port);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SoundWriteRegistryDWORD(RegistryPath, SOUND_REG_DMACHANNEL, DmaChannel);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SoundWriteRegistryDWORD(RegistryPath, SOUND_REG_INTERRUPT, Interrupt);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SoundReadConfiguration(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
)
|
|
/*++
|
|
|
|
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
|
|
|
|
--*/
|
|
{
|
|
PSOUND_CONFIG_DATA ConfigData;
|
|
|
|
ConfigData = Context;
|
|
|
|
if (ValueType == REG_DWORD) {
|
|
|
|
if (_wcsicmp(ValueName, SOUND_REG_PORT) == 0) {
|
|
ConfigData->Port = *(PULONG)ValueData;
|
|
dprintf3(("Read Port Base : %x", ConfigData->Port));
|
|
}
|
|
|
|
else if (_wcsicmp(ValueName, SOUND_REG_INTERRUPT) == 0) {
|
|
ConfigData->InterruptNumber = *(PULONG)ValueData;
|
|
dprintf3(("Read Interrupt : %x", ConfigData->InterruptNumber));
|
|
}
|
|
|
|
else if (_wcsicmp(ValueName, SOUND_REG_DMACHANNEL) == 0) {
|
|
ConfigData->DmaChannel = *(PULONG)ValueData;
|
|
dprintf3(("Read DMA Channel : %x", ConfigData->DmaChannel));
|
|
}
|
|
|
|
else if (_wcsicmp(ValueName, SOUND_REG_DMABUFFERSIZE) == 0) {
|
|
ConfigData->DmaBufferSize = *(PULONG)ValueData;
|
|
dprintf3(("Read Buffer size : %x", ConfigData->DmaBufferSize));
|
|
}
|
|
|
|
else if (_wcsicmp(ValueName, SOUND_REG_SINGLEMODEDMA) == 0) {
|
|
ConfigData->SingleModeDMA = *(PULONG)ValueData;
|
|
dprintf3(("Read DemandMode : %x", ConfigData->SingleModeDMA));
|
|
}
|
|
} 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;
|
|
}
|