⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minwave.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
 * 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 + -