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 
9 #include "hdaudbus.h"
10 
11 DRIVER_DISPATCH HDA_Pnp;
12 DRIVER_DISPATCH HDA_SystemControl;
13 DRIVER_DISPATCH HDA_Power;
14 DRIVER_ADD_DEVICE HDA_AddDevice;
15 DRIVER_UNLOAD HDA_Unload;
16 extern "C" DRIVER_INITIALIZE DriverEntry;
17 
18 PVOID
19 AllocateItem(
20     _In_ POOL_TYPE PoolType,
21     _In_ SIZE_T NumberOfBytes)
22 {
23     return ExAllocatePoolZero(PoolType, NumberOfBytes, TAG_HDA);
24 }
25 
26 VOID
27 FreeItem(
28     __drv_freesMem(Mem) PVOID Item)
29 {
30     ExFreePoolWithTag(Item, TAG_HDA);
31 }
32 
33 NTSTATUS
34 HDA_FdoPnp(
35     _In_ PDEVICE_OBJECT DeviceObject,
36     _Inout_ PIRP Irp)
37 {
38     NTSTATUS Status;
39     PIO_STACK_LOCATION IoStack;
40     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
41     ULONG CodecIndex, AFGIndex;
42     PHDA_CODEC_ENTRY CodecEntry;
43     PHDA_PDO_DEVICE_EXTENSION ChildDeviceExtension;
44 
45     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
46     IoStack = IoGetCurrentIrpStackLocation(Irp);
47 
48     switch (IoStack->MinorFunction)
49     {
50     case IRP_MN_START_DEVICE:
51         Status = HDA_FDOStartDevice(DeviceObject, Irp);
52         Irp->IoStatus.Status = Status;
53         IoCompleteRequest(Irp, IO_NO_INCREMENT);
54         return Status;
55     case IRP_MN_REMOVE_DEVICE:
56         return HDA_FDORemoveDevice(DeviceObject, Irp);
57     case IRP_MN_SURPRISE_REMOVAL:
58         for (CodecIndex = 0; CodecIndex < HDA_MAX_CODECS; CodecIndex++)
59         {
60             CodecEntry = FDODeviceExtension->Codecs[CodecIndex];
61 
62             ASSERT(CodecEntry->AudioGroupCount <= HDA_MAX_AUDIO_GROUPS);
63             for (AFGIndex = 0; AFGIndex < CodecEntry->AudioGroupCount; AFGIndex++)
64             {
65                 ChildDeviceExtension = static_cast<PHDA_PDO_DEVICE_EXTENSION>(CodecEntry->AudioGroups[AFGIndex]->ChildPDO->DeviceExtension);
66                 ChildDeviceExtension->ReportedMissing = TRUE;
67             }
68         }
69         Irp->IoStatus.Status = STATUS_SUCCESS;
70         break;
71     case IRP_MN_QUERY_REMOVE_DEVICE:
72     case IRP_MN_CANCEL_REMOVE_DEVICE:
73         Irp->IoStatus.Status = STATUS_SUCCESS;
74         break;
75     case IRP_MN_QUERY_DEVICE_RELATIONS:
76         /* handle bus device relations */
77         if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
78         {
79             Status = HDA_FDOQueryBusRelations(DeviceObject, Irp);
80             Irp->IoStatus.Status = Status;
81             if (!NT_SUCCESS(Status))
82             {
83                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
84                 return Status;
85             }
86         }
87         break;
88     }
89 
90     IoSkipCurrentIrpStackLocation(Irp);
91     return IoCallDriver(FDODeviceExtension->LowerDevice, Irp);
92 }
93 
94 NTSTATUS
95 HDA_PdoPnp(
96     _In_ PDEVICE_OBJECT DeviceObject,
97     _Inout_ PIRP Irp)
98 {
99     NTSTATUS Status;
100     PIO_STACK_LOCATION IoStack;
101     PDEVICE_RELATIONS DeviceRelation;
102 
103     IoStack = IoGetCurrentIrpStackLocation(Irp);
104 
105     switch (IoStack->MinorFunction)
106     {
107     case IRP_MN_START_DEVICE:
108         /* no op for pdo */
109         Status = STATUS_SUCCESS;
110         break;
111     case IRP_MN_REMOVE_DEVICE:
112         Status = HDA_PDORemoveDevice(DeviceObject);
113         break;
114     case IRP_MN_QUERY_REMOVE_DEVICE:
115     case IRP_MN_CANCEL_REMOVE_DEVICE:
116         Status = STATUS_SUCCESS;
117         break;
118     case IRP_MN_QUERY_BUS_INFORMATION:
119         /* query bus information */
120         Status = HDA_PDOQueryBusInformation(Irp);
121         break;
122     case IRP_MN_QUERY_PNP_DEVICE_STATE:
123         /* query pnp state */
124         Status = HDA_PDOQueryBusDevicePnpState(Irp);
125         break;
126     case IRP_MN_QUERY_DEVICE_RELATIONS:
127         if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
128         {
129             /* handle target device relations */
130             ASSERT(Irp->IoStatus.Information == 0);
131 
132             /* allocate device relation */
133             DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
134             if (DeviceRelation)
135             {
136                 DeviceRelation->Count = 1;
137                 DeviceRelation->Objects[0] = DeviceObject;
138 
139                 /* reference self */
140                 ObReferenceObject(DeviceObject);
141 
142                 /* store result */
143                 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
144 
145                 /* done */
146                 Status = STATUS_SUCCESS;
147             }
148             else
149             {
150                 /* no memory */
151                 Status = STATUS_INSUFFICIENT_RESOURCES;
152             }
153         }
154         else
155         {
156             Status = Irp->IoStatus.Status;
157         }
158         break;
159     case IRP_MN_QUERY_CAPABILITIES:
160         /* query capabilities */
161         Status = HDA_PDOQueryBusDeviceCapabilities(Irp);
162         break;
163     case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
164         /* no op */
165         Status = STATUS_SUCCESS;
166         break;
167     case IRP_MN_QUERY_RESOURCES:
168         /* no op */
169         Status = STATUS_SUCCESS;
170         break;
171     case IRP_MN_QUERY_ID:
172         Status = HDA_PDOQueryId(DeviceObject, Irp);
173         break;
174     case IRP_MN_QUERY_DEVICE_TEXT:
175         Status = HDA_PDOHandleQueryDeviceText(Irp);
176         break;
177     case IRP_MN_QUERY_INTERFACE:
178         Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp);
179         break;
180     default:
181         /* get default status */
182         Status = Irp->IoStatus.Status;
183         break;
184     }
185 
186     Irp->IoStatus.Status = Status;
187     IoCompleteRequest(Irp, IO_NO_INCREMENT);
188 
189     return Status;
190 }
191 
192 NTSTATUS
193 NTAPI
194 HDA_Pnp(
195     _In_ PDEVICE_OBJECT DeviceObject,
196     _Inout_ PIRP Irp)
197 {
198     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
199 
200     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
201 
202     if (FDODeviceExtension->IsFDO)
203     {
204         return HDA_FdoPnp(DeviceObject, Irp);
205     }
206     else
207     {
208         return HDA_PdoPnp(DeviceObject, Irp);
209     }
210 }
211 
212 NTSTATUS
213 NTAPI
214 HDA_SystemControl(
215     _In_ PDEVICE_OBJECT DeviceObject,
216     _Inout_ PIRP Irp)
217 {
218     NTSTATUS Status;
219     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
220 
221     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
222 
223     if (FDODeviceExtension->IsFDO)
224     {
225         IoSkipCurrentIrpStackLocation(Irp);
226         return IoCallDriver(FDODeviceExtension->LowerDevice, Irp);
227     }
228     else
229     {
230         Status = Irp->IoStatus.Status;
231         IoCompleteRequest(Irp, IO_NO_INCREMENT);
232         return Status;
233     }
234 }
235 
236 NTSTATUS
237 NTAPI
238 HDA_Power(
239     _In_ PDEVICE_OBJECT DeviceObject,
240     _Inout_ PIRP Irp)
241 {
242     NTSTATUS Status;
243     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
244 
245     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
246 
247     if (FDODeviceExtension->IsFDO)
248     {
249         PoStartNextPowerIrp(Irp);
250         IoSkipCurrentIrpStackLocation(Irp);
251         return PoCallDriver(FDODeviceExtension->LowerDevice, Irp);
252     }
253     else
254     {
255         Status = Irp->IoStatus.Status;
256         PoStartNextPowerIrp(Irp);
257         IoCompleteRequest(Irp, IO_NO_INCREMENT);
258         return Status;
259     }
260 }
261 
262 NTSTATUS
263 NTAPI
264 HDA_AddDevice(
265     _In_ PDRIVER_OBJECT DriverObject,
266     _In_ PDEVICE_OBJECT PhysicalDeviceObject)
267 {
268     PDEVICE_OBJECT DeviceObject;
269     PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
270     NTSTATUS Status;
271 
272     /* create device object */
273     Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
274     if (!NT_SUCCESS(Status))
275     {
276         /* failed */
277         return Status;
278     }
279 
280     /* get device extension*/
281     DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
282 
283     /* init device extension*/
284     DeviceExtension->IsFDO = TRUE;
285     DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
286     IoInitializeDpcRequest(DeviceObject, HDA_DpcForIsr);
287     RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1));
288 
289     /* set device flags */
290     DeviceObject->Flags |= DO_POWER_PAGABLE;
291 
292     return Status;
293 }
294 
295 VOID
296 NTAPI
297 HDA_Unload(
298     _In_ PDRIVER_OBJECT DriverObject)
299 {
300 }
301 
302 extern "C"
303 {
304 
305 NTSTATUS
306 NTAPI
307 DriverEntry(
308     _In_ PDRIVER_OBJECT DriverObject,
309     _In_ PUNICODE_STRING RegistryPathName)
310 {
311     DriverObject->DriverUnload = HDA_Unload;
312     DriverObject->DriverExtension->AddDevice = HDA_AddDevice;
313     DriverObject->MajorFunction[IRP_MJ_POWER] = HDA_Power;
314     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HDA_SystemControl;
315     DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp;
316 
317     return STATUS_SUCCESS;
318 }
319 
320 } // extern "C"
321