f30f9de21a95b35df81ebda8da8bbbf4511e0912
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / irp.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS
4 * FILE: drivers/wdm/audio/backpln/portcls/irp.cpp
5 * PURPOSE: Port Class driver / IRP Handling
6 * PROGRAMMER: Andrew Greenwood
7 * Johannes Anderwald
8 * HISTORY:
9 * 27 Jan 07 Created
10 */
11
12
13 #include "private.hpp"
14
15 typedef struct
16 {
17 PIRP Irp;
18 PDEVICE_OBJECT DeviceObject;
19 }QUERY_POWER_CONTEXT, *PQUERY_POWER_CONTEXT;
20
21
22 NTSTATUS
23 NTAPI
24 PortClsCreate(
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp)
27 {
28 DPRINT("PortClsCreate called\n");
29
30 return KsDispatchIrp(DeviceObject, Irp);
31 }
32
33
34 NTSTATUS
35 NTAPI
36 PortClsPnp(
37 IN PDEVICE_OBJECT DeviceObject,
38 IN PIRP Irp)
39 {
40 NTSTATUS Status;
41 PPCLASS_DEVICE_EXTENSION DeviceExt;
42 PIO_STACK_LOCATION IoStack;
43 POWER_STATE PowerState;
44 IResourceList* resource_list = NULL;
45 //ULONG Index;
46 //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
47
48 DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
49 IoStack = IoGetCurrentIrpStackLocation(Irp);
50
51
52 DPRINT("PortClsPnp called %u\n", IoStack->MinorFunction);
53
54 //PC_ASSERT(DeviceExt);
55
56 switch (IoStack->MinorFunction)
57 {
58 case IRP_MN_START_DEVICE:
59 DPRINT("IRP_MN_START_DEVICE\n");
60
61 // Create the resource list
62 Status = PcNewResourceList(
63 &resource_list,
64 NULL,
65 PagedPool,
66 IoStack->Parameters.StartDevice.AllocatedResourcesTranslated,
67 IoStack->Parameters.StartDevice.AllocatedResources);
68 if (!NT_SUCCESS(Status))
69 {
70 DPRINT("PcNewResourceList failed [0x%8x]\n", Status);
71 Irp->IoStatus.Status = Status;
72 IoCompleteRequest(Irp, IO_NO_INCREMENT);
73 return Status;
74 }
75
76 // forward irp to lower device object
77 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
78
79 if (!NT_SUCCESS(Status))
80 {
81 // lower device object failed to start
82 resource_list->Release();
83 // complete the request
84 IoCompleteRequest(Irp, IO_NO_INCREMENT);
85 // return result
86 return Status;
87 }
88
89 // sanity check
90 //PC_ASSERT(DeviceExt->StartDevice);
91 // Call the StartDevice routine
92 DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt->StartDevice);
93 Status = DeviceExt->StartDevice(DeviceObject, Irp, resource_list);
94 if (!NT_SUCCESS(Status))
95 {
96 DPRINT("StartDevice returned a failure code [0x%8x]\n", Status);
97 Irp->IoStatus.Status = Status;
98 IoCompleteRequest(Irp, IO_NO_INCREMENT);
99 return Status;
100 }
101
102 // Assign the resource list to our extension
103 DeviceExt->resources = resource_list;
104
105 // store device power state
106 DeviceExt->DevicePowerState = PowerDeviceD0;
107 DeviceExt->SystemPowerState = PowerSystemWorking;
108
109 // notify power manager of current state
110 PowerState = *((POWER_STATE*)&DeviceExt->DevicePowerState);
111 PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
112
113 Irp->IoStatus.Status = STATUS_SUCCESS;
114 IoCompleteRequest(Irp, IO_NO_INCREMENT);
115 return Status;
116
117 case IRP_MN_REMOVE_DEVICE:
118 // Clean up
119 DPRINT("IRP_MN_REMOVE_DEVICE\n");
120
121 DeviceExt->resources->Release();
122 IoDeleteDevice(DeviceObject);
123
124 // Forward request
125 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
126 return PcCompleteIrp(DeviceObject, Irp, Status);
127
128 case IRP_MN_QUERY_INTERFACE:
129 DPRINT("IRP_MN_QUERY_INTERFACE\n");
130 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
131 return PcCompleteIrp(DeviceObject, Irp, Status);
132 case IRP_MN_QUERY_DEVICE_RELATIONS:
133 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
134 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
135 return PcCompleteIrp(DeviceObject, Irp, Status);
136 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
137 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
138 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
139 return PcCompleteIrp(DeviceObject, Irp, Status);
140 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
141 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
142 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
143 return PcCompleteIrp(DeviceObject, Irp, Status);
144 case IRP_MN_READ_CONFIG:
145 DPRINT("IRP_MN_READ_CONFIG\n");
146 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
147 return PcCompleteIrp(DeviceObject, Irp, Status);
148 }
149
150 DPRINT("unhandled function %u\n", IoStack->MinorFunction);
151
152 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
153 IoCompleteRequest(Irp, IO_NO_INCREMENT);
154 return STATUS_UNSUCCESSFUL;
155 }
156
157 VOID
158 CALLBACK
159 PwrCompletionFunction(
160 IN PDEVICE_OBJECT DeviceObject,
161 IN UCHAR MinorFunction,
162 IN POWER_STATE PowerState,
163 IN PVOID Context,
164 IN PIO_STATUS_BLOCK IoStatus)
165 {
166 NTSTATUS Status;
167 PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context;
168
169 if (NT_SUCCESS(IoStatus->Status))
170 {
171 // forward request to lower device object
172 Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp);
173 }
174 else
175 {
176 // failed
177 Status = IoStatus->Status;
178 }
179
180 // start next power irp
181 PoStartNextPowerIrp(PwrContext->Irp);
182
183 // complete request
184 PwrContext->Irp->IoStatus.Status = Status;
185 IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT);
186
187 // free context
188 FreeItem(PwrContext, TAG_PORTCLASS);
189 }
190
191
192 NTSTATUS
193 NTAPI
194 PortClsPower(
195 IN PDEVICE_OBJECT DeviceObject,
196 IN PIRP Irp)
197 {
198 PIO_STACK_LOCATION IoStack;
199 PPCLASS_DEVICE_EXTENSION DeviceExtension;
200 PQUERY_POWER_CONTEXT PwrContext;
201 POWER_STATE PowerState;
202 NTSTATUS Status = STATUS_SUCCESS;
203
204 DPRINT("PortClsPower called\n");
205
206 // get currrent stack location
207 IoStack = IoGetCurrentIrpStackLocation(Irp);
208
209 if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER)
210 {
211 // just forward the request
212 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
213
214 // start next power irp
215 PoStartNextPowerIrp(Irp);
216
217 // complete request
218 Irp->IoStatus.Status = Status;
219 IoCompleteRequest(Irp, IO_NO_INCREMENT);
220
221 // done
222 return Status;
223 }
224
225
226 // get device extension
227 DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
228
229 // get current request type
230 if (IoStack->Parameters.Power.Type == DevicePowerState)
231 {
232 // request for device power state
233 if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState)
234 {
235 // nothing has changed
236 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
237 {
238 // only forward query requests
239 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
240 }
241
242 // start next power irp
243 PoStartNextPowerIrp(Irp);
244
245 // complete request
246 Irp->IoStatus.Status = Status;
247 IoCompleteRequest(Irp, IO_NO_INCREMENT);
248
249 // done
250 return Status;
251 }
252
253 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
254 {
255 // check if there is a registered adapter power management
256 if (DeviceExtension->AdapterPowerManagement)
257 {
258 // it is query if the change can be changed
259 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
260 Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState);
261
262 // sanity check
263 PC_ASSERT(Status == STATUS_SUCCESS);
264 }
265
266 // only forward query requests
267 PcForwardIrpSynchronous(DeviceObject, Irp);
268
269 // start next power irp
270 PoStartNextPowerIrp(Irp);
271
272 // complete request
273 Irp->IoStatus.Status = Status;
274 IoCompleteRequest(Irp, IO_NO_INCREMENT);
275
276 // done
277 return Status;
278 }
279 else
280 {
281 // set power state
282 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
283 PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
284
285 // check if there is a registered adapter power management
286 if (DeviceExtension->AdapterPowerManagement)
287 {
288 // notify of a power change state
289 DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState);
290 }
291
292 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
293
294 // store new power state
295 DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState;
296
297 // complete request
298 Irp->IoStatus.Status = Status;
299 IoCompleteRequest(Irp, IO_NO_INCREMENT);
300
301 // done
302 return Status;
303 }
304 }
305 else
306 {
307 // sanity check
308 PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState);
309
310 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
311 {
312 // mark irp as pending
313 IoMarkIrpPending(Irp);
314
315 // allocate power completion context
316 PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS);
317
318 if (!PwrContext)
319 {
320 // no memory
321 PoStartNextPowerIrp(Irp);
322
323 // complete and forget
324 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
325 IoCompleteRequest(Irp, IO_NO_INCREMENT);
326
327 // done
328 return Status;
329 }
330
331 // setup power context
332 PwrContext->Irp = Irp;
333 PwrContext->DeviceObject = DeviceObject;
334
335 // pass the irp down
336 PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState);
337 Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL);
338
339 // check for success
340 if (!NT_SUCCESS(Status))
341 {
342 // failed
343 Irp->IoStatus.Status = Status;
344 IoCompleteRequest(Irp, IO_NO_INCREMENT);
345
346 // done
347 return Status;
348 }
349
350 // done
351 return STATUS_PENDING;
352 }
353 else
354 {
355 // set power request
356 DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState;
357
358 // only forward query requests
359 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
360
361 // start next power irp
362 PoStartNextPowerIrp(Irp);
363
364 // complete request
365 Irp->IoStatus.Status = Status;
366 IoCompleteRequest(Irp, IO_NO_INCREMENT);
367
368 // done
369 return Status;
370 }
371 }
372 }
373
374 NTSTATUS
375 NTAPI
376 PortClsSysControl(
377 IN PDEVICE_OBJECT DeviceObject,
378 IN PIRP Irp)
379 {
380 DPRINT("PortClsSysControl called\n");
381
382 // TODO
383
384 Irp->IoStatus.Status = STATUS_SUCCESS;
385 Irp->IoStatus.Information = 0;
386 IoCompleteRequest(Irp, IO_NO_INCREMENT);
387
388 return STATUS_SUCCESS;
389 }
390
391 NTSTATUS
392 NTAPI
393 PortClsShutdown(
394 IN PDEVICE_OBJECT DeviceObject,
395 IN PIRP Irp)
396 {
397 PPCLASS_DEVICE_EXTENSION DeviceExtension;
398 DPRINT("PortClsShutdown called\n");
399
400 // get device extension
401 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
402
403 if (DeviceExtension->AdapterPowerManagement)
404 {
405 // release adapter power management
406 DPRINT("Power %u\n", DeviceExtension->AdapterPowerManagement->Release());
407 }
408
409 Irp->IoStatus.Status = STATUS_SUCCESS;
410 Irp->IoStatus.Information = 0;
411 IoCompleteRequest(Irp, IO_NO_INCREMENT);
412
413 return STATUS_SUCCESS;
414 }
415
416 NTSTATUS
417 NTAPI
418 PcDispatchIrp(
419 IN PDEVICE_OBJECT DeviceObject,
420 IN PIRP Irp)
421 {
422 PIO_STACK_LOCATION IoStack;
423
424 IoStack = IoGetCurrentIrpStackLocation(Irp);
425
426 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
427
428 switch ( IoStack->MajorFunction )
429 {
430 // PortCls
431 case IRP_MJ_CREATE :
432 return PortClsCreate(DeviceObject, Irp);
433
434 case IRP_MJ_PNP :
435 return PortClsPnp(DeviceObject, Irp);
436
437 case IRP_MJ_POWER :
438 return PortClsPower(DeviceObject, Irp);
439
440 case IRP_MJ_DEVICE_CONTROL:
441 return KsDispatchIrp(DeviceObject, Irp);
442
443 case IRP_MJ_CLOSE:
444 return KsDispatchIrp(DeviceObject, Irp);
445
446 case IRP_MJ_SYSTEM_CONTROL :
447 return PortClsSysControl(DeviceObject, Irp);
448
449 case IRP_MJ_SHUTDOWN:
450 return PortClsShutdown(DeviceObject, Irp);
451
452 default:
453 DPRINT("Unhandled function %x\n", IoStack->MajorFunction);
454 break;
455 };
456
457 // If we reach here, we just complete the IRP
458 Irp->IoStatus.Status = STATUS_SUCCESS;
459 Irp->IoStatus.Information = 0;
460 IoCompleteRequest(Irp, IO_NO_INCREMENT);
461
462 return STATUS_SUCCESS;
463 }
464
465
466 NTSTATUS
467 NTAPI
468 PcCompleteIrp(
469 IN PDEVICE_OBJECT DeviceObject,
470 IN PIRP Irp,
471 IN NTSTATUS Status)
472 {
473 #if 0
474 PC_ASSERT(DeviceObject);
475 PC_ASSERT(Irp);
476 PC_ASSERT(Status != STATUS_PENDING);
477 #endif
478
479 Irp->IoStatus.Status = Status;
480 IoCompleteRequest(Irp, IO_NO_INCREMENT);
481
482 return Status;
483 }
484
485 NTSTATUS
486 NTAPI
487 CompletionRoutine(
488 IN PDEVICE_OBJECT DeviceObject,
489 IN PIRP Irp,
490 IN PVOID Context)
491 {
492 if (Irp->PendingReturned == TRUE)
493 {
494 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
495 }
496 return STATUS_MORE_PROCESSING_REQUIRED;
497 }
498
499 #undef IoSetCompletionRoutine
500 #define IoSetCompletionRoutine(_Irp, \
501 _CompletionRoutine, \
502 _Context, \
503 _InvokeOnSuccess, \
504 _InvokeOnError, \
505 _InvokeOnCancel) \
506 { \
507 PIO_STACK_LOCATION _IrpSp; \
508 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
509 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
510 _IrpSp->Context = (_Context); \
511 _IrpSp->Control = 0; \
512 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
513 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
514 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
515 }
516
517
518
519 NTSTATUS
520 NTAPI
521 PcForwardIrpSynchronous(
522 IN PDEVICE_OBJECT DeviceObject,
523 IN PIRP Irp)
524 {
525 KEVENT Event;
526 PPCLASS_DEVICE_EXTENSION DeviceExt;
527 NTSTATUS Status;
528
529 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
530
531 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
532
533 // initialize the notification event
534 KeInitializeEvent(&Event, NotificationEvent, FALSE);
535
536 IoCopyCurrentIrpStackLocationToNext(Irp);
537
538 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
539
540 // now call the driver
541 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
542 // did the request complete yet
543 if (Status == STATUS_PENDING)
544 {
545 // not yet, lets wait a bit
546 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
547 Status = Irp->IoStatus.Status;
548 }
549 return Status;
550 }