Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmpu401.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS kernel 00005 * FILE: services/dd/mpu401/mpu401.c 00006 * PURPOSE: MPU-401 MIDI device driver 00007 * PROGRAMMER: Andrew Greenwood 00008 * UPDATE HISTORY: 00009 * Sept 26, 2003: Copied from beep.c as template 00010 * Sept 27, 2003: Implemented MPU-401 init & playback 00011 */ 00012 00013 /* INCLUDES ****************************************************************/ 00014 00015 #include <ntddk.h> 00016 //#include <ntddbeep.h> 00017 00018 //#define NDEBUG 00019 #include <debug.h> 00020 00021 #include "mpu401.h" 00022 00023 00024 /* INTERNAL VARIABLES ******************************************************/ 00025 00026 ULONG DeviceCount = 0; 00027 00028 00029 /* FUNCTIONS ***************************************************************/ 00030 00031 static NTSTATUS InitDevice( 00032 IN PUNICODE_STRING RegistryPath, 00033 IN PVOID Context) 00034 { 00035 // PDEVICE_INSTANCE Instance = Context; 00036 PDEVICE_OBJECT DeviceObject; // = Context; 00037 PDEVICE_EXTENSION Parameters; // = DeviceObject->DeviceExtension; 00038 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MidiOut0"); 00039 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\MidiOut0"); 00040 // CONFIG Config; 00041 RTL_QUERY_REGISTRY_TABLE Table[2]; 00042 NTSTATUS s; 00043 00044 // This is TEMPORARY, to ensure that we don't process more than 1 device. 00045 // I'll remove this limitation in the future. 00046 if (DeviceCount > 0) 00047 { 00048 DPRINT("Sorry - only 1 device supported by MPU401 driver at present :(\n"); 00049 return STATUS_NOT_IMPLEMENTED; 00050 } 00051 00052 DPRINT("Creating IO device\n"); 00053 00054 s = IoCreateDevice(Context, // driverobject 00055 sizeof(DEVICE_EXTENSION), 00056 &DeviceName, 00057 FILE_DEVICE_SOUND, // Correct? 00058 0, 00059 FALSE, 00060 &DeviceObject); 00061 00062 if (!NT_SUCCESS(s)) 00063 return s; 00064 00065 DPRINT("Device Extension at 0x%x\n", DeviceObject->DeviceExtension); 00066 Parameters = DeviceObject->DeviceExtension; 00067 00068 DPRINT("Creating DOS link\n"); 00069 00070 /* Create the dos device link */ 00071 IoCreateSymbolicLink(&SymlinkName, 00072 &DeviceName); 00073 00074 DPRINT("Initializing device\n"); 00075 00076 // DPRINT("Allocating memory for parameters structure\n"); 00077 // Bodged: 00078 // Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION)); 00079 // DeviceObject->DeviceExtension = Parameters; 00080 // Parameters = Instance->DriverObject->DriverExtension; 00081 00082 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject, Parameters); 00083 00084 if (! Parameters) 00085 { 00086 DPRINT("NULL POINTER!\n"); 00087 return STATUS_INSUFFICIENT_RESOURCES; 00088 } 00089 00090 // Instance->DriverObject->DriverExtension = Parameters; 00091 00092 DPRINT("Setting reg path\n"); 00093 Parameters->RegistryPath = RegistryPath; 00094 // Parameters->DriverObject = Instance->DriverObject; 00095 00096 DPRINT("Zeroing table memory and setting query routine\n"); 00097 RtlZeroMemory(Table, sizeof(Table)); 00098 Table[0].QueryRoutine = LoadSettings; 00099 00100 DPRINT("Setting port and IRQ defaults\n"); 00101 Parameters->Port = DEFAULT_PORT; 00102 Parameters->IRQ = DEFAULT_IRQ; 00103 00104 // Only to be enabled once we can get support for multiple cards working :) 00105 /* 00106 DPRINT("Loading settings from: %S\n", RegistryPath); 00107 00108 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table, 00109 &Parameters, NULL); 00110 */ 00111 00112 if (! NT_SUCCESS(s)) 00113 return s; 00114 00115 DPRINT("Port 0x%x IRQ %d\n", Parameters->Port, Parameters->IRQ); 00116 00117 // Instance->P 00118 00119 // Enter UART mode (should be done in init phase 00120 if (! InitUARTMode(Parameters->Port)) 00121 { 00122 DPRINT("UART mode initialization FAILED!\n"); 00123 // Set state indication somehow 00124 // Failure - what error code do we give?! 00125 // return STATUS_???? 00126 } 00127 00128 DeviceCount ++; 00129 00130 return STATUS_SUCCESS; 00131 } 00132 00133 00134 static NTSTATUS NTAPI 00135 MPU401Create(PDEVICE_OBJECT DeviceObject, 00136 PIRP Irp) 00137 /* 00138 * FUNCTION: Handles user mode requests 00139 * ARGUMENTS: 00140 * DeviceObject = Device for request 00141 * Irp = I/O request packet describing request 00142 * RETURNS: Success or failure 00143 */ 00144 { 00145 DPRINT("MPU401Create() called!\n"); 00146 00147 // Initialize the MPU-401? 00148 // ... do stuff ... 00149 00150 00151 // Play a note to say we're alive: 00152 WaitToSend(MPU401_PORT); 00153 MPU401_WRITE_DATA(MPU401_PORT, 0x90); 00154 WaitToSend(MPU401_PORT); 00155 MPU401_WRITE_DATA(MPU401_PORT, 0x50); 00156 WaitToSend(MPU401_PORT); 00157 MPU401_WRITE_DATA(MPU401_PORT, 0x7f); 00158 00159 Irp->IoStatus.Status = STATUS_SUCCESS; 00160 Irp->IoStatus.Information = 0; 00161 IoCompleteRequest(Irp, 00162 IO_NO_INCREMENT); 00163 00164 return(STATUS_SUCCESS); 00165 } 00166 00167 00168 static NTSTATUS NTAPI 00169 MPU401Close(PDEVICE_OBJECT DeviceObject, 00170 PIRP Irp) 00171 /* 00172 * FUNCTION: Handles user mode requests 00173 * ARGUMENTS: 00174 * DeviceObject = Device for request 00175 * Irp = I/O request packet describing request 00176 * RETURNS: Success or failure 00177 */ 00178 { 00179 PDEVICE_EXTENSION DeviceExtension; 00180 NTSTATUS Status; 00181 00182 DPRINT("MPU401Close() called!\n"); 00183 00184 DeviceExtension = DeviceObject->DeviceExtension; 00185 00186 Status = STATUS_SUCCESS; 00187 00188 Irp->IoStatus.Status = Status; 00189 Irp->IoStatus.Information = 0; 00190 IoCompleteRequest(Irp, 00191 IO_NO_INCREMENT); 00192 00193 return(Status); 00194 } 00195 00196 00197 static NTSTATUS NTAPI 00198 MPU401Cleanup(PDEVICE_OBJECT DeviceObject, 00199 PIRP Irp) 00200 /* 00201 * FUNCTION: Handles user mode requests 00202 * ARGUMENTS: 00203 * DeviceObject = Device for request 00204 * Irp = I/O request packet describing request 00205 * RETURNS: Success or failure 00206 */ 00207 { 00208 ULONG Channel; 00209 DPRINT("MPU401Cleanup() called!\n"); 00210 00211 // Reset the device (should we do this?) 00212 for (Channel = 0; Channel <= 15; Channel ++) 00213 { 00214 // All notes off 00215 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0); 00216 // All controllers off 00217 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0); 00218 } 00219 00220 00221 Irp->IoStatus.Status = STATUS_SUCCESS; 00222 Irp->IoStatus.Information = 0; 00223 IoCompleteRequest(Irp, 00224 IO_NO_INCREMENT); 00225 00226 return(STATUS_SUCCESS); 00227 } 00228 00229 00230 static NTSTATUS NTAPI 00231 MPU401DeviceControl(PDEVICE_OBJECT DeviceObject, 00232 PIRP Irp) 00233 /* 00234 * FUNCTION: Handles user mode requests 00235 * ARGUMENTS: 00236 * DeviceObject = Device for request 00237 * Irp = I/O request packet describing request 00238 * RETURNS: Success or failure 00239 */ 00240 { 00241 PIO_STACK_LOCATION Stack; 00242 PDEVICE_EXTENSION DeviceExtension; 00243 ULONG ByteCount; 00244 PUCHAR Data; 00245 00246 DPRINT("MPU401DeviceControl() called!\n"); 00247 00248 DeviceExtension = DeviceObject->DeviceExtension; 00249 Stack = IoGetCurrentIrpStackLocation(Irp); 00250 00251 DPRINT("Control code %d [0x%x]\n", Stack->Parameters.DeviceIoControl.IoControlCode, 00252 Stack->Parameters.DeviceIoControl.IoControlCode); 00253 00254 switch(Stack->Parameters.DeviceIoControl.IoControlCode) 00255 { 00256 case IOCTL_MIDI_PLAY : 00257 { 00258 DPRINT("Received IOCTL_MIDI_PLAY\n"); 00259 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer; 00260 00261 DPRINT("Sending %d bytes of MIDI data to 0x%d:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port); 00262 00263 for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++) 00264 { 00265 DPRINT("0x%x ", Data[ByteCount]); 00266 00267 MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]); 00268 // if (WaitToSend(MPU401_PORT)) 00269 // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]); 00270 } 00271 00272 Irp->IoStatus.Status = STATUS_SUCCESS; 00273 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00274 00275 return(STATUS_SUCCESS); 00276 } 00277 } 00278 00279 return(STATUS_SUCCESS); 00280 00281 /* 00282 DeviceExtension = DeviceObject->DeviceExtension; 00283 Stack = IoGetCurrentIrpStackLocation(Irp); 00284 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; 00285 00286 Irp->IoStatus.Information = 0; 00287 00288 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET) 00289 { 00290 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 00291 IoCompleteRequest(Irp, 00292 IO_NO_INCREMENT); 00293 return(STATUS_NOT_IMPLEMENTED); 00294 } 00295 00296 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS)) 00297 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM) 00298 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM)) 00299 { 00300 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 00301 IoCompleteRequest(Irp, 00302 IO_NO_INCREMENT); 00303 return(STATUS_INVALID_PARAMETER); 00304 } 00305 00306 DueTime.QuadPart = 0; 00307 */ 00308 /* do the beep!! */ 00309 /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n", 00310 pbsp->Frequency, 00311 pbsp->Duration); 00312 00313 if (BeepParam->Duration >= 0) 00314 { 00315 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000; 00316 00317 KeSetTimer(&DeviceExtension->Timer, 00318 DueTime, 00319 &DeviceExtension->Dpc); 00320 00321 HalMakeBeep(BeepParam->Frequency); 00322 DeviceExtension->BeepOn = TRUE; 00323 KeWaitForSingleObject(&DeviceExtension->Event, 00324 Executive, 00325 KernelMode, 00326 FALSE, 00327 NULL); 00328 } 00329 else if (BeepParam->Duration == (DWORD)-1) 00330 { 00331 if (DeviceExtension->BeepOn == TRUE) 00332 { 00333 HalMakeBeep(0); 00334 DeviceExtension->BeepOn = FALSE; 00335 } 00336 else 00337 { 00338 HalMakeBeep(BeepParam->Frequency); 00339 DeviceExtension->BeepOn = TRUE; 00340 } 00341 } 00342 00343 DPRINT("Did the beep!\n"); 00344 00345 Irp->IoStatus.Status = STATUS_SUCCESS; 00346 IoCompleteRequest(Irp, 00347 IO_NO_INCREMENT); 00348 return(STATUS_SUCCESS); 00349 */ 00350 } 00351 00352 00353 static VOID NTAPI 00354 MPU401Unload(PDRIVER_OBJECT DriverObject) 00355 { 00356 DPRINT("MPU401Unload() called!\n"); 00357 } 00358 00359 00360 NTSTATUS NTAPI 00361 DriverEntry(PDRIVER_OBJECT DriverObject, 00362 PUNICODE_STRING RegistryPath) 00363 /* 00364 * FUNCTION: Called by the system to initalize the driver 00365 * ARGUMENTS: 00366 * DriverObject = object describing this driver 00367 * RegistryPath = path to our configuration entries 00368 * RETURNS: Success or failure 00369 */ 00370 { 00371 // PDEVICE_EXTENSION DeviceExtension; 00372 // PDEVICE_OBJECT DeviceObject; 00373 // DEVICE_INSTANCE Instance; 00374 // Doesn't support multiple instances (yet ...) 00375 NTSTATUS Status; 00376 00377 DPRINT("MPU401 Device Driver 0.0.1\n"); 00378 00379 // Is this really necessary? Yes! (Talking to myself again...) 00380 // Instance.DriverObject = DriverObject; 00381 // previous instance = NULL... 00382 00383 // DeviceExtension->RegistryPath = RegistryPath; 00384 00385 DriverObject->Flags = 0; 00386 DriverObject->MajorFunction[IRP_MJ_CREATE] = MPU401Create; 00387 DriverObject->MajorFunction[IRP_MJ_CLOSE] = MPU401Close; 00388 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MPU401Cleanup; 00389 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MPU401DeviceControl; 00390 DriverObject->DriverUnload = MPU401Unload; 00391 00392 // Major hack to just get this damn thing working: 00393 Status = InitDevice(RegistryPath, DriverObject); // ???? 00394 00395 // DPRINT("Enumerating devices at %wZ\n", RegistryPath); 00396 00397 // Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance; 00398 00399 // check error 00400 00401 /* set up device extension */ 00402 // DeviceExtension = DeviceObject->DeviceExtension; 00403 // DeviceExtension->BeepOn = FALSE; 00404 00405 return(STATUS_SUCCESS); 00406 } 00407 00408 /* EOF */ Generated on Thu May 24 2012 04:28:23 for ReactOS by
1.7.6.1
|