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