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(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation);
135             ASSERT(Irp->IoStatus.Information == 0);
136 
137             /* allocate device relation */
138             DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
139             if (DeviceRelation)
140             {
141                 DeviceRelation->Count = 1;
142                 DeviceRelation->Objects[0] = DeviceObject;
143 
144                 /* reference self */
145                 ObReferenceObject(DeviceObject);
146 
147                 /* store result */
148                 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
149 
150                 /* done */
151                 Status = STATUS_SUCCESS;
152             }
153             else
154             {
155                 /* no memory */
156                 Status = STATUS_INSUFFICIENT_RESOURCES;
157             }
158         }
159         break;
160     case IRP_MN_QUERY_CAPABILITIES:
161         /* query capabilities */
162         Status = HDA_PDOQueryBusDeviceCapabilities(Irp);
163         break;
164     case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
165         /* no op */
166         Status = STATUS_SUCCESS;
167         break;
168     case IRP_MN_QUERY_RESOURCES:
169         /* no op */
170         Status = STATUS_SUCCESS;
171         break;
172     case IRP_MN_QUERY_ID:
173         Status = HDA_PDOQueryId(DeviceObject, Irp);
174         break;
175     case IRP_MN_QUERY_DEVICE_TEXT:
176         Status = HDA_PDOHandleQueryDeviceText(Irp);
177         break;
178     case IRP_MN_QUERY_INTERFACE:
179         Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp);
180         break;
181     default:
182         /* get default status */
183         Status = Irp->IoStatus.Status;
184         break;
185     }
186 
187     Irp->IoStatus.Status = Status;
188     IoCompleteRequest(Irp, IO_NO_INCREMENT);
189 
190     return Status;
191 }
192 
193 NTSTATUS
194 NTAPI
195 HDA_Pnp(
196     _In_ PDEVICE_OBJECT DeviceObject,
197     _Inout_ PIRP Irp)
198 {
199     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
200 
201     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
202 
203     if (FDODeviceExtension->IsFDO)
204     {
205         return HDA_FdoPnp(DeviceObject, Irp);
206     }
207     else
208     {
209         return HDA_PdoPnp(DeviceObject, Irp);
210     }
211 }
212 
213 NTSTATUS
214 NTAPI
215 HDA_SystemControl(
216     _In_ PDEVICE_OBJECT DeviceObject,
217     _Inout_ PIRP Irp)
218 {
219     NTSTATUS Status;
220     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
221 
222     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
223 
224     if (FDODeviceExtension->IsFDO)
225     {
226         IoSkipCurrentIrpStackLocation(Irp);
227         return IoCallDriver(FDODeviceExtension->LowerDevice, Irp);
228     }
229     else
230     {
231         Status = Irp->IoStatus.Status;
232         IoCompleteRequest(Irp, IO_NO_INCREMENT);
233         return Status;
234     }
235 }
236 
237 NTSTATUS
238 NTAPI
239 HDA_Power(
240     _In_ PDEVICE_OBJECT DeviceObject,
241     _Inout_ PIRP Irp)
242 {
243     NTSTATUS Status;
244     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
245 
246     FDODeviceExtension = static_cast<PHDA_FDO_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
247 
248     if (FDODeviceExtension->IsFDO)
249     {
250         PoStartNextPowerIrp(Irp);
251         IoSkipCurrentIrpStackLocation(Irp);
252         return PoCallDriver(FDODeviceExtension->LowerDevice, Irp);
253     }
254     else
255     {
256         Status = Irp->IoStatus.Status;
257         PoStartNextPowerIrp(Irp);
258         IoCompleteRequest(Irp, IO_NO_INCREMENT);
259         return Status;
260     }
261 }
262 
263 NTSTATUS
264 NTAPI
265 HDA_AddDevice(
266     _In_ PDRIVER_OBJECT DriverObject,
267     _In_ PDEVICE_OBJECT PhysicalDeviceObject)
268 {
269     PDEVICE_OBJECT DeviceObject;
270     PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
271     NTSTATUS Status;
272 
273     /* create device object */
274     Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
275     if (!NT_SUCCESS(Status))
276     {
277         /* failed */
278         return Status;
279     }
280 
281     /* get device extension*/
282     DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
283 
284     /* init device extension*/
285     DeviceExtension->IsFDO = TRUE;
286     DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
287     IoInitializeDpcRequest(DeviceObject, HDA_DpcForIsr);
288     RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1));
289 
290     /* set device flags */
291     DeviceObject->Flags |= DO_POWER_PAGABLE;
292 
293     return Status;
294 }
295 
296 VOID
297 NTAPI
298 HDA_Unload(
299     _In_ PDRIVER_OBJECT DriverObject)
300 {
301 }
302 
303 extern "C"
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 }
321