- Implement CPortFilterWaveCyclic::FastDeviceIoControl
[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 DPRINT1("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 PLIST_ENTRY Entry;
178 PPHYSICAL_CONNECTION Connection;
179 DPRINT("PortClsShutdown called\n");
180
181 // get device extension
182 DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
183
184 while(!IsListEmpty(&DeviceExtension->PhysicalConnectionList))
185 {
186 // get connection entry
187 Entry = RemoveHeadList(&DeviceExtension->PhysicalConnectionList);
188 Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry);
189
190 if (Connection->FromSubDevice)
191 {
192 // release subdevice
193 Connection->FromSubDevice->Release();
194 }
195
196 if (Connection->ToSubDevice)
197 {
198 // release subdevice
199 Connection->ToSubDevice->Release();
200 }
201 FreeItem(Connection, TAG_PORTCLASS);
202 }
203
204 if (DeviceExtension->AdapterPowerManagement)
205 {
206 // release adapter power management
207 DPRINT1("Power %u\n", DeviceExtension->AdapterPowerManagement->Release());
208 }
209
210 Irp->IoStatus.Status = STATUS_SUCCESS;
211 Irp->IoStatus.Information = 0;
212 IoCompleteRequest(Irp, IO_NO_INCREMENT);
213
214 return STATUS_SUCCESS;
215 }
216
217 NTSTATUS
218 NTAPI
219 PcDispatchIrp(
220 IN PDEVICE_OBJECT DeviceObject,
221 IN PIRP Irp)
222 {
223 PIO_STACK_LOCATION IoStack;
224
225 DPRINT("PcDispatchIrp called - handling IRP in PortCls\n");
226
227 IoStack = IoGetCurrentIrpStackLocation(Irp);
228
229 switch ( IoStack->MajorFunction )
230 {
231 // PortCls
232 case IRP_MJ_CREATE :
233 return PortClsCreate(DeviceObject, Irp);
234
235 case IRP_MJ_PNP :
236 return PortClsPnp(DeviceObject, Irp);
237
238 case IRP_MJ_POWER :
239 return PortClsPower(DeviceObject, Irp);
240
241 case IRP_MJ_DEVICE_CONTROL:
242 return KsDispatchIrp(DeviceObject, Irp);
243
244 case IRP_MJ_CLOSE:
245 return KsDispatchIrp(DeviceObject, Irp);
246
247 case IRP_MJ_SYSTEM_CONTROL :
248 return PortClsSysControl(DeviceObject, Irp);
249
250 case IRP_MJ_SHUTDOWN:
251 return PortClsShutdown(DeviceObject, Irp);
252
253 default:
254 DPRINT1("Unhandled function %x\n", IoStack->MajorFunction);
255 break;
256 };
257
258 // If we reach here, we just complete the IRP
259 Irp->IoStatus.Status = STATUS_SUCCESS;
260 Irp->IoStatus.Information = 0;
261 IoCompleteRequest(Irp, IO_NO_INCREMENT);
262
263 return STATUS_SUCCESS;
264 }
265
266
267 NTSTATUS
268 NTAPI
269 PcCompleteIrp(
270 IN PDEVICE_OBJECT DeviceObject,
271 IN PIRP Irp,
272 IN NTSTATUS Status)
273 {
274 #if 0
275 PC_ASSERT(DeviceObject);
276 PC_ASSERT(Irp);
277 PC_ASSERT(Status != STATUS_PENDING);
278 #endif
279
280 Irp->IoStatus.Status = Status;
281 IoCompleteRequest(Irp, IO_NO_INCREMENT);
282
283 return Status;
284 }
285
286 NTSTATUS
287 NTAPI
288 CompletionRoutine(
289 IN PDEVICE_OBJECT DeviceObject,
290 IN PIRP Irp,
291 IN PVOID Context)
292 {
293 if (Irp->PendingReturned == TRUE)
294 {
295 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
296 }
297 return STATUS_MORE_PROCESSING_REQUIRED;
298 }
299
300 #undef IoSetCompletionRoutine
301 #define IoSetCompletionRoutine(_Irp, \
302 _CompletionRoutine, \
303 _Context, \
304 _InvokeOnSuccess, \
305 _InvokeOnError, \
306 _InvokeOnCancel) \
307 { \
308 PIO_STACK_LOCATION _IrpSp; \
309 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
310 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
311 _IrpSp->Context = (_Context); \
312 _IrpSp->Control = 0; \
313 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
314 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
315 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
316 }
317
318
319
320 NTSTATUS
321 NTAPI
322 PcForwardIrpSynchronous(
323 IN PDEVICE_OBJECT DeviceObject,
324 IN PIRP Irp)
325 {
326 KEVENT Event;
327 PPCLASS_DEVICE_EXTENSION DeviceExt;
328 NTSTATUS Status;
329
330 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
331
332 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
333
334 // initialize the notification event
335 KeInitializeEvent(&Event, NotificationEvent, FALSE);
336
337 IoCopyCurrentIrpStackLocationToNext(Irp);
338
339 IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
340
341 // now call the driver
342 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
343 // did the request complete yet
344 if (Status == STATUS_PENDING)
345 {
346 // not yet, lets wait a bit
347 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
348 Status = Irp->IoStatus.Status;
349 }
350 return Status;
351 }