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