xref: /reactos/sdk/lib/drivers/arbiter/arbiter.c (revision fec440d8)
1 /*
2  * PROJECT:     ReactOS Kernel&Driver SDK
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Hardware Resources Arbiter Library
5  * COPYRIGHT:   Copyright 2020 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 /* INCLUDES *******************************************************************/
9 
10 #include <ntifs.h>
11 #include <ndk/rtlfuncs.h>
12 #include "arbiter.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
19 /* DATA **********************************************************************/
20 
21 /* FUNCTIONS ******************************************************************/
22 
23 CODE_SEG("PAGE")
24 NTSTATUS
25 NTAPI
ArbTestAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)26 ArbTestAllocation(
27     _In_ PARBITER_INSTANCE Arbiter,
28     _In_ PLIST_ENTRY ArbitrationList)
29 {
30     PAGED_CODE();
31 
32     UNIMPLEMENTED;
33     return STATUS_NOT_IMPLEMENTED;
34 }
35 
36 CODE_SEG("PAGE")
37 NTSTATUS
38 NTAPI
ArbRetestAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)39 ArbRetestAllocation(
40     _In_ PARBITER_INSTANCE Arbiter,
41     _In_ PLIST_ENTRY ArbitrationList)
42 {
43     PAGED_CODE();
44 
45     UNIMPLEMENTED;
46     return STATUS_NOT_IMPLEMENTED;
47 }
48 
49 CODE_SEG("PAGE")
50 NTSTATUS
51 NTAPI
ArbCommitAllocation(_In_ PARBITER_INSTANCE Arbiter)52 ArbCommitAllocation(
53     _In_ PARBITER_INSTANCE Arbiter)
54 {
55     PAGED_CODE();
56 
57     UNIMPLEMENTED;
58     return STATUS_NOT_IMPLEMENTED;
59 }
60 
61 CODE_SEG("PAGE")
62 NTSTATUS
63 NTAPI
ArbRollbackAllocation(_In_ PARBITER_INSTANCE Arbiter)64 ArbRollbackAllocation(
65     _In_ PARBITER_INSTANCE Arbiter)
66 {
67     PAGED_CODE();
68 
69     UNIMPLEMENTED;
70     return STATUS_NOT_IMPLEMENTED;
71 }
72 
73 /* FIXME: the prototype is not correct yet. */
74 CODE_SEG("PAGE")
75 NTSTATUS
76 NTAPI
ArbAddReserved(_In_ PARBITER_INSTANCE Arbiter)77 ArbAddReserved(
78     _In_ PARBITER_INSTANCE Arbiter)
79 {
80     PAGED_CODE();
81 
82     UNIMPLEMENTED;
83     return STATUS_NOT_IMPLEMENTED;
84 }
85 
86 CODE_SEG("PAGE")
87 NTSTATUS
88 NTAPI
ArbPreprocessEntry(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)89 ArbPreprocessEntry(
90     _In_ PARBITER_INSTANCE Arbiter,
91     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
92 {
93     PAGED_CODE();
94 
95     return STATUS_SUCCESS;
96 }
97 
98 CODE_SEG("PAGE")
99 NTSTATUS
100 NTAPI
ArbAllocateEntry(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)101 ArbAllocateEntry(
102     _In_ PARBITER_INSTANCE Arbiter,
103     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
104 {
105     PAGED_CODE();
106 
107     UNIMPLEMENTED;
108     return STATUS_NOT_IMPLEMENTED;
109 }
110 
111 CODE_SEG("PAGE")
112 BOOLEAN
113 NTAPI
ArbGetNextAllocationRange(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)114 ArbGetNextAllocationRange(
115     _In_ PARBITER_INSTANCE Arbiter,
116     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
117 {
118     PAGED_CODE();
119 
120     UNIMPLEMENTED;
121     return FALSE;
122 }
123 
124 CODE_SEG("PAGE")
125 BOOLEAN
126 NTAPI
ArbFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)127 ArbFindSuitableRange(
128     _In_ PARBITER_INSTANCE Arbiter,
129     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
130 {
131     PAGED_CODE();
132 
133     UNIMPLEMENTED;
134     return FALSE;
135 }
136 
137 CODE_SEG("PAGE")
138 VOID
139 NTAPI
ArbAddAllocation(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)140 ArbAddAllocation(
141     _In_ PARBITER_INSTANCE Arbiter,
142     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
143 {
144     PAGED_CODE();
145 
146     UNIMPLEMENTED;
147 }
148 
149 CODE_SEG("PAGE")
150 VOID
151 NTAPI
ArbBacktrackAllocation(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)152 ArbBacktrackAllocation(
153     _In_ PARBITER_INSTANCE Arbiter,
154     _Inout_ PARBITER_ALLOCATION_STATE ArbState)
155 {
156     PAGED_CODE();
157 
158     UNIMPLEMENTED;
159 }
160 
161 /* FIXME: the prototype is not correct yet. */
162 CODE_SEG("PAGE")
163 NTSTATUS
164 NTAPI
ArbOverrideConflict(_In_ PARBITER_INSTANCE Arbiter)165 ArbOverrideConflict(
166     _In_ PARBITER_INSTANCE Arbiter)
167 {
168     PAGED_CODE();
169 
170     UNIMPLEMENTED;
171     return STATUS_NOT_IMPLEMENTED;
172 }
173 
174 CODE_SEG("PAGE")
175 NTSTATUS
176 NTAPI
ArbBootAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)177 ArbBootAllocation(
178     _In_ PARBITER_INSTANCE Arbiter,
179     _In_ PLIST_ENTRY ArbitrationList)
180 {
181     PAGED_CODE();
182 
183     UNIMPLEMENTED;
184     return STATUS_NOT_IMPLEMENTED;
185 }
186 
187 /* FIXME: the prototype is not correct yet. */
188 CODE_SEG("PAGE")
189 NTSTATUS
190 NTAPI
ArbQueryConflict(_In_ PARBITER_INSTANCE Arbiter)191 ArbQueryConflict(
192     _In_ PARBITER_INSTANCE Arbiter)
193 {
194     PAGED_CODE();
195 
196     UNIMPLEMENTED;
197     return STATUS_NOT_IMPLEMENTED;
198 }
199 
200 /* FIXME: the prototype is not correct yet. */
201 CODE_SEG("PAGE")
202 NTSTATUS
203 NTAPI
ArbStartArbiter(_In_ PARBITER_INSTANCE Arbiter)204 ArbStartArbiter(
205     _In_ PARBITER_INSTANCE Arbiter)
206 {
207     PAGED_CODE();
208 
209     UNIMPLEMENTED;
210     return STATUS_NOT_IMPLEMENTED;
211 }
212 
213 CODE_SEG("PAGE")
214 NTSTATUS
215 NTAPI
ArbAddOrdering(_Out_ PARBITER_ORDERING_LIST OrderList,_In_ UINT64 MinimumAddress,_In_ UINT64 MaximumAddress)216 ArbAddOrdering(
217     _Out_ PARBITER_ORDERING_LIST OrderList,
218     _In_ UINT64 MinimumAddress,
219     _In_ UINT64 MaximumAddress)
220 {
221     PAGED_CODE();
222 
223     UNIMPLEMENTED;
224     return STATUS_NOT_IMPLEMENTED;
225 }
226 
227 CODE_SEG("PAGE")
228 NTSTATUS
229 NTAPI
ArbPruneOrdering(_Out_ PARBITER_ORDERING_LIST OrderingList,_In_ UINT64 MinimumAddress,_In_ UINT64 MaximumAddress)230 ArbPruneOrdering(
231     _Out_ PARBITER_ORDERING_LIST OrderingList,
232     _In_ UINT64 MinimumAddress,
233     _In_ UINT64 MaximumAddress)
234 {
235     PAGED_CODE();
236 
237     UNIMPLEMENTED;
238     return STATUS_NOT_IMPLEMENTED;
239 }
240 
241 CODE_SEG("PAGE")
242 NTSTATUS
243 NTAPI
ArbInitializeOrderingList(_Out_ PARBITER_ORDERING_LIST OrderList)244 ArbInitializeOrderingList(
245     _Out_ PARBITER_ORDERING_LIST OrderList)
246 {
247     PAGED_CODE();
248 
249     UNIMPLEMENTED;
250     return STATUS_NOT_IMPLEMENTED;
251 }
252 
253 CODE_SEG("PAGE")
254 VOID
255 NTAPI
ArbFreeOrderingList(_Out_ PARBITER_ORDERING_LIST OrderList)256 ArbFreeOrderingList(
257     _Out_ PARBITER_ORDERING_LIST OrderList)
258 {
259     PAGED_CODE();
260 
261     UNIMPLEMENTED;
262 }
263 
264 CODE_SEG("PAGE")
265 NTSTATUS
266 NTAPI
ArbBuildAssignmentOrdering(_Inout_ PARBITER_INSTANCE ArbInstance,_In_ PCWSTR OrderName,_In_ PCWSTR ReservedOrderName,_In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)267 ArbBuildAssignmentOrdering(
268     _Inout_ PARBITER_INSTANCE ArbInstance,
269     _In_ PCWSTR OrderName,
270     _In_ PCWSTR ReservedOrderName,
271     _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
272 {
273     PAGED_CODE();
274 
275     UNIMPLEMENTED;
276     return STATUS_SUCCESS;
277 }
278 
279 CODE_SEG("PAGE")
280 NTSTATUS
281 NTAPI
ArbInitializeArbiterInstance(_Inout_ PARBITER_INSTANCE Arbiter,_In_ PDEVICE_OBJECT BusDeviceObject,_In_ CM_RESOURCE_TYPE ResourceType,_In_ PCWSTR ArbiterName,_In_ PCWSTR OrderName,_In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)282 ArbInitializeArbiterInstance(
283     _Inout_ PARBITER_INSTANCE Arbiter,
284     _In_ PDEVICE_OBJECT BusDeviceObject,
285     _In_ CM_RESOURCE_TYPE ResourceType,
286     _In_ PCWSTR ArbiterName,
287     _In_ PCWSTR OrderName,
288     _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
289 {
290     NTSTATUS Status;
291 
292     PAGED_CODE();
293 
294     DPRINT("ArbInitializeArbiterInstance: '%S'\n", ArbiterName);
295 
296     ASSERT(Arbiter->UnpackRequirement != NULL);
297     ASSERT(Arbiter->PackResource != NULL);
298     ASSERT(Arbiter->UnpackResource != NULL);
299     ASSERT(Arbiter->MutexEvent == NULL);
300     ASSERT(Arbiter->Allocation == NULL);
301     ASSERT(Arbiter->PossibleAllocation == NULL);
302     ASSERT(Arbiter->AllocationStack == NULL);
303 
304     Arbiter->Signature = ARBITER_SIGNATURE;
305     Arbiter->BusDeviceObject = BusDeviceObject;
306 
307     Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
308     if (!Arbiter->MutexEvent)
309     {
310         DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
311         return STATUS_INSUFFICIENT_RESOURCES;
312     }
313 
314     KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);
315 
316     Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARB_ALLOCATION);
317     if (!Arbiter->AllocationStack)
318     {
319         DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
320         ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
321         return STATUS_INSUFFICIENT_RESOURCES;
322     }
323 
324     Arbiter->AllocationStackMaxSize = PAGE_SIZE;
325 
326     Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
327     if (!Arbiter->Allocation)
328     {
329         DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
330         ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
331         ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
332         return STATUS_INSUFFICIENT_RESOURCES;
333     }
334 
335     Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
336     if (!Arbiter->PossibleAllocation)
337     {
338         DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
339         ExFreePoolWithTag(Arbiter->Allocation, TAG_ARB_RANGE);
340         ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
341         ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
342         return STATUS_INSUFFICIENT_RESOURCES;
343     }
344 
345     RtlInitializeRangeList(Arbiter->Allocation);
346     RtlInitializeRangeList(Arbiter->PossibleAllocation);
347 
348     Arbiter->Name = ArbiterName;
349     Arbiter->ResourceType = ResourceType;
350     Arbiter->TransactionInProgress = FALSE;
351 
352     if (!Arbiter->TestAllocation)
353         Arbiter->TestAllocation = ArbTestAllocation;
354 
355     if (!Arbiter->RetestAllocation)
356         Arbiter->RetestAllocation = ArbRetestAllocation;
357 
358     if (!Arbiter->CommitAllocation)
359         Arbiter->CommitAllocation = ArbCommitAllocation;
360 
361     if (!Arbiter->RollbackAllocation)
362         Arbiter->RollbackAllocation = ArbRollbackAllocation;
363 
364     if (!Arbiter->AddReserved)
365         Arbiter->AddReserved = ArbAddReserved;
366 
367     if (!Arbiter->PreprocessEntry)
368         Arbiter->PreprocessEntry = ArbPreprocessEntry;
369 
370     if (!Arbiter->AllocateEntry)
371         Arbiter->AllocateEntry = ArbAllocateEntry;
372 
373     if (!Arbiter->GetNextAllocationRange)
374         Arbiter->GetNextAllocationRange = ArbGetNextAllocationRange;
375 
376     if (!Arbiter->FindSuitableRange)
377         Arbiter->FindSuitableRange = ArbFindSuitableRange;
378 
379     if (!Arbiter->AddAllocation)
380         Arbiter->AddAllocation = ArbAddAllocation;
381 
382     if (!Arbiter->BacktrackAllocation)
383         Arbiter->BacktrackAllocation = ArbBacktrackAllocation;
384 
385     if (!Arbiter->OverrideConflict)
386         Arbiter->OverrideConflict = ArbOverrideConflict;
387 
388     if (!Arbiter->BootAllocation)
389         Arbiter->BootAllocation = ArbBootAllocation;
390 
391     if (!Arbiter->QueryConflict)
392         Arbiter->QueryConflict = ArbQueryConflict;
393 
394     if (!Arbiter->StartArbiter)
395         Arbiter->StartArbiter = ArbStartArbiter;
396 
397     Status = ArbBuildAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
398     if (NT_SUCCESS(Status))
399     {
400         return STATUS_SUCCESS;
401     }
402 
403     DPRINT1("ArbInitializeArbiterInstance: Status %X\n", Status);
404 
405     return Status;
406 }
407