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 
11 PVOID
12 AllocateItem(
13     IN POOL_TYPE PoolType,
14     IN SIZE_T NumberOfBytes)
15 {
16     PVOID Item = ExAllocatePoolWithTag(PoolType, NumberOfBytes, TAG_HDA);
17     if (!Item)
18         return Item;
19 
20     RtlZeroMemory(Item, NumberOfBytes);
21     return Item;
22 }
23 
24 VOID
25 FreeItem(
26     IN PVOID Item)
27 {
28     ExFreePool(Item);
29 }
30 
31 NTSTATUS
32 NTAPI
33 HDA_SyncForwardIrpCompletionRoutine(
34     IN PDEVICE_OBJECT DeviceObject,
35     IN PIRP Irp,
36     IN PVOID Context)
37 {
38     if (Irp->PendingReturned)
39     {
40         KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
41     }
42     return STATUS_MORE_PROCESSING_REQUIRED;
43 }
44 
45 NTSTATUS
46 NTAPI
47 HDA_SyncForwardIrp(
48     IN PDEVICE_OBJECT DeviceObject,
49     IN PIRP Irp)
50 {
51     KEVENT Event;
52     NTSTATUS Status;
53 
54     /* Initialize event */
55     KeInitializeEvent(&Event, NotificationEvent, FALSE);
56 
57     /* Copy irp stack location */
58     IoCopyCurrentIrpStackLocationToNext(Irp);
59 
60     /* Set completion routine */
61     IoSetCompletionRoutine(Irp,
62         HDA_SyncForwardIrpCompletionRoutine,
63         &Event,
64         TRUE,
65         TRUE,
66         TRUE);
67 
68     /* Call driver */
69     Status = IoCallDriver(DeviceObject, Irp);
70 
71     /* Check if pending */
72     if (Status == STATUS_PENDING)
73     {
74         /* Wait for the request to finish */
75         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
76 
77         /* Copy status code */
78         Status = Irp->IoStatus.Status;
79     }
80 
81     /* Done */
82     return Status;
83 }
84 
85 NTSTATUS
86 NTAPI
87 HDA_Pnp(
88     IN PDEVICE_OBJECT DeviceObject,
89     IN PIRP Irp)
90 {
91     NTSTATUS Status = STATUS_NOT_SUPPORTED;
92     PIO_STACK_LOCATION IoStack;
93     PDEVICE_RELATIONS DeviceRelation;
94     PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
95     //PHDA_PDO_DEVICE_EXTENSION ChildDeviceExtension;
96 
97     FDODeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
98     //ChildDeviceExtension = (PHDA_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
99 
100     IoStack = IoGetCurrentIrpStackLocation(Irp);
101     if (FDODeviceExtension->IsFDO)
102     {
103         if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
104         {
105             Status = HDA_FDOStartDevice(DeviceObject, Irp);
106         }
107         else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
108         {
109             /* handle bus device relations */
110             if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
111             {
112                 Status = HDA_FDOQueryBusRelations(DeviceObject, Irp);
113             }
114             else
115             {
116                 Status = Irp->IoStatus.Status;
117             }
118         }
119         else
120         {
121             /* get default status */
122             Status = Irp->IoStatus.Status;
123         }
124     }
125     else
126     {
127         if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
128         {
129             /* no op for pdo */
130             Status = STATUS_SUCCESS;
131         }
132         else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION)
133         {
134             /* query bus information */
135             Status = HDA_PDOQueryBusInformation(Irp);
136         }
137         else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
138         {
139             /* query pnp state */
140             Status = HDA_PDOQueryBusDevicePnpState(Irp);
141         }
142         else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
143         {
144             if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
145             {
146                 /* handle target device relations */
147                 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation);
148                 ASSERT(Irp->IoStatus.Information == 0);
149 
150                 /* allocate device relation */
151                 DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
152                 if (DeviceRelation)
153                 {
154                     DeviceRelation->Count = 1;
155                     DeviceRelation->Objects[0] = DeviceObject;
156 
157                     /* reference self */
158                     ObReferenceObject(DeviceObject);
159 
160                     /* store result */
161                     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
162 
163                     /* done */
164                     Status = STATUS_SUCCESS;
165                 }
166                 else
167                 {
168                     /* no memory */
169                     Status = STATUS_INSUFFICIENT_RESOURCES;
170                 }
171             }
172         }
173         else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES)
174         {
175             /* query capabilities */
176             Status = HDA_PDOQueryBusDeviceCapabilities(Irp);
177         }
178         else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
179         {
180             /* no op */
181             Status = STATUS_SUCCESS;
182         }
183         else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES)
184         {
185             /* no op */
186             Status = STATUS_SUCCESS;
187         }
188         else if (IoStack->MinorFunction == IRP_MN_QUERY_ID)
189         {
190             Status = HDA_PDOQueryId(DeviceObject, Irp);
191         }
192         else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_TEXT)
193         {
194             Status = HDA_PDOHandleQueryDeviceText(Irp);
195         }
196         else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE)
197         {
198             Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp);
199         }
200         else
201         {
202             /* get default status */
203             Status = Irp->IoStatus.Status;
204         }
205     }
206 
207     Irp->IoStatus.Status = Status;
208     IoCompleteRequest(Irp, IO_NO_INCREMENT);
209 
210 
211     return Status;
212 }
213 
214 
215 //PDRIVER_ADD_DEVICE HDA_AddDevice;
216 
217 NTSTATUS
218 NTAPI
219 HDA_AddDevice(
220 IN PDRIVER_OBJECT DriverObject,
221 IN PDEVICE_OBJECT PhysicalDeviceObject)
222 {
223     PDEVICE_OBJECT DeviceObject;
224     PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
225     NTSTATUS Status;
226 
227     /* create device object */
228     Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
229     if (!NT_SUCCESS(Status))
230     {
231         /* failed */
232         return Status;
233     }
234 
235     /* get device extension*/
236     DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
237 
238     /* init device extension*/
239     DeviceExtension->IsFDO = TRUE;
240     DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
241     RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1));
242 
243     /* set device flags */
244     DeviceObject->Flags |= DO_POWER_PAGABLE;
245 
246     return Status;
247 }
248 extern "C"
249 {
250 NTSTATUS
251 NTAPI
252 DriverEntry(
253     IN PDRIVER_OBJECT DriverObject,
254     IN PUNICODE_STRING RegistryPathName)
255 {
256     DriverObject->DriverExtension->AddDevice = HDA_AddDevice;
257     DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp;
258 
259     return STATUS_SUCCESS;
260 }
261 
262 }