From 30bfd875a818e3dae9196901cbb2aabe04a10472 Mon Sep 17 00:00:00 2001 From: Andrew Greenwood Date: Wed, 14 Mar 2007 21:31:31 +0000 Subject: [PATCH] Yet more files I've been meaning to commit... (and again they're mostly incomplete) svn path=/trunk/; revision=26103 --- .../drivers/multimedia/sb16_ks/adapter.cpp | 137 +++++ reactos/drivers/multimedia/sb16_ks/main.cpp | 356 +++++++++++++ reactos/drivers/multimedia/sb16_ks/sb16.h | 141 +++++ .../drivers/multimedia/sb16_ks/sb16.rbuild | 11 + .../drivers/multimedia/sb16_ks/sb16_ks.def | 6 + reactos/drivers/multimedia/sb16_ks/stdunk.cpp | 68 +++ reactos/drivers/multimedia/sb16_nt4/control.c | 222 ++++++++ .../drivers/multimedia/sb16_nt4/interrupt.c | 61 +++ reactos/drivers/multimedia/sb16_nt4/main.c | 489 ++++++++++++++++++ .../drivers/multimedia/sb16_nt4/sb16_nt4.def | 6 + .../multimedia/sb16_nt4/sb16_nt4.rbuild | 11 + reactos/drivers/multimedia/sb16_nt4/sndblst.h | 155 ++++++ reactos/drivers/multimedia/stdunk/stdunk.c | 62 +++ reactos/drivers/multimedia/stdunk/stdunk.cpp | 98 ++++ 14 files changed, 1823 insertions(+) create mode 100644 reactos/drivers/multimedia/sb16_ks/adapter.cpp create mode 100644 reactos/drivers/multimedia/sb16_ks/main.cpp create mode 100644 reactos/drivers/multimedia/sb16_ks/sb16.h create mode 100644 reactos/drivers/multimedia/sb16_ks/sb16.rbuild create mode 100644 reactos/drivers/multimedia/sb16_ks/sb16_ks.def create mode 100644 reactos/drivers/multimedia/sb16_ks/stdunk.cpp create mode 100644 reactos/drivers/multimedia/sb16_nt4/control.c create mode 100644 reactos/drivers/multimedia/sb16_nt4/interrupt.c create mode 100644 reactos/drivers/multimedia/sb16_nt4/main.c create mode 100644 reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def create mode 100644 reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild create mode 100644 reactos/drivers/multimedia/sb16_nt4/sndblst.h create mode 100644 reactos/drivers/multimedia/stdunk/stdunk.c create mode 100644 reactos/drivers/multimedia/stdunk/stdunk.cpp diff --git a/reactos/drivers/multimedia/sb16_ks/adapter.cpp b/reactos/drivers/multimedia/sb16_ks/adapter.cpp new file mode 100644 index 00000000000..16e7ed0c6b2 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/adapter.cpp @@ -0,0 +1,137 @@ +#include "sb16.h" + +class CAdapterSB16 : + public IAdapterSB16, + public IAdapterPowerManagement, + public CUnknown +{ + public : + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CAdapterSB16); + ~CAdapterSB16(); + + STDMETHODIMP_(NTSTATUS) Init( + IN PRESOURCELIST ResourceList, + IN PDEVICE_OBJECT DeviceObject); + + STDMETHODIMP_(PINTERRUPTSYNC) GetInterruptSync(void); + + STDMETHODIMP_(void) SetWaveMiniport( + IN PWAVEMINIPORTSB16 Miniport); + + STDMETHODIMP_(BYTE) Read(void); + + STDMETHODIMP_(BOOLEAN) Write( + IN BYTE Value); + + STDMETHODIMP_(NTSTATUS) Reset(void); + + STDMETHODIMP_(void) SetMixerValue( + IN BYTE Index, + IN BYTE Value); + + STDMETHODIMP_(BYTE) GetMixerValue( + IN BYTE Index); + + STDMETHODIMP_(void) ResetMixer(void); + + //IMP_IAdapterPowerManagement; +}; + + +NTSTATUS +NewAdapter( + OUT PUNKNOWN* Unknown, + IN REFCLSID, + IN PUNKNOWN UnknownOuter OPTIONAL, + IN POOL_TYPE PoolType) +{ + STD_CREATE_BODY_( CAdapterSB16, Unknown, UnknownOuter, PoolType, PADAPTERSB16 ); +} + + +NTSTATUS CAdapterSB16::Init( + IN PRESOURCELIST ResourceList, + IN PDEVICE_OBJECT DeviceObject) +{ + return STATUS_UNSUCCESSFUL; +} + +CAdapterSB16::~CAdapterSB16() +{ +} +/* +STDMETHODIMP +CAdapterSB16::NonDelegatingQueryInterface( + REFIID Interface, + PVOID* Object) +{ + return STATUS_UNSUCCESSFUL; +} +*/ +STDMETHODIMP_(PINTERRUPTSYNC) +CAdapterSB16::GetInterruptSync() +{ + return NULL; +} + +STDMETHODIMP_(BYTE) +CAdapterSB16::Read() +{ + return 0x00; +} + +STDMETHODIMP_(BOOLEAN) +CAdapterSB16::Write( + IN BYTE Value) +{ + return FALSE; +} + +STDMETHODIMP_(NTSTATUS) +CAdapterSB16::Reset() +{ + return STATUS_UNSUCCESSFUL; +} + +STDMETHODIMP_(void) +CAdapterSB16::SetMixerValue( + IN BYTE Index, + IN BYTE Value) +{ +} + +STDMETHODIMP_(BYTE) +CAdapterSB16::GetMixerValue( + IN BYTE Index) +{ + return 0x00; +} + +STDMETHODIMP_(void) +CAdapterSB16::ResetMixer() +{ +} + + +/* +STDMETHODIMP_(void) +CAdapterSB16::PowerChangeState( + IN POWER_STATE NewState) +{ +} + +STDMETHODIMP_(NTSTATUS) +CAdapterSB16::QueryPowerChangeState( + IN POWER_STATE NewStateQuery) +{ + return STATUS_UNSUCCESSFUL; +} + +STDMETHODIMP_(NTSTATUS) +CAdapterSB16::QueryDeviceCapabilities( + IN PDEVICE_CAPABILITIES) +{ + return STATUS_UNSUCCESSFUL; +} +*/ diff --git a/reactos/drivers/multimedia/sb16_ks/main.cpp b/reactos/drivers/multimedia/sb16_ks/main.cpp new file mode 100644 index 00000000000..39a69fe3e7b --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/main.cpp @@ -0,0 +1,356 @@ +/* + ReactOS Operating System + Sound Blaster KS Driver + + AUTHORS: + Andrew Greenwood + + NOTES: + WaveTable is not supported. +*/ + +#include + +/* How many miniports do we support? */ +#define MAX_MINIPORTS 1 + + +typedef struct +{ + PRESOURCELIST Wave; + PRESOURCELIST WaveTable; + PRESOURCELIST FmSynth; + PRESOURCELIST Uart; + PRESOURCELIST Adapter; +} Resources; + + +DWORD +DetectPlatform( + PPORTTOPOLOGY Port) +{ + /* ASSERT(Port); */ + + PPORTCLSVERSION portcls_version; + PDRMPORT drm_port; + PPORTEVENTS port_events; + DWORD version; + +/* + TODO: This stuff needs IID impls + + Port->QueryInterface( IID_IPortClsVersion, (PVOID*) &portcls_version); + Port->QueryInterface( IID_IDrmPort, (PVOID*) &drm_port); + Port->QueryInterface( IID_IPortEvents, (PVOID*) &port_events); +*/ + + if ( portcls_version ) + { + version = portcls_version->GetVersion(); + portcls_version->Release(); + } + + /* If we don't support portcls' GetVersion, we can try other methods */ + else if ( drm_port ) + { + version = kVersionWinME; + // ASSERT(IoIsWdmVersionAvailable(0x01, 0x05)); + } + + /* If portcls GetVersion and DRMPort not supported, it'll be Win98 */ + else if ( port_events ) + { + version = kVersionWin98SE; + } + + /* IPortEvents was added in Win 98 SE so if not supported, it's not 98 SE */ + else + { + version = kVersionWin98; + } + + return version; +} + + +NTSTATUS +DetectFeatures( + IN PRESOURCELIST ResourceList, + OUT PBOOLEAN HasUart, + OUT PBOOLEAN HasFmSynth, + OUT PBOOLEAN HasWaveTable) +{ + NTSTATUS status = STATUS_SUCCESS; + + BOOLEAN DetectedWaveTable = FALSE; + BOOLEAN DetectedUart = FALSE; + BOOLEAN DetectedFmSynth = FALSE; + + ULONG IoCount = ResourceList->NumberOfPorts(); + ULONG IrqCount = ResourceList->NumberOfInterrupts(); + ULONG DmaCount = ResourceList->NumberOfDmas(); + + switch ( IoCount ) + { + case 1 : /* No FM / UART */ + { + if ( ( ResourceList->FindTranslatedPort(0)->u.Port.Length < 16 ) || + ( IrqCount < 1 ) || + ( DmaCount < 1 ) ) + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + } + + break; + + case 2 : + { + if ( ( ResourceList->FindTranslatedPort(0)->u.Port.Length < 16 ) || + ( IrqCount < 1 ) || + ( DmaCount < 1 ) ) + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + } + + else + { + /* The length of the port indicates the function provided */ + + switch ( ResourceList->FindTranslatedPort(1)->u.Port.Length ) + { + case 2 : + { + DetectedUart = TRUE; + break; + } + case 4: + { + DetectedFmSynth = TRUE; + break; + } + default : + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + } + } + } + + break; + } + + case 3 : + { + if ( ( ResourceList->FindTranslatedPort(0)->u.Port.Length < 16 ) || + ( ResourceList->FindTranslatedPort(1)->u.Port.Length != 2 ) || + ( ResourceList->FindTranslatedPort(2)->u.Port.Length != 4 ) || + ( IrqCount < 1 ) || + ( DmaCount < 1 ) ) + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + } + else + { + DetectedUart = TRUE; + DetectedFmSynth = TRUE; + } + + break; + } + + default : + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + break; + } + } + + if ( HasUart ) + *HasUart = DetectedUart; + if ( HasFmSynth ) + *HasFmSynth = DetectedFmSynth; + if ( HasWaveTable ) + *HasWaveTable = DetectedWaveTable; + + return status; +} + + +NTSTATUS +AssignResources( + IN PRESOURCELIST ResourceList, + OUT Resources* Resources) +{ + NTSTATUS status; + BOOLEAN HasUart, HasFmSynth, HasWaveTable; + + Resources->Adapter = NULL; + Resources->Wave = NULL; + Resources->Uart = NULL; + Resources->FmSynth = NULL; + Resources->WaveTable = NULL; + + status = DetectFeatures(ResourceList, &HasUart, &HasFmSynth, &HasWaveTable); + + if ( ! NT_SUCCESS(status) ) + { + return status; + } + + /* Wave I/O resources */ + + status = PcNewResourceSublist(Resources->Wave, + NULL, + PagedPool, + ResourceList, + ResourceList->NumberOfDmas() + + ResourceList->NumberOfInterrupts + 1); + + if ( NT_SUCCESS(status) ) + { + ULONG i; + + /* Base port address */ + status = (*Resources->Wave)->AddPortFromParent(ResourceList, 0); + + /* DMA channels */ + if ( NT_SUCCESS(status) ) + { + for ( i = 0; i < ResourceList->NumberOfDmas(); i ++ ) + { + status = (*Resources->Wave)->AddDmaFromParent(ResourceList, i); + + if ( ! NT_SUCCESS(status) ) + break; + } + } + + /* IRQs */ + if ( NT_SUCCESS(status) ) + { + for ( i = 0; i < ResourceList->NumberOfInterrupts(); i ++ ) + { + status = (*Resources->Wave)->AddInterruptFromParent(ResourceList, i); + + if ( ! NT_SUCCESS(status) ) + break; + } + } + } + + /* UART resources */ + + if ( NT_SUCCESS(status) && HasUart ) + { + /* TODO */ + } + + /* FM Synth resources */ + + if ( NT_SUCCESS(status) && HasFmSynth ) + { + /* TODO */ + } + + /* Adapter resources */ + + if ( NT_SUCCESS(status) ) + { + status = PcNewResourceSublist(Resources->Adapter, + NULL, + PagedPool, + ResourceList, + 3); + + if ( NT_SUCCESS(status) ) + { + status = (*Resources->Adapter)->AddInterruptFromParent(ResourceList, 0); + } + + if ( NT_SUCCESS(status) ) + { + status = (*Resources->Adapter)->AddPortFromParent(ResourceList, 0); + } + + if ( NT_SUCCESS(status) && HasUart ) + { + /* TODO */ + } + } + + /* Cleanup - TODO: Make this cleanup UART, FM etc. */ + + if ( ! NT_SUCCESS(status) ) + { + if ( *Resources->Wave ) + { + (*Resources->Wave)->Release(); + *Resources->Wave = NULL; + } + + if ( *Resources->Adapter ) + { + (*Resources->Adapter)->Release(); + *Resources->Adapter = NULL; + } + } + + return status; +} + + +NTSTATUS +StartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PRESOURCELIST ResourceList) +{ + NTSTATUS status = STATUS_SUCCESS; + + Resources DeviceResources; + + PUNKNOWN UnknownTopology = NULL; + PUNKNOWN UnknownWave = NULL; + PUNKNOWN UnknownWaveTable = NUL; + PUNKNOWN UnknownFmSynth = NULL; + + PADAPTERCOMMON AdapterCommon = NULL; + PUNKNOWN UnknownCommon = NULL; + + status = AssignResources(ResourceList, &DeviceResources); + + if ( NT_SUCCESS(status) ) + { + } + + return status; +} + +extern "C" +NSTATUS +AddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + return PcAddAdapterDevice(DriverObject, + PhysicalDeviceObject, + StartDevice, + MAX_MINIPORTS, + 0); +} + +extern "C" +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPathName) +{ + NTSTATUS status; + + status = PcInitializeAdapterDriver(DriverObject, + RegistryPathName, + AddDevice); + + /* TODO: Add our own IRP handlers here */ + + return status; +} \ No newline at end of file diff --git a/reactos/drivers/multimedia/sb16_ks/sb16.h b/reactos/drivers/multimedia/sb16_ks/sb16.h new file mode 100644 index 00000000000..3c14f9e3149 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/sb16.h @@ -0,0 +1,141 @@ +/* + ReactOS Operating System + Sound Blaster KS Driver + + AUTHORS: + Andrew Greenwood + + NOTES: + Ah, the Sound Blaster 16. I remember it well... +*/ + +#include +#include + +#ifndef SB16_H +#define SB16_H + +#define MAX_DMA_BUFFER_SIZE 65536 + +enum DspRegister +{ + DspRegCMSD0 = 0x00, + DspRegCMSR0 = 0x01, + DspRegCMSD1 = 0x02, + DspRegCMSR1 = 0x03, + DspRegMixerReg = 0x04, + DspRegMixerData = 0x05, + DspRegReset = 0x06, + DspRegFMD0 = 0x08, + DspRegFMR0 = 0x09, + DspRegRead = 0x0a, + DspRegWrite = 0x0c, + DspRegDataAvailable = 0x0e, + + DspRegAck8 = 0x0e, + DspRegAck16 = 0x0f +}; + +enum DspCommand +{ + DspWriteWaveProgrammedIo = 0x10, + DspWriteWave = 0x14, + DspWriteWaveAuto = 0x1c, + DspReadWave = 0x24, + DspReadWaveAuto = 0x2C, + DspWriteHighSpeedWave = 0x90, + DspReadHighSpeedWave = 0x98, + DspSetSampleRate = 0x40, + DspSetBlockSize = 0x48, + DspEnableOutput = 0xd1, + DspDisableOutput = 0xd3, + DspOutputStatus = 0xd8, + DspPauseDma = 0xd0, + DspContinueDma = 0xd4, + DspHaltAutoDma = 0xda, + DspInverter = 0xe0, + DspGetVersion = 0xe1, + DspGenerateInterrupt = 0xf2, + + /* SB16 only */ + DspSetDacRate = 0x41, + DspSetAdcRate = 0x42, + DspStartDac16 = 0xb6, + DspStartAdc16 = 0xbe, + DspStartDac8 = 0xc6, + DspStartAdc8 = 0xc3, + DspPauseDma16 = 0xd5, + DspContinueDma16 = 0xd6, + DspHaltAutoDma16 = 0xd9 +}; + +enum DspMixerRegister +{ + DspMixMasterVolumeLeft = 0x00, + DspMixMasterVolumeRight = 0x01, + DspMixVoiceVolumeLeft = 0x02, + DspMixVoiceVolumeRight = 0x03, + /* ... */ + DspMixIrqConfig = 0x80, + DspMixDmaConfig = 0x81 +}; + + +#define MPU401_OUTPUT_READY 0x40 +#define MPU401_INPUT_READY 0x80 + +#define MPU401_RESET 0xff +#define MPU401_UART_MODE 0x3f + +DEFINE_GUID(IID_IWaveMiniportSB16, + 0xbe23b2d7, 0xa760, 0x43ab, 0xb7, 0x6e, 0xbc, 0x3e, 0x93, 0xe6, 0xff, 0x54); + +DECLARE_INTERFACE_(IWaveMiniportSB16, IUnknown) +{ + DEFINE_ABSTRACT_UNKNOWN() + + STDMETHOD_(void, RestoreSampleRate)( THIS ) PURE; + STDMETHOD_(void, ServiceWaveISR)( THIS ) PURE; +}; + +typedef IWaveMiniportSB16 *PWAVEMINIPORTSB16; + + +DEFINE_GUID(IID_IAdapterSB16, + 0xfba9052c, 0x0544, 0x4bc4, 0x97, 0x3f, 0x70, 0xb7, 0x06, 0x46, 0x81, 0xe5); + +DECLARE_INTERFACE_(IAdapterSB16, IUnknown) +{ + DEFINE_ABSTRACT_UNKNOWN() + + STDMETHOD_(NTSTATUS, Init)( THIS_ + IN PRESOURCELIST ResourceList, + IN PDEVICE_OBJECT DeviceObject) PURE; + + STDMETHOD_(PINTERRUPTSYNC, GetInterruptSync)( THIS ) PURE; + + STDMETHOD_(void, SetWaveMiniport)( THIS_ + IN PWAVEMINIPORTSB16 Miniport) PURE; + + STDMETHOD_(BYTE, Read)( THIS ) PURE; + + STDMETHOD_(BOOLEAN, Write)( THIS_ + IN BYTE Value) PURE; + + STDMETHOD_(NTSTATUS, Reset)( THIS ) PURE; + + STDMETHOD_(void, SetMixerValue)( THIS_ + IN BYTE Index, + IN BYTE Value) PURE; + + STDMETHOD_(BYTE, GetMixerValue)( THIS_ + IN BYTE Index) PURE; + + STDMETHOD_(void, ResetMixer)( THIS ) PURE; + + /* TODO - Save/load settings */ +}; + +typedef IAdapterSB16 *PADAPTERSB16; + +#endif diff --git a/reactos/drivers/multimedia/sb16_ks/sb16.rbuild b/reactos/drivers/multimedia/sb16_ks/sb16.rbuild new file mode 100644 index 00000000000..d84265274b0 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/sb16.rbuild @@ -0,0 +1,11 @@ + + . + .. + + ntoskrnl + portcls + + stdunk.cpp + adapter.cpp + main.cpp + diff --git a/reactos/drivers/multimedia/sb16_ks/sb16_ks.def b/reactos/drivers/multimedia/sb16_ks/sb16_ks.def new file mode 100644 index 00000000000..32ef407d0a6 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/sb16_ks.def @@ -0,0 +1,6 @@ +; +; Exports definition file for sb16_ks.sys +; +EXPORTS +DriverEntry@8 + diff --git a/reactos/drivers/multimedia/sb16_ks/stdunk.cpp b/reactos/drivers/multimedia/sb16_ks/stdunk.cpp new file mode 100644 index 00000000000..7ebfe1d4e2f --- /dev/null +++ b/reactos/drivers/multimedia/sb16_ks/stdunk.cpp @@ -0,0 +1,68 @@ +/* + ReactOS Kernel-Mode COM + IUnknown implementations + + LICENSE + Please see COPYING in the top-level directory for license information. + + AUTHORS + Andrew Greenwood +*/ + +#include + +CUnknown::CUnknown(PUNKNOWN outer_unknown) +{ + m_ref_count = 0; + + if ( outer_unknown ) + m_outer_unknown = outer_unknown; + else + m_outer_unknown = PUNKNOWN(dynamic_cast(this)); +} + +CUnknown::~CUnknown() +{ +} + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingAddRef() +{ + InterlockedIncrement(&m_ref_count); + return m_ref_count; +} + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingRelease() +{ + if ( InterlockedDecrement(&m_ref_count) == 0 ) + { + m_ref_count ++; + delete this; + return 0; + } + + return m_ref_count; +} + +STDMETHODIMP_(NTSTATUS) +CUnknown::NonDelegatingQueryInterface( + IN REFIID iid, + PVOID* ppVoid) +{ + /* FIXME */ + #if 0 + if ( IsEqualGUID(iid, IID_IUnknown) ) /* TODO: Aligned? */ + *ppVoid = PVOID(PUNKNOWN(this)); + else + *ppVoid = NULL; + #endif + + if ( *ppVoid ) + { + PUNKNOWN(*ppVoid)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} diff --git a/reactos/drivers/multimedia/sb16_nt4/control.c b/reactos/drivers/multimedia/sb16_nt4/control.c new file mode 100644 index 00000000000..cb506da6ea7 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/control.c @@ -0,0 +1,222 @@ +#include + +/* + TODO: MmMapIoSpace() +*/ + +/* + This checks the read or write status port of the device. +*/ + +BOOLEAN +WaitForReady( + PSOUND_BLASTER_PARAMETERS SBDevice, + UCHAR Port) +{ + ULONG timeout = SB_TIMEOUT; + BOOL ready = FALSE; + + while ( ( ! ready ) && ( timeout > 0 ) ) + { + if ( SbRead(SBDevice, Port) & 0x80 ) + return TRUE; + + timeout --; + } + + return FALSE; +} + +BOOLEAN +SbWriteData( + PSOUND_BLASTER_PARAMETERS SBDevice, + UCHAR Data) +{ + if ( ! WaitToWrite(SBDevice) ) + return FALSE; + + DPRINT("Writing 0x%x to Sound Blaster card (data)\n", Data); + SbWrite(SBDevice, SB_WRITE_DATA_PORT, Data); + + return TRUE; +} + +BOOLEAN +SbReadData( + PSOUND_BLASTER_PARAMETERS SBDevice, + PUCHAR Data) +{ + if ( ! WaitToWrite(SBDevice) ) + return FALSE; + + *Data = SbRead(SBDevice, SB_READ_DATA_PORT); + DPRINT("Read 0x%x from Sound Blaster card (data)\n", *Data); + + return TRUE; +} + +BOOLEAN +ResetSoundBlaster( + PSOUND_BLASTER_PARAMETERS SBDevice) +{ + BOOLEAN acked = FALSE; + ULONG timeout; + + SbWriteReset(SBDevice, 0x01); + for (timeout = 0; timeout < 30000; timeout ++ ); + SbWriteReset(SBDevice, 0x00); + + DPRINT("Waiting for SB to acknowledge our reset request\n"); + + if ( ! WaitToRead(SBDevice) ) + { + DPRINT("Didn't get an ACK :(\n"); + return FALSE; + } + + timeout = 0; + + while ( ( ! acked ) && ( timeout < SB_TIMEOUT ) ) + { + acked = ( SbReadDataWithoutWait(SBDevice) == SB_DSP_READY ); + timeout ++; + } + + if ( ! acked ) + { + DPRINT("Didn't get an ACK :(\n"); + return FALSE; + } + + return TRUE; +} + +ULONG +GetSoundBlasterModel( + PSOUND_BLASTER_PARAMETERS SBDevice) +{ + UCHAR MajorVer, MinorVer; + + DPRINT("Querying DSP version\n"); + + if ( ! SbWriteData(SBDevice, SbGetDspVersion) ) + return NotDetected; + + if ( ! WaitToRead(SBDevice) ) + return NotDetected; + + if ( SbReadData(SBDevice, &MajorVer) ) + { + if ( SbReadData(SBDevice, &MinorVer) ) + { + DPRINT("Version %d.%d\n", MajorVer, MinorVer); + + SBDevice->dsp_version = (MajorVer * 256) + MinorVer; + + if ( SBDevice->dsp_version < 0x0200 ) + return SoundBlaster; + else if ( ( SBDevice->dsp_version & 0xFF00 ) == 0x0200 ) + return SoundBlaster2; + else if ( ( SBDevice->dsp_version & 0xFF00 ) == 0x0300 ) + return SoundBlasterPro; + else if ( SBDevice->dsp_version >= 0x0400 ) + return SoundBlaster16; + + return NotDetected; + } + } + + return NotDetected; +} + + +BOOLEAN +IsSampleRateCompatible( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG SampleRate) +{ + /* TODO */ + return TRUE; +} + +BOOLEAN +SetOutputSampleRate( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG SampleRate) +{ + /* Only works for DSP v4.xx */ + DPRINT("Setting sample rate\n"); + + SbWriteData(SBDevice, SbSetOutputRate); + SbWriteData(SBDevice, SampleRate / 256); + SbWriteData(SBDevice, SampleRate % 256); + + return TRUE; +} + +BOOLEAN +EnableSpeaker( + PSOUND_BLASTER_PARAMETERS SBDevice) +{ + DPRINT("Enabling speaker\n"); + + return SbWriteData(SBDevice, SbEnableSpeaker); +} + +BOOLEAN +DisableSpeaker( + PSOUND_BLASTER_PARAMETERS SBDevice) +{ + DPRINT("Disabling speaker\n"); + + return SbWriteData(SBDevice, SbDisableSpeaker); +} + +BOOLEAN +StartSoundOutput( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG BitDepth, + ULONG Channels, + ULONG BlockSize) +{ + DPRINT("Initializing output with %d channels at %d bits/sample\n", Channels, BitDepth); + + UCHAR command = 0xc6, mode = 0x00; + + if ( ( Channels < 1 ) || ( Channels > 2 ) ) + return FALSE; + + if ( ( BitDepth != 8 ) && ( BitDepth != 16 ) ) + return FALSE; + + switch ( BitDepth ) + { + case 8 : command = 0xc6; break; + case 16 : command = 0xb6; break; + }; + + switch ( Channels ) + { + case 1 : mode = 0x00; break; + case 2 : mode = 0x20; break; + } +#if 0 + first_byte = (BitDepth == 16) ? 0xb6 : 0xc6; + second_byte = (Channels == 1) ? 0x20 : 0x00; +#endif + + if ( SBDevice->dsp_version < 0x0400 ) + { + /* TODO: Additional programming required */ + } + + /* Send freq */ + SbWriteData(SBDevice, command); + SbWriteData(SBDevice, mode); + SbWriteData(SBDevice, BlockSize % 256); + SbWriteData(SBDevice, BlockSize / 256); + + DPRINT("Finished programming the DSP\n"); + + return TRUE; +} diff --git a/reactos/drivers/multimedia/sb16_nt4/interrupt.c b/reactos/drivers/multimedia/sb16_nt4/interrupt.c new file mode 100644 index 00000000000..91a526805a0 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/interrupt.c @@ -0,0 +1,61 @@ +/* +*/ + +#include + +BOOLEAN +CheckIrq( + PDEVICE_OBJECT DeviceObject) +{ +/* PSOUND_BLASTER_PARAMETERS parameters = DeviceObject->DriverExtension;*/ + + /* TODO */ + + return TRUE; +} + +BOOLEAN +ServiceSoundBlasterInterrupt( + IN PKINTERRUPT Interrupt, + IN PVOID Context) +{ + DPRINT("* Processing ISR *\n"); + return FALSE; +} + +NTSTATUS +EnableIrq( + PDEVICE_OBJECT DeviceObject) +{ + PSOUND_BLASTER_PARAMETERS parameters = DeviceObject->DeviceExtension; + ULONG vector; + KIRQL irq_level; + KAFFINITY affinity; + NTSTATUS status = STATUS_SUCCESS; + + vector = HalGetInterruptVector(Isa, + 0, + parameters->irq, + parameters->irq, + &irq_level, + &affinity); + + DPRINT("Vector is 0x%x\n", vector); + + status = IoConnectInterrupt(parameters->interrupt, + ServiceSoundBlasterInterrupt, + DeviceObject, + (PKSPIN_LOCK) NULL, + vector, + irq_level, + irq_level, + Latched, /* Latched / LevelSensitive */ + FALSE, /* shareable */ + affinity, + FALSE); + + if ( status == STATUS_INVALID_PARAMETER ) + status = STATUS_DEVICE_CONFIGURATION_ERROR; + + return status; +} diff --git a/reactos/drivers/multimedia/sb16_nt4/main.c b/reactos/drivers/multimedia/sb16_nt4/main.c new file mode 100644 index 00000000000..c85317d58e0 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/main.c @@ -0,0 +1,489 @@ +/* + ReactOS + Sound Blaster driver + + Programmers: + Andrew Greenwood + + Notes: + Compatible with NT4 +*/ + +#include + + +/* + IRP DISPATCH ROUTINES +*/ + +NTSTATUS STDCALL +CreateSoundBlaster( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension; + + DPRINT("CreateSoundBlaster() called - extension 0x%x\n", sb_device); + + EnableSpeaker(sb_device); + /*SetOutputSampleRate(sb_device, 22*/ + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +CloseSoundBlaster( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension; + + DPRINT("CloseSoundBlaster() called\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +CleanupSoundBlaster( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension; + + DPRINT("CleanupSoundBlaster() called\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +ControlSoundBlaster( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION stack; + PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension; + + DPRINT("ControlSoundBlaster() called\n"); + + stack = IoGetCurrentIrpStackLocation(Irp); + + switch ( stack->Parameters.DeviceIoControl.IoControlCode) + { + /* TODO */ + }; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +WriteSoundBlaster( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension; + + DPRINT("WriteSoundBlaster() called\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +VOID STDCALL +UnloadSoundBlaster( + PDRIVER_OBJECT DriverObject) +{ + DPRINT("Sound Blaster driver unload\n"); +} + +NTSTATUS STDCALL +OpenSubkey( + PUNICODE_STRING RegistryPath, + PWSTR Subkey, + ACCESS_MASK DesiredAccess, + OUT HANDLE* DevicesKeyHandle) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES attribs; + UNICODE_STRING subkey_name; + HANDLE key_handle; + + /* TODO: Check for NULL ptr in DevicesKeyHandle */ + + InitializeObjectAttributes(&attribs, + RegistryPath, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&key_handle, KEY_READ, &attribs); + + if ( ! NT_SUCCESS(status) ) + { + DPRINT("Couldn't open subkey %wZ\n", Subkey); + return status; + } + + RtlInitUnicodeString(&subkey_name, Subkey); + + InitializeObjectAttributes(&attribs, + &subkey_name, + OBJ_CASE_INSENSITIVE, + key_handle, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(*DevicesKeyHandle, DesiredAccess, &attribs); + ZwClose(key_handle); + + return status; +} + + +PWSTR STDCALL +AllocateRegistryPathInfo( + PUNICODE_STRING BasePath, + PUNICODE_STRING ParametersPath, + PKEY_BASIC_INFORMATION KeyInfo) +{ + PWSTR name; + PWSTR pos; + + DPRINT("Allocating memory for path info\n"); + name = ExAllocatePool(PagedPool, + BasePath->Length + sizeof(WCHAR) + + ParametersPath->Length + sizeof(WCHAR) + + KeyInfo->NameLength + sizeof(UNICODE_NULL)); + + if ( ! name ) + return NULL; + + DPRINT("Copying info\n"); + pos = name; + + RtlCopyMemory((PVOID)Pos, (PVOID)BasePath->Buffer, BasePath->Length); + pos += BasePath->Length / sizeof(WCHAR); + pos[0] = '\\'; + pos ++; + + RtlCopyMemory((PVOID)Pos, (PVOID)ParametersPath->Buffer, ParametersPath->Length); + pos += ParametersPath->Length / sizeof(WCHAR); + pos[0] = '\\'; + pos ++; + + RtlCopyMemory((PVOID)Pos, (PVOID)ParametersPath->Buffer, ParametersPath->Length); + pos += KeyInfo->NameLength / sizeof(WCHAR); + pos[0] = UNICODE_NULL; + + DPRINT("All OK\n"); + return name; +} + +#define FreeRegistryPathInfo(ptr) \ + ExFreePool(ptr) + + +#define TAG_REG_INFO (ULONG)'IgeR' +#define TAG_REG_NAME (ULONG)'NgeR' + +NTSTATUS STDCALL +EnumerateSubkey( + PUNICODE_STRING RegistryPath, + PWSTR Subkey, + PREGISTRY_CALLBACK_ROUTINE Callback, + PDRIVER_OBJECT DriverObject) +{ + NTSTATUS status; + UNICODE_STRING subkey_name; + HANDLE devices_key_handle; + + ULONG key_index = 0; + ULONG result_length; + + status = OpenSubkey(RegistryPath, Subkey, KEY_ENUMERATE_SUB_KEYS, &devices_key_handle); + + if ( ! NT_SUCCESS(status) ) + return status; + + while ( TRUE ) + { + KEY_BASIC_INFORMATION test_info; + PKEY_BASIC_INFORMATION info; + ULONG size; + PWSTR name; + + status = ZwEnumerateKey(devices_key_handle, + key_index, + KeyBasicInformation, + &test_info, + sizeof(test_info), + &result_length); + + if ( status == STATUS_NO_MORE_ENTRIES ) + break; + + size = result_length + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]); + + info = (PKEY_BASIC_INFORMATION) ExAllocatePoolWithTag(PagedPool, size, TAG_REG_INFO); + + if ( ! info ) + { + DPRINT("Out of memory\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + status = ZwEnumerateKey(devices_key_handle, + key_index, + KeyBasicInformation, + info, + size, + &result_length); + + if ( ! NT_SUCCESS(status) ) + { + DPRINT("Unable to enumerate keys\n"); + ExFreePoolWithTag(info, TAG_REG_INFO); + status = STATUS_INTERNAL_ERROR; + break; + } + + /* Is this ok? */ + RtlInitUnicodeString(&subkey_name, Subkey); + + name = AllocateRegistryPathInfo(RegistryPath, &subkey_name, info); + + if ( ! name ) + { + DPRINT("Out of memory\n"); + ExFreePoolWithTag(info, TAG_REG_INFO); + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ExFreePoolWithTag(info, TAG_REG_INFO); + + /* Call the callback */ + status = Callback(DriverObject, name); + + FreeRegistryPathInfo(name); + + if ( ! NT_SUCCESS(status) ) + { + DPRINT("Callback FAILED\n"); + break; + } + + key_index ++; + } + + ZwClose(devices_key_handle); + + DPRINT("Found %d subkey entries\n", key_index); + + if ( ( key_index == 0 ) && ( status == STATUS_NO_MORE_ENTRIES ) ) + return STATUS_DEVICE_CONFIGURATION_ERROR; + + if ( status == STATUS_NO_MORE_ENTRIES ) + status = STATUS_SUCCESS; + + return status; +} + +#define EnumerateDeviceKeys(path, callback, driver_obj) \ + EnumerateSubkey(path, L"Devices", callback, driver_obj) + + +NTSTATUS +CreateDeviceName( + PCWSTR PrePrefix, + PCWSTR Prefix, + UCHAR Index, + PUNICODE_STRING DeviceName) +{ + UNICODE_STRING number; + WCHAR number_buffer[5]; + UNICODE_STRING unicode_pre_prefix; + UNICODE_STRING unicode_prefix; + ULONG size; + + RtlInitUnicodeString(&unicode_pre_prefix, PrePrefix); + RtlInitUnicodeString(&unicode_prefix, Prefix); + + size = unicode_pre_prefix.Length + + unicode_prefix.Length + + sizeof(number_buffer) + + sizeof(UNICODE_NULL); + + DeviceName->Buffer = ExAllocatePool(PagedPool, size); + DeviceName->MaximumLength = (USHORT) size; + + if ( ! DeviceName->Buffer ) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlCopyUnicodeString(DeviceName, &unicode_pre_prefix); + RtlAppendUnicodeStringToString(DeviceName, &unicode_prefix); + + if ( Index != 255 ) + { + number.Buffer = number_buffer; + number.MaximumLength = sizeof(number_buffer); + + RtlIntegerToUnicodeString((ULONG) Index, 10, &number); + RtlAppendUnicodeStringToString(DeviceName, &number); + } + + DeviceName->Buffer[DeviceName->Length / sizeof(UNICODE_NULL)] = UNICODE_NULL; + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +InitializeSoundBlaster( + PDRIVER_OBJECT DriverObject, + PWSTR RegistryPath) +{ + NTSTATUS status; + PDEVICE_OBJECT device_object; + PSOUND_BLASTER_PARAMETERS parameters = NULL; + UNICODE_STRING device_name; + UNICODE_STRING dos_device_name; + + UCHAR device_index = 0; + + DPRINT("Initializing a Sound Blaster device\n"); + + /* Change these later */ + status = CreateDeviceName(L"", + L"\\Device\\WaveOut", + device_index, + &device_name); + + if ( ! NT_SUCCESS(status) ) + return status; + + status = CreateDeviceName(L"\\DosDevices\\", + L"\\Device\\WaveOut" + wcslen(L"\\Device\\"), + device_index, + &dos_device_name); + + if ( ! NT_SUCCESS(status) ) + { + /* TODO */ + return status; + } + + DPRINT("Device: %wZ\n", device_name); + DPRINT("Symlink: %wZ\n", dos_device_name); + + /* + Create the device and DOS symlink + */ + + status = IoCreateDevice(DriverObject, + sizeof(SOUND_BLASTER_PARAMETERS), + &device_name, + FILE_DEVICE_SOUND, + 0, + FALSE, + &device_object); + + if ( ! NT_SUCCESS(status) ) + return status; + + DPRINT("Created a device extension at 0x%x\n", device_object->DeviceExtension); + parameters = device_object->DeviceExtension; + + status = IoCreateSymbolicLink(&dos_device_name, &device_name); + + ExFreePool(dos_device_name.Buffer); + ExFreePool(device_name.Buffer); + + if ( ! NT_SUCCESS(status) ) + { + IoDeleteDevice(device_object); + device_object = NULL; + return status; + } + + /* IoRegisterShutdownNotification( */ + + /* + Settings + */ + + device_object->AlignmentRequirement = FILE_BYTE_ALIGNMENT; + + parameters->driver = DriverObject; + parameters->registry_path = RegistryPath; + parameters->port = DEFAULT_PORT; + parameters->irq = DEFAULT_IRQ; + parameters->dma = DEFAULT_DMA; + parameters->buffer_size = DEFAULT_BUFFER_SIZE; + + /* TODO: Load the settings from the registry */ + + DPRINT("Port %x IRQ %d DMA %d\n", parameters->port, parameters->irq, parameters->dma); + + DPRINT("Resetting the sound card\n"); + + if ( ! ResetSoundBlaster(parameters) ) + { + /* TODO */ + return STATUS_UNSUCCESSFUL; + } + + /* + DPRINT("What kind of SB card is this?\n"); + GetSoundBlasterModel(parameters); + */ + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + NTSTATUS status; + + DPRINT("Sound Blaster driver 0.1 by Silver Blade\n"); + + DriverObject->Flags = 0; + DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateSoundBlaster; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseSoundBlaster; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CleanupSoundBlaster; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlSoundBlaster; + DriverObject->MajorFunction[IRP_MJ_WRITE] = WriteSoundBlaster; + DriverObject->DriverUnload = UnloadSoundBlaster; + + DPRINT("Beginning device key enumeration\n"); + + status = EnumerateDeviceKeys(RegistryPath, *InitializeSoundBlaster, DriverObject); + + return status; +} diff --git a/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def b/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def new file mode 100644 index 00000000000..32ef407d0a6 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def @@ -0,0 +1,6 @@ +; +; Exports definition file for sb16_ks.sys +; +EXPORTS +DriverEntry@8 + diff --git a/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild b/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild new file mode 100644 index 00000000000..d0345ed9c6a --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild @@ -0,0 +1,11 @@ + + . + .. + + ntoskrnl + hal + + main.c + control.c + interrupt.c + diff --git a/reactos/drivers/multimedia/sb16_nt4/sndblst.h b/reactos/drivers/multimedia/sb16_nt4/sndblst.h new file mode 100644 index 00000000000..d11ebefebf2 --- /dev/null +++ b/reactos/drivers/multimedia/sb16_nt4/sndblst.h @@ -0,0 +1,155 @@ +#ifndef SNDBLST_H +#define SNDBLST_H + +#include +#include + +#define SB_WAVE_IN_DEVICE_NAME L"\\Device\\SBWaveIn" +#define SB_WAVE_OUT_DEVICE_NAME L"\\Device\\SBWaveOut" +/* TODO: MIDI */ +#define SB_AUX_DEVICE_NAME L"\\Device\\SBAux" +#define SB_MIXER_DEVICE_NAME L"\\Device\\SBMixer" + +#define DEFAULT_PORT 0x220 +#define DEFAULT_IRQ 5 +#define DEFAULT_DMA 1 +#define DEFAULT_BUFFER_SIZE 65535 + +#define SB_TIMEOUT 1000000 + +#define SB_DSP_READY 0xaa + +enum +{ + NotDetected, + SoundBlaster, + SoundBlasterPro, + SoundBlaster2, + SoundBlasterPro2, + SoundBlasterProMCV, + SoundBlaster16 +}; + +enum +{ + SB_RESET_PORT = 0x06, + SB_READ_DATA_PORT = 0x0a, + SB_WRITE_DATA_PORT = 0x0c, + SB_WRITE_STATUS_PORT = 0x0c, + SB_READ_STATUS_PORT = 0x0e +}; + +enum +{ + SbAutoInitDmaOutput = 0x1c, + SbAutoInitDmaInput = 0x2c, + SbSetOutputRate = 0x41, /* DSP v4.xx */ + SbSetInputRate = 0x42, /* DSP v4.xx */ + SbSetBlockSize = 0x48, /* DSP v2.00 + */ + SbPauseDac = 0x80, + SbPauseDmaOutput = 0xd0, + SbEnableSpeaker = 0xd1, + SbDisableSpeaker = 0xd3, + SbGetSpeakerStatus = 0xd8, /* DSP v2.00 + */ + SbGetDspVersion = 0xe1 +}; + +typedef struct _SOUND_BLASTER_PARAMETERS +{ + PDRIVER_OBJECT driver; + PWSTR registry_path; + PKINTERRUPT interrupt; + ULONG port; + ULONG irq; + ULONG dma; + ULONG buffer_size; + USHORT dsp_version; +} SOUND_BLASTER_PARAMETERS, *PSOUND_BLASTER_PARAMETERS; + + +typedef STDCALL NTSTATUS REGISTRY_CALLBACK_ROUTINE(PDRIVER_OBJECT DriverObject, PWSTR RegistryPath); +typedef REGISTRY_CALLBACK_ROUTINE *PREGISTRY_CALLBACK_ROUTINE; + + +/* + Port I/O +*/ + +#define SbWrite(sbdevice, subport, data) \ + WRITE_PORT_UCHAR((PUCHAR) sbdevice->port + subport, data) + +#define SbRead(sbdevice, subport) \ + READ_PORT_UCHAR((PUCHAR) sbdevice->port + subport) + +#define SbWriteReset(sbdevice, data) \ + SbWrite(sbdevice, SB_RESET_PORT, data) + +#define SbWriteDataWithoutWait(sbdevice, data) \ + SbWrite(sbdevice, SB_WRITE_DATA_PORT, data) + +#define SbReadDataWithoutWait(sbdevice) \ + SbRead(sbdevice, SB_READ_DATA_PORT) + + +#define SbGetWriteStatus(sbdevice) \ + SbRead(sbdevice, SB_WRITE_STATUS_PORT) + +#define SbGetReadStatus(sbdevice) \ + SbRead(sbdevice, SB_READ_STATUS_PORT) + + + +BOOLEAN +WaitForReady( + PSOUND_BLASTER_PARAMETERS SBDevice, + UCHAR Port); + +#define WaitToWrite(sbdevice) \ + WaitForReady(sbdevice, SB_WRITE_STATUS_PORT) + +#define WaitToRead(sbdevice) \ + WaitForReady(sbdevice, SB_READ_STATUS_PORT) + +BOOLEAN +ResetSoundBlaster( + PSOUND_BLASTER_PARAMETERS SBDevice); + +ULONG +GetSoundBlasterModel( + PSOUND_BLASTER_PARAMETERS SBDevice); + +BOOLEAN +IsSampleRateCompatible( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG SampleRate); + +BOOLEAN +SetOutputSampleRate( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG SampleRate); + +BOOLEAN +EnableSpeaker( + PSOUND_BLASTER_PARAMETERS SBDevice); + +BOOLEAN +DisableSpeaker( + PSOUND_BLASTER_PARAMETERS SBDevice); + +BOOLEAN +StartSoundOutput( + PSOUND_BLASTER_PARAMETERS SBDevice, + ULONG BitDepth, + ULONG Channels, + ULONG BlockSize); + + +/* + interrupt.c +*/ + +NTSTATUS +EnableIrq( + PDEVICE_OBJECT DeviceObject); + +#endif diff --git a/reactos/drivers/multimedia/stdunk/stdunk.c b/reactos/drivers/multimedia/stdunk/stdunk.c new file mode 100644 index 00000000000..c8586a0fe39 --- /dev/null +++ b/reactos/drivers/multimedia/stdunk/stdunk.c @@ -0,0 +1,62 @@ +/* + "Unknown" implementation, in C + by Andrew Greenwood + + Not quite sure how this is used, but the C++ variant is intended for + implementing a NonDelegatingUnknown object +*/ + +#include + +STDMETHODCALLTYPE +NTSTATUS +Unknown_QueryInterface( + IUnknown* this, + IN REFIID refiid, + OUT PVOID* output) +{ + /* TODO */ + return STATUS_SUCCESS; +} + +STDMETHODCALLTYPE +ULONG +Unknown_AddRef( + IUnknown* unknown_this) +{ + struct CUnknown* this = CONTAINING_RECORD(unknown_this, struct CUnknown, IUnknown); + + InterlockedIncrement(&this->m_ref_count); + return this->m_ref_count; +} + +STDMETHODCALLTYPE +ULONG +Unknown_Release( + IUnknown* unknown_this) +{ + struct CUnknown* this = CONTAINING_RECORD(unknown_this, struct CUnknown, IUnknown); + + InterlockedDecrement(&this->m_ref_count); + + if ( this->m_ref_count == 0 ) + { + ExFreePool(this); + return 0; + } + + return this->m_ref_count; +} + + +/* + The vtable for Unknown +*/ + +const IUnknownVtbl UnknownVtbl = +{ + Unknown_QueryInterface, + Unknown_AddRef, + Unknown_Release +}; + diff --git a/reactos/drivers/multimedia/stdunk/stdunk.cpp b/reactos/drivers/multimedia/stdunk/stdunk.cpp new file mode 100644 index 00000000000..8c5bd3575e4 --- /dev/null +++ b/reactos/drivers/multimedia/stdunk/stdunk.cpp @@ -0,0 +1,98 @@ +/* + TODO: + Need to call ASSERT on m_ref_count to ensure it is valid. +*/ + +#define PUT_GUIDS_HERE + +//#include +#include +#include + +#include + + +/* + HACK ALERT + This is a little bit of a hack, but ReactOS doesn't seem to have this + defined. TODO: Make the aligned test truly aligned. +*/ + +#define IsEqualGUID(a, b) \ + RtlEqualMemory(&a, &b, sizeof(GUID)) + +#define IsEqualGUIDAligned(a, b) \ + IsEqualGUID(a, b) + +/* + Shut the linker up - can also pass -defsym ___cxa_pure_virtual=0 +*/ +extern "C" void __cxa_pure_virtual(void) {} + +/* + IUnknown +*/ + +CUnknown::CUnknown(PUNKNOWN outer_unknown) +{ + m_ref_count = 0; + + if ( outer_unknown ) + { + m_outer_unknown = outer_unknown; + } + else + { + m_outer_unknown = PUNKNOWN(dynamic_cast(this)); + } +} + +CUnknown::~CUnknown() +{ +} + +/* + INonDelegatingUnknown +*/ + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingAddRef(void) +{ + InterlockedIncrement(&m_ref_count); + return m_ref_count; +} + +STDMETHODIMP_(ULONG) +CUnknown::NonDelegatingRelease(void) +{ + if ( InterlockedDecrement(&m_ref_count) == 0 ) + { + delete this; + return 0; + } + + return m_ref_count; +} + +STDMETHODIMP_(NTSTATUS) +CUnknown::NonDelegatingQueryInterface( + IN REFIID iid, + IN PVOID* ppvoid) +{ + //if ( RtlEqualMemory(&iid, &IID_IUnknown, sizeof(GUID)) ) + { + *ppvoid = (PVOID)((PUNKNOWN) this); + } + // else + { + *ppvoid = NULL; + } + + if ( *ppvoid ) + { + ((PUNKNOWN)(*ppvoid))->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +}