mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
Yet more files I've been meaning to commit...
(and again they're mostly incomplete) svn path=/trunk/; revision=26103
This commit is contained in:
parent
b4da8c5ab8
commit
30bfd875a8
14 changed files with 1823 additions and 0 deletions
137
reactos/drivers/multimedia/sb16_ks/adapter.cpp
Normal file
137
reactos/drivers/multimedia/sb16_ks/adapter.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
*/
|
356
reactos/drivers/multimedia/sb16_ks/main.cpp
Normal file
356
reactos/drivers/multimedia/sb16_ks/main.cpp
Normal file
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
ReactOS Operating System
|
||||
Sound Blaster KS Driver
|
||||
|
||||
AUTHORS:
|
||||
Andrew Greenwood
|
||||
|
||||
NOTES:
|
||||
WaveTable is not supported.
|
||||
*/
|
||||
|
||||
#include <sb16.h>
|
||||
|
||||
/* 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;
|
||||
}
|
141
reactos/drivers/multimedia/sb16_ks/sb16.h
Normal file
141
reactos/drivers/multimedia/sb16_ks/sb16.h
Normal file
|
@ -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 <portcls.h>
|
||||
#include <stdunk.h>
|
||||
|
||||
#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
|
11
reactos/drivers/multimedia/sb16_ks/sb16.rbuild
Normal file
11
reactos/drivers/multimedia/sb16_ks/sb16.rbuild
Normal file
|
@ -0,0 +1,11 @@
|
|||
<module name="sb16_ks" type="exportdriver" installbase="system32/drivers" installname="sb16_ks.sys" allowwarnings="true">
|
||||
<include base="sb16_ks">.</include>
|
||||
<include base="sb16_ks">..</include>
|
||||
<importlibrary definition="sb16_ks.def" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>portcls</library>
|
||||
<define name="__USE_W32API" />
|
||||
<file>stdunk.cpp</file>
|
||||
<file>adapter.cpp</file>
|
||||
<file>main.cpp</file>
|
||||
</module>
|
6
reactos/drivers/multimedia/sb16_ks/sb16_ks.def
Normal file
6
reactos/drivers/multimedia/sb16_ks/sb16_ks.def
Normal file
|
@ -0,0 +1,6 @@
|
|||
;
|
||||
; Exports definition file for sb16_ks.sys
|
||||
;
|
||||
EXPORTS
|
||||
DriverEntry@8
|
||||
|
68
reactos/drivers/multimedia/sb16_ks/stdunk.cpp
Normal file
68
reactos/drivers/multimedia/sb16_ks/stdunk.cpp
Normal file
|
@ -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 <stdunk.h>
|
||||
|
||||
CUnknown::CUnknown(PUNKNOWN outer_unknown)
|
||||
{
|
||||
m_ref_count = 0;
|
||||
|
||||
if ( outer_unknown )
|
||||
m_outer_unknown = outer_unknown;
|
||||
else
|
||||
m_outer_unknown = PUNKNOWN(dynamic_cast<PNONDELEGATINGUNKNOWN>(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;
|
||||
}
|
222
reactos/drivers/multimedia/sb16_nt4/control.c
Normal file
222
reactos/drivers/multimedia/sb16_nt4/control.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
#include <sndblst.h>
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
61
reactos/drivers/multimedia/sb16_nt4/interrupt.c
Normal file
61
reactos/drivers/multimedia/sb16_nt4/interrupt.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
*/
|
||||
|
||||
#include <sndblst.h>
|
||||
|
||||
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;
|
||||
}
|
489
reactos/drivers/multimedia/sb16_nt4/main.c
Normal file
489
reactos/drivers/multimedia/sb16_nt4/main.c
Normal file
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
ReactOS
|
||||
Sound Blaster driver
|
||||
|
||||
Programmers:
|
||||
Andrew Greenwood
|
||||
|
||||
Notes:
|
||||
Compatible with NT4
|
||||
*/
|
||||
|
||||
#include <sndblst.h>
|
||||
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
6
reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def
Normal file
6
reactos/drivers/multimedia/sb16_nt4/sb16_nt4.def
Normal file
|
@ -0,0 +1,6 @@
|
|||
;
|
||||
; Exports definition file for sb16_ks.sys
|
||||
;
|
||||
EXPORTS
|
||||
DriverEntry@8
|
||||
|
11
reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild
Normal file
11
reactos/drivers/multimedia/sb16_nt4/sb16_nt4.rbuild
Normal file
|
@ -0,0 +1,11 @@
|
|||
<module name="sb16_nt4" type="exportdriver" installbase="system32/drivers" installname="sndblst.sys" allowwarnings="true">
|
||||
<include base="sb16_nt4">.</include>
|
||||
<include base="sb16_nt4">..</include>
|
||||
<importlibrary definition="sb16_nt4.def" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<define name="__USE_W32API" />
|
||||
<file>main.c</file>
|
||||
<file>control.c</file>
|
||||
<file>interrupt.c</file>
|
||||
</module>
|
155
reactos/drivers/multimedia/sb16_nt4/sndblst.h
Normal file
155
reactos/drivers/multimedia/sb16_nt4/sndblst.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
#ifndef SNDBLST_H
|
||||
#define SNDBLST_H
|
||||
|
||||
#include <debug.h>
|
||||
#include <ntddk.h>
|
||||
|
||||
#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
|
62
reactos/drivers/multimedia/stdunk/stdunk.c
Normal file
62
reactos/drivers/multimedia/stdunk/stdunk.c
Normal file
|
@ -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 <stdunk.h>
|
||||
|
||||
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
|
||||
};
|
||||
|
98
reactos/drivers/multimedia/stdunk/stdunk.cpp
Normal file
98
reactos/drivers/multimedia/stdunk/stdunk.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
TODO:
|
||||
Need to call ASSERT on m_ref_count to ensure it is valid.
|
||||
*/
|
||||
|
||||
#define PUT_GUIDS_HERE
|
||||
|
||||
//#include <portcls.h>
|
||||
#include <punknown.h>
|
||||
#include <stdunk.h>
|
||||
|
||||
#include <ntddk.h>
|
||||
|
||||
|
||||
/*
|
||||
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<PNONDELEGATINGUNKNOWN>(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;
|
||||
}
|
Loading…
Reference in a new issue