[HDAUDBUS] Split FDO/PDO PNP handling into separate functions.
[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 if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
101 {
102 Status = HDA_FDOStartDevice(DeviceObject, Irp);
103 }
104 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
105 {
106 /* handle bus device relations */
107 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
108 {
109 Status = HDA_FDOQueryBusRelations(DeviceObject, Irp);
110 }
111 else
112 {
113 Status = Irp->IoStatus.Status;
114 }
115 }
116 else
117 {
118 /* get default status */
119 Status = Irp->IoStatus.Status;
120 }
121
122 Irp->IoStatus.Status = Status;
123 IoCompleteRequest(Irp, IO_NO_INCREMENT);
124
125 return Status;
126 }
127
128 NTSTATUS
129 HDA_PdoPnp(
130 _In_ PDEVICE_OBJECT DeviceObject,
131 _Inout_ PIRP Irp)
132 {
133 NTSTATUS Status;
134 PIO_STACK_LOCATION IoStack;
135 PDEVICE_RELATIONS DeviceRelation;
136
137 IoStack = IoGetCurrentIrpStackLocation(Irp);
138
139 if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
140 {
141 /* no op for pdo */
142 Status = STATUS_SUCCESS;
143 }
144 else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION)
145 {
146 /* query bus information */
147 Status = HDA_PDOQueryBusInformation(Irp);
148 }
149 else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
150 {
151 /* query pnp state */
152 Status = HDA_PDOQueryBusDevicePnpState(Irp);
153 }
154 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
155 {
156 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
157 {
158 /* handle target device relations */
159 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation);
160 ASSERT(Irp->IoStatus.Information == 0);
161
162 /* allocate device relation */
163 DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
164 if (DeviceRelation)
165 {
166 DeviceRelation->Count = 1;
167 DeviceRelation->Objects[0] = DeviceObject;
168
169 /* reference self */
170 ObReferenceObject(DeviceObject);
171
172 /* store result */
173 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
174
175 /* done */
176 Status = STATUS_SUCCESS;
177 }
178 else
179 {
180 /* no memory */
181 Status = STATUS_INSUFFICIENT_RESOURCES;
182 }
183 }
184 }
185 else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES)
186 {
187 /* query capabilities */
188 Status = HDA_PDOQueryBusDeviceCapabilities(Irp);
189 }
190 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
191 {
192 /* no op */
193 Status = STATUS_SUCCESS;
194 }
195 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES)
196 {
197 /* no op */
198 Status = STATUS_SUCCESS;
199 }
200 else if (IoStack->MinorFunction == IRP_MN_QUERY_ID)
201 {
202 Status = HDA_PDOQueryId(DeviceObject, Irp);
203 }
204 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_TEXT)
205 {
206 Status = HDA_PDOHandleQueryDeviceText(Irp);
207 }
208 else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE)
209 {
210 Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp);
211 }
212 else
213 {
214 /* get default status */
215 Status = Irp->IoStatus.Status;
216 }
217
218 Irp->IoStatus.Status = Status;
219 IoCompleteRequest(Irp, IO_NO_INCREMENT);
220
221 return Status;
222 }
223
224 NTSTATUS
225 NTAPI
226 HDA_Pnp(
227 _In_ PDEVICE_OBJECT DeviceObject,
228 _Inout_ PIRP Irp)
229 {
230 PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
231
232 FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
233
234 if (FDODeviceExtension->IsFDO)
235 {
236 return HDA_FdoPnp(DeviceObject, Irp);
237 }
238 else
239 {
240 return HDA_PdoPnp(DeviceObject, Irp);
241 }
242 }
243
244
245 NTSTATUS
246 NTAPI
247 HDA_AddDevice(
248 _In_ PDRIVER_OBJECT DriverObject,
249 _In_ PDEVICE_OBJECT PhysicalDeviceObject)
250 {
251 PDEVICE_OBJECT DeviceObject;
252 PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
253 NTSTATUS Status;
254
255 /* create device object */
256 Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
257 if (!NT_SUCCESS(Status))
258 {
259 /* failed */
260 return Status;
261 }
262
263 /* get device extension*/
264 DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
265
266 /* init device extension*/
267 DeviceExtension->IsFDO = TRUE;
268 DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
269 RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1));
270
271 /* set device flags */
272 DeviceObject->Flags |= DO_POWER_PAGABLE;
273
274 return Status;
275 }
276 extern "C"
277 {
278 NTSTATUS
279 NTAPI
280 DriverEntry(
281 _In_ PDRIVER_OBJECT DriverObject,
282 _In_ PUNICODE_STRING RegistryPathName)
283 {
284 DriverObject->DriverExtension->AddDevice = HDA_AddDevice;
285 DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp;
286
287 return STATUS_SUCCESS;
288 }
289
290 }