Merge trunk head (r43756)
[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 NTSTATUS
16 NTAPI
17 PortClsCreate(
18 IN PDEVICE_OBJECT DeviceObject,
19 IN PIRP Irp)
20 {
21 DPRINT("PortClsCreate called\n");
22
23 return KsDispatchIrp(DeviceObject, Irp);
24 }
25
26
27 NTSTATUS
28 NTAPI
29 PortClsPnp(
30 IN PDEVICE_OBJECT DeviceObject,
31 IN PIRP Irp)
32 {
33 NTSTATUS Status;
34 PPCLASS_DEVICE_EXTENSION DeviceExt;
35 PIO_STACK_LOCATION IoStack;
36 IResourceList* resource_list = NULL;
37
38 DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
39 IoStack = IoGetCurrentIrpStackLocation(Irp);
40
41
42 DPRINT("PortClsPnp called %u\n", IoStack->MinorFunction);
43
44 //PC_ASSERT(DeviceExt);
45
46 switch (IoStack->MinorFunction)
47 {
48 case IRP_MN_START_DEVICE:
49 DPRINT("IRP_MN_START_DEVICE\n");
50
51 // Create the resource list
52 Status = PcNewResourceList(
53 &resource_list,
54 NULL,
55 PagedPool,
56 IoStack->Parameters.StartDevice.AllocatedResourcesTranslated,
57 IoStack->Parameters.StartDevice.AllocatedResources);
58 if (!NT_SUCCESS(Status))
59 {
60 DPRINT("PcNewResourceList failed [0x%8x]\n", Status);
61 Irp->IoStatus.Status = Status;
62 IoCompleteRequest(Irp, IO_NO_INCREMENT);
63 return Status;
64 }
65
66 // forward irp to lower device object
67 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
68
69 if (!NT_SUCCESS(Status))
70 {
71 // lower device object failed to start
72 resource_list->Release();
73 // complete the request
74 IoCompleteRequest(Irp, IO_NO_INCREMENT);
75 // return result
76 return Status;
77 }
78
79 // sanity check
80 //PC_ASSERT(DeviceExt->StartDevice);
81 // Call the StartDevice routine
82 DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt->StartDevice);
83 Status = DeviceExt->StartDevice(DeviceObject, Irp, resource_list);
84 if (!NT_SUCCESS(Status))
85 {
86 DPRINT("StartDevice returned a failure code [0x%8x]\n", Status);
87 Irp->IoStatus.Status = Status;
88 IoCompleteRequest(Irp, IO_NO_INCREMENT);
89 return Status;
90 }
91
92 // Assign the resource list to our extension
93 DeviceExt->resources = resource_list;
94
95 Irp->IoStatus.Status = STATUS_SUCCESS;
96 IoCompleteRequest(Irp, IO_NO_INCREMENT);
97 return Status;
98
99 case IRP_MN_REMOVE_DEVICE:
100 // Clean up
101 DPRINT("IRP_MN_REMOVE_DEVICE\n");
102
103 DeviceExt->resources->Release();
104 IoDeleteDevice(DeviceObject);
105
106 // Do not complete?
107 Irp->IoStatus.Status = STATUS_SUCCESS;
108 IoCompleteRequest(Irp, IO_NO_INCREMENT);
109 return STATUS_SUCCESS;
110
111 case IRP_MN_QUERY_INTERFACE:
112 DPRINT("IRP_MN_QUERY_INTERFACE\n");
113 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
114 return PcCompleteIrp(DeviceObject, Irp, Status);
115 case IRP_MN_QUERY_DEVICE_RELATIONS:
116 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
117 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
118 return PcCompleteIrp(DeviceObject, Irp, Status);
119 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
120 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
121 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
122 return PcCompleteIrp(DeviceObject, Irp, Status);
123 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
124 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
125 Status = PcForwardIrpSynchronous(DeviceObject, Irp);
126 return PcCompleteIrp(DeviceObject, Irp, Status);
127 }
128
129 DPRINT("unhandled function %u\n", IoStack->MinorFunction);
130
131 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
132 IoCompleteRequest(Irp, IO_NO_INCREMENT);
133 return STATUS_UNSUCCESSFUL;
134 }
135
136 NTSTATUS
137 NTAPI
138 PortClsPower(
139 IN PDEVICE_OBJECT DeviceObject,
140 IN PIRP Irp)
141 {
142 DPRINT("PortClsPower called\n");
143
144 // TODO
145
146 Irp->IoStatus.Status = STATUS_SUCCESS;
147 Irp->IoStatus.Information = 0;
148 IoCompleteRequest(Irp, IO_NO_INCREMENT);
149
150 return STATUS_SUCCESS;
151 }
152
153 NTSTATUS
154 NTAPI
155 PortClsSysControl(
156 IN PDEVICE_OBJECT DeviceObject,
157 IN PIRP Irp)
158 {
159 DPRINT("PortClsSysControl called\n");
160
161 // TODO
162
163 Irp->IoStatus.Status = STATUS_SUCCESS;
164 Irp->IoStatus.Information = 0;
165 IoCompleteRequest(Irp, IO_NO_INCREMENT);
166
167 return STATUS_SUCCESS;
168 }
169
170 NTSTATUS
171 NTAPI
172 PortClsShutdown(
173 IN PDEVICE_OBJECT DeviceObject,
174 IN PIRP Irp)
175 {
176 PPCLASS_DEVICE_EXTENSION DeviceExtension;
177 DPRINT("PortClsShutdown called\n");
178
179 // get device extension
180 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
181
182 if (DeviceExtension->AdapterPowerManagement)
183 {
184 // release adapter power management
185 DPRINT("Power %u\n", DeviceExtension->AdapterPowerManagement->Release());
186 }
187
188 Irp->IoStatus.Status = STATUS_SUCCESS;
189 Irp->IoStatus.Information = 0;
190 IoCompleteRequest(Irp, IO_NO_INCREMENT);
191
192 return STATUS_SUCCESS;
193 }
194
195 NTSTATUS
196 NTAPI
197 PcDispatchIrp(
198 IN PDEVICE_OBJECT DeviceObject,
199 IN PIRP Irp)
200 {
201 PIO_STACK_LOCATION IoStack;
202
203 DPRINT("PcDispatchIrp called - handling IRP in PortCls\n");
204
205 IoStack = IoGetCurrentIrpStackLocation(Irp);
206
207 switch ( IoStack->MajorFunction )
208 {
209 // PortCls
210 case IRP_MJ_CREATE :
211 return PortClsCreate(DeviceObject, Irp);
212
213 case IRP_MJ_PNP :
214 return PortClsPnp(DeviceObject, Irp);
215
216 case IRP_MJ_POWER :
217 return PortClsPower(DeviceObject, Irp);
218
219 case IRP_MJ_DEVICE_CONTROL:
220 return KsDispatchIrp(DeviceObject, Irp);
221
222 case IRP_MJ_CLOSE:
223 return KsDispatchIrp(DeviceObject, Irp);
224
225 case IRP_MJ_SYSTEM_CONTROL :
226 return PortClsSysControl(DeviceObject, Irp);
227
228 case IRP_MJ_SHUTDOWN:
229 return PortClsShutdown(DeviceObject, Irp);
230
231 default:
232 DPRINT("Unhandled function %x\n", IoStack->MajorFunction);
233 break;
234 };
235
236 // If we reach here, we just complete the IRP
237 Irp->IoStatus.Status = STATUS_SUCCESS;
238 Irp->IoStatus.Information = 0;
239 IoCompleteRequest(Irp, IO_NO_INCREMENT);
240
241 return STATUS_SUCCESS;
242 }
243
244
245 NTSTATUS
246 NTAPI
247 PcCompleteIrp(
248 IN PDEVICE_OBJECT DeviceObject,
249 IN PIRP Irp,
250 IN NTSTATUS Status)
251 {
252 #if 0
253 PC_ASSERT(DeviceObject);
254 PC_ASSERT(Irp);
255 PC_ASSERT(Status != STATUS_PENDING);
256 #endif
257
258 Irp->IoStatus.Status = Status;
259 IoCompleteRequest(Irp, IO_NO_INCREMENT);
260
261 return Status;
262 }
263
264 NTSTATUS
265 NTAPI
266 CompletionRoutine(
267 IN PDEVICE_OBJECT DeviceObject,
268 IN PIRP Irp,
269 IN PVOID Context)
270 {
271 if (Irp->PendingReturned == TRUE)
272 {
273 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
274 }
275 return STATUS_MORE_PROCESSING_REQUIRED;
276 }
277
278 #undef IoSetCompletionRoutine
279 #define IoSetCompletionRoutine(_Irp, \
280 _CompletionRoutine, \
281 _Context, \
282 _InvokeOnSuccess, \
283 _InvokeOnError, \
284 _InvokeOnCancel) \
285 { \
286 PIO_STACK_LOCATION _IrpSp; \
287 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
288 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
289 _IrpSp->Context = (_Context); \
290 _IrpSp->Control = 0; \
291 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
292 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
293 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
294 }
295
296
297
298 NTSTATUS
299 NTAPI
300 PcForwardIrpSynchronous(
301 IN PDEVICE_OBJECT DeviceObject,
302 IN PIRP Irp)
303 {
304 KEVENT Event;
305 PPCLASS_DEVICE_EXTENSION DeviceExt;
306 NTSTATUS Status;
307
308 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
309
310 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
311
312 // initialize the notification event
313 KeInitializeEvent(&Event, NotificationEvent, FALSE);
314
315 IoCopyCurrentIrpStackLocationToNext(Irp);
316
317 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
318
319 // now call the driver
320 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
321 // did the request complete yet
322 if (Status == STATUS_PENDING)
323 {
324 // not yet, lets wait a bit
325 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
326 Status = Irp->IoStatus.Status;
327 }
328 return Status;
329 }