3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/dd/sndblst/sndblst.c
6 * PURPOSE: Sound Blaster / SB Pro / SB 16 driver
7 * PROGRAMMER: Andrew Greenwood
9 * Sept 28, 2003: Copied from mpu401.c as a template
12 /* INCLUDES ****************************************************************/
18 DriverEntry(PDRIVER_OBJECT DriverObject
,
19 PUNICODE_STRING RegistryPath
);
21 /* INTERNAL VARIABLES ******************************************************/
23 ULONG DeviceCount
= 0;
26 /* FUNCTIONS ***************************************************************/
28 static NTSTATUS
InitDevice(
29 IN PWSTR RegistryPath
,
32 // PDEVICE_INSTANCE Instance = Context;
33 PDEVICE_OBJECT DeviceObject
; // = Context;
34 PDEVICE_EXTENSION Parameters
; // = DeviceObject->DeviceExtension;
35 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\WaveOut0"); // CHANGE THESE?
36 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\??\\WaveOut0");
39 RTL_QUERY_REGISTRY_TABLE Table
[2];
41 USHORT DSP_Version
= 0;
42 UCHAR DSP_Major
= 0, DSP_Minor
= 0;
44 // This is TEMPORARY, to ensure that we don't process more than 1 device.
45 // This limitation should be removed in future.
48 DPRINT("Sorry - only 1 device supported by Sound Blaster driver at present :(\n");
49 return STATUS_NOT_IMPLEMENTED
;
52 DPRINT("Creating IO device\n");
54 s
= IoCreateDevice(Context
, // driverobject
55 sizeof(DEVICE_EXTENSION
),
57 FILE_DEVICE_SOUND
, // Correct?
65 DPRINT("Device Extension at 0x%x\n", DeviceObject
->DeviceExtension
);
66 Parameters
= DeviceObject
->DeviceExtension
;
68 DPRINT("Creating DOS link\n");
70 /* Create the dos device link */
71 s
= IoCreateSymbolicLink(&SymlinkName
,
76 IoDeleteDevice(DeviceObject
);
80 DPRINT("Initializing device\n");
82 // DPRINT("Allocating memory for parameters structure\n");
84 // Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
85 // DeviceObject->DeviceExtension = Parameters;
86 // Parameters = Instance->DriverObject->DriverExtension;
88 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject
, Parameters
);
92 DPRINT("NULL POINTER!\n");
93 return STATUS_INSUFFICIENT_RESOURCES
;
96 // Instance->DriverObject->DriverExtension = Parameters;
98 DPRINT("Setting reg path\n");
99 Parameters
->RegistryPath
= RegistryPath
;
100 // Parameters->DriverObject = Instance->DriverObject;
102 DPRINT("Zeroing table memory and setting query routine\n");
103 RtlZeroMemory(Table
, sizeof(Table
));
104 Table
[0].QueryRoutine
= LoadSettings
;
106 DPRINT("Setting port and IRQ defaults\n");
107 Parameters
->Port
= DEFAULT_PORT
;
108 Parameters
->IRQ
= DEFAULT_IRQ
;
109 Parameters
->DMA
= DEFAULT_DMA
;
110 Parameters
->BufferSize
= DEFAULT_BUFSIZE
;
112 // Only to be enabled once we can get support for multiple cards working :)
114 DPRINT("Loading settings from: %S\n", RegistryPath);
116 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
123 DPRINT("Port 0x%x IRQ %d DMA %d\n", Parameters
->Port
, Parameters
->IRQ
, Parameters
->DMA
);
127 // Initialize the card
128 DSP_Version
= InitSoundCard(Parameters
->Port
);
131 DPRINT("Sound card initialization FAILED!\n");
132 // Set state indication somehow
133 // Failure - what error code do we give?!
134 // return STATUS_????
135 IoDeleteDevice(DeviceObject
);
136 return STATUS_UNSUCCESSFUL
;
139 DSP_Major
= DSP_Version
/ 256;
140 DSP_Minor
= DSP_Version
% 256;
142 // Do stuff related to version here...
144 DPRINT("Allocating DMA\n");
145 if (! CreateDMA(DeviceObject
))
146 DPRINT("FAILURE!\n");
148 // TEMPORARY TESTING STUFF: should be in BlasterCreate
149 EnableSpeaker(Parameters
->Port
, TRUE
);
150 SetOutputSampleRate(Parameters
->Port
, 2205);
151 BeginPlayback(Parameters
->Port
, 16, 2, Parameters
->BufferSize
);
155 return STATUS_SUCCESS
;
159 static NTSTATUS NTAPI
160 BlasterCreate(PDEVICE_OBJECT DeviceObject
,
163 * FUNCTION: Handles user mode requests
165 * DeviceObject = Device for request
166 * Irp = I/O request packet describing request
167 * RETURNS: Success or failure
170 DPRINT("BlasterCreate() called!\n");
172 // Initialize the MPU-401
176 // Play a note to say we're alive:
177 // WaitToSend(MPU401_PORT);
178 // MPU401_WRITE_DATA(MPU401_PORT, 0x90);
179 // WaitToSend(MPU401_PORT);
180 // MPU401_WRITE_DATA(MPU401_PORT, 0x50);
181 // WaitToSend(MPU401_PORT);
182 // MPU401_WRITE_DATA(MPU401_PORT, 0x7f);
184 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
185 Irp
->IoStatus
.Information
= 0;
187 DPRINT("IoCompleteRequest()\n");
189 IoCompleteRequest(Irp
,
192 DPRINT("BlasterCreate() completed\n");
194 return(STATUS_SUCCESS
);
198 static NTSTATUS NTAPI
199 BlasterClose(PDEVICE_OBJECT DeviceObject
,
202 * FUNCTION: Handles user mode requests
204 * DeviceObject = Device for request
205 * Irp = I/O request packet describing request
206 * RETURNS: Success or failure
209 PDEVICE_EXTENSION DeviceExtension
;
212 DPRINT("BlasterClose() called!\n");
214 DeviceExtension
= DeviceObject
->DeviceExtension
;
216 Status
= STATUS_SUCCESS
;
218 Irp
->IoStatus
.Status
= Status
;
219 Irp
->IoStatus
.Information
= 0;
220 IoCompleteRequest(Irp
,
227 static NTSTATUS NTAPI
228 BlasterCleanup(PDEVICE_OBJECT DeviceObject
,
231 * FUNCTION: Handles user mode requests
233 * DeviceObject = Device for request
234 * Irp = I/O request packet describing request
235 * RETURNS: Success or failure
239 DPRINT("BlasterCleanup() called!\n");
241 // Reset the device (should we do this?)
242 for (Channel
= 0; Channel
<= 15; Channel
++)
245 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
246 // All controllers off
247 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
251 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
252 Irp
->IoStatus
.Information
= 0;
253 IoCompleteRequest(Irp
,
256 return(STATUS_SUCCESS
);
260 static NTSTATUS NTAPI
261 BlasterWrite(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
263 PIO_STACK_LOCATION Stack
;
264 PDEVICE_EXTENSION DeviceExtension
;
268 DPRINT("BlasterWrite() called!\n");
270 DeviceExtension
= DeviceObject
->DeviceExtension
;
271 Stack
= IoGetCurrentIrpStackLocation(Irp
);
273 DPRINT("%d bytes\n", Stack
->Parameters
.Write
.Length
);
275 Data
= (PUCHAR
) Irp
->AssociatedIrp
.SystemBuffer
;
277 for (ByteCount
= 0; ByteCount
< Stack
->Parameters
.Write
.Length
; ByteCount
++)
279 // DPRINT("0x%x ", Data[ByteCount]);
281 // MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
284 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
285 Irp
->IoStatus
.Information
= 0;
286 IoCompleteRequest(Irp
,
289 return(STATUS_SUCCESS
);
293 static NTSTATUS NTAPI
294 BlasterDeviceControl(PDEVICE_OBJECT DeviceObject
,
297 * FUNCTION: Handles user mode requests
299 * DeviceObject = Device for request
300 * Irp = I/O request packet describing request
301 * RETURNS: Success or failure
304 PIO_STACK_LOCATION Stack
;
305 PDEVICE_EXTENSION DeviceExtension
;
307 DPRINT("BlasterDeviceControl() called!\n");
309 DeviceExtension
= DeviceObject
->DeviceExtension
;
310 Stack
= IoGetCurrentIrpStackLocation(Irp
);
312 switch(Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
314 /* case IOCTL_MIDI_PLAY :
316 DPRINT("Received IOCTL_MIDI_PLAY\n");
317 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
319 DPRINT("Sending %d bytes of MIDI data to 0x%x:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port);
321 for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++)
323 DPRINT("0x%x ", Data[ByteCount]);
325 MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
326 // if (WaitToSend(MPU401_PORT))
327 // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
330 Irp->IoStatus.Status = STATUS_SUCCESS;
331 IoCompleteRequest(Irp, IO_NO_INCREMENT);
333 return(STATUS_SUCCESS);
338 return(STATUS_SUCCESS
);
341 DeviceExtension = DeviceObject->DeviceExtension;
342 Stack = IoGetCurrentIrpStackLocation(Irp);
343 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
345 Irp->IoStatus.Information = 0;
347 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
349 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
350 IoCompleteRequest(Irp,
352 return(STATUS_NOT_IMPLEMENTED);
355 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
356 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
357 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
359 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
360 IoCompleteRequest(Irp,
362 return(STATUS_INVALID_PARAMETER);
365 DueTime.QuadPart = 0;
368 /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
372 if (BeepParam->Duration >= 0)
374 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
376 KeSetTimer(&DeviceExtension->Timer,
378 &DeviceExtension->Dpc);
380 HalMakeBeep(BeepParam->Frequency);
381 DeviceExtension->BeepOn = TRUE;
382 KeWaitForSingleObject(&DeviceExtension->Event,
388 else if (BeepParam->Duration == (DWORD)-1)
390 if (DeviceExtension->BeepOn == TRUE)
393 DeviceExtension->BeepOn = FALSE;
397 HalMakeBeep(BeepParam->Frequency);
398 DeviceExtension->BeepOn = TRUE;
402 DPRINT("Did the beep!\n");
404 Irp->IoStatus.Status = STATUS_SUCCESS;
405 IoCompleteRequest(Irp,
407 return(STATUS_SUCCESS);
413 BlasterUnload(PDRIVER_OBJECT DriverObject
)
415 DPRINT("BlasterUnload() called!\n");
420 DriverEntry(PDRIVER_OBJECT DriverObject
,
421 PUNICODE_STRING RegistryPath
)
423 * FUNCTION: Called by the system to initialize the driver
425 * DriverObject = object describing this driver
426 * RegistryPath = path to our configuration entries
427 * RETURNS: Success or failure
430 // PDEVICE_EXTENSION DeviceExtension;
431 // PDEVICE_OBJECT DeviceObject;
432 // DEVICE_INSTANCE Instance;
433 // Doesn't support multiple instances (yet ...)
436 DPRINT("Sound Blaster Device Driver 0.0.2\n");
438 // Instance.DriverObject = DriverObject;
439 // previous instance = NULL...
441 // DeviceExtension->RegistryPath = RegistryPath;
443 DriverObject
->Flags
= 0;
444 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = BlasterCreate
;
445 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = BlasterClose
;
446 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = BlasterCleanup
;
447 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = BlasterDeviceControl
;
448 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = BlasterWrite
;
449 DriverObject
->DriverUnload
= BlasterUnload
;
451 // Major hack to just get this damn thing working:
452 Status
= InitDevice(RegistryPath
->Buffer
, DriverObject
); // ????
454 // DPRINT("Enumerating devices at %wZ\n", RegistryPath);
456 // Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
460 /* set up device extension */
461 // DeviceExtension = DeviceObject->DeviceExtension;
462 // DeviceExtension->BeepOn = FALSE;
464 // return(STATUS_SUCCESS);