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 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 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 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 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 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 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 413 BlasterUnload(PDRIVER_OBJECT DriverObject) 414 { 415 DPRINT("BlasterUnload() called!\n"); 416 } 417 418 419 NTSTATUS NTAPI 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