You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
864 lines
21 KiB
864 lines
21 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
arbiter.h
|
|
|
|
Abstract:
|
|
|
|
This module contains support routines for the Pnp resource arbiters.
|
|
|
|
Author:
|
|
|
|
Andrew Thornton (andrewth) 1-April-1997
|
|
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
--*/
|
|
|
|
#ifndef _ARBITER_
|
|
#define _ARBITER_
|
|
|
|
#if !defined(MAXULONGLONG)
|
|
#define MAXULONGLONG ((ULONGLONG)-1)
|
|
#endif
|
|
|
|
|
|
#if ARB_DBG
|
|
|
|
//
|
|
// Debug print level:
|
|
// -1 = no messages
|
|
// 0 = vital messages only
|
|
// 1 = call trace
|
|
// 2 = verbose messages
|
|
//
|
|
|
|
extern LONG ArbDebugLevel;
|
|
|
|
#define ARB_PRINT(Level, Message) \
|
|
if (Level <= ArbDebugLevel) DbgPrint Message
|
|
|
|
#define ARB_INDENT(Level, Count) \
|
|
if (Level < ArbDebugLevel) ArbpIndent(Count)
|
|
|
|
#else
|
|
|
|
#define ARB_PRINT(Level, Message)
|
|
#define ARB_INDENT(Level, Count)
|
|
|
|
#endif // ARB_DBG
|
|
|
|
|
|
//
|
|
// The ARBITER_ORDRING_LIST abstract data type
|
|
//
|
|
|
|
typedef struct _ARBITER_ORDERING {
|
|
ULONGLONG Start;
|
|
ULONGLONG End;
|
|
} ARBITER_ORDERING, *PARBITER_ORDERING;
|
|
|
|
|
|
typedef struct _ARBITER_ORDERING_LIST {
|
|
|
|
//
|
|
// The number of valid entries in the array
|
|
//
|
|
USHORT Count;
|
|
|
|
//
|
|
// The maximum number of entries that can fit in the Ordering buffer
|
|
//
|
|
USHORT Maximum;
|
|
|
|
//
|
|
// Array of orderings
|
|
//
|
|
PARBITER_ORDERING Orderings;
|
|
|
|
} ARBITER_ORDERING_LIST, *PARBITER_ORDERING_LIST;
|
|
|
|
|
|
NTSTATUS
|
|
ArbInitializeOrderingList(
|
|
IN OUT PARBITER_ORDERING_LIST List
|
|
);
|
|
|
|
VOID
|
|
ArbFreeOrderingList(
|
|
IN OUT PARBITER_ORDERING_LIST List
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbCopyOrderingList(
|
|
OUT PARBITER_ORDERING_LIST Destination,
|
|
IN PARBITER_ORDERING_LIST Source
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbAddOrdering(
|
|
OUT PARBITER_ORDERING_LIST List,
|
|
IN ULONGLONG Start,
|
|
IN ULONGLONG End
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbPruneOrdering(
|
|
IN OUT PARBITER_ORDERING_LIST OrderingList,
|
|
IN ULONGLONG Start,
|
|
IN ULONGLONG End
|
|
);
|
|
|
|
//
|
|
// ULONGLONG
|
|
// ALIGN_ADDRESS_DOWN(
|
|
// ULONGLONG address,
|
|
// ULONG alignment
|
|
// );
|
|
//
|
|
// This aligns address to the previously correctly aligned value
|
|
//
|
|
#define ALIGN_ADDRESS_DOWN(address, alignment) \
|
|
((address) & ~((ULONGLONG)alignment - 1))
|
|
|
|
//
|
|
// ULONGLONG
|
|
// ALIGN_ADDRESS_UP(
|
|
// ULONGLONG address,
|
|
// ULONG alignment
|
|
// );
|
|
//
|
|
// This aligns address to the next correctly aligned value
|
|
//
|
|
#define ALIGN_ADDRESS_UP(address, alignment) \
|
|
(ALIGN_ADDRESS_DOWN( (address + alignment - 1), alignment))
|
|
|
|
|
|
#define LENGTH_OF(_start, _end) \
|
|
((_end) - (_start) + 1)
|
|
|
|
//
|
|
// This indicates that the alternative can coexist with shared resources and
|
|
// should be added to the range lists shared
|
|
//
|
|
#define ARBITER_ALTERNATIVE_FLAG_SHARED 0x00000001
|
|
|
|
//
|
|
// This indicates that the request if for a specific range with no alternatives.
|
|
// ie (End - Start + 1 == Length) eg port 60-60 L1 A1
|
|
//
|
|
#define ARBITER_ALTERNATIVE_FLAG_FIXED 0x00000002
|
|
|
|
//
|
|
// This indicates that request is invalid
|
|
//
|
|
#define ARBITER_ALTERNATIVE_FLAG_INVALID 0x00000004
|
|
|
|
typedef struct _ARBITER_ALTERNATIVE {
|
|
|
|
//
|
|
// The minimum acceptable start value from the requirement descriptor
|
|
//
|
|
ULONGLONG Minimum;
|
|
|
|
//
|
|
// The maximum acceptable end value from the requirement descriptor
|
|
//
|
|
ULONGLONG Maximum;
|
|
|
|
//
|
|
// The length from the requirement descriptor
|
|
//
|
|
ULONG Length;
|
|
|
|
//
|
|
// The alignment from the requirement descriptor
|
|
//
|
|
ULONG Alignment;
|
|
|
|
//
|
|
// Priority index - see comments below
|
|
//
|
|
|
|
LONG Priority;
|
|
|
|
//
|
|
// Flags - ARBITER_ALTERNATIVE_FLAG_SHARED - indicates the current
|
|
// requirement was for a shared resource.
|
|
// ARBITER_ALTERNATIVE_FLAG_FIXED - indicates the current
|
|
// requirement is for a specific resource (eg ports 220-230 and
|
|
// nothing else)
|
|
//
|
|
ULONG Flags;
|
|
|
|
//
|
|
// Descriptor - the descriptor describing this alternative
|
|
//
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
//
|
|
// Packing...
|
|
//
|
|
ULONG Reserved[3];
|
|
|
|
} ARBITER_ALTERNATIVE, *PARBITER_ALTERNATIVE;
|
|
|
|
|
|
/*
|
|
The priorities are a LONG values organised as:
|
|
|
|
<------Preferred priorities-----> <-----Ordinary Priorities----->
|
|
|
|
MINLONG--------------------------0-----------------------------MAXLONG
|
|
^ ^ ^ ^
|
|
| | | |
|
|
NULL PREFERRED_RESERVED | |
|
|
RESERVED |
|
|
EXHAUSTED
|
|
|
|
An ordinary priority is calculated the (index + 1) of the next ordering it
|
|
intersects with (and has enough space for an allocation).
|
|
|
|
A preferred priority is the ordinary priority * - 1
|
|
|
|
In this way by examining each of the alternatives in priority order (lowest
|
|
first) we achieve the desired allocation order of:
|
|
|
|
(1) Preferred alternative with non-reserved resources
|
|
(2) Alternatives with non-reserved resources
|
|
(3) Preferred reserved resources
|
|
(4) Reserved Resources
|
|
|
|
MAXLONG the worst priority indicates that there are no more allocation range
|
|
left.
|
|
*/
|
|
|
|
//
|
|
// The least significant 16 bits are reserved for the base arbitration code
|
|
// the most significant are arbiter specific
|
|
//
|
|
|
|
#define ARBITER_STATE_FLAG_RETEST 0x0001
|
|
#define ARBITER_STATE_FLAG_BOOT 0x0002
|
|
#define ARBITER_STATE_FLAG_CONFLICT 0x0004
|
|
#define ARBITER_STATE_FLAG_NULL_CONFLICT_OK 0x0008
|
|
|
|
typedef struct _ARBITER_ALLOCATION_STATE {
|
|
|
|
//
|
|
// The current value being considered as a possible start value
|
|
//
|
|
ULONGLONG Start;
|
|
|
|
//
|
|
// The current value being considered as a possible end value
|
|
//
|
|
ULONGLONG End;
|
|
|
|
//
|
|
// The values currently being considered as the Minimum and Maximum (this is
|
|
// different because the prefered orderings can restrict the ranges where
|
|
// we can allocate)
|
|
//
|
|
ULONGLONG CurrentMinimum;
|
|
ULONGLONG CurrentMaximum;
|
|
|
|
//
|
|
// The entry in the arbitration list containing this request.
|
|
//
|
|
PARBITER_LIST_ENTRY Entry;
|
|
|
|
//
|
|
// The alternative currently being considered
|
|
//
|
|
PARBITER_ALTERNATIVE CurrentAlternative;
|
|
|
|
//
|
|
// The number of alternatives in the Alternatives array
|
|
//
|
|
ULONG AlternativeCount;
|
|
|
|
//
|
|
// The arbiters representation of the alternatives being considered
|
|
//
|
|
PARBITER_ALTERNATIVE Alternatives;
|
|
|
|
//
|
|
// Flags - ARBITER_STATE_FLAG_RETEST - indicates that we are in a retest
|
|
// operation not a test.
|
|
// ARBITER_STATE_FLAG_BOOT - indicates we are in a boot allocation
|
|
// operation not a test.
|
|
//
|
|
USHORT Flags;
|
|
|
|
//
|
|
// RangeAttributes - these are logically ORed in to the attributes for all
|
|
// ranges added to the range list.
|
|
//
|
|
UCHAR RangeAttributes;
|
|
|
|
//
|
|
// Ranges that are to be considered available
|
|
//
|
|
UCHAR RangeAvailableAttributes;
|
|
|
|
//
|
|
// Space for the arbiter to use as it wishes
|
|
//
|
|
ULONG_PTR WorkSpace;
|
|
|
|
} ARBITER_ALLOCATION_STATE, *PARBITER_ALLOCATION_STATE;
|
|
|
|
typedef struct _ARBITER_INSTANCE ARBITER_INSTANCE, *PARBITER_INSTANCE;
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_UNPACK_REQUIREMENT) (
|
|
IN PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
OUT PULONGLONG Minimum,
|
|
OUT PULONGLONG Maximum,
|
|
OUT PULONG Length,
|
|
OUT PULONG Alignment
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_PACK_RESOURCE) (
|
|
IN PIO_RESOURCE_DESCRIPTOR Requirement,
|
|
IN ULONGLONG Start,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_UNPACK_RESOURCE) (
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
|
|
OUT PULONGLONG Start,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
typedef
|
|
LONG
|
|
(*PARBITER_SCORE_REQUIREMENT) (
|
|
IN PIO_RESOURCE_DESCRIPTOR Descriptor
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_PREPROCESS_ENTRY)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE Entry
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_ALLOCATE_ENTRY)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE Entry
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_TEST_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_COMMIT_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_ROLLBACK_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_RETEST_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_BOOT_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_ADD_RESERVED)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PIO_RESOURCE_DESCRIPTOR Requirement OPTIONAL,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource OPTIONAL
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PARBITER_GET_NEXT_ALLOCATION_RANGE)(
|
|
PARBITER_INSTANCE Arbiter,
|
|
PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PARBITER_FIND_SUITABLE_RANGE)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(*PARBITER_ADD_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(*PARBITER_BACKTRACK_ALLOCATION)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(*PARBITER_OVERRIDE_CONFLICT)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_QUERY_ARBITRATE)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_QUERY_CONFLICT)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
IN PIO_RESOURCE_DESCRIPTOR ConflictingResource,
|
|
OUT PULONG ConflictCount,
|
|
OUT PARBITER_CONFLICT_INFO *Conflicts
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_START_ARBITER)(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PCM_RESOURCE_LIST StartResources
|
|
);
|
|
|
|
//
|
|
// Attributes for the ranges
|
|
//
|
|
|
|
#define ARBITER_RANGE_BOOT_ALLOCATED 0x01
|
|
#define ARBITER_RANGE_SHARE_DRIVER_EXCLUSIVE 0x02
|
|
|
|
#define ARBITER_RANGE_ALIAS 0x10
|
|
#define ARBITER_RANGE_POSITIVE_DECODE 0x20
|
|
|
|
#define INITIAL_ALLOCATION_STATE_SIZE PAGE_SIZE
|
|
|
|
#define ARBITER_INSTANCE_SIGNATURE 'sbrA'
|
|
|
|
|
|
typedef struct _ARBITER_INSTANCE {
|
|
//
|
|
// Signature - must be ARBITER_INSTANCE_SIGNATURE
|
|
//
|
|
ULONG Signature;
|
|
|
|
//
|
|
// Synchronisation lock
|
|
//
|
|
PKEVENT MutexEvent;
|
|
|
|
//
|
|
// The name of this arbiter - used for debugging and registry storage
|
|
//
|
|
PWSTR Name;
|
|
|
|
//
|
|
// The resource type this arbiter arbitrates.
|
|
//
|
|
CM_RESOURCE_TYPE ResourceType;
|
|
|
|
//
|
|
// Pointer to a pool allocated range list which contains the current
|
|
// allocation
|
|
//
|
|
PRTL_RANGE_LIST Allocation;
|
|
|
|
//
|
|
// Pointer to a pool allocated range list which contains the allocation
|
|
// under considetation. This is set by test allocation.
|
|
//
|
|
PRTL_RANGE_LIST PossibleAllocation;
|
|
|
|
//
|
|
// The order in which these resources should be allocated. Taken from the
|
|
// HKLM\System\CurrentControlSet\Control\SystemResources\AssignmentOrdering
|
|
// key and modified based on the reserved resources.
|
|
//
|
|
ARBITER_ORDERING_LIST OrderingList;
|
|
|
|
//
|
|
// The resources that should be reserved (not allocated until absolutley
|
|
// necessary)
|
|
//
|
|
ARBITER_ORDERING_LIST ReservedList;
|
|
|
|
//
|
|
// The reference count of the number of entities that are using the
|
|
// ARBITER_INTERFACE associated with this instance.
|
|
//
|
|
LONG ReferenceCount;
|
|
|
|
//
|
|
// The ARBITER_INTERFACE associated with this instance.
|
|
//
|
|
PARBITER_INTERFACE Interface;
|
|
|
|
//
|
|
// The size in bytes of the currently allocated AllocationStack
|
|
//
|
|
ULONG AllocationStackMaxSize;
|
|
|
|
//
|
|
// A pointer to an array of ARBITER_ALLOCATION_STATE entries encapsulating
|
|
// the state of the current arbitration
|
|
//
|
|
PARBITER_ALLOCATION_STATE AllocationStack;
|
|
|
|
|
|
//
|
|
// Required helper function dispatches - these functions must always be
|
|
// provided
|
|
//
|
|
|
|
PARBITER_UNPACK_REQUIREMENT UnpackRequirement;
|
|
PARBITER_PACK_RESOURCE PackResource;
|
|
PARBITER_UNPACK_RESOURCE UnpackResource;
|
|
PARBITER_SCORE_REQUIREMENT ScoreRequirement;
|
|
|
|
|
|
//
|
|
// Main arbiter action dispatches
|
|
//
|
|
PARBITER_TEST_ALLOCATION TestAllocation; OPTIONAL
|
|
PARBITER_RETEST_ALLOCATION RetestAllocation; OPTIONAL
|
|
PARBITER_COMMIT_ALLOCATION CommitAllocation; OPTIONAL
|
|
PARBITER_ROLLBACK_ALLOCATION RollbackAllocation; OPTIONAL
|
|
PARBITER_BOOT_ALLOCATION BootAllocation; OPTIONAL
|
|
PARBITER_QUERY_ARBITRATE QueryArbitrate; OPTIONAL
|
|
PARBITER_QUERY_CONFLICT QueryConflict; OPTIONAL
|
|
PARBITER_ADD_RESERVED AddReserved; OPTIONAL
|
|
PARBITER_START_ARBITER StartArbiter; OPTIONAL
|
|
//
|
|
// Optional helper functions
|
|
//
|
|
PARBITER_PREPROCESS_ENTRY PreprocessEntry; OPTIONAL
|
|
PARBITER_ALLOCATE_ENTRY AllocateEntry; OPTIONAL
|
|
PARBITER_GET_NEXT_ALLOCATION_RANGE GetNextAllocationRange; OPTIONAL
|
|
PARBITER_FIND_SUITABLE_RANGE FindSuitableRange; OPTIONAL
|
|
PARBITER_ADD_ALLOCATION AddAllocation; OPTIONAL
|
|
PARBITER_BACKTRACK_ALLOCATION BacktrackAllocation; OPTIONAL
|
|
PARBITER_OVERRIDE_CONFLICT OverrideConflict; OPTIONAL
|
|
|
|
//
|
|
// Debugging support
|
|
//
|
|
BOOLEAN TransactionInProgress;
|
|
|
|
//
|
|
// Arbiter specific extension - can be used to store extra arbiter specific
|
|
// information
|
|
//
|
|
PVOID Extension;
|
|
|
|
//
|
|
// The bus device we arbitrate for
|
|
//
|
|
PDEVICE_OBJECT BusDeviceObject;
|
|
|
|
//
|
|
// Callback and context for RtlFindRange/RtlIsRangeAvailable to allow
|
|
// complex conflicts
|
|
//
|
|
PVOID ConflictCallbackContext;
|
|
PRTL_CONFLICT_RANGE_CALLBACK ConflictCallback;
|
|
|
|
} ARBITER_INSTANCE, *PARBITER_INSTANCE;
|
|
|
|
|
|
//
|
|
// Lock primitives that leave us at PASSIVE_LEVEL after acquiring the lock.
|
|
// (A FAST_MUTEX or CriticalRegion leave us at APC level and some people (ACPI)
|
|
// need to be at passive level in their arbiter)
|
|
//
|
|
|
|
#define ArbAcquireArbiterLock(_Arbiter) \
|
|
KeWaitForSingleObject( (_Arbiter)->MutexEvent, Executive, KernelMode, FALSE, NULL )
|
|
|
|
#define ArbReleaseArbiterLock(_Arbiter) \
|
|
KeSetEvent( (_Arbiter)->MutexEvent, 0, FALSE )
|
|
|
|
//
|
|
// Iteration macros
|
|
//
|
|
|
|
//
|
|
// Control macro (used like a for loop) which iterates over all entries in
|
|
// a standard doubly linked list. Head is the list head and the entries are of
|
|
// type Type. A member called ListEntry is assumed to be the LIST_ENTRY
|
|
// structure linking the entries together. Current contains a pointer to each
|
|
// entry in turn.
|
|
//
|
|
#define FOR_ALL_IN_LIST(Type, Head, Current) \
|
|
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry); \
|
|
(Head) != &(Current)->ListEntry; \
|
|
(Current) = CONTAINING_RECORD((Current)->ListEntry.Flink, \
|
|
Type, \
|
|
ListEntry) \
|
|
)
|
|
//
|
|
// Similar to the above only iteration is over an array of length _Size.
|
|
//
|
|
#define FOR_ALL_IN_ARRAY(_Array, _Size, _Current) \
|
|
for ( (_Current) = (_Array); \
|
|
(_Current) < (_Array) + (_Size); \
|
|
(_Current)++ )
|
|
|
|
//
|
|
// As above only iteration begins with the entry _Current
|
|
//
|
|
#define FOR_REST_IN_ARRAY(_Array, _Size, _Current) \
|
|
for ( ; \
|
|
(_Current) < (_Array) + (_Size); \
|
|
(_Current)++ )
|
|
|
|
//
|
|
// BOOLEAN
|
|
// INTERSECT(
|
|
// ULONGLONG s1,
|
|
// ULONGLONG e1,
|
|
// ULONGLONG s2,
|
|
// ULONGLONG e2
|
|
// );
|
|
//
|
|
// Determines if the ranges s1-e1 and s2-e2 intersect
|
|
//
|
|
#define INTERSECT(s1,e1,s2,e2) \
|
|
!( ((s1) < (s2) && (e1) < (s2)) \
|
|
||((s2) < (s1) && (e2) < (s1)) )
|
|
|
|
|
|
//
|
|
// ULONGLONG
|
|
// INTERSECT_SIZE(
|
|
// ULONGLONG s1,
|
|
// ULONGLONG e1,
|
|
// ULONGLONG s2,
|
|
// ULONGLONG e2
|
|
// );
|
|
//
|
|
// Returns the size of the intersection of s1-e1 and s2-e2, undefined if they
|
|
// don't intersect
|
|
//
|
|
#define INTERSECT_SIZE(s1,e1,s2,e2) \
|
|
( __min((e1),(e2)) - __max((s1),(s2)) + 1)
|
|
|
|
|
|
#define LEGACY_REQUEST(_Entry) \
|
|
((_Entry)->RequestSource == ArbiterRequestLegacyReported || \
|
|
(_Entry)->RequestSource == ArbiterRequestLegacyAssigned)
|
|
|
|
#define PNP_REQUEST(_Entry) \
|
|
((_Entry)->RequestSource == ArbiterRequestPnpDetected || \
|
|
(_Entry)->RequestSource == ArbiterRequestPnpEnumerated)
|
|
|
|
//
|
|
// Priorities used in ArbGetNextAllocationRange
|
|
//
|
|
|
|
#define ARBITER_PRIORITY_NULL 0
|
|
#define ARBITER_PRIORITY_PREFERRED_RESERVED (MAXLONG-2)
|
|
#define ARBITER_PRIORITY_RESERVED (MAXLONG-1)
|
|
#define ARBITER_PRIORITY_EXHAUSTED (MAXLONG)
|
|
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PARBITER_TRANSLATE_ALLOCATION_ORDER)(
|
|
OUT PIO_RESOURCE_DESCRIPTOR TranslatedDescriptor,
|
|
IN PIO_RESOURCE_DESCRIPTOR RawDescriptor
|
|
);
|
|
|
|
//
|
|
// Common arbiter routines
|
|
//
|
|
|
|
NTSTATUS
|
|
ArbInitializeArbiterInstance(
|
|
OUT PARBITER_INSTANCE Arbiter,
|
|
IN PDEVICE_OBJECT BusDevice,
|
|
IN CM_RESOURCE_TYPE ResourceType,
|
|
IN PWSTR Name,
|
|
IN PWSTR OrderingName,
|
|
IN PARBITER_TRANSLATE_ALLOCATION_ORDER TranslateOrdering
|
|
);
|
|
|
|
VOID
|
|
ArbDeleteArbiterInstance(
|
|
IN PARBITER_INSTANCE Arbiter
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbArbiterHandler(
|
|
IN PVOID Context,
|
|
IN ARBITER_ACTION Action,
|
|
IN OUT PARBITER_PARAMETERS Params
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbTestAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbRetestAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbCommitAllocation(
|
|
PARBITER_INSTANCE Arbiter
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbRollbackAllocation(
|
|
PARBITER_INSTANCE Arbiter
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbAddReserved(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PIO_RESOURCE_DESCRIPTOR Requirement OPTIONAL,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbPreprocessEntry(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbAllocateEntry(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbSortArbitrationList(
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
VOID
|
|
ArbConfirmAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
BOOLEAN
|
|
ArbOverrideConflict(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
ArbQueryConflict(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
IN PIO_RESOURCE_DESCRIPTOR ConflictingResource,
|
|
OUT PULONG ConflictCount,
|
|
OUT PARBITER_CONFLICT_INFO *Conflicts
|
|
);
|
|
|
|
VOID
|
|
ArbBacktrackAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
BOOLEAN
|
|
ArbGetNextAllocationRange(
|
|
PARBITER_INSTANCE Arbiter,
|
|
PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
BOOLEAN
|
|
ArbFindSuitableRange(
|
|
PARBITER_INSTANCE Arbiter,
|
|
PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
VOID
|
|
ArbAddAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PARBITER_ALLOCATION_STATE State
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbBootAllocation(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN OUT PLIST_ENTRY ArbitrationList
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbStartArbiter(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PCM_RESOURCE_LIST StartResources
|
|
);
|
|
|
|
NTSTATUS
|
|
ArbBuildAssignmentOrdering(
|
|
IN OUT PARBITER_INSTANCE Arbiter,
|
|
IN PWSTR AllocationOrderName,
|
|
IN PWSTR ReservedResourcesName,
|
|
IN PARBITER_TRANSLATE_ALLOCATION_ORDER Translate OPTIONAL
|
|
);
|
|
|
|
|
|
#if ARB_DBG
|
|
|
|
VOID
|
|
ArbpIndent(
|
|
ULONG Count
|
|
);
|
|
|
|
#endif // DBG
|
|
|
|
|
|
#endif
|
|
|
|
|