3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/dd/mpu401/mpu401.c
6 * PURPOSE: MPU-401 MIDI device driver
7 * PROGRAMMER: Andrew Greenwood
9 * Sept 26, 2003: Copied from beep.c as template
10 * Sept 27, 2003: Implemented MPU-401 init & playback
13 /* INCLUDES ****************************************************************/
15 #include <ddk/ntddk.h>
16 #include <rosrtl/string.h>
17 //#include <ddk/ntddbeep.h>
25 /* INTERNAL VARIABLES ******************************************************/
30 /* FUNCTIONS ***************************************************************/
33 IN PUNICODE_STRING RegistryPath
,
36 // PDEVICE_INSTANCE Instance = Context;
37 PDEVICE_OBJECT DeviceObject
; // = Context;
38 PDEVICE_EXTENSION Parameters
; // = DeviceObject->DeviceExtension;
39 UNICODE_STRING DeviceName
= ROS_STRING_INITIALIZER(L
"\\Device\\MidiOut0");
40 UNICODE_STRING SymlinkName
= ROS_STRING_INITIALIZER(L
"\\??\\MidiOut0");
42 RTL_QUERY_REGISTRY_TABLE Table
[2];
45 // This is TEMPORARY, to ensure that we don't process more than 1 device.
46 // I'll remove this limitation in the future.
49 DPRINT("Sorry - only 1 device supported by MPU401 driver at present :(\n");
50 return STATUS_NOT_IMPLEMENTED
;
53 DPRINT("Creating IO device\n");
55 s
= IoCreateDevice(Context
, // driverobject
56 sizeof(DEVICE_EXTENSION
),
58 FILE_DEVICE_SOUND
, // Correct?
66 DPRINT("Device Extension at 0x%x\n", DeviceObject
->DeviceExtension
);
67 Parameters
= DeviceObject
->DeviceExtension
;
69 DPRINT("Creating DOS link\n");
71 /* Create the dos device link */
72 IoCreateSymbolicLink(&SymlinkName
,
75 DPRINT("Initializing device\n");
77 // DPRINT("Allocating memory for parameters structure\n");
79 // Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
80 // DeviceObject->DeviceExtension = Parameters;
81 // Parameters = Instance->DriverObject->DriverExtension;
83 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject
, Parameters
);
87 DPRINT("NULL POINTER!\n");
88 return STATUS_INSUFFICIENT_RESOURCES
;
91 // Instance->DriverObject->DriverExtension = Parameters;
93 DPRINT("Setting reg path\n");
94 Parameters
->RegistryPath
= RegistryPath
;
95 // Parameters->DriverObject = Instance->DriverObject;
97 DPRINT("Zeroing table memory and setting query routine\n");
98 RtlZeroMemory(Table
, sizeof(Table
));
99 Table
[0].QueryRoutine
= LoadSettings
;
101 DPRINT("Setting port and IRQ defaults\n");
102 Parameters
->Port
= DEFAULT_PORT
;
103 Parameters
->IRQ
= DEFAULT_IRQ
;
105 // Only to be enabled once we can get support for multiple cards working :)
107 DPRINT("Loading settings from: %S\n", RegistryPath);
109 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
116 DPRINT("Port 0x%x IRQ %d\n", Parameters
->Port
, Parameters
->IRQ
);
120 // Enter UART mode (should be done in init phase
121 if (! InitUARTMode(Parameters
->Port
))
123 DPRINT("UART mode initialization FAILED!\n");
124 // Set state indication somehow
125 // Failure - what error code do we give?!
126 // return STATUS_????
131 return STATUS_SUCCESS
;
135 static NTSTATUS STDCALL
136 MPU401Create(PDEVICE_OBJECT DeviceObject
,
139 * FUNCTION: Handles user mode requests
141 * DeviceObject = Device for request
142 * Irp = I/O request packet describing request
143 * RETURNS: Success or failure
146 DPRINT("MPU401Create() called!\n");
148 // Initialize the MPU-401?
152 // Play a note to say we're alive:
153 WaitToSend(MPU401_PORT
);
154 MPU401_WRITE_DATA(MPU401_PORT
, 0x90);
155 WaitToSend(MPU401_PORT
);
156 MPU401_WRITE_DATA(MPU401_PORT
, 0x50);
157 WaitToSend(MPU401_PORT
);
158 MPU401_WRITE_DATA(MPU401_PORT
, 0x7f);
160 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
161 Irp
->IoStatus
.Information
= 0;
162 IoCompleteRequest(Irp
,
165 return(STATUS_SUCCESS
);
169 static NTSTATUS STDCALL
170 MPU401Close(PDEVICE_OBJECT DeviceObject
,
173 * FUNCTION: Handles user mode requests
175 * DeviceObject = Device for request
176 * Irp = I/O request packet describing request
177 * RETURNS: Success or failure
180 PDEVICE_EXTENSION DeviceExtension
;
183 DPRINT("MPU401Close() called!\n");
185 DeviceExtension
= DeviceObject
->DeviceExtension
;
187 Status
= STATUS_SUCCESS
;
189 Irp
->IoStatus
.Status
= Status
;
190 Irp
->IoStatus
.Information
= 0;
191 IoCompleteRequest(Irp
,
198 static NTSTATUS STDCALL
199 MPU401Cleanup(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
210 DPRINT("MPU401Cleanup() called!\n");
212 // Reset the device (should we do this?)
213 for (Channel
= 0; Channel
<= 15; Channel
++)
216 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
217 // All controllers off
218 // MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
222 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
223 Irp
->IoStatus
.Information
= 0;
224 IoCompleteRequest(Irp
,
227 return(STATUS_SUCCESS
);
231 static NTSTATUS STDCALL
232 MPU401DeviceControl(PDEVICE_OBJECT DeviceObject
,
235 * FUNCTION: Handles user mode requests
237 * DeviceObject = Device for request
238 * Irp = I/O request packet describing request
239 * RETURNS: Success or failure
242 PIO_STACK_LOCATION Stack
;
243 PDEVICE_EXTENSION DeviceExtension
;
247 DPRINT("MPU401DeviceControl() called!\n");
249 DeviceExtension
= DeviceObject
->DeviceExtension
;
250 Stack
= IoGetCurrentIrpStackLocation(Irp
);
252 DPRINT("Control code %d [0x%x]\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
,
253 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
255 switch(Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
257 case IOCTL_MIDI_PLAY
:
259 DPRINT("Received IOCTL_MIDI_PLAY\n");
260 Data
= (PBYTE
) Irp
->AssociatedIrp
.SystemBuffer
;
262 DPRINT("Sending %d bytes of MIDI data to 0x%d:\n", Stack
->Parameters
.DeviceIoControl
.InputBufferLength
, DeviceExtension
->Port
);
264 for (ByteCount
= 0; ByteCount
< Stack
->Parameters
.DeviceIoControl
.InputBufferLength
; ByteCount
++)
266 DPRINT("0x%x ", Data
[ByteCount
]);
268 MPU401_WRITE_BYTE(DeviceExtension
->Port
, Data
[ByteCount
]);
269 // if (WaitToSend(MPU401_PORT))
270 // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
273 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
274 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
276 return(STATUS_SUCCESS
);
280 return(STATUS_SUCCESS
);
283 DeviceExtension = DeviceObject->DeviceExtension;
284 Stack = IoGetCurrentIrpStackLocation(Irp);
285 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
287 Irp->IoStatus.Information = 0;
289 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
291 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
292 IoCompleteRequest(Irp,
294 return(STATUS_NOT_IMPLEMENTED);
297 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
298 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
299 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
301 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
302 IoCompleteRequest(Irp,
304 return(STATUS_INVALID_PARAMETER);
307 DueTime.QuadPart = 0;
310 /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
314 if (BeepParam->Duration >= 0)
316 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
318 KeSetTimer(&DeviceExtension->Timer,
320 &DeviceExtension->Dpc);
322 HalMakeBeep(BeepParam->Frequency);
323 DeviceExtension->BeepOn = TRUE;
324 KeWaitForSingleObject(&DeviceExtension->Event,
330 else if (BeepParam->Duration == (DWORD)-1)
332 if (DeviceExtension->BeepOn == TRUE)
335 DeviceExtension->BeepOn = FALSE;
339 HalMakeBeep(BeepParam->Frequency);
340 DeviceExtension->BeepOn = TRUE;
344 DPRINT("Did the beep!\n");
346 Irp->IoStatus.Status = STATUS_SUCCESS;
347 IoCompleteRequest(Irp,
349 return(STATUS_SUCCESS);
355 MPU401Unload(PDRIVER_OBJECT DriverObject
)
357 DPRINT("MPU401Unload() called!\n");
362 DriverEntry(PDRIVER_OBJECT DriverObject
,
363 PUNICODE_STRING RegistryPath
)
365 * FUNCTION: Called by the system to initalize the driver
367 * DriverObject = object describing this driver
368 * RegistryPath = path to our configuration entries
369 * RETURNS: Success or failure
372 // PDEVICE_EXTENSION DeviceExtension;
373 // PDEVICE_OBJECT DeviceObject;
374 // DEVICE_INSTANCE Instance;
375 // Doesn't support multiple instances (yet ...)
378 DPRINT("MPU401 Device Driver 0.0.1\n");
380 // Is this really necessary? Yes! (Talking to myself again...)
381 // Instance.DriverObject = DriverObject;
382 // previous instance = NULL...
384 // DeviceExtension->RegistryPath = RegistryPath;
386 DriverObject
->Flags
= 0;
387 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = MPU401Create
;
388 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = MPU401Close
;
389 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = MPU401Cleanup
;
390 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = MPU401DeviceControl
;
391 DriverObject
->DriverUnload
= MPU401Unload
;
393 // Major hack to just get this damn thing working:
394 Status
= InitDevice(RegistryPath
, DriverObject
); // ????
396 // DPRINT("Enumerating devices at %wZ\n", RegistryPath);
398 // Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
402 /* set up device extension */
403 // DeviceExtension = DeviceObject->DeviceExtension;
404 // DeviceExtension->BeepOn = FALSE;
406 return(STATUS_SUCCESS
);