/*++ 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; }