ReactOS 0.4.17-dev-806-gffa4164
handler.c File Reference
#include <ntifs.h>
#include <ndk/rtlfuncs.h>
#include "arbiter.h"
#include <debug.h>
Include dependency graph for handler.c:

Go to the source code of this file.

Classes

struct  _ARBITER_SEED_WINDOW
 Seeds a range list with the resources the bus actually decodes: every descriptor of the arbiter's resource type becomes one unowned range. More...
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _ARBITER_SEED_WINDOW ARBITER_SEED_WINDOW
 Seeds a range list with the resources the bus actually decodes: every descriptor of the arbiter's resource type becomes one unowned range.
 
typedef struct _ARBITER_SEED_WINDOWPARBITER_SEED_WINDOW
 

Functions

static VOID ArbpAcquireLock (_In_ PARBITER_INSTANCE Arbiter)
 Acquires the arbiter's per-instance lock: one arbitration at a time.
 
static VOID ArbpReleaseLock (_In_ PARBITER_INSTANCE Arbiter)
 Releases the arbiter's per-instance lock.
 
NTSTATUS NTAPI ArbiterLibQueryArbitrate (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_QUERY_ARBITRATE_PARAMETERS Parameters)
 The QueryArbitrate action default: reports that this arbiter is willing to arbitrate the given list.
 
NTSTATUS NTAPI ArbiterLibAddReserved (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ADD_RESERVED_PARAMETERS Parameters)
 The AddReserved action default: nothing to reserve.
 
NTSTATUS NTAPI ArbiterLibHandler (_In_ PVOID Context, _In_ ARBITER_ACTION Action, _Inout_ PARBITER_PARAMETERS Parameters)
 The single ARBITER_ACTION dispatcher every exported ARBITER_INTERFACE points its ArbiterHandler at; Context is the ARBITER_INSTANCE.
 
static NTSTATUS ArbpSeedRangeList (_In_ PARBITER_INSTANCE Arbiter, _In_ ULONG ResourceCount, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resources, _Inout_ PRTL_RANGE_LIST RangeList)
 
NTSTATUS NTAPI ArbiterLibInitializeRangeList (_In_ PARBITER_INSTANCE Arbiter, _In_ ULONG ResourceCount, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resources, _Inout_ PRTL_RANGE_LIST RangeList)
 The InitializeRangeList callback default.
 
NTSTATUS NTAPI ArbiterLibStartArbiter (_In_ PARBITER_INSTANCE Arbiter, _In_ PCM_RESOURCE_LIST StartResources)
 The StartArbiter action default: seeds the committed allocation with the windows the bus decodes, so arbitration starts from the hardware's real extent.
 
VOID NTAPI ArbiterLibReserveRange (_In_ PARBITER_INSTANCE Arbiter, _In_ ULONGLONG Start, _In_ ULONGLONG End, _In_opt_ PVOID Owner, _In_ BOOLEAN Shared)
 Commits a single [Start, End] range into the arbiter as an ordinary allocation owned by Owner.
 
VOID NTAPI ArbiterLibReleaseResources (_In_ PARBITER_INSTANCE Arbiter, _In_ PVOID Owner)
 Releases every committed range owned by Owner.
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file handler.c.

Typedef Documentation

◆ ARBITER_SEED_WINDOW

Seeds a range list with the resources the bus actually decodes: every descriptor of the arbiter's resource type becomes one unowned range.

Parameters
[in]ArbiterThe arbiter instance whose UnpackResource decodes the descriptors and whose resource type filters them.
[in]ResourceCountThe number of descriptors in Resources.
[in]ResourcesThe CM partial resource descriptors describing the decoded windows.
[in,out]RangeListThe range list to rebuild from the descriptors. What lands in it is everything outside those windows, because a range list records what is unavailable.
Returns
STATUS_SUCCESS, or STATUS_INSUFFICIENT_RESOURCES.

One window a bus decodes, while the windows are being sorted.

◆ PARBITER_SEED_WINDOW

Function Documentation

◆ ArbiterLibAddReserved()

NTSTATUS NTAPI ArbiterLibAddReserved ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ADD_RESERVED_PARAMETERS  Parameters 
)

The AddReserved action default: nothing to reserve.

Parameters
[in]ArbiterThe arbiter instance the reservation was aimed at.
[in,out]ParametersThe action parameters (pre-Vista builds receive the requirement and resource descriptors directly).
Returns
Returns STATUS_SUCCESS.

Definition at line 112 of file handler.c.

115{
116 PAGED_CODE();
117 UNREFERENCED_PARAMETER(Arbiter);
119 return STATUS_SUCCESS;
120}
#define PAGED_CODE()
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibHandler()

NTSTATUS NTAPI ArbiterLibHandler ( _In_ PVOID  Context,
_In_ ARBITER_ACTION  Action,
_Inout_ PARBITER_PARAMETERS  Parameters 
)

The single ARBITER_ACTION dispatcher every exported ARBITER_INTERFACE points its ArbiterHandler at; Context is the ARBITER_INSTANCE.

Parameters
[in]ContextThe ARBITER_INSTANCE the interface was created for.
[in]ActionThe ARBITER_ACTION to perform.
[in,out]ParametersThe parameters union matching the action.
Returns
Returns the dispatched action's status, STATUS_NOT_IMPLEMENTED for a known but unrouted action, or STATUS_INVALID_PARAMETER for an unrecognized one.
Remarks
The call runs under the instance lock, so a Test and its later Commit or Rollback apply to the same transaction. On Vista+ the transaction event tracks that window: Test and Retest arm it, Commit and Rollback resolve it and wake waiters.

Definition at line 164 of file handler.c.

168{
171
172 PAGED_CODE();
173
174 ArbpAcquireLock(Arbiter);
175
176 switch (Action)
177 {
179#if (NTDDI_VERSION >= NTDDI_VISTA)
180 Status = Arbiter->TestAllocation(Arbiter, &Parameters->Parameters.TestAllocation);
181#else
182 Status = Arbiter->TestAllocation(
183 Arbiter,
184 Parameters->Parameters.TestAllocation.ArbitrationList);
185#endif
186 break;
187
189#if (NTDDI_VERSION >= NTDDI_VISTA)
190 Status = Arbiter->RetestAllocation(Arbiter, &Parameters->Parameters.RetestAllocation);
191#else
192 Status = Arbiter->RetestAllocation(
193 Arbiter,
194 Parameters->Parameters.RetestAllocation.ArbitrationList);
195#endif
196 break;
197
199 Status = Arbiter->CommitAllocation(Arbiter);
200 break;
201
203 Status = Arbiter->RollbackAllocation(Arbiter);
204 break;
205
207#if (NTDDI_VERSION >= NTDDI_VISTA)
208 Status = Arbiter->BootAllocation(Arbiter, &Parameters->Parameters.BootAllocation);
209#else
210 Status = Arbiter->BootAllocation(
211 Arbiter,
212 Parameters->Parameters.BootAllocation.ArbitrationList);
213#endif
214 break;
215
217#if (NTDDI_VERSION >= NTDDI_VISTA)
218 Status = Arbiter->QueryConflict(Arbiter, &Parameters->Parameters.QueryConflict);
219#else
220 Status = Arbiter->QueryConflict(
221 Arbiter,
222 Parameters->Parameters.QueryConflict.PhysicalDeviceObject,
223 Parameters->Parameters.QueryConflict.ConflictingResource,
224 Parameters->Parameters.QueryConflict.ConflictCount,
225 Parameters->Parameters.QueryConflict.Conflicts);
226#endif
227 break;
228
230#if (NTDDI_VERSION >= NTDDI_VISTA)
231 Status = Arbiter->QueryArbitrate(Arbiter, &Parameters->Parameters.QueryArbitrate);
232#else
233 Status = Arbiter->QueryArbitrate(
234 Arbiter,
235 Parameters->Parameters.QueryArbitrate.ArbitrationList);
236#endif
237 break;
238
239 /*
240 * Actions the interface defines but this arbiter does not carry
241 * out. AddReserved is one: the instance slot exists and is
242 * defaulted, but nothing routes to it.
243 */
248 break;
249
250 default:
252 break;
253 }
254
255#if (NTDDI_VERSION >= NTDDI_VISTA)
256 /* Track the tested-but-not-yet-committed window for transaction waiters. */
257 if (NT_SUCCESS(Status))
258 {
261 {
262 Arbiter->TransactionInProgress = TRUE;
264 }
267 {
268 Arbiter->TransactionInProgress = FALSE;
270 }
271 }
272#endif
273
274 ArbpReleaseLock(Arbiter);
275 return Status;
276}
struct _ARBITER_INSTANCE * PARBITER_INSTANCE
Definition: arbiter.h:110
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
Status
Definition: gdiplustypes.h:24
static VOID ArbpReleaseLock(_In_ PARBITER_INSTANCE Arbiter)
Releases the arbiter's per-instance lock.
Definition: handler.c:47
static VOID ArbpAcquireLock(_In_ PARBITER_INSTANCE Arbiter)
Acquires the arbiter's per-instance lock: one arbitration at a time.
Definition: handler.c:30
_In_ PVOID Context
Definition: storport.h:2269
PARB_RETEST_ALLOCATION RetestAllocation
Definition: arbiter.h:315
BOOLEAN TransactionInProgress
Definition: arbiter.h:333
PARB_QUERY_ARBITRATE QueryArbitrate
Definition: arbiter.h:319
PARB_BOOT_ALLOCATION BootAllocation
Definition: arbiter.h:318
PARB_TEST_ALLOCATION TestAllocation
Definition: arbiter.h:314
PARB_QUERY_CONFLICT QueryConflict
Definition: arbiter.h:320
PKEVENT TransactionEvent
Definition: arbiter.h:335
PARB_COMMIT_ALLOCATION CommitAllocation
Definition: arbiter.h:316
PARB_ROLLBACK_ALLOCATION RollbackAllocation
Definition: arbiter.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ ArbiterActionQueryConflict
Definition: iotypes.h:4556
@ ArbiterActionQueryArbitrate
Definition: iotypes.h:4557
@ ArbiterActionBootAllocation
Definition: iotypes.h:4559
@ ArbiterActionWriteReservedResources
Definition: iotypes.h:4555
@ ArbiterActionAddReserved
Definition: iotypes.h:4558
@ ArbiterActionCommitAllocation
Definition: iotypes.h:4552
@ ArbiterActionRollbackAllocation
Definition: iotypes.h:4553
@ ArbiterActionRetestAllocation
Definition: iotypes.h:4551
@ ArbiterActionQueryAllocatedResources
Definition: iotypes.h:4554
@ ArbiterActionTestAllocation
Definition: iotypes.h:4550

Referenced by PciArbiterConstructor().

◆ ArbiterLibInitializeRangeList()

NTSTATUS NTAPI ArbiterLibInitializeRangeList ( _In_ PARBITER_INSTANCE  Arbiter,
_In_ ULONG  ResourceCount,
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  Resources,
_Inout_ PRTL_RANGE_LIST  RangeList 
)

The InitializeRangeList callback default.

Parameters
[in]ArbiterThe arbiter instance the range list belongs to.
[in]ResourceCountThe number of descriptors in Resources.
[in]ResourcesThe CM partial resource descriptors describing the decoded windows.
[in,out]RangeListThe range list to rebuild from the descriptors.
Returns
Returns STATUS_SUCCESS.

Definition at line 440 of file handler.c.

445{
446 PAGED_CODE();
447 return ArbpSeedRangeList(Arbiter, ResourceCount, Resources, RangeList);
448}
static ULONG ResourceCount
Definition: inbv.c:50
static NTSTATUS ArbpSeedRangeList(_In_ PARBITER_INSTANCE Arbiter, _In_ ULONG ResourceCount, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Resources, _Inout_ PRTL_RANGE_LIST RangeList)
Definition: handler.c:319

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibQueryArbitrate()

NTSTATUS NTAPI ArbiterLibQueryArbitrate ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_QUERY_ARBITRATE_PARAMETERS  Parameters 
)

The QueryArbitrate action default: reports that this arbiter is willing to arbitrate the given list.

Parameters
[in]ArbiterThe arbiter instance being queried.
[in,out]ParametersThe action parameters carrying the arbitration list (pre-Vista builds receive the list directly).
Returns
Returns STATUS_SUCCESS.

Definition at line 73 of file handler.c.

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibReleaseResources()

VOID NTAPI ArbiterLibReleaseResources ( _In_ PARBITER_INSTANCE  Arbiter,
_In_ PVOID  Owner 
)

Releases every committed range owned by Owner.

Parameters
[in]ArbiterThe arbiter instance to release the ranges from.
[in]OwnerThe owning device object (a removed device's PDO).
Remarks
Without this a torn-down device's ranges stay reserved forever and later devices see phantom conflicts.

Definition at line 561 of file handler.c.

564{
565 PAGED_CODE();
566
567 ArbpAcquireLock(Arbiter);
568 RtlDeleteOwnersRanges(Arbiter->Allocation, Owner);
569 ArbpReleaseLock(Arbiter);
570}
NTSYSAPI NTSTATUS NTAPI RtlDeleteOwnersRanges(_Inout_ PRTL_RANGE_LIST RangeList, _In_ _Maybenull_ PVOID Owner)
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1629

◆ ArbiterLibReserveRange()

VOID NTAPI ArbiterLibReserveRange ( _In_ PARBITER_INSTANCE  Arbiter,
_In_ ULONGLONG  Start,
_In_ ULONGLONG  End,
_In_opt_ PVOID  Owner,
_In_ BOOLEAN  Shared 
)

Commits a single [Start, End] range into the arbiter as an ordinary allocation owned by Owner.

Parameters
[in]ArbiterThe arbiter instance to reserve the range in.
[in]StartThe first address (or unit) of the range.
[in]EndThe last address (or unit) of the range, inclusive.
[in]OwnerThe owning device object, or NULL for a system reservation.
[in]SharedTRUE if the range may be shared with other shareable owners.
Remarks
Used to record resources assigned outside the PnP transaction (e.g. a legacy device's IoAssignResources), so later arbitration sees them. Unlike a boot reservation this carries no BOOT_ALLOCATED attribute, so it is not treated as reclaimable.

Definition at line 528 of file handler.c.

534{
535 PAGED_CODE();
536
537 ArbpAcquireLock(Arbiter);
538 RtlAddRange(Arbiter->Allocation, Start, End, 0,
540 NULL, Owner);
541 ArbpReleaseLock(Arbiter);
542}
static _Out_opt_ PULONGLONG Start
#define NULL
Definition: types.h:112
NTSYSAPI NTSTATUS NTAPI RtlAddRange(_Inout_ PRTL_RANGE_LIST RangeList, _In_ ULONGLONG Start, _In_ ULONGLONG End, _In_ UCHAR Attributes, _In_ ULONG Flags, _In_opt_ PVOID UserData, _In_opt_ PVOID Owner)
#define RTL_RANGE_LIST_ADD_IF_CONFLICT
Definition: rtltypes.h:81
#define RTL_RANGE_LIST_ADD_SHARED
Definition: rtltypes.h:82

◆ ArbiterLibStartArbiter()

NTSTATUS NTAPI ArbiterLibStartArbiter ( _In_ PARBITER_INSTANCE  Arbiter,
_In_ PCM_RESOURCE_LIST  StartResources 
)

The StartArbiter action default: seeds the committed allocation with the windows the bus decodes, so arbitration starts from the hardware's real extent.

Parameters
[in]ArbiterThe arbiter instance being started.
[in]StartResourcesThe bus's decoded resources; NULL or empty means nothing to seed.
Returns
Returns the range-list initialization status.

Definition at line 470 of file handler.c.

473{
475
476 PAGED_CODE();
477
478 if (StartResources == NULL || StartResources->Count == 0)
479 return STATUS_SUCCESS;
480
481 Full = &StartResources->List[0];
482
483#if (NTDDI_VERSION >= NTDDI_VISTA)
484 /* Vista+ routes through the slot, so an arbiter may override the seeding. */
485 return Arbiter->InitializeRangeList(Arbiter,
486 Full->PartialResourceList.Count,
487 Full->PartialResourceList.PartialDescriptors,
488 Arbiter->Allocation);
489#else
490 return ArbpSeedRangeList(Arbiter,
491 Full->PartialResourceList.Count,
492 Full->PartialResourceList.PartialDescriptors,
493 Arbiter->Allocation);
494#endif
495}
static BOOL Full
Definition: pageheap.c:12

Referenced by ArbiterLibInitializeInstance().

◆ ArbpAcquireLock()

static VOID ArbpAcquireLock ( _In_ PARBITER_INSTANCE  Arbiter)
static

Acquires the arbiter's per-instance lock: one arbitration at a time.

Parameters
[in]ArbiterThe arbiter instance to lock.

Definition at line 30 of file handler.c.

32{
33 PAGED_CODE();
34 KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);
35}
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KernelMode
Definition: asm.h:38
@ Executive
Definition: ketypes.h:467

Referenced by ArbiterLibHandler(), ArbiterLibReleaseResources(), and ArbiterLibReserveRange().

◆ ArbpReleaseLock()

static VOID ArbpReleaseLock ( _In_ PARBITER_INSTANCE  Arbiter)
static

Releases the arbiter's per-instance lock.

Parameters
[in]ArbiterThe arbiter instance to unlock.

Definition at line 47 of file handler.c.

49{
50 PAGED_CODE();
51 KeSetEvent(Arbiter->MutexEvent, IO_NO_INCREMENT, FALSE);
52}

Referenced by ArbiterLibHandler(), ArbiterLibReleaseResources(), and ArbiterLibReserveRange().

◆ ArbpSeedRangeList()

static NTSTATUS ArbpSeedRangeList ( _In_ PARBITER_INSTANCE  Arbiter,
_In_ ULONG  ResourceCount,
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  Resources,
_Inout_ PRTL_RANGE_LIST  RangeList 
)
static

Definition at line 319 of file handler.c.

324{
325 PARBITER_SEED_WINDOW Windows;
326 ULONG WindowCount = 0;
328 ULONG Index;
329
330 PAGED_CODE();
331
332 RtlFreeRangeList(RangeList);
333 RtlInitializeRangeList(RangeList);
334
335 if ((Arbiter->UnpackResource == NULL) || (ResourceCount == 0))
336 return STATUS_SUCCESS;
337
341 if (Windows == NULL)
343
344 /* Collect the windows of our own resource type, lowest first */
345 for (Index = 0; Index < ResourceCount; ++Index)
346 {
348 ULONG Insert;
349
350 if (Resources[Index].Type != (UCHAR)Arbiter->ResourceType)
351 continue;
352
353 Arbiter->UnpackResource(&Resources[Index], &Start, &Length);
354 if (Length == 0)
355 continue;
356
357 for (Insert = WindowCount; Insert > 0; --Insert)
358 {
359 if (Windows[Insert - 1].Start <= Start)
360 break;
361
362 Windows[Insert] = Windows[Insert - 1];
363 }
364
365 Windows[Insert].Start = Start;
366 Windows[Insert].End = Start + Length - 1;
367 WindowCount++;
368 }
369
370 /*
371 * A bus that reports no window of this kind is not saying it decodes
372 * nothing; it is saying it has nothing to add. Leaving the list empty
373 * leaves every address available, which is how the root arbiters run.
374 */
375 if (WindowCount == 0)
376 {
378 return STATUS_SUCCESS;
379 }
380
381 /*
382 * What goes in the list is what the arbiter may NOT hand out, so the
383 * windows themselves are the gaps in it. Recording the windows instead
384 * would wall off exactly the addresses the bus exists to give away.
385 */
386 Next = 0;
387
388 for (Index = 0; Index < WindowCount; ++Index)
389 {
390 if (Windows[Index].Start > Next)
391 {
392 RtlAddRange(RangeList, Next, Windows[Index].Start - 1, 0,
394 }
395
396 /* Overlapping windows merge, so only ever move the mark forward */
397 if (Windows[Index].End >= Next)
398 Next = Windows[Index].End + 1;
399
400 /* A window running to the top of the space leaves no tail to block */
401 if (Windows[Index].End == ARBITER_MAXIMUM_ADDRESS)
402 {
404 return STATUS_SUCCESS;
405 }
406 }
407
410
412
413 return STATUS_SUCCESS;
414}
Type
Definition: Type.h:7
#define ARBITER_MAXIMUM_ADDRESS
Definition: arbiter.h:13
#define TAG_ARBITER
Definition: arbiter.h:10
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static UINT WindowCount
Definition: multiwin.c:4
NTSYSAPI VOID NTAPI RtlInitializeRangeList(_Out_ PRTL_RANGE_LIST RangeList)
NTSYSAPI VOID NTAPI RtlFreeRangeList(_In_ PRTL_RANGE_LIST RangeList)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
Seeds a range list with the resources the bus actually decodes: every descriptor of the arbiter's res...
Definition: handler.c:311
ULONGLONG Start
Definition: handler.c:312
unsigned char UCHAR
Definition: typedefs.h:53
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFCOLLECTION _In_ ULONG Index

Referenced by ArbiterLibInitializeRangeList(), and ArbiterLibStartArbiter().