[HDAUDBUS] Forward FDO requests instead of completing them.
[reactos.git] / drivers / wdm / audio / hdaudbus / hdaudbus.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/hdaudbus/hdaudbus.cpp
5 * PURPOSE: HDA Driver Entry
6 * PROGRAMMER: Johannes Anderwald
7 */
8 #include "hdaudbus.h"
9
10 DRIVER_DISPATCH HDA_Pnp;
11 DRIVER_ADD_DEVICE HDA_AddDevice;
12 extern "C" DRIVER_INITIALIZE DriverEntry;
13
14 PVOID
15 AllocateItem(
16 _In_ POOL_TYPE PoolType,
17 _In_ SIZE_T NumberOfBytes)
18 {
19 PVOID Item = ExAllocatePoolWithTag(PoolType, NumberOfBytes, TAG_HDA);
20 if (!Item)
21 return Item;
22
23 RtlZeroMemory(Item, NumberOfBytes);
24 return Item;
25 }
26
27 VOID
28 FreeItem(
29 __drv_freesMem(Mem) PVOID Item)
30 {
31 ExFreePool(Item);
32 }
33
34 NTSTATUS
35 NTAPI
36 HDA_SyncForwardIrpCompletionRoutine(
37 IN PDEVICE_OBJECT DeviceObject,
38 IN PIRP Irp,
39 IN PVOID Context)
40 {
41 if (Irp->PendingReturned)
42 {
43 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
44 }
45 return STATUS_MORE_PROCESSING_REQUIRED;
46 }
47
48 NTSTATUS
49 NTAPI
50 HDA_SyncForwardIrp(
51 IN PDEVICE_OBJECT DeviceObject,
52 IN PIRP Irp)
53 {
54 KEVENT Event;
55 NTSTATUS Status;
56
57 /* Initialize event */
58 KeInitializeEvent(&Event, NotificationEvent, FALSE);
59
60 /* Copy irp stack location */
61 IoCopyCurrentIrpStackLocationToNext(Irp);
62
63 /* Set completion routine */
64 IoSetCompletionRoutine(Irp,
65 HDA_SyncForwardIrpCompletionRoutine,
66 &Event,
67 TRUE,
68 TRUE,
69 TRUE);
70
71 /* Call driver */
72 Status = IoCallDriver(DeviceObject, Irp);
73
74 /* Check if pending */
75 if (Status == STATUS_PENDING)
76 {
77 /* Wait for the request to finish */
78 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
79
80 /* Copy status code */
81 Status = Irp->IoStatus.Status;
82 }
83
84 /* Done */
85 return Status;
86 }
87
88 NTSTATUS
89 HDA_FdoPnp(
90 _In_ PDEVICE_OBJECT DeviceObject,
91 _Inout_ PIRP Irp)
92 {
93 NTSTATUS Status;
94 PIO_STACK_LOCATION IoStack;
95 PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
96
97 FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
98 IoStack = IoGetCurrentIrpStackLocation(Irp);
99
100 switch (IoStack->MinorFunction)
101 {
102 case IRP_MN_START_DEVICE:
103 Status = HDA_FDOStartDevice(DeviceObject, Irp);
104 Irp->IoStatus.Status = Status;
105 IoCompleteRequest(Irp, IO_NO_INCREMENT);
106 return Status;
107 case IRP_MN_QUERY_DEVICE_RELATIONS:
108 /* handle bus device relations */
109 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
110 {
111 Status = HDA_FDOQueryBusRelations(DeviceObject, Irp);
112 Irp->IoStatus.Status = Status;
113 if (!NT_SUCCESS(Status))
114 {
115 IoCompleteRequest(Irp, IO_NO_INCREMENT);
116 return Status;
117 }
118 }
119 break;
120 }
121
122 IoSkipCurrentIrpStackLocation(Irp);
123 return IoCallDriver(FDODeviceExtension->LowerDevice, Irp);
124 }
125
126 NTSTATUS
127 HDA_PdoPnp(
128 _In_ PDEVICE_OBJECT DeviceObject,
129 _Inout_ PIRP Irp)
130 {
131 NTSTATUS Status;
132 PIO_STACK_LOCATION IoStack;
133 PDEVICE_RELATIONS DeviceRelation;
134
135 IoStack = IoGetCurrentIrpStackLocation(Irp);
136
137 switch (IoStack->MinorFunction)
138 {
139 case IRP_MN_START_DEVICE:
140 /* no op for pdo */
141 Status = STATUS_SUCCESS;
142 break;
143 case IRP_MN_QUERY_BUS_INFORMATION:
144 /* query bus information */
145 Status = HDA_PDOQueryBusInformation(Irp);
146 break;
147 case IRP_MN_QUERY_PNP_DEVICE_STATE:
148 /* query pnp state */
149 Status = HDA_PDOQueryBusDevicePnpState(Irp);
150 break;
151 case IRP_MN_QUERY_DEVICE_RELATIONS:
152 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
153 {
154 /* handle target device relations */
155 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation);
156 ASSERT(Irp->IoStatus.Information == 0);
157
158 /* allocate device relation */
159 DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
160 if (DeviceRelation)
161 {
162 DeviceRelation->Count = 1;
163 DeviceRelation->Objects[0] = DeviceObject;
164
165 /* reference self */
166 ObReferenceObject(DeviceObject);
167
168 /* store result */
169 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
170
171 /* done */
172 Status = STATUS_SUCCESS;
173 }
174 else
175 {
176 /* no memory */
177 Status = STATUS_INSUFFICIENT_RESOURCES;
178 }
179 }
180 break;
181 case IRP_MN_QUERY_CAPABILITIES:
182 /* query capabilities */
183 Status = HDA_PDOQueryBusDeviceCapabilities(Irp);
184 break;
185 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
186 /* no op */
187 Status = STATUS_SUCCESS;
188 break;
189 case IRP_MN_QUERY_RESOURCES:
190 /* no op */
191 Status = STATUS_SUCCESS;
192 break;
193 case IRP_MN_QUERY_ID:
194 Status = HDA_PDOQueryId(DeviceObject, Irp);
195 break;
196 case IRP_MN_QUERY_DEVICE_TEXT:
197 Status = HDA_PDOHandleQueryDeviceText(Irp);
198 break;
199 case IRP_MN_QUERY_INTERFACE:
200 Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp);
201 break;
202 default:
203 /* get default status */
204 Status = Irp->IoStatus.Status;
205 break;
206 }
207
208 Irp->IoStatus.Status = Status;
209 IoCompleteRequest(Irp, IO_NO_INCREMENT);
210
211 return Status;
212 }
213
214 NTSTATUS
215 NTAPI
216 HDA_Pnp(
217 _In_ PDEVICE_OBJECT DeviceObject,
218 _Inout_ PIRP Irp)
219 {
220 PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
221
222 FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
223
224 if (FDODeviceExtension->IsFDO)
225 {
226 return HDA_FdoPnp(DeviceObject, Irp);
227 }
228 else
229 {
230 return HDA_PdoPnp(DeviceObject, Irp);
231 }
232 }
233
234
235 NTSTATUS
236 NTAPI
237 HDA_AddDevice(
238 _In_ PDRIVER_OBJECT DriverObject,
239 _In_ PDEVICE_OBJECT PhysicalDeviceObject)
240 {
241 PDEVICE_OBJECT DeviceObject;
242 PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
243 NTSTATUS Status;
244
245 /* create device object */
246 Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
247 if (!NT_SUCCESS(Status))
248 {
249 /* failed */
250 return Status;
251 }
252
253 /* get device extension*/
254 DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
255
256 /* init device extension*/
257 DeviceExtension->IsFDO = TRUE;
258 DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
259 RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1));
260
261 /* set device flags */
262 DeviceObject->Flags |= DO_POWER_PAGABLE;
263
264 return Status;
265 }
266 extern "C"
267 {
268 NTSTATUS
269 NTAPI
270 DriverEntry(
271 _In_ PDRIVER_OBJECT DriverObject,
272 _In_ PUNICODE_STRING RegistryPathName)
273 {
274 DriverObject->DriverExtension->AddDevice = HDA_AddDevice;
275 DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp;
276
277 return STATUS_SUCCESS;
278 }
279
280 }