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