reactos/drivers/multimedia/audio/sndblst.old/sndblst.c

468 lines
12 KiB
C

/*
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/dd/sndblst/sndblst.c
* PURPOSE: Sound Blaster / SB Pro / SB 16 driver
* PROGRAMMER: Andrew Greenwood
* UPDATE HISTORY:
* Sept 28, 2003: Copied from mpu401.c as a template
*/
/* INCLUDES ****************************************************************/
#include <ntddk.h>
#include "sndblst.h"
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
/* INTERNAL VARIABLES ******************************************************/
ULONG DeviceCount = 0;
/* FUNCTIONS ***************************************************************/
static NTSTATUS InitDevice(
IN PWSTR RegistryPath,
IN PVOID Context)
{
// PDEVICE_INSTANCE Instance = Context;
PDEVICE_OBJECT DeviceObject; // = Context;
PDEVICE_EXTENSION Parameters; // = DeviceObject->DeviceExtension;
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\WaveOut0"); // CHANGE THESE?
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\WaveOut0");
// CONFIG Config;
RTL_QUERY_REGISTRY_TABLE Table[2];
NTSTATUS s;
USHORT DSP_Version = 0;
UCHAR DSP_Major = 0, DSP_Minor = 0;
// This is TEMPORARY, to ensure that we don't process more than 1 device.
// This limitation should be removed in future.
if (DeviceCount > 0)
{
DPRINT("Sorry - only 1 device supported by Sound Blaster driver at present :(\n");
return STATUS_NOT_IMPLEMENTED;
}
DPRINT("Creating IO device\n");
s = IoCreateDevice(Context, // driverobject
sizeof(DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_SOUND, // Correct?
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(s))
return s;
DPRINT("Device Extension at 0x%x\n", DeviceObject->DeviceExtension);
Parameters = DeviceObject->DeviceExtension;
DPRINT("Creating DOS link\n");
/* Create the dos device link */
s = IoCreateSymbolicLink(&SymlinkName,
&DeviceName);
if (!NT_SUCCESS(s))
{
IoDeleteDevice(DeviceObject);
return s;
}
DPRINT("Initializing device\n");
// DPRINT("Allocating memory for parameters structure\n");
// Bodged:
// Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
// DeviceObject->DeviceExtension = Parameters;
// Parameters = Instance->DriverObject->DriverExtension;
DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject, Parameters);
if (! Parameters)
{
DPRINT("NULL POINTER!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Instance->DriverObject->DriverExtension = Parameters;
DPRINT("Setting reg path\n");
Parameters->RegistryPath = RegistryPath;
// Parameters->DriverObject = Instance->DriverObject;
DPRINT("Zeroing table memory and setting query routine\n");
RtlZeroMemory(Table, sizeof(Table));
Table[0].QueryRoutine = LoadSettings;
DPRINT("Setting port and IRQ defaults\n");
Parameters->Port = DEFAULT_PORT;
Parameters->IRQ = DEFAULT_IRQ;
Parameters->DMA = DEFAULT_DMA;
Parameters->BufferSize = DEFAULT_BUFSIZE;
// Only to be enabled once we can get support for multiple cards working :)
/*
DPRINT("Loading settings from: %S\n", RegistryPath);
s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
&Parameters, NULL);
if (! NT_SUCCESS(s))
return s;
*/
DPRINT("Port 0x%x IRQ %d DMA %d\n", Parameters->Port, Parameters->IRQ, Parameters->DMA);
// Instance->P
// Initialize the card
DSP_Version = InitSoundCard(Parameters->Port);
if (! DSP_Version)
{
DPRINT("Sound card initialization FAILED!\n");
// Set state indication somehow
// Failure - what error code do we give?!
// return STATUS_????
IoDeleteDevice(DeviceObject);
return STATUS_UNSUCCESSFUL;
}
DSP_Major = DSP_Version / 256;
DSP_Minor = DSP_Version % 256;
// Do stuff related to version here...
DPRINT("Allocating DMA\n");
if (! CreateDMA(DeviceObject))
DPRINT("FAILURE!\n");
// TEMPORARY TESTING STUFF: should be in BlasterCreate
EnableSpeaker(Parameters->Port, TRUE);
SetOutputSampleRate(Parameters->Port, 2205);
BeginPlayback(Parameters->Port, 16, 2, Parameters->BufferSize);
DeviceCount ++;
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
BlasterCreate(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
DPRINT("BlasterCreate() called!\n");
// Initialize the MPU-401
// ... do stuff ...
// Play a note to say we're alive:
// WaitToSend(MPU401_PORT);
// MPU401_WRITE_DATA(MPU401_PORT, 0x90);
// WaitToSend(MPU401_PORT);
// MPU401_WRITE_DATA(MPU401_PORT, 0x50);
// WaitToSend(MPU401_PORT);
// MPU401_WRITE_DATA(MPU401_PORT, 0x7f);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
DPRINT("IoCompleteRequest()\n");
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
DPRINT("BlasterCreate() completed\n");
return(STATUS_SUCCESS);
}
static NTSTATUS NTAPI
BlasterClose(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("BlasterClose() called!\n");
DeviceExtension = DeviceObject->DeviceExtension;
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(Status);
}
static NTSTATUS NTAPI
BlasterCleanup(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
ULONG Channel;
DPRINT("BlasterCleanup() called!\n");
// Reset the device (should we do this?)
for (Channel = 0; Channel <= 15; Channel ++)
{
// All notes off
// MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
// All controllers off
// MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
static NTSTATUS NTAPI
BlasterWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PDEVICE_EXTENSION DeviceExtension;
ULONG ByteCount;
PUCHAR Data;
DPRINT("BlasterWrite() called!\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("%d bytes\n", Stack->Parameters.Write.Length);
Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
for (ByteCount = 0; ByteCount < Stack->Parameters.Write.Length; ByteCount ++)
{
// DPRINT("0x%x ", Data[ByteCount]);
// MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
static NTSTATUS NTAPI
BlasterDeviceControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PIO_STACK_LOCATION Stack;
PDEVICE_EXTENSION DeviceExtension;
DPRINT("BlasterDeviceControl() called!\n");
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
{
/* case IOCTL_MIDI_PLAY :
{
DPRINT("Received IOCTL_MIDI_PLAY\n");
Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
DPRINT("Sending %d bytes of MIDI data to 0x%x:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port);
for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++)
{
DPRINT("0x%x ", Data[ByteCount]);
MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
// if (WaitToSend(MPU401_PORT))
// MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
*/
}
return(STATUS_SUCCESS);
/*
DeviceExtension = DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
Irp->IoStatus.Information = 0;
if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
{
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_NOT_IMPLEMENTED);
}
if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
|| (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
|| (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_INVALID_PARAMETER);
}
DueTime.QuadPart = 0;
*/
/* do the beep!! */
/* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
pbsp->Frequency,
pbsp->Duration);
if (BeepParam->Duration >= 0)
{
DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
KeSetTimer(&DeviceExtension->Timer,
DueTime,
&DeviceExtension->Dpc);
HalMakeBeep(BeepParam->Frequency);
DeviceExtension->BeepOn = TRUE;
KeWaitForSingleObject(&DeviceExtension->Event,
Executive,
KernelMode,
FALSE,
NULL);
}
else if (BeepParam->Duration == (DWORD)-1)
{
if (DeviceExtension->BeepOn != FALSE)
{
HalMakeBeep(0);
DeviceExtension->BeepOn = FALSE;
}
else
{
HalMakeBeep(BeepParam->Frequency);
DeviceExtension->BeepOn = TRUE;
}
}
DPRINT("Did the beep!\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_SUCCESS);
*/
}
static VOID NTAPI
BlasterUnload(PDRIVER_OBJECT DriverObject)
{
DPRINT("BlasterUnload() called!\n");
}
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initialize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS: Success or failure
*/
{
// PDEVICE_EXTENSION DeviceExtension;
// PDEVICE_OBJECT DeviceObject;
// DEVICE_INSTANCE Instance;
// Doesn't support multiple instances (yet ...)
NTSTATUS Status;
DPRINT("Sound Blaster Device Driver 0.0.2\n");
// Instance.DriverObject = DriverObject;
// previous instance = NULL...
// DeviceExtension->RegistryPath = RegistryPath;
DriverObject->Flags = 0;
DriverObject->MajorFunction[IRP_MJ_CREATE] = BlasterCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = BlasterClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BlasterCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BlasterDeviceControl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = BlasterWrite;
DriverObject->DriverUnload = BlasterUnload;
// Major hack to just get this damn thing working:
Status = InitDevice(RegistryPath->Buffer, DriverObject); // ????
// DPRINT("Enumerating devices at %wZ\n", RegistryPath);
// Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
// check error
/* set up device extension */
// DeviceExtension = DeviceObject->DeviceExtension;
// DeviceExtension->BeepOn = FALSE;
// return(STATUS_SUCCESS);
return(Status);
}
/* EOF */