1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/wdm/audio/backpln/portcls/api.cpp
5  * PURPOSE:         Port api functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "private.hpp"
10 
11 #ifndef YDEBUG
12 #define NDEBUG
13 #endif
14 
15 #include <debug.h>
16 
17 NTSTATUS
18 NTAPI
19 PcGetDeviceProperty(
20     IN  PVOID DeviceObject,
21     IN  DEVICE_REGISTRY_PROPERTY DeviceProperty,
22     IN  ULONG BufferLength,
23     OUT PVOID PropertyBuffer,
24     OUT PULONG ResultLength)
25 {
26     PPCLASS_DEVICE_EXTENSION DeviceExtension;
27 
28     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
29 
30     DeviceExtension = (PPCLASS_DEVICE_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
31 
32     return IoGetDeviceProperty(DeviceExtension->PhysicalDeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength);
33 }
34 
35 ULONGLONG
36 NTAPI
37 PcGetTimeInterval(
38     IN  ULONGLONG Since)
39 {
40     LARGE_INTEGER CurrentTime;
41 
42     KeQuerySystemTime(&CurrentTime);
43 
44     return (CurrentTime.QuadPart - Since);
45 }
46 
47 VOID
48 NTAPI
49 PcIoTimerRoutine(
50     IN PDEVICE_OBJECT  DeviceObject,
51     IN PVOID  Context)
52 {
53     PPCLASS_DEVICE_EXTENSION DeviceExtension;
54     KIRQL OldIrql;
55     PLIST_ENTRY ListEntry;
56     PTIMER_CONTEXT CurContext;
57 
58     if (!DeviceObject || !DeviceObject->DeviceExtension)
59         return;
60 
61     DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
62 
63     KeAcquireSpinLock(&DeviceExtension->TimerListLock, &OldIrql);
64 
65     ListEntry = DeviceExtension->TimerList.Flink;
66     while(ListEntry != &DeviceExtension->TimerList)
67     {
68         CurContext = (PTIMER_CONTEXT)CONTAINING_RECORD(ListEntry, TIMER_CONTEXT, Entry);
69 
70         CurContext->pTimerRoutine(DeviceObject, CurContext->Context);
71         ListEntry = ListEntry->Flink;
72     }
73 
74     KeReleaseSpinLock(&DeviceExtension->TimerListLock, OldIrql);
75 }
76 
77 NTSTATUS
78 NTAPI
79 PcRegisterIoTimeout(
80     IN  PDEVICE_OBJECT pDeviceObject,
81     IN  PIO_TIMER_ROUTINE pTimerRoutine,
82     IN  PVOID pContext)
83 {
84     NTSTATUS Status = STATUS_SUCCESS;
85     PTIMER_CONTEXT TimerContext, CurContext;
86     KIRQL OldIrql;
87     PLIST_ENTRY ListEntry;
88     BOOLEAN bFound;
89     PPCLASS_DEVICE_EXTENSION DeviceExtension;
90 
91     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
92 
93     if (!pDeviceObject || !pDeviceObject->DeviceExtension)
94         return STATUS_INVALID_PARAMETER;
95 
96     DeviceExtension = (PPCLASS_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;
97 
98     TimerContext = (PTIMER_CONTEXT)AllocateItem(NonPagedPool, sizeof(TIMER_CONTEXT), TAG_PORTCLASS);
99     if (!TimerContext)
100     {
101         DPRINT("Failed to allocate memory\n");
102         return STATUS_INSUFFICIENT_RESOURCES;
103     }
104 
105     KeAcquireSpinLock(&DeviceExtension->TimerListLock, &OldIrql);
106 
107     ListEntry = DeviceExtension->TimerList.Flink;
108     bFound = FALSE;
109     while(ListEntry != &DeviceExtension->TimerList)
110     {
111         CurContext = (PTIMER_CONTEXT)CONTAINING_RECORD(ListEntry, TIMER_CONTEXT, Entry);
112 
113         if (CurContext->Context == pContext && CurContext->pTimerRoutine == pTimerRoutine)
114         {
115             bFound = TRUE;
116             Status = STATUS_UNSUCCESSFUL;
117             FreeItem(TimerContext, TAG_PORTCLASS);
118             break;
119         }
120         ListEntry = ListEntry->Flink;
121     }
122 
123     if (!bFound)
124     {
125         TimerContext->Context = pContext;
126         TimerContext->pTimerRoutine = pTimerRoutine;
127         InsertTailList(&DeviceExtension->TimerList, &TimerContext->Entry);
128     }
129 
130     KeReleaseSpinLock(&DeviceExtension->TimerListLock, OldIrql);
131 
132     return Status;
133 }
134 
135 NTSTATUS
136 NTAPI
137 PcUnregisterIoTimeout(
138     IN  PDEVICE_OBJECT pDeviceObject,
139     IN  PIO_TIMER_ROUTINE pTimerRoutine,
140     IN  PVOID pContext)
141 {
142     PTIMER_CONTEXT CurContext;
143     KIRQL OldIrql;
144     PLIST_ENTRY ListEntry;
145     BOOLEAN bFound;
146     PPCLASS_DEVICE_EXTENSION DeviceExtension;
147 
148     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
149 
150     if (!pDeviceObject || !pDeviceObject->DeviceExtension)
151         return STATUS_INVALID_PARAMETER;
152 
153 
154     DeviceExtension = (PPCLASS_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;
155 
156 
157     KeAcquireSpinLock(&DeviceExtension->TimerListLock, &OldIrql);
158 
159     ListEntry = DeviceExtension->TimerList.Flink;
160     bFound = FALSE;
161 
162     while(ListEntry != &DeviceExtension->TimerList)
163     {
164         CurContext = (PTIMER_CONTEXT)CONTAINING_RECORD(ListEntry, TIMER_CONTEXT, Entry);
165 
166         if (CurContext->Context == pContext && CurContext->pTimerRoutine == pTimerRoutine)
167         {
168             bFound = TRUE;
169             RemoveEntryList(&CurContext->Entry);
170             FreeItem(CurContext, TAG_PORTCLASS);
171             break;
172         }
173         ListEntry = ListEntry->Flink;
174     }
175 
176     KeReleaseSpinLock(&DeviceExtension->TimerListLock, OldIrql);
177 
178     if (bFound)
179         return STATUS_SUCCESS;
180     else
181         return STATUS_NOT_FOUND;
182 }
183 
184 
185 
186 NTSTATUS
187 NTAPI
188 PcCompletePendingPropertyRequest(
189     IN  PPCPROPERTY_REQUEST PropertyRequest,
190     IN  NTSTATUS NtStatus)
191 {
192     // sanity checks
193     PC_ASSERT_IRQL(DISPATCH_LEVEL);
194 
195     if (!PropertyRequest || !PropertyRequest->Irp || NtStatus == STATUS_PENDING)
196         return STATUS_INVALID_PARAMETER;
197 
198     // set the final status code
199     PropertyRequest->Irp->IoStatus.Status = NtStatus;
200 
201     // complete the irp
202     IoCompleteRequest(PropertyRequest->Irp, IO_SOUND_INCREMENT);
203 
204     // free the property request
205     FreeItem(PropertyRequest, TAG_PORTCLASS);
206 
207     // return success
208     return STATUS_SUCCESS;
209 }
210 
211 NTSTATUS
212 NTAPI
213 PcDmaMasterDescription(
214     IN PRESOURCELIST ResourceList OPTIONAL,
215     IN BOOLEAN ScatterGather,
216     IN BOOLEAN Dma32BitAddresses,
217     IN BOOLEAN IgnoreCount,
218     IN BOOLEAN Dma64BitAddresses,
219     IN DMA_WIDTH DmaWidth,
220     IN DMA_SPEED DmaSpeed,
221     IN ULONG MaximumLength,
222     IN ULONG DmaPort,
223     OUT PDEVICE_DESCRIPTION DeviceDescription)
224 {
225 
226     RtlZeroMemory(DeviceDescription, sizeof(DEVICE_DESCRIPTION));
227 
228     DeviceDescription->Master = TRUE;
229     DeviceDescription->Version = DEVICE_DESCRIPTION_VERSION1;
230     DeviceDescription->ScatterGather= ScatterGather;
231     DeviceDescription->Dma32BitAddresses = Dma32BitAddresses;
232     DeviceDescription->IgnoreCount = IgnoreCount;
233     DeviceDescription->Dma64BitAddresses = Dma64BitAddresses;
234     DeviceDescription->DmaWidth = DmaWidth;
235     DeviceDescription->DmaSpeed = DmaSpeed;
236     DeviceDescription->MaximumLength = MaximumLength;
237     DeviceDescription->DmaPort = DmaPort;
238 
239     return STATUS_SUCCESS;
240 }
241 
242 NTSTATUS
243 NTAPI
244 PcDmaSlaveDescription(
245     IN PRESOURCELIST  ResourceList OPTIONAL,
246     IN ULONG DmaIndex,
247     IN BOOLEAN DemandMode,
248     IN BOOLEAN AutoInitialize,
249     IN DMA_SPEED DmaSpeed,
250     IN ULONG MaximumLength,
251     IN ULONG DmaPort,
252     OUT PDEVICE_DESCRIPTION DeviceDescription)
253 {
254 
255     RtlZeroMemory(DeviceDescription, sizeof(DEVICE_DESCRIPTION));
256 
257     DeviceDescription->Version = DEVICE_DESCRIPTION_VERSION1;
258     DeviceDescription->DemandMode = DemandMode;
259     DeviceDescription->AutoInitialize = AutoInitialize;
260     DeviceDescription->DmaSpeed = DmaSpeed;
261     DeviceDescription->MaximumLength = MaximumLength;
262     DeviceDescription->DmaPort = DmaPort;
263 
264     return STATUS_SUCCESS;
265 }
266 
267