9617a8990b6d6daf5c1acd7cf666c918952e2b0f
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / irp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS
4 * FILE: drivers/multimedia/portcls/irp.c
5 * PURPOSE: Port Class driver / IRP Handling
6 * PROGRAMMER: Andrew Greenwood
7 *
8 * HISTORY:
9 * 27 Jan 07 Created
10 */
11
12
13 #include "private.h"
14 #include <portcls.h>
15
16 /*
17 A safe place for IRPs to be bounced to, if no handler has been
18 set. Whether this is a good idea or not...?
19 */
20 #if 0
21 static
22 NTSTATUS
23 NTAPI
24 IrpStub(
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp)
27 {
28 NTSTATUS status = STATUS_NOT_SUPPORTED;
29
30 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
31 Irp->IoStatus.Information = 0;
32 IoCompleteRequest(Irp, IO_NO_INCREMENT);
33
34 DPRINT1("IRP Stub called\n");
35
36 return status;
37 }
38 #endif
39
40 /*
41 Handles IRP_MJ_CREATE, which occurs when someone wants to make use of
42 a device.
43 */
44 NTSTATUS
45 NTAPI
46 PortClsCreate(
47 IN PDEVICE_OBJECT DeviceObject,
48 IN PIRP Irp)
49 {
50 DPRINT1("PortClsCreate called\n");
51
52 /* TODO */
53
54 Irp->IoStatus.Status = STATUS_SUCCESS;
55 Irp->IoStatus.Information = 0;
56 IoCompleteRequest(Irp, IO_NO_INCREMENT);
57
58 return STATUS_SUCCESS;
59 }
60
61
62 /*
63 IRP_MJ_PNP handler
64 Used for things like IRP_MN_START_DEVICE
65 */
66 NTSTATUS
67 NTAPI
68 PortClsPnp(
69 IN PDEVICE_OBJECT DeviceObject,
70 IN PIRP Irp)
71 {
72 NTSTATUS status;
73 PCExtension* portcls_ext;
74 PIO_STACK_LOCATION irp_stack;
75
76 DPRINT1("PortClsPnp called\n");
77
78 portcls_ext = (PCExtension*) DeviceObject->DeviceExtension;
79 irp_stack = IoGetCurrentIrpStackLocation(Irp);
80
81 ASSERT(portcls_ext);
82
83 /*
84 if IRP_MN_START_DEVICE, call the driver's customer start device routine.
85 Before we do so, we must create a ResourceList to pass to the Start
86 routine.
87 */
88 if ( irp_stack->MinorFunction == IRP_MN_START_DEVICE )
89 {
90 IResourceList* resource_list;
91 DPRINT("IRP_MN_START_DEVICE\n");
92
93 /* Create the resource list */
94 status = PcNewResourceList(
95 &resource_list,
96 NULL,
97 PagedPool,
98 irp_stack->Parameters.StartDevice.AllocatedResourcesTranslated,
99 irp_stack->Parameters.StartDevice.AllocatedResources);
100
101 if ( ! NT_SUCCESS(status) )
102 {
103 DPRINT("PcNewResourceList failed [0x%8x]\n", status);
104 Irp->IoStatus.Status = status;
105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
106
107 return status;
108 }
109
110 /* Assign the resource list to our extension */
111 portcls_ext->resources = resource_list;
112
113 ASSERT(portcls_ext->StartDevice);
114
115 /* Call the StartDevice routine */
116 DPRINT("Calling StartDevice at 0x%8p\n", portcls_ext->StartDevice);
117 status = portcls_ext->StartDevice(DeviceObject, Irp, resource_list);
118
119 if ( ! NT_SUCCESS(status) )
120 {
121 DPRINT("StartDevice returned a failure code [0x%8x]\n", status);
122 //resource_list->lpVtbl->Release(resource_list);
123
124 Irp->IoStatus.Status = status;
125 IoCompleteRequest(Irp, IO_NO_INCREMENT);
126
127 return status;
128 }
129
130 Irp->IoStatus.Status = STATUS_SUCCESS;
131 IoCompleteRequest(Irp, IO_NO_INCREMENT);
132 }
133 else if ( irp_stack->MinorFunction == IRP_MN_REMOVE_DEVICE )
134 {
135 DPRINT("IRP_MN_REMOVE_DEVICE\n");
136 /* Clean up */
137 portcls_ext->resources->lpVtbl->Release(portcls_ext->resources);
138
139 IoDeleteDevice(DeviceObject);
140
141 /* Do not complete? */
142 Irp->IoStatus.Status = STATUS_SUCCESS;
143 }
144
145 return STATUS_SUCCESS;
146 }
147
148 /*
149 Power management. Handles IRP_MJ_POWER
150 (not implemented)
151 */
152 NTSTATUS
153 NTAPI
154 PortClsPower(
155 IN PDEVICE_OBJECT DeviceObject,
156 IN PIRP Irp)
157 {
158 DPRINT1("PortClsPower called\n");
159
160 /* TODO */
161
162 Irp->IoStatus.Status = STATUS_SUCCESS;
163 Irp->IoStatus.Information = 0;
164 IoCompleteRequest(Irp, IO_NO_INCREMENT);
165
166 return STATUS_SUCCESS;
167 }
168
169 /*
170 System control. Handles IRP_MJ_SYSTEM_CONTROL
171 (not implemented)
172 */
173 NTSTATUS
174 NTAPI
175 PortClsSysControl(
176 IN PDEVICE_OBJECT DeviceObject,
177 IN PIRP Irp)
178 {
179 DPRINT1("PortClsSysControl called\n");
180
181 /* TODO */
182
183 Irp->IoStatus.Status = STATUS_SUCCESS;
184 Irp->IoStatus.Information = 0;
185 IoCompleteRequest(Irp, IO_NO_INCREMENT);
186
187 return STATUS_SUCCESS;
188 }
189
190
191 /*
192 ==========================================================================
193 API EXPORTS
194 ==========================================================================
195 */
196
197 /*
198 Drivers may implement their own IRP handlers. If a driver decides to let
199 PortCls handle the IRP, it can do so by calling this.
200 */
201 NTSTATUS NTAPI
202 PcDispatchIrp(
203 IN PDEVICE_OBJECT DeviceObject,
204 IN PIRP Irp)
205 {
206 PIO_STACK_LOCATION irp_stack;
207
208 DPRINT("PcDispatchIrp called - handling IRP in PortCls\n");
209
210 irp_stack = IoGetCurrentIrpStackLocation(Irp);
211
212 switch ( irp_stack->MajorFunction )
213 {
214 /* PortCls */
215 case IRP_MJ_CREATE :
216 return PortClsCreate(DeviceObject, Irp);
217
218 case IRP_MJ_PNP :
219 return PortClsPnp(DeviceObject, Irp);
220
221 case IRP_MJ_POWER :
222 return PortClsPower(DeviceObject, Irp);
223
224 case IRP_MJ_SYSTEM_CONTROL :
225 return PortClsSysControl(DeviceObject, Irp);
226
227 /* KS - TODO */
228
229 #if 0
230 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
231 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
232 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_FLUSH_BUFFERS);
233 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_QUERY_SECURITY);
234 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_READ);
235 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_SET_SECURITY);
236 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
237 #endif
238
239 default :
240 break;
241 };
242
243 /* If we reach here, we just complete the IRP */
244 Irp->IoStatus.Status = STATUS_SUCCESS;
245 Irp->IoStatus.Information = 0;
246 IoCompleteRequest(Irp, IO_NO_INCREMENT);
247
248 return STATUS_SUCCESS;
249 }
250
251 /*
252 * @unimplemented
253 */
254 NTSTATUS NTAPI
255 PcCompleteIrp(
256 IN PDEVICE_OBJECT DeviceObject,
257 IN PIRP Irp,
258 IN NTSTATUS Status)
259 {
260 UNIMPLEMENTED;
261 return STATUS_UNSUCCESSFUL;
262 }
263
264 static
265 NTSTATUS
266 NTAPI
267 IrpCompletionRoutine(
268 IN PDEVICE_OBJECT DeviceObject,
269 IN PIRP Irp,
270 IN PVOID Context)
271 {
272 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
273 return STATUS_SUCCESS;
274 }
275
276
277 /*
278 * @implemented
279 */
280 NTSTATUS NTAPI
281 PcForwardIrpSynchronous(
282 IN PDEVICE_OBJECT DeviceObject,
283 IN PIRP Irp)
284 {
285 KEVENT Event;
286 PCExtension* DeviceExt;
287 NTSTATUS Status;
288
289 DPRINT1("PcRegisterSubdevice\n");
290
291 DeviceExt = (PCExtension*)DeviceObject->DeviceExtension;
292
293 /* initialize the notification event */
294 KeInitializeEvent(&Event, NotificationEvent, FALSE);
295
296 /* setup a completion routine */
297 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&Event, TRUE, FALSE, FALSE);
298
299 /* now call the driver */
300 Status = IoCallDriver(DeviceExt->PrevDeviceObject, Irp);
301 /* did the request complete yet */
302 if (Status == STATUS_PENDING)
303 {
304 /* not yet, lets wait a bit */
305 KeWaitForSingleObject(&Event, Executive, FALSE, FALSE, NULL);
306 Status = STATUS_SUCCESS;
307 }
308
309 return Status;
310 }