18a089dadf71def174537acdd1e0cc2f807e1d42
[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 }
145
146 DPRINT("unhandled function %u\n", IoStack->MinorFunction);
147
148 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
149 IoCompleteRequest(Irp, IO_NO_INCREMENT);
150 return STATUS_UNSUCCESSFUL;
151 }
152
153 VOID
154 CALLBACK
155 PwrCompletionFunction(
156 IN PDEVICE_OBJECT DeviceObject,
157 IN UCHAR MinorFunction,
158 IN POWER_STATE PowerState,
159 IN PVOID Context,
160 IN PIO_STATUS_BLOCK IoStatus)
161 {
162 NTSTATUS Status;
163 PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context;
164
165 if (NT_SUCCESS(IoStatus->Status))
166 {
167 // forward request to lower device object
168 Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp);
169 }
170 else
171 {
172 // failed
173 Status = IoStatus->Status;
174 }
175
176 // start next power irp
177 PoStartNextPowerIrp(PwrContext->Irp);
178
179 // complete request
180 PwrContext->Irp->IoStatus.Status = Status;
181 IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT);
182
183 // free context
184 FreeItem(PwrContext, TAG_PORTCLASS);
185 }
186
187
188 NTSTATUS
189 NTAPI
190 PortClsPower(
191 IN PDEVICE_OBJECT DeviceObject,
192 IN PIRP Irp)
193 {
194 PIO_STACK_LOCATION IoStack;
195 PPCLASS_DEVICE_EXTENSION DeviceExtension;
196 PQUERY_POWER_CONTEXT PwrContext;
197 POWER_STATE PowerState;
198 NTSTATUS Status = STATUS_SUCCESS;
199
200 DPRINT("PortClsPower called\n");
201
202 // get currrent stack location
203 IoStack = IoGetCurrentIrpStackLocation(Irp);
204
205 if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER)
206 {
207 // just forward the request
208 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
209
210 // start next power irp
211 PoStartNextPowerIrp(Irp);
212
213 // complete request
214 Irp->IoStatus.Status = Status;
215 IoCompleteRequest(Irp, IO_NO_INCREMENT);
216
217 // done
218 return Status;
219 }
220
221
222 // get device extension
223 DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
224
225 // get current request type
226 if (IoStack->Parameters.Power.Type == DevicePowerState)
227 {
228 // request for device power state
229 if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState)
230 {
231 // nothing has changed
232 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
233 {
234 // only forward query requests
235 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
236 }
237
238 // start next power irp
239 PoStartNextPowerIrp(Irp);
240
241 // complete request
242 Irp->IoStatus.Status = Status;
243 IoCompleteRequest(Irp, IO_NO_INCREMENT);
244
245 // done
246 return Status;
247 }
248
249 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
250 {
251 // check if there is a registered adapter power management
252 if (DeviceExtension->AdapterPowerManagement)
253 {
254 // it is query if the change can be changed
255 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
256 Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState);
257
258 // sanity check
259 PC_ASSERT(Status == STATUS_SUCCESS);
260 }
261
262 // only forward query requests
263 PcForwardIrpSynchronous(DeviceObject, Irp);
264
265 // start next power irp
266 PoStartNextPowerIrp(Irp);
267
268 // complete request
269 Irp->IoStatus.Status = Status;
270 IoCompleteRequest(Irp, IO_NO_INCREMENT);
271
272 // done
273 return Status;
274 }
275 else
276 {
277 // set power state
278 PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
279 PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
280
281 // check if there is a registered adapter power management
282 if (DeviceExtension->AdapterPowerManagement)
283 {
284 // notify of a power change state
285 DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState);
286 }
287
288 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
289
290 // store new power state
291 DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState;
292
293 // complete request
294 Irp->IoStatus.Status = Status;
295 IoCompleteRequest(Irp, IO_NO_INCREMENT);
296
297 // done
298 return Status;
299 }
300 }
301 else
302 {
303 // sanity check
304 PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState);
305
306 if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
307 {
308 // mark irp as pending
309 IoMarkIrpPending(Irp);
310
311 // allocate power completion context
312 PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS);
313
314 if (!PwrContext)
315 {
316 // no memory
317 PoStartNextPowerIrp(Irp);
318
319 // complete and forget
320 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
321 IoCompleteRequest(Irp, IO_NO_INCREMENT);
322
323 // done
324 return Status;
325 }
326
327 // setup power context
328 PwrContext->Irp = Irp;
329 PwrContext->DeviceObject = DeviceObject;
330
331 // pass the irp down
332 PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState);
333 Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL);
334
335 // check for success
336 if (!NT_SUCCESS(Status))
337 {
338 // failed
339 Irp->IoStatus.Status = Status;
340 IoCompleteRequest(Irp, IO_NO_INCREMENT);
341
342 // done
343 return Status;
344 }
345
346 // done
347 return STATUS_PENDING;
348 }
349 else
350 {
351 // set power request
352 DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState;
353
354 // only forward query requests
355 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
356
357 // start next power irp
358 PoStartNextPowerIrp(Irp);
359
360 // complete request
361 Irp->IoStatus.Status = Status;
362 IoCompleteRequest(Irp, IO_NO_INCREMENT);
363
364 // done
365 return Status;
366 }
367 }
368 }
369
370 NTSTATUS
371 NTAPI
372 PortClsSysControl(
373 IN PDEVICE_OBJECT DeviceObject,
374 IN PIRP Irp)
375 {
376 DPRINT("PortClsSysControl called\n");
377
378 // TODO
379
380 Irp->IoStatus.Status = STATUS_SUCCESS;
381 Irp->IoStatus.Information = 0;
382 IoCompleteRequest(Irp, IO_NO_INCREMENT);
383
384 return STATUS_SUCCESS;
385 }
386
387 NTSTATUS
388 NTAPI
389 PortClsShutdown(
390 IN PDEVICE_OBJECT DeviceObject,
391 IN PIRP Irp)
392 {
393 PPCLASS_DEVICE_EXTENSION DeviceExtension;
394 DPRINT("PortClsShutdown called\n");
395
396 // get device extension
397 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
398
399 if (DeviceExtension->AdapterPowerManagement)
400 {
401 // release adapter power management
402 DPRINT("Power %u\n", DeviceExtension->AdapterPowerManagement->Release());
403 }
404
405 Irp->IoStatus.Status = STATUS_SUCCESS;
406 Irp->IoStatus.Information = 0;
407 IoCompleteRequest(Irp, IO_NO_INCREMENT);
408
409 return STATUS_SUCCESS;
410 }
411
412 NTSTATUS
413 NTAPI
414 PcDispatchIrp(
415 IN PDEVICE_OBJECT DeviceObject,
416 IN PIRP Irp)
417 {
418 PIO_STACK_LOCATION IoStack;
419
420 IoStack = IoGetCurrentIrpStackLocation(Irp);
421
422 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
423
424 switch ( IoStack->MajorFunction )
425 {
426 // PortCls
427 case IRP_MJ_CREATE :
428 return PortClsCreate(DeviceObject, Irp);
429
430 case IRP_MJ_PNP :
431 return PortClsPnp(DeviceObject, Irp);
432
433 case IRP_MJ_POWER :
434 return PortClsPower(DeviceObject, Irp);
435
436 case IRP_MJ_DEVICE_CONTROL:
437 return KsDispatchIrp(DeviceObject, Irp);
438
439 case IRP_MJ_CLOSE:
440 return KsDispatchIrp(DeviceObject, Irp);
441
442 case IRP_MJ_SYSTEM_CONTROL :
443 return PortClsSysControl(DeviceObject, Irp);
444
445 case IRP_MJ_SHUTDOWN:
446 return PortClsShutdown(DeviceObject, Irp);
447
448 default:
449 DPRINT("Unhandled function %x\n", IoStack->MajorFunction);
450 break;
451 };
452
453 // If we reach here, we just complete the IRP
454 Irp->IoStatus.Status = STATUS_SUCCESS;
455 Irp->IoStatus.Information = 0;
456 IoCompleteRequest(Irp, IO_NO_INCREMENT);
457
458 return STATUS_SUCCESS;
459 }
460
461
462 NTSTATUS
463 NTAPI
464 PcCompleteIrp(
465 IN PDEVICE_OBJECT DeviceObject,
466 IN PIRP Irp,
467 IN NTSTATUS Status)
468 {
469 #if 0
470 PC_ASSERT(DeviceObject);
471 PC_ASSERT(Irp);
472 PC_ASSERT(Status != STATUS_PENDING);
473 #endif
474
475 Irp->IoStatus.Status = Status;
476 IoCompleteRequest(Irp, IO_NO_INCREMENT);
477
478 return Status;
479 }
480
481 NTSTATUS
482 NTAPI
483 CompletionRoutine(
484 IN PDEVICE_OBJECT DeviceObject,
485 IN PIRP Irp,
486 IN PVOID Context)
487 {
488 if (Irp->PendingReturned == TRUE)
489 {
490 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
491 }
492 return STATUS_MORE_PROCESSING_REQUIRED;
493 }
494
495 #undef IoSetCompletionRoutine
496 #define IoSetCompletionRoutine(_Irp, \
497 _CompletionRoutine, \
498 _Context, \
499 _InvokeOnSuccess, \
500 _InvokeOnError, \
501 _InvokeOnCancel) \
502 { \
503 PIO_STACK_LOCATION _IrpSp; \
504 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
505 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
506 _IrpSp->Context = (_Context); \
507 _IrpSp->Control = 0; \
508 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
509 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
510 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
511 }
512
513
514
515 NTSTATUS
516 NTAPI
517 PcForwardIrpSynchronous(
518 IN PDEVICE_OBJECT DeviceObject,
519 IN PIRP Irp)
520 {
521 KEVENT Event;
522 PPCLASS_DEVICE_EXTENSION DeviceExt;
523 NTSTATUS Status;
524
525 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
526
527 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
528
529 // initialize the notification event
530 KeInitializeEvent(&Event, NotificationEvent, FALSE);
531
532 IoCopyCurrentIrpStackLocationToNext(Irp);
533
534 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
535
536 // now call the driver
537 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
538 // did the request complete yet
539 if (Status == STATUS_PENDING)
540 {
541 // not yet, lets wait a bit
542 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
543 Status = Irp->IoStatus.Status;
544 }
545 return Status;
546 }