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 IoCreateSymbolicLink(&SymlinkName
,
74 DPRINT("Initializing device\n");
76 // DPRINT("Allocating memory for parameters structure\n");
78 // Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
79 // DeviceObject->DeviceExtension = Parameters;
80 // Parameters = Instance->DriverObject->DriverExtension;
82 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject
, Parameters
);
86 DPRINT("NULL POINTER!\n");
87 return STATUS_INSUFFICIENT_RESOURCES
;
90 // Instance->DriverObject->DriverExtension = Parameters;
92 DPRINT("Setting reg path\n");
93 Parameters
->RegistryPath
= RegistryPath
;
94 // Parameters->DriverObject = Instance->DriverObject;
96 DPRINT("Zeroing table memory and setting query routine\n");
97 RtlZeroMemory(Table
, sizeof(Table
));
98 Table
[0].QueryRoutine
= LoadSettings
;
100 DPRINT("Setting port and IRQ defaults\n");
101 Parameters
->Port
= DEFAULT_PORT
;
102 Parameters
->IRQ
= DEFAULT_IRQ
;
103 Parameters
->DMA
= DEFAULT_DMA
;
104 Parameters
->BufferSize
= DEFAULT_BUFSIZE
;
106 // Only to be enabled once we can get support for multiple cards working :)
108 DPRINT("Loading settings from: %S\n", RegistryPath);
110 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
117 DPRINT("Port 0x%x IRQ %d DMA %d\n", Parameters
->Port
, Parameters
->IRQ
, Parameters
->DMA
);
121 // Initialize the card
122 DSP_Version
= InitSoundCard(Parameters
->Port
);
125 DPRINT("Sound card initialization FAILED!\n");
126 // Set state indication somehow
127 // Failure - what error code do we give?!
128 // return STATUS_????
129 return STATUS_UNSUCCESSFUL
;
132 DSP_Major
= DSP_Version
/ 256;
133 DSP_Minor
= DSP_Version
% 256;
135 // Do stuff related to version here...
137 DPRINT("Allocating DMA\n");
138 if (! CreateDMA(DeviceObject
))
139 DPRINT("FAILURE!\n");
141 // TEMPORARY TESTING STUFF: should be in BlasterCreate
142 EnableSpeaker(Parameters
->Port
, TRUE
);
143 SetOutputSampleRate(Parameters
->Port
, 2205);
144 BeginPlayback(Parameters
->Port
, 16, 2, Parameters
->BufferSize
);
148 return STATUS_SUCCESS
;
152 static NTSTATUS STDCALL
153 BlasterCreate(PDEVICE_OBJECT DeviceObject
,
156 * FUNCTION: Handles user mode requests
158 * DeviceObject = Device for request
159 * Irp = I/O request packet describing request
160 * RETURNS: Success or failure
163 DPRINT("BlasterCreate() called!\n");
165 // Initialize the MPU-401
169 // Play a note to say we're alive:
170 // WaitToSend(MPU401_PORT);
171 // MPU401_WRITE_DATA(MPU401_PORT, 0x90);
172 // WaitToSend(MPU401_PORT);
173 // MPU401_WRITE_DATA(MPU401_PORT, 0x50);
174 // WaitToSend(MPU401_PORT);
175 // MPU401_WRITE_DATA(MPU401_PORT, 0x7f);
177 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
178 Irp
->IoStatus
.Information
= 0;
180 DPRINT("IoCompleteRequest()\n");
182 IoCompleteRequest(Irp
,
185 DPRINT("BlasterCreate() completed\n");
187 return(STATUS_SUCCESS
);
191 static NTSTATUS STDCALL
192 BlasterClose(PDEVICE_OBJECT DeviceObject
,
195 * FUNCTION: Handles user mode requests
197 * DeviceObject = Device for request
198 * Irp = I/O request packet describing request
199 * RETURNS: Success or failure
202 PDEVICE_EXTENSION DeviceExtension
;
205 DPRINT("BlasterClose() called!\n");
207 DeviceExtension
= DeviceObject
->DeviceExtension
;
209 Status
= STATUS_SUCCESS
;
211 Irp
->IoStatus
.Status
= Status
;
212 Irp
->IoStatus
.Information
= 0;
213 IoCompleteRequest(Irp
,
220 static NTSTATUS STDCALL
221 BlasterCleanup(PDEVICE_OBJECT DeviceObject
,
224 * FUNCTION: Handles user mode requests
226 * DeviceObject = Device for request
227 * Irp = I/O request packet describing request
228 * RETURNS: Success or failure
232 DPRINT("BlasterCleanup() called!\n");
234 // Reset the device (should we do this?)
235 for (Channel
= 0; Channel
<= 15; Channel
++)
238 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
239 // All controllers off
240 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
244 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
245 Irp
->IoStatus
.Information
= 0;
246 IoCompleteRequest(Irp
,
249 return(STATUS_SUCCESS
);
253 static NTSTATUS STDCALL
254 BlasterWrite(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
256 PIO_STACK_LOCATION Stack
;
257 PDEVICE_EXTENSION DeviceExtension
;
261 DPRINT("BlasterWrite() called!\n");
263 DeviceExtension
= DeviceObject
->DeviceExtension
;
264 Stack
= IoGetCurrentIrpStackLocation(Irp
);
266 DPRINT("%d bytes\n", Stack
->Parameters
.Write
.Length
);
268 Data
= (PUCHAR
) Irp
->AssociatedIrp
.SystemBuffer
;
270 for (ByteCount
= 0; ByteCount
< Stack
->Parameters
.Write
.Length
; ByteCount
++)
272 // DPRINT("0x%x ", Data[ByteCount]);
274 // MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
277 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
278 Irp
->IoStatus
.Information
= 0;
279 IoCompleteRequest(Irp
,
282 return(STATUS_SUCCESS
);
286 static NTSTATUS STDCALL
287 BlasterDeviceControl(PDEVICE_OBJECT DeviceObject
,
290 * FUNCTION: Handles user mode requests
292 * DeviceObject = Device for request
293 * Irp = I/O request packet describing request
294 * RETURNS: Success or failure
297 PIO_STACK_LOCATION Stack
;
298 PDEVICE_EXTENSION DeviceExtension
;
300 DPRINT("BlasterDeviceControl() called!\n");
302 DeviceExtension
= DeviceObject
->DeviceExtension
;
303 Stack
= IoGetCurrentIrpStackLocation(Irp
);
305 switch(Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
307 /* case IOCTL_MIDI_PLAY :
309 DPRINT("Received IOCTL_MIDI_PLAY\n");
310 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
312 DPRINT("Sending %d bytes of MIDI data to 0x%d:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port);
314 for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++)
316 DPRINT("0x%x ", Data[ByteCount]);
318 MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
319 // if (WaitToSend(MPU401_PORT))
320 // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
323 Irp->IoStatus.Status = STATUS_SUCCESS;
324 IoCompleteRequest(Irp, IO_NO_INCREMENT);
326 return(STATUS_SUCCESS);
331 return(STATUS_SUCCESS
);
334 DeviceExtension = DeviceObject->DeviceExtension;
335 Stack = IoGetCurrentIrpStackLocation(Irp);
336 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
338 Irp->IoStatus.Information = 0;
340 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
342 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
343 IoCompleteRequest(Irp,
345 return(STATUS_NOT_IMPLEMENTED);
348 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
349 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
350 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
352 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
353 IoCompleteRequest(Irp,
355 return(STATUS_INVALID_PARAMETER);
358 DueTime.QuadPart = 0;
361 /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
365 if (BeepParam->Duration >= 0)
367 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
369 KeSetTimer(&DeviceExtension->Timer,
371 &DeviceExtension->Dpc);
373 HalMakeBeep(BeepParam->Frequency);
374 DeviceExtension->BeepOn = TRUE;
375 KeWaitForSingleObject(&DeviceExtension->Event,
381 else if (BeepParam->Duration == (DWORD)-1)
383 if (DeviceExtension->BeepOn == TRUE)
386 DeviceExtension->BeepOn = FALSE;
390 HalMakeBeep(BeepParam->Frequency);
391 DeviceExtension->BeepOn = TRUE;
395 DPRINT("Did the beep!\n");
397 Irp->IoStatus.Status = STATUS_SUCCESS;
398 IoCompleteRequest(Irp,
400 return(STATUS_SUCCESS);
406 BlasterUnload(PDRIVER_OBJECT DriverObject
)
408 DPRINT("BlasterUnload() called!\n");
413 DriverEntry(PDRIVER_OBJECT DriverObject
,
414 PUNICODE_STRING RegistryPath
)
416 * FUNCTION: Called by the system to initalize the driver
418 * DriverObject = object describing this driver
419 * RegistryPath = path to our configuration entries
420 * RETURNS: Success or failure
423 // PDEVICE_EXTENSION DeviceExtension;
424 // PDEVICE_OBJECT DeviceObject;
425 // DEVICE_INSTANCE Instance;
426 // Doesn't support multiple instances (yet ...)
429 DPRINT("Sound Blaster Device Driver 0.0.2\n");
431 // Instance.DriverObject = DriverObject;
432 // previous instance = NULL...
434 // DeviceExtension->RegistryPath = RegistryPath;
436 DriverObject
->Flags
= 0;
437 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = BlasterCreate
;
438 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = BlasterClose
;
439 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = BlasterCleanup
;
440 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = BlasterDeviceControl
;
441 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = BlasterWrite
;
442 DriverObject
->DriverUnload
= BlasterUnload
;
444 // Major hack to just get this damn thing working:
445 Status
= InitDevice(RegistryPath
->Buffer
, DriverObject
); // ????
447 // DPRINT("Enumerating devices at %wZ\n", RegistryPath);
449 // Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
453 /* set up device extension */
454 // DeviceExtension = DeviceObject->DeviceExtension;
455 // DeviceExtension->BeepOn = FALSE;
457 // return(STATUS_SUCCESS);