PIO_RESOURCE_REQUIREMENTS_LIST IopAddDefaultResourceList ( IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, IN PCM_RESOURCE_LIST CmResourceList ) /*++ Routine Description: This functions builds an IO resource list by adjusting input IoResourceList to the ranges specified by CmResourceList and merges the new Io resource list to the input IoResourceList and returns the combined list. If IoResourceList has zero descriptor, this routine bulds an IO RESOURCE REQUIREMENTS LIST by simply converting the CmResourceList. It's caller's responsiblity to free the returned list. Arguments: IoResourceList - The resource requirements list which needs to be adjusted. CmResourceList - the cm resource list to specify the resource ranges desired. Return Value: returns a IO_RESOURCE_REQUIREMENTS_LISTST if succeeds. Otherwise a NULL value is returned. --*/ { PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList, combinedList = NULL; SUPPORTED_RANGES supportRanges; SUPPORTED_RANGE interruptRange; PSUPPORTED_RANGE range, tmpRange; PSUPPORTED_RANGE intRange = NULL, ioRange = NULL, memRange = NULL, dmaRange = NULL; ULONG size, i, j, addressSpace = 0; PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc; PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc; NTSTATUS status; if (!IoResourceList) { // // If IoResourceList is NULL, return failure. // return NULL; } else if (IoResourceList->List[0].Count == 0) { // // an empty Io resource requirements list, simply return the converted // list. // ioResReqList = IopCmResourcesToIoResources(IoResourceList->SlotNumber, CmResourceList); return ioResReqList; } // // Clip the IoResourceList against CmResourceList. // First, build the supported ranges structure to do the clipping. // RtlZeroMemory(&supportRanges, sizeof(supportRanges)); supportRanges.Version = BUS_SUPPORTED_RANGE_VERSION; supportRanges.Sorted = FALSE; ioResReqList = NULL; cmFullDesc = &CmResourceList->List[0]; for (i = 0; i < CmResourceList->Count; i++) { cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0]; for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) { size = 0; range = NULL; switch (cmPartDesc->Type) { case CmResourceTypePort: if (!ioRange) { range = &supportRanges.IO; } else { range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); ioRange->Next = range; } range->SystemAddressSpace = 1; range->SystemBase = 0; range->Base = cmPartDesc->u.Port.Start.QuadPart; range->Limit = cmPartDesc->u.Port.Start.QuadPart + cmPartDesc->u.Port.Length - 1; range->Next = NULL; ioRange = range; supportRanges.NoIO++; break; case CmResourceTypeInterrupt: if (!intRange) { range = &interruptRange; } else { range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); intRange->Next = range; } range->SystemAddressSpace = 0; range->SystemBase = 0; range->Base = cmPartDesc->u.Interrupt.Vector; range->Limit = cmPartDesc->u.Interrupt.Vector; range->Next = NULL; intRange = range; break; case CmResourceTypeMemory: if (!memRange) { range = &supportRanges.Memory; } else { range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); memRange->Next = range; } range->SystemAddressSpace = 0; range->SystemBase = 0; range->Base = cmPartDesc->u.Memory.Start.QuadPart; range->Limit = cmPartDesc->u.Memory.Start.QuadPart + cmPartDesc->u.Memory.Length - 1; range->Next = NULL; memRange = range; supportRanges.NoMemory++; break; case CmResourceTypeDma: if (!dmaRange) { range = &supportRanges.Dma; } else { range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); dmaRange->Next = range; } range->SystemAddressSpace = 0; range->SystemBase = 0; range->Base = cmPartDesc->u.Dma.Channel; range->Limit = cmPartDesc->u.Dma.Channel; range->Next = NULL; dmaRange = range; supportRanges.NoDma++; break; case CmResourceTypeDeviceSpecific: size = cmPartDesc->u.DeviceSpecificData.DataSize; break; } cmPartDesc++; cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size); } cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc; } // // Adjust the input resource requirements list ... // status = IopAdjustResourceListRange ( &supportRanges, &interruptRange, IoResourceList, &ioResReqList ); if (!NT_SUCCESS(status)) { goto exit0; } // // Combine the clipped io resource requirements list with the original resource // list. // size = ioResReqList->ListSize + IoResourceList->ListSize - FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List); combinedList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size); if (combinedList) { RtlMoveMemory(combinedList, ioResReqList, ioResReqList->ListSize); combinedList->ListSize = size; combinedList->AlternativeLists += IoResourceList->AlternativeLists; RtlMoveMemory((PUCHAR)combinedList + ioResReqList->ListSize, (PUCHAR)IoResourceList->List, IoResourceList->ListSize - FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) ); } ExFreePool(ioResReqList); exit0: // // Release the space allocated for supported ranges... // range = interruptRange.Next; while (range) { tmpRange = range; range = range->Next; ExFreePool(tmpRange); } range = supportRanges.IO.Next; while (range) { tmpRange = range; range = range->Next; ExFreePool(tmpRange); } range = supportRanges.Memory.Next; while (range) { tmpRange = range; range = range->Next; ExFreePool(tmpRange); } range = supportRanges.Dma.Next; while (range) { tmpRange = range; range = range->Next; ExFreePool(tmpRange); } return combinedList; }
NTSTATUS IoReportResourceUsageInternal( IN ARBITER_REQUEST_SOURCE AllocationType, IN PUNICODE_STRING DriverClassName OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PCM_RESOURCE_LIST DriverList OPTIONAL, IN ULONG DriverListSize OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PCM_RESOURCE_LIST DeviceList OPTIONAL, IN ULONG DeviceListSize OPTIONAL, IN BOOLEAN OverrideConflict, OUT PBOOLEAN ConflictDetected ) /*++ Routine Description: This internal routine will do all the work for IoReportResourceUsage. Arguments: AllocationType - Specifies the request type. DriverClassName - Optional pointer to a UNICODE_STRING which describes the class of driver under which the driver information should be stored. A default type is used if none is given. DriverObject - Pointer to the driver's driver object. DriverList - Optional pointer to the driver's resource list. DriverListSize - Optional value determining the size of the driver's resource list. DeviceObject - Optional pointer to driver's device object. DeviceList - Optional pointer to the device's resource list. DriverListSize - Optional value determining the size of the driver's resource list. OverrideConflict - Determines if the information should be reported in the configuration registry eventhough a conflict was found with another driver or device. ConflictDetected - Supplies a pointer to a boolean that is set to TRUE if the resource list conflicts with an already existing resource list in the configuration registry. Return Value: The status returned is the final completion status of the operation. --*/ { NTSTATUS status = STATUS_UNSUCCESSFUL; PCM_RESOURCE_LIST resourceList; PCM_RESOURCE_LIST allocatedResources; PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements; ULONG attempt; BOOLEAN freeAllocatedResources; ASSERT(DriverObject && ConflictDetected); if (DeviceList) { resourceList = DeviceList; } else if (DriverList) { resourceList = DriverList; } else { resourceList = NULL; } resourceRequirements = NULL; if (resourceList) { if (resourceList->Count && resourceList->List[0].PartialResourceList.Count) { resourceRequirements = IopCmResourcesToIoResources (0, resourceList, LCPRI_NORMAL); if (resourceRequirements == NULL) { return status; } } else { resourceList = NULL; } } *ConflictDetected = TRUE; attempt = 0; allocatedResources = resourceList; freeAllocatedResources = FALSE; do { // // Do the legacy resource allocation. // status = IopLegacyResourceAllocation ( AllocationType, DriverObject, DeviceObject, resourceRequirements, &allocatedResources); if (NT_SUCCESS(status)) { *ConflictDetected = FALSE; break; } // // Change the interface type and try again. // if (!IopChangeInterfaceType(resourceRequirements, &allocatedResources)) { break; } freeAllocatedResources = TRUE; } while (++attempt < 2); if (resourceRequirements) { ExFreePool(resourceRequirements); } if (freeAllocatedResources) { ExFreePool(allocatedResources); } if (NT_SUCCESS(status)) { status = STATUS_SUCCESS; } else { status = STATUS_INSUFFICIENT_RESOURCES; } return status; }