359 lines
7.3 KiB
C
359 lines
7.3 KiB
C
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
arbiter.c
|
|
|
|
Abstract:
|
|
|
|
This module provides arbiters for the resources consumed by PDOs.
|
|
|
|
Author:
|
|
|
|
Andy Thornton (andrewth) 20-Oct-97
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "mfp.h"
|
|
#include "arbiter.h"
|
|
|
|
|
|
NTSTATUS
|
|
MfInitializeArbiters(
|
|
IN PMF_PARENT_EXTENSION Parent
|
|
);
|
|
|
|
NTSTATUS
|
|
MfInitializeArbiter(
|
|
OUT PMF_ARBITER Arbiter,
|
|
IN PDEVICE_OBJECT BusDeviceObject,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
|
|
);
|
|
|
|
LONG
|
|
MfNopScore(
|
|
IN PIO_RESOURCE_DESCRIPTOR Descriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
MfStartArbiter(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PCM_RESOURCE_LIST StartResources
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text(PAGE, MfInitializeArbiters)
|
|
#pragma alloc_text(PAGE, MfInitializeArbiter)
|
|
#pragma alloc_text(PAGE, MfNopScore)
|
|
#pragma alloc_text(PAGE, MfStartArbiter)
|
|
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
MfInitializeArbiters(
|
|
IN PMF_PARENT_EXTENSION Parent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This initializes the arbiters required to arbitrated resources for the
|
|
parent device.
|
|
|
|
Arguments:
|
|
|
|
Parent - The MF device we are initializing arbiters for.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
|
|
PMF_ARBITER arbiter, newArbiter = NULL;
|
|
BOOLEAN existingArbiter;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// REBALANCE - if restart then free the old arbiters
|
|
// until we do that, assume we're not restarting
|
|
//
|
|
|
|
ASSERT(IsListEmpty(&Parent->Arbiters));
|
|
|
|
//
|
|
// If we don't have any resources we don't need any arbiters
|
|
//
|
|
|
|
if (!Parent->ResourceList) {
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
FOR_ALL_CM_DESCRIPTORS(Parent->ResourceList, descriptor) {
|
|
|
|
//
|
|
// Check if this is an nonarbitrated resource - if it is then we won't
|
|
// be needing an arbiter for it!
|
|
//
|
|
|
|
if (!IS_ARBITRATED_RESOURCE(descriptor->Type)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// See if we already have an arbiter for this resource
|
|
//
|
|
|
|
existingArbiter = FALSE;
|
|
|
|
FOR_ALL_IN_LIST(MF_ARBITER, &Parent->Arbiters, arbiter) {
|
|
|
|
if (arbiter->Type == descriptor->Type) {
|
|
|
|
//
|
|
// We already have an arbiter so we don't need
|
|
// to create a new one
|
|
//
|
|
|
|
existingArbiter = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!existingArbiter) {
|
|
|
|
//
|
|
// We don't have an arbiter for this resource type so make one!
|
|
//
|
|
|
|
DEBUG_MSG(1,
|
|
("Creating arbiter for %s\n",
|
|
MfDbgCmResourceTypeToText(descriptor->Type)
|
|
));
|
|
|
|
newArbiter = ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(MF_ARBITER),
|
|
MF_ARBITER_TAG
|
|
);
|
|
|
|
if (!newArbiter) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
status = MfInitializeArbiter(newArbiter, Parent->Self, descriptor);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
InsertHeadList(&Parent->Arbiters, &newArbiter->ListEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FOR_ALL_IN_LIST(MF_ARBITER, &Parent->Arbiters, arbiter) {
|
|
|
|
MfStartArbiter(&(arbiter->Instance), Parent->ResourceList);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
cleanup:
|
|
|
|
if (newArbiter) {
|
|
|
|
ExFreePool(newArbiter);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
LONG
|
|
MfNopScore(
|
|
IN PIO_RESOURCE_DESCRIPTOR Descriptor
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
return 0;
|
|
}
|
|
|
|
NTSTATUS
|
|
MfInitializeArbiter(
|
|
OUT PMF_ARBITER Arbiter,
|
|
IN PDEVICE_OBJECT BusDeviceObject,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
|
|
)
|
|
/*
|
|
|
|
Routine Description:
|
|
|
|
This initializes an arbiter to arbitrated the resources described in
|
|
Descriptor
|
|
|
|
Arguments:
|
|
|
|
Arbiter - Pointer to a buffer where the arbiter should reside.
|
|
|
|
Descriptor - Describes the resources available to the arbiter.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
PMF_RESOURCE_TYPE resType;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Do we understand these resources
|
|
//
|
|
|
|
resType = MfFindResourceType(Descriptor->Type);
|
|
|
|
if (!resType) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Arbiter->Type = Descriptor->Type;
|
|
|
|
RtlZeroMemory(&Arbiter->Instance, sizeof(ARBITER_INSTANCE));
|
|
|
|
Arbiter->Instance.PackResource = resType->PackResource;
|
|
Arbiter->Instance.UnpackResource = resType->UnpackResource;
|
|
Arbiter->Instance.UnpackRequirement = resType->UnpackRequirement;
|
|
|
|
//
|
|
// Initialize the arbiter
|
|
//
|
|
|
|
status = ArbInitializeArbiterInstance(&Arbiter->Instance,
|
|
BusDeviceObject,
|
|
Arbiter->Type,
|
|
L"Mf Arbiter",
|
|
L"Root", // should be NULL
|
|
NULL
|
|
);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Arbiter support functions
|
|
//
|
|
|
|
NTSTATUS
|
|
MfStartArbiter(
|
|
IN PARBITER_INSTANCE Arbiter,
|
|
IN PCM_RESOURCE_LIST StartResources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This initializes an arbiter's range list to arbitrate the
|
|
resources described in StartResources
|
|
|
|
Arguments:
|
|
|
|
Arbiter - Pointer to the arbiter.
|
|
|
|
StartResources - Describes the resources available to the arbiter.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
RTL_RANGE_LIST invertedAllocation;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
|
|
ULONGLONG start;
|
|
ULONG length;
|
|
NTSTATUS status;
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
RtlInitializeRangeList(&invertedAllocation);
|
|
|
|
//
|
|
// Iterate through resource descriptors, adding the resources
|
|
// this arbiter arbitrates to the ReverseAllocation
|
|
//
|
|
|
|
FOR_ALL_CM_DESCRIPTORS(StartResources,descriptor) {
|
|
|
|
if (descriptor->Type == Arbiter->ResourceType) {
|
|
|
|
status = Arbiter->UnpackResource(descriptor,
|
|
&start,
|
|
&length);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (length > 0) {
|
|
|
|
//
|
|
// we don't care about Attributes, UserData or Owner since this
|
|
// list is going to get trashed in a minute anyway
|
|
//
|
|
|
|
status = RtlAddRange(&invertedAllocation,
|
|
start,
|
|
END_OF_RANGE(start,length),
|
|
0, // Attributes
|
|
RTL_RANGE_LIST_ADD_SHARED|RTL_RANGE_LIST_ADD_IF_CONFLICT,
|
|
0, // UserData
|
|
NULL); // Owner
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
status = RtlInvertRangeList(Arbiter->Allocation,&invertedAllocation);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
cleanup:
|
|
|
|
RtlFreeRangeList(&invertedAllocation);
|
|
return status;
|
|
}
|
|
|