1 /*
2 *
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
8 * UPDATE HISTORY:
9 * Sept 28, 2003: Copied from mpu401.c as a template
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ntddk.h>
15 #include "sndblst.h"
16
17 NTSTATUS NTAPI
18 DriverEntry(PDRIVER_OBJECT DriverObject,
19 PUNICODE_STRING RegistryPath);
20
21 /* INTERNAL VARIABLES ******************************************************/
22
23 ULONG DeviceCount = 0;
24
25
26 /* FUNCTIONS ***************************************************************/
27
InitDevice(IN PWSTR RegistryPath,IN PVOID Context)28 static NTSTATUS InitDevice(
29 IN PWSTR RegistryPath,
30 IN PVOID Context)
31 {
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");
37
38 // CONFIG Config;
39 RTL_QUERY_REGISTRY_TABLE Table[2];
40 NTSTATUS s;
41 USHORT DSP_Version = 0;
42 UCHAR DSP_Major = 0, DSP_Minor = 0;
43
44 // This is TEMPORARY, to ensure that we don't process more than 1 device.
45 // This limitation should be removed in future.
46 if (DeviceCount > 0)
47 {
48 DPRINT("Sorry - only 1 device supported by Sound Blaster driver at present :(\n");
49 return STATUS_NOT_IMPLEMENTED;
50 }
51
52 DPRINT("Creating IO device\n");
53
54 s = IoCreateDevice(Context, // driverobject
55 sizeof(DEVICE_EXTENSION),
56 &DeviceName,
57 FILE_DEVICE_SOUND, // Correct?
58 0,
59 FALSE,
60 &DeviceObject);
61
62 if (!NT_SUCCESS(s))
63 return s;
64
65 DPRINT("Device Extension at 0x%x\n", DeviceObject->DeviceExtension);
66 Parameters = DeviceObject->DeviceExtension;
67
68 DPRINT("Creating DOS link\n");
69
70 /* Create the dos device link */
71 s = IoCreateSymbolicLink(&SymlinkName,
72 &DeviceName);
73
74 if (!NT_SUCCESS(s))
75 {
76 IoDeleteDevice(DeviceObject);
77 return s;
78 }
79
80 DPRINT("Initializing device\n");
81
82 // DPRINT("Allocating memory for parameters structure\n");
83 // Bodged:
84 // Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
85 // DeviceObject->DeviceExtension = Parameters;
86 // Parameters = Instance->DriverObject->DriverExtension;
87
88 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject, Parameters);
89
90 if (! Parameters)
91 {
92 DPRINT("NULL POINTER!\n");
93 return STATUS_INSUFFICIENT_RESOURCES;
94 }
95
96 // Instance->DriverObject->DriverExtension = Parameters;
97
98 DPRINT("Setting reg path\n");
99 Parameters->RegistryPath = RegistryPath;
100 // Parameters->DriverObject = Instance->DriverObject;
101
102 DPRINT("Zeroing table memory and setting query routine\n");
103 RtlZeroMemory(Table, sizeof(Table));
104 Table[0].QueryRoutine = LoadSettings;
105
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;
111
112 // Only to be enabled once we can get support for multiple cards working :)
113 /*
114 DPRINT("Loading settings from: %S\n", RegistryPath);
115
116 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
117 &Parameters, NULL);
118
119 if (! NT_SUCCESS(s))
120 return s;
121 */
122
123 DPRINT("Port 0x%x IRQ %d DMA %d\n", Parameters->Port, Parameters->IRQ, Parameters->DMA);
124
125 // Instance->P
126
127 // Initialize the card
128 DSP_Version = InitSoundCard(Parameters->Port);
129 if (! DSP_Version)
130 {
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;
137 }
138
139 DSP_Major = DSP_Version / 256;
140 DSP_Minor = DSP_Version % 256;
141
142 // Do stuff related to version here...
143
144 DPRINT("Allocating DMA\n");
145 if (! CreateDMA(DeviceObject))
146 DPRINT("FAILURE!\n");
147
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);
152
153 DeviceCount ++;
154
155 return STATUS_SUCCESS;
156 }
157
158
159 static NTSTATUS NTAPI
BlasterCreate(PDEVICE_OBJECT DeviceObject,PIRP Irp)160 BlasterCreate(PDEVICE_OBJECT DeviceObject,
161 PIRP Irp)
162 /*
163 * FUNCTION: Handles user mode requests
164 * ARGUMENTS:
165 * DeviceObject = Device for request
166 * Irp = I/O request packet describing request
167 * RETURNS: Success or failure
168 */
169 {
170 DPRINT("BlasterCreate() called!\n");
171
172 // Initialize the MPU-401
173 // ... do stuff ...
174
175
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);
183
184 Irp->IoStatus.Status = STATUS_SUCCESS;
185 Irp->IoStatus.Information = 0;
186
187 DPRINT("IoCompleteRequest()\n");
188
189 IoCompleteRequest(Irp,
190 IO_NO_INCREMENT);
191
192 DPRINT("BlasterCreate() completed\n");
193
194 return(STATUS_SUCCESS);
195 }
196
197
198 static NTSTATUS NTAPI
BlasterClose(PDEVICE_OBJECT DeviceObject,PIRP Irp)199 BlasterClose(PDEVICE_OBJECT DeviceObject,
200 PIRP Irp)
201 /*
202 * FUNCTION: Handles user mode requests
203 * ARGUMENTS:
204 * DeviceObject = Device for request
205 * Irp = I/O request packet describing request
206 * RETURNS: Success or failure
207 */
208 {
209 PDEVICE_EXTENSION DeviceExtension;
210 NTSTATUS Status;
211
212 DPRINT("BlasterClose() called!\n");
213
214 DeviceExtension = DeviceObject->DeviceExtension;
215
216 Status = STATUS_SUCCESS;
217
218 Irp->IoStatus.Status = Status;
219 Irp->IoStatus.Information = 0;
220 IoCompleteRequest(Irp,
221 IO_NO_INCREMENT);
222
223 return(Status);
224 }
225
226
227 static NTSTATUS NTAPI
BlasterCleanup(PDEVICE_OBJECT DeviceObject,PIRP Irp)228 BlasterCleanup(PDEVICE_OBJECT DeviceObject,
229 PIRP Irp)
230 /*
231 * FUNCTION: Handles user mode requests
232 * ARGUMENTS:
233 * DeviceObject = Device for request
234 * Irp = I/O request packet describing request
235 * RETURNS: Success or failure
236 */
237 {
238 ULONG Channel;
239 DPRINT("BlasterCleanup() called!\n");
240
241 // Reset the device (should we do this?)
242 for (Channel = 0; Channel <= 15; Channel ++)
243 {
244 // All notes off
245 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
246 // All controllers off
247 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
248 }
249
250
251 Irp->IoStatus.Status = STATUS_SUCCESS;
252 Irp->IoStatus.Information = 0;
253 IoCompleteRequest(Irp,
254 IO_NO_INCREMENT);
255
256 return(STATUS_SUCCESS);
257 }
258
259
260 static NTSTATUS NTAPI
BlasterWrite(PDEVICE_OBJECT DeviceObject,PIRP Irp)261 BlasterWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
262 {
263 PIO_STACK_LOCATION Stack;
264 PDEVICE_EXTENSION DeviceExtension;
265 ULONG ByteCount;
266 PUCHAR Data;
267
268 DPRINT("BlasterWrite() called!\n");
269
270 DeviceExtension = DeviceObject->DeviceExtension;
271 Stack = IoGetCurrentIrpStackLocation(Irp);
272
273 DPRINT("%d bytes\n", Stack->Parameters.Write.Length);
274
275 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
276
277 for (ByteCount = 0; ByteCount < Stack->Parameters.Write.Length; ByteCount ++)
278 {
279 // DPRINT("0x%x ", Data[ByteCount]);
280
281 // MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
282 }
283
284 Irp->IoStatus.Status = STATUS_SUCCESS;
285 Irp->IoStatus.Information = 0;
286 IoCompleteRequest(Irp,
287 IO_NO_INCREMENT);
288
289 return(STATUS_SUCCESS);
290 }
291
292
293 static NTSTATUS NTAPI
BlasterDeviceControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)294 BlasterDeviceControl(PDEVICE_OBJECT DeviceObject,
295 PIRP Irp)
296 /*
297 * FUNCTION: Handles user mode requests
298 * ARGUMENTS:
299 * DeviceObject = Device for request
300 * Irp = I/O request packet describing request
301 * RETURNS: Success or failure
302 */
303 {
304 PIO_STACK_LOCATION Stack;
305 PDEVICE_EXTENSION DeviceExtension;
306
307 DPRINT("BlasterDeviceControl() called!\n");
308
309 DeviceExtension = DeviceObject->DeviceExtension;
310 Stack = IoGetCurrentIrpStackLocation(Irp);
311
312 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
313 {
314 /* case IOCTL_MIDI_PLAY :
315 {
316 DPRINT("Received IOCTL_MIDI_PLAY\n");
317 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
318
319 DPRINT("Sending %d bytes of MIDI data to 0x%x:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port);
320
321 for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++)
322 {
323 DPRINT("0x%x ", Data[ByteCount]);
324
325 MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
326 // if (WaitToSend(MPU401_PORT))
327 // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
328 }
329
330 Irp->IoStatus.Status = STATUS_SUCCESS;
331 IoCompleteRequest(Irp, IO_NO_INCREMENT);
332
333 return(STATUS_SUCCESS);
334 }
335 */
336 }
337
338 return(STATUS_SUCCESS);
339
340 /*
341 DeviceExtension = DeviceObject->DeviceExtension;
342 Stack = IoGetCurrentIrpStackLocation(Irp);
343 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
344
345 Irp->IoStatus.Information = 0;
346
347 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
348 {
349 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
350 IoCompleteRequest(Irp,
351 IO_NO_INCREMENT);
352 return(STATUS_NOT_IMPLEMENTED);
353 }
354
355 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
356 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
357 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
358 {
359 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
360 IoCompleteRequest(Irp,
361 IO_NO_INCREMENT);
362 return(STATUS_INVALID_PARAMETER);
363 }
364
365 DueTime.QuadPart = 0;
366 */
367 /* do the beep!! */
368 /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
369 pbsp->Frequency,
370 pbsp->Duration);
371
372 if (BeepParam->Duration >= 0)
373 {
374 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
375
376 KeSetTimer(&DeviceExtension->Timer,
377 DueTime,
378 &DeviceExtension->Dpc);
379
380 HalMakeBeep(BeepParam->Frequency);
381 DeviceExtension->BeepOn = TRUE;
382 KeWaitForSingleObject(&DeviceExtension->Event,
383 Executive,
384 KernelMode,
385 FALSE,
386 NULL);
387 }
388 else if (BeepParam->Duration == (DWORD)-1)
389 {
390 if (DeviceExtension->BeepOn != FALSE)
391 {
392 HalMakeBeep(0);
393 DeviceExtension->BeepOn = FALSE;
394 }
395 else
396 {
397 HalMakeBeep(BeepParam->Frequency);
398 DeviceExtension->BeepOn = TRUE;
399 }
400 }
401
402 DPRINT("Did the beep!\n");
403
404 Irp->IoStatus.Status = STATUS_SUCCESS;
405 IoCompleteRequest(Irp,
406 IO_NO_INCREMENT);
407 return(STATUS_SUCCESS);
408 */
409 }
410
411
412 static VOID NTAPI
BlasterUnload(PDRIVER_OBJECT DriverObject)413 BlasterUnload(PDRIVER_OBJECT DriverObject)
414 {
415 DPRINT("BlasterUnload() called!\n");
416 }
417
418
419 NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)420 DriverEntry(PDRIVER_OBJECT DriverObject,
421 PUNICODE_STRING RegistryPath)
422 /*
423 * FUNCTION: Called by the system to initialize the driver
424 * ARGUMENTS:
425 * DriverObject = object describing this driver
426 * RegistryPath = path to our configuration entries
427 * RETURNS: Success or failure
428 */
429 {
430 // PDEVICE_EXTENSION DeviceExtension;
431 // PDEVICE_OBJECT DeviceObject;
432 // DEVICE_INSTANCE Instance;
433 // Doesn't support multiple instances (yet ...)
434 NTSTATUS Status;
435
436 DPRINT("Sound Blaster Device Driver 0.0.2\n");
437
438 // Instance.DriverObject = DriverObject;
439 // previous instance = NULL...
440
441 // DeviceExtension->RegistryPath = RegistryPath;
442
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;
450
451 // Major hack to just get this damn thing working:
452 Status = InitDevice(RegistryPath->Buffer, DriverObject); // ????
453
454 // DPRINT("Enumerating devices at %wZ\n", RegistryPath);
455
456 // Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
457
458 // check error
459
460 /* set up device extension */
461 // DeviceExtension = DeviceObject->DeviceExtension;
462 // DeviceExtension->BeepOn = FALSE;
463
464 // return(STATUS_SUCCESS);
465 return(Status);
466 }
467
468 /* EOF */
469