📄 minwave.cpp
字号:
/*****************************************************************************
* miniport.cpp - SB16 wave miniport implementation
*****************************************************************************
* Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
*/
#include "minwave.h"
#define STR_MODULENAME "sb16wave: "
#pragma code_seg("PAGE")
/*****************************************************************************
* CreateMiniportWaveCyclicSB16()
*****************************************************************************
* Creates a cyclic wave miniport object for the SB16 adapter. This uses a
* macro from STDUNK.H to do all the work.
*/
NTSTATUS
CreateMiniportWaveCyclicSB16
(
OUT PUNKNOWN * Unknown,
IN REFCLSID,
IN PUNKNOWN UnknownOuter OPTIONAL,
IN POOL_TYPE PoolType
)
{
PAGED_CODE();
ASSERT(Unknown);
STD_CREATE_BODY_(CMiniportWaveCyclicSB16,Unknown,UnknownOuter,PoolType,PMINIPORTWAVECYCLIC);
}
/*****************************************************************************
* MapUsingTable()
*****************************************************************************
* Performs a table-based mapping, returning the table index of the indicated
* value. -1 is returned if the value is not found.
*/
int
MapUsingTable
(
IN ULONG Value,
IN PULONG Map,
IN ULONG MapSize
)
{
PAGED_CODE();
ASSERT(Map);
for (int result = 0; result < int(MapSize); result++)
{
if (*Map++ == Value)
{
return result;
}
}
return -1;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::ConfigureDevice()
*****************************************************************************
* Configures the hardware to use the indicated interrupt and DMA channels.
* Returns FALSE iff the configuration is invalid.
*/
BOOLEAN
CMiniportWaveCyclicSB16::
ConfigureDevice
(
IN ULONG Interrupt,
IN ULONG Dma8Bit,
IN ULONG Dma16Bit
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::ConfigureDevice]"));
//
// Tables mapping DMA and IRQ values to register bit offsets.
//
static ULONG validDma[] = { 0, 1, ULONG(-1), 3, ULONG(-1), 5, 6, 7 } ;
static ULONG validIrq[] = { 9, 5, 7, 10 } ;
//
// Make sure we are using the right DMA channels.
//
if (Dma8Bit > 3)
{
return FALSE;
}
if (Dma16Bit < 5)
{
return FALSE;
}
//
// Generate the register value for interrupts.
//
int bit = MapUsingTable(Interrupt,validIrq,SIZEOF_ARRAY(validIrq));
if (bit == -1)
{
return FALSE;
}
BYTE irqConfig = BYTE(1 << bit);
//
// Generate the register value for DMA.
//
bit = MapUsingTable(Dma8Bit,validDma,SIZEOF_ARRAY(validDma));
if (bit == -1)
{
return FALSE;
}
BYTE dmaConfig = BYTE(1 << bit);
if (Dma16Bit != ULONG(-1))
{
bit = MapUsingTable(Dma16Bit,validDma,SIZEOF_ARRAY(validDma));
if (bit == -1)
{
return FALSE;
}
dmaConfig |= BYTE(1 << bit);
}
//
// Inform the hardware.
//
AdapterCommon->MixerRegWrite(DSP_MIX_IRQCONFIG,irqConfig);
AdapterCommon->MixerRegWrite(DSP_MIX_DMACONFIG,dmaConfig);
return TRUE;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::ProcessResources()
*****************************************************************************
* Processes the resource list, setting up helper objects accordingly.
*/
NTSTATUS
CMiniportWaveCyclicSB16::
ProcessResources
(
IN PRESOURCELIST ResourceList
)
{
PAGED_CODE();
ASSERT(ResourceList);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::ProcessResources]"));
ULONG intNumber = ULONG(-1);
ULONG dma8Bit = ULONG(-1);
ULONG dma16Bit = ULONG(-1);
//
// Get counts for the types of resources.
//
ULONG countIO = ResourceList->NumberOfPorts();
ULONG countIRQ = ResourceList->NumberOfInterrupts();
ULONG countDMA = ResourceList->NumberOfDmas();
#if (DBG)
_DbgPrintF(DEBUGLVL_VERBOSE,("Starting SB16 wave on IRQ 0x%X",
ResourceList->FindUntranslatedInterrupt(0)->u.Interrupt.Level) );
_DbgPrintF(DEBUGLVL_VERBOSE,("Starting SB16 wave on Port 0x%X",
ResourceList->FindTranslatedPort(0)->u.Port.Start.LowPart) );
for (ULONG i = 0; i < countDMA; i++)
{
_DbgPrintF(DEBUGLVL_VERBOSE,("Starting SB16 wave on DMA 0x%X",
ResourceList->FindUntranslatedDma(i)->u.Dma.Channel) );
}
#endif
NTSTATUS ntStatus = STATUS_SUCCESS;
//
// Make sure we have the expected number of resources.
//
if ( (countIO != 1)
|| (countIRQ < 1)
|| (countDMA < 1)
)
{
_DbgPrintF(DEBUGLVL_TERSE,("unknown configuraton; check your code!"));
ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
}
if (NT_SUCCESS(ntStatus))
{
//
// Instantiate a DMA channel for 8-bit transfers.
//
ntStatus =
Port->NewSlaveDmaChannel
(
&DmaChannel8,
NULL,
ResourceList,
0,
MAXLEN_DMA_BUFFER,
FALSE, // DemandMode
Compatible
);
//
// Allocate the buffer for 8-bit transfers.
//
if (NT_SUCCESS(ntStatus))
{
ULONG lDMABufferLength = MAXLEN_DMA_BUFFER;
do {
ntStatus = DmaChannel8->AllocateBuffer(lDMABufferLength,NULL);
lDMABufferLength >>= 1;
} while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2)));
}
if (NT_SUCCESS(ntStatus))
{
dma8Bit = ResourceList->FindUntranslatedDma(0)->u.Dma.Channel;
if (countDMA > 1)
{
//
// Instantiate a DMA channel for 16-bit transfers.
//
ntStatus =
Port->NewSlaveDmaChannel
(
&DmaChannel16,
NULL,
ResourceList,
1,
MAXLEN_DMA_BUFFER,
FALSE,
Compatible
);
//
// Allocate the buffer for 16-bit transfers.
//
if (NT_SUCCESS(ntStatus))
{
ULONG lDMABufferLength = MAXLEN_DMA_BUFFER;
do {
ntStatus = DmaChannel16->AllocateBuffer(lDMABufferLength,NULL);
lDMABufferLength >>= 1;
} while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2)));
}
if (NT_SUCCESS(ntStatus))
{
dma16Bit =
ResourceList->FindUntranslatedDma(1)->u.Dma.Channel;
}
}
if (NT_SUCCESS(ntStatus))
{
//
// Get the interrupt number and configure the device.
//
intNumber =
ResourceList->
FindUntranslatedInterrupt(0)->u.Interrupt.Level;
if (! ConfigureDevice(intNumber,dma8Bit,dma16Bit))
{
_DbgPrintF(DEBUGLVL_TERSE,("ConfigureDevice Failure"));
ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
}
}
else
{
_DbgPrintF(DEBUGLVL_TERSE,("NewSlaveDmaChannel 2 Failure %X", ntStatus ));
}
}
else
{
_DbgPrintF(DEBUGLVL_TERSE,("NewSlaveDmaChannel 1 Failure %X", ntStatus ));
}
}
//
// In case of failure object gets destroyed and cleans up.
//
return ntStatus;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::ValidateFormat()
*****************************************************************************
* Validates a wave format.
*/
NTSTATUS
CMiniportWaveCyclicSB16::
ValidateFormat
(
IN PKSDATAFORMAT Format
)
{
PAGED_CODE();
ASSERT(Format);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::ValidateFormat]"));
NTSTATUS ntStatus;
//
// A WAVEFORMATEX structure should appear after the generic KSDATAFORMAT
// if the GUIDs turn out as we expect.
//
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1);
//
// KSDATAFORMAT contains three GUIDs to support extensible format. The
// first two GUIDs identify the type of data. The third indicates the
// type of specifier used to indicate format specifics. We are only
// supporting PCM audio formats that use WAVEFORMATEX.
//
if ( (Format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX))
&& IsEqualGUIDAligned(Format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO)
&& IsEqualGUIDAligned(Format->SubFormat,KSDATAFORMAT_SUBTYPE_PCM)
&& IsEqualGUIDAligned(Format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
&& (waveFormat->wFormatTag == WAVE_FORMAT_PCM)
&& ((waveFormat->wBitsPerSample == 8) || (waveFormat->wBitsPerSample == 16))
&& ((waveFormat->nChannels == 1) || (waveFormat->nChannels == 2))
&& ((waveFormat->nSamplesPerSec >= 5000) && (waveFormat->nSamplesPerSec <= 44100))
)
{
ntStatus = STATUS_SUCCESS;
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
return ntStatus;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::NonDelegatingQueryInterface()
*****************************************************************************
* Obtains an interface. This function works just like a COM QueryInterface
* call and is used if the object is not being aggregated.
*/
STDMETHODIMP
CMiniportWaveCyclicSB16::
NonDelegatingQueryInterface
(
IN REFIID Interface,
OUT PVOID * Object
)
{
PAGED_CODE();
ASSERT(Object);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::NonDelegatingQueryInterface]"));
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
{
*Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this)));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniport))
{
*Object = PVOID(PMINIPORT(this));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclic))
{
*Object = PVOID(PMINIPORTWAVECYCLIC(this));
}
else
{
*Object = NULL;
}
if (*Object)
{
//
// We reference the interface for the caller.
//
PUNKNOWN(*Object)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::~CMiniportWaveCyclicSB16()
*****************************************************************************
* Destructor.
*/
CMiniportWaveCyclicSB16::
~CMiniportWaveCyclicSB16
( void
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::~CMiniportWaveCyclicSB16]"));
if (AdapterCommon)
{
AdapterCommon->SetWaveMiniport (NULL);
AdapterCommon->Release();
AdapterCommon = NULL;
}
if (Port)
{
Port->Release();
Port = NULL;
}
if (DmaChannel8)
{
DmaChannel8->Release();
DmaChannel8 = NULL;
}
if (DmaChannel16)
{
DmaChannel16->Release();
DmaChannel16 = NULL;
}
if (ServiceGroup)
{
ServiceGroup->Release();
ServiceGroup = NULL;
}
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::Init()
*****************************************************************************
* Initializes a the miniport.
*/
STDMETHODIMP
CMiniportWaveCyclicSB16::
Init
(
IN PUNKNOWN UnknownAdapter,
IN PRESOURCELIST ResourceList,
IN PPORTWAVECYCLIC Port_
)
{
PAGED_CODE();
ASSERT(UnknownAdapter);
ASSERT(ResourceList);
ASSERT(Port_);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::init]"));
//
// AddRef() is required because we are keeping this pointer.
//
Port = Port_;
Port->AddRef();
//
// Initialize the member variables.
//
ServiceGroup = NULL;
DmaChannel8 = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -