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