Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

filter.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 All rights reserved 00005 00006 Module Name: 00007 00008 filter.c 00009 00010 Abstract: 00011 00012 This module contains support functions for IoAssignResources to filter caller's 00013 IoRequirementResourceList. 00014 Some of the stuff here is copied from KenR's Hal code. 00015 00016 Author: 00017 00018 Shie-Lin Tzong (shielint) Apr-7-1995 00019 00020 Environment: 00021 00022 Kernel mode only. 00023 00024 Revision History: 00025 00026 */ 00027 00028 #include "iop.h" 00029 00030 #if _PNP_POWER_ 00031 00032 typedef struct _NRParams { 00033 PIO_RESOURCE_DESCRIPTOR InDesc; 00034 PIO_RESOURCE_DESCRIPTOR OutDesc; 00035 PSUPPORTED_RANGE CurrentPosition; 00036 LONGLONG Base; 00037 LONGLONG Limit; 00038 UCHAR DescOpt; 00039 BOOLEAN AnotherListPending; 00040 } NRPARAMS, *PNRPARAMS; 00041 00042 PIO_RESOURCE_REQUIREMENTS_LIST 00043 IopCmResourcesToIoResources ( 00044 IN ULONG SlotNumber, 00045 IN PCM_RESOURCE_LIST CmResourceList 00046 ); 00047 00048 NTSTATUS 00049 IopAdjustResourceListRange ( 00050 IN PSUPPORTED_RANGES SupportedRanges, 00051 IN PSUPPORTED_RANGE InterruptRange, 00052 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00053 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList 00054 ); 00055 00056 NTSTATUS 00057 IopGetNextSupportedRange ( 00058 IN LONGLONG MinimumAddress, 00059 IN LONGLONG MaximumAddress, 00060 IN OUT PNRPARAMS PNRParams, 00061 OUT PIO_RESOURCE_DESCRIPTOR *IoDescriptor 00062 ); 00063 00064 ULONG 00065 IopSortRanges ( 00066 IN PSUPPORTED_RANGE RangeList 00067 ); 00068 00069 #ifdef ALLOC_PRAGMA 00070 #pragma alloc_text(PAGE,IopAdjustResourceListRange) 00071 #pragma alloc_text(PAGE,IopSortRanges) 00072 #pragma alloc_text(PAGE,IopGetNextSupportedRange) 00073 #pragma alloc_text(PAGE,IopAddDefaultResourceList) 00074 #pragma alloc_text(PAGE,IopCmResourcesToIoResources) 00075 #endif 00076 00077 PIO_RESOURCE_REQUIREMENTS_LIST 00078 IopAddDefaultResourceList ( 00079 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00080 IN PCM_RESOURCE_LIST CmResourceList 00081 ) 00082 /*++ 00083 00084 Routine Description: 00085 00086 This functions builds an IO resource list by adjusting input IoResourceList to 00087 the ranges specified by CmResourceList and merges the new Io resource list to the 00088 input IoResourceList and returns the combined list. 00089 If IoResourceList has zero descriptor, this routine bulds an 00090 IO RESOURCE REQUIREMENTS LIST by simply converting the CmResourceList. 00091 It's caller's responsiblity to free the returned list. 00092 00093 Arguments: 00094 00095 IoResourceList - The resource requirements list which needs to 00096 be adjusted. 00097 00098 CmResourceList - the cm resource list to specify the resource ranges desired. 00099 00100 Return Value: 00101 00102 returns a IO_RESOURCE_REQUIREMENTS_LISTST if succeeds. Otherwise a NULL value is 00103 returned. 00104 00105 --*/ 00106 { 00107 PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList, combinedList = NULL; 00108 SUPPORTED_RANGES supportRanges; 00109 SUPPORTED_RANGE interruptRange; 00110 PSUPPORTED_RANGE range, tmpRange; 00111 PSUPPORTED_RANGE intRange = NULL, ioRange = NULL, memRange = NULL, dmaRange = NULL; 00112 ULONG size, i, j, addressSpace = 0; 00113 PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc; 00114 PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc; 00115 NTSTATUS status; 00116 00117 if (!IoResourceList) { 00118 00119 // 00120 // If IoResourceList is NULL, return failure. 00121 // 00122 00123 return NULL; 00124 } else if (IoResourceList->List[0].Count == 0) { 00125 00126 // 00127 // an empty Io resource requirements list, simply return the converted 00128 // list. 00129 // 00130 00131 ioResReqList = IopCmResourcesToIoResources(IoResourceList->SlotNumber, 00132 CmResourceList); 00133 return ioResReqList; 00134 } 00135 00136 // 00137 // Clip the IoResourceList against CmResourceList. 00138 // First, build the supported ranges structure to do the clipping. 00139 // 00140 00141 RtlZeroMemory(&supportRanges, sizeof(supportRanges)); 00142 supportRanges.Version = BUS_SUPPORTED_RANGE_VERSION; 00143 supportRanges.Sorted = FALSE; 00144 ioResReqList = NULL; 00145 00146 cmFullDesc = &CmResourceList->List[0]; 00147 for (i = 0; i < CmResourceList->Count; i++) { 00148 cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0]; 00149 for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) { 00150 size = 0; 00151 range = NULL; 00152 switch (cmPartDesc->Type) { 00153 case CmResourceTypePort: 00154 if (!ioRange) { 00155 range = &supportRanges.IO; 00156 } else { 00157 range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); 00158 ioRange->Next = range; 00159 } 00160 range->SystemAddressSpace = 1; 00161 range->SystemBase = 0; 00162 range->Base = cmPartDesc->u.Port.Start.QuadPart; 00163 range->Limit = cmPartDesc->u.Port.Start.QuadPart + 00164 cmPartDesc->u.Port.Length - 1; 00165 range->Next = NULL; 00166 ioRange = range; 00167 supportRanges.NoIO++; 00168 break; 00169 case CmResourceTypeInterrupt: 00170 if (!intRange) { 00171 range = &interruptRange; 00172 } else { 00173 range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); 00174 intRange->Next = range; 00175 } 00176 range->SystemAddressSpace = 0; 00177 range->SystemBase = 0; 00178 range->Base = cmPartDesc->u.Interrupt.Vector; 00179 range->Limit = cmPartDesc->u.Interrupt.Vector; 00180 range->Next = NULL; 00181 intRange = range; 00182 break; 00183 case CmResourceTypeMemory: 00184 if (!memRange) { 00185 range = &supportRanges.Memory; 00186 } else { 00187 range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); 00188 memRange->Next = range; 00189 } 00190 range->SystemAddressSpace = 0; 00191 range->SystemBase = 0; 00192 range->Base = cmPartDesc->u.Memory.Start.QuadPart; 00193 range->Limit = cmPartDesc->u.Memory.Start.QuadPart + 00194 cmPartDesc->u.Memory.Length - 1; 00195 range->Next = NULL; 00196 memRange = range; 00197 supportRanges.NoMemory++; 00198 break; 00199 case CmResourceTypeDma: 00200 if (!dmaRange) { 00201 range = &supportRanges.Dma; 00202 } else { 00203 range = (PSUPPORTED_RANGE)ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); 00204 dmaRange->Next = range; 00205 } 00206 range->SystemAddressSpace = 0; 00207 range->SystemBase = 0; 00208 range->Base = cmPartDesc->u.Dma.Channel; 00209 range->Limit = cmPartDesc->u.Dma.Channel; 00210 range->Next = NULL; 00211 dmaRange = range; 00212 supportRanges.NoDma++; 00213 break; 00214 case CmResourceTypeDeviceSpecific: 00215 size = cmPartDesc->u.DeviceSpecificData.DataSize; 00216 break; 00217 } 00218 cmPartDesc++; 00219 cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size); 00220 } 00221 cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc; 00222 } 00223 00224 // 00225 // Adjust the input resource requirements list ... 00226 // 00227 00228 status = IopAdjustResourceListRange ( 00229 &supportRanges, 00230 &interruptRange, 00231 IoResourceList, 00232 &ioResReqList 00233 ); 00234 00235 if (!NT_SUCCESS(status)) { 00236 goto exit0; 00237 } 00238 00239 // 00240 // Combine the clipped io resource requirements list with the original resource 00241 // list. 00242 // 00243 00244 size = ioResReqList->ListSize + IoResourceList->ListSize - 00245 FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List); 00246 combinedList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size); 00247 if (combinedList) { 00248 RtlMoveMemory(combinedList, ioResReqList, ioResReqList->ListSize); 00249 combinedList->ListSize = size; 00250 combinedList->AlternativeLists += IoResourceList->AlternativeLists; 00251 RtlMoveMemory((PUCHAR)combinedList + ioResReqList->ListSize, 00252 (PUCHAR)IoResourceList->List, 00253 IoResourceList->ListSize - FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) 00254 ); 00255 } 00256 ExFreePool(ioResReqList); 00257 exit0: 00258 00259 // 00260 // Release the space allocated for supported ranges... 00261 // 00262 00263 range = interruptRange.Next; 00264 while (range) { 00265 tmpRange = range; 00266 range = range->Next; 00267 ExFreePool(tmpRange); 00268 } 00269 range = supportRanges.IO.Next; 00270 while (range) { 00271 tmpRange = range; 00272 range = range->Next; 00273 ExFreePool(tmpRange); 00274 } 00275 range = supportRanges.Memory.Next; 00276 while (range) { 00277 tmpRange = range; 00278 range = range->Next; 00279 ExFreePool(tmpRange); 00280 } 00281 range = supportRanges.Dma.Next; 00282 while (range) { 00283 tmpRange = range; 00284 range = range->Next; 00285 ExFreePool(tmpRange); 00286 } 00287 return combinedList; 00288 } 00289 00290 PIO_RESOURCE_REQUIREMENTS_LIST 00291 IopCmResourcesToIoResources ( 00292 IN ULONG SlotNumber, 00293 IN PCM_RESOURCE_LIST CmResourceList 00294 ) 00295 00296 /*++ 00297 00298 Routine Description: 00299 00300 This routines converts the input CmResourceList to IO_RESOURCE_REQUIREMENTS_LIST. 00301 Note, the SlotNumber field of the returned list is not initialized. Caller must 00302 fill in the correct value. 00303 00304 Arguments: 00305 00306 SlotNumber - supplies the SlotNumber the resources refer to. 00307 00308 CmResourceList - the cm resource list to convert. 00309 00310 Return Value: 00311 00312 returns a IO_RESOURCE_REQUIREMENTS_LISTST if succeeds. Otherwise a NULL value is 00313 returned. 00314 00315 --*/ 00316 { 00317 PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList; 00318 ULONG count = 0, size, i, j; 00319 PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc; 00320 PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc; 00321 PIO_RESOURCE_DESCRIPTOR ioDesc; 00322 00323 // 00324 // First determine number of descriptors required. 00325 // 00326 00327 cmFullDesc = &CmResourceList->List[0]; 00328 for (i = 0; i < CmResourceList->Count; i++) { 00329 count += cmFullDesc->PartialResourceList.Count; 00330 cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0]; 00331 for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) { 00332 size = 0; 00333 switch (cmPartDesc->Type) { 00334 case CmResourceTypeDeviceSpecific: 00335 size = cmPartDesc->u.DeviceSpecificData.DataSize; 00336 break; 00337 } 00338 cmPartDesc++; 00339 cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size); 00340 } 00341 cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc; 00342 } 00343 00344 // 00345 // Allocate heap space for IO RESOURCE REQUIREMENTS LIST 00346 // 00347 00348 ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool( 00349 PagedPool, 00350 sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + 00351 count * sizeof(IO_RESOURCE_DESCRIPTOR) 00352 ); 00353 if (!ioResReqList) { 00354 return NULL; 00355 } 00356 00357 // 00358 // Parse the cm resource descriptor and build its corresponding IO resource descriptor 00359 // 00360 00361 ioResReqList->InterfaceType = CmResourceList->List[0].InterfaceType; 00362 ioResReqList->BusNumber = CmResourceList->List[0].BusNumber; 00363 ioResReqList->SlotNumber = SlotNumber; 00364 ioResReqList->Reserved[0] = 0; 00365 ioResReqList->Reserved[1] = 0; 00366 ioResReqList->Reserved[2] = 0; 00367 ioResReqList->AlternativeLists = 1; 00368 ioResReqList->List[0].Version = 1; 00369 ioResReqList->List[0].Revision = 1; 00370 ioResReqList->List[0].Count = count; 00371 00372 ioDesc = &ioResReqList->List[0].Descriptors[0]; 00373 cmFullDesc = &CmResourceList->List[0]; 00374 for (i = 0; i < CmResourceList->Count; i++) { 00375 cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0]; 00376 for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) { 00377 ioDesc->Option = IO_RESOURCE_PREFERRED; 00378 ioDesc->Type = cmPartDesc->Type; 00379 ioDesc->ShareDisposition = cmPartDesc->ShareDisposition; 00380 ioDesc->Flags = cmPartDesc->Flags; 00381 ioDesc->Spare1 = 0; 00382 ioDesc->Spare2 = 0; 00383 00384 size = 0; 00385 switch (cmPartDesc->Type) { 00386 case CmResourceTypePort: 00387 ioDesc->u.Port.MinimumAddress = cmPartDesc->u.Port.Start; 00388 ioDesc->u.Port.MaximumAddress.QuadPart = cmPartDesc->u.Port.Start.QuadPart + 00389 cmPartDesc->u.Port.Length - 1; 00390 ioDesc->u.Port.Alignment = 1; 00391 ioDesc->u.Port.Length = cmPartDesc->u.Port.Length; 00392 ioDesc++; 00393 break; 00394 case CmResourceTypeInterrupt: 00395 ioDesc->u.Interrupt.MinimumVector = cmPartDesc->u.Interrupt.Vector; 00396 ioDesc->u.Interrupt.MaximumVector = cmPartDesc->u.Interrupt.Vector; 00397 ioDesc++; 00398 break; 00399 case CmResourceTypeMemory: 00400 ioDesc->u.Memory.MinimumAddress = cmPartDesc->u.Memory.Start; 00401 ioDesc->u.Memory.MaximumAddress.QuadPart = cmPartDesc->u.Memory.Start.QuadPart + 00402 cmPartDesc->u.Memory.Length - 1; 00403 ioDesc->u.Memory.Alignment = 1; 00404 ioDesc->u.Memory.Length = cmPartDesc->u.Memory.Length; 00405 ioDesc++; 00406 break; 00407 case CmResourceTypeDma: 00408 ioDesc->u.Dma.MinimumChannel = cmPartDesc->u.Dma.Channel; 00409 ioDesc->u.Dma.MaximumChannel = cmPartDesc->u.Dma.Channel; 00410 ioDesc++; 00411 break; 00412 case CmResourceTypeDeviceSpecific: 00413 size = cmPartDesc->u.DeviceSpecificData.DataSize; 00414 break; 00415 } 00416 cmPartDesc++; 00417 cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size); 00418 } 00419 cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc; 00420 } 00421 ioResReqList->ListSize = (ULONG)ioDesc - (ULONG)ioResReqList; 00422 return ioResReqList; 00423 } 00424 00425 NTSTATUS 00426 IopAdjustResourceListRange ( 00427 IN PSUPPORTED_RANGES SupportedRanges, 00428 IN PSUPPORTED_RANGE InterruptRange, 00429 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00430 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList 00431 ) 00432 /*++ 00433 00434 Routine Description: 00435 00436 This functions takes an IO_RESOURCE_REQUIREMENT_LIST and 00437 adjusts it such that all ranges in the list fit in the 00438 ranges specified by SupportedRanges & InterruptRange. 00439 00440 This function is used by some HALs to clip the possible 00441 settings to be contained on what the particular bus supports 00442 in reponse to a HalAdjustResourceList call. 00443 00444 Arguments: 00445 00446 SupportedRanges - Valid IO, Memory, Prefetch Memory, and DMA ranges. 00447 InterruptRange - Valid InterruptRanges 00448 00449 pResourceList - The resource requirements list which needs to 00450 be adjusted to only contain the ranges as 00451 described by SupportedRanges & InterruptRange. 00452 00453 Return Value: 00454 00455 STATUS_SUCCESS or an appropiate error return. 00456 00457 --*/ 00458 { 00459 PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList, OutCompleteList; 00460 PIO_RESOURCE_LIST InResourceList, OutResourceList; 00461 PIO_RESOURCE_DESCRIPTOR HeadOutDesc, SetDesc; 00462 NRPARAMS Pos; 00463 ULONG len, alt, cnt, i; 00464 ULONG icnt, ListCount; 00465 NTSTATUS status; 00466 00467 // 00468 // Sanity check 00469 // 00470 00471 if (!SupportedRanges || SupportedRanges->Version != BUS_SUPPORTED_RANGE_VERSION) { 00472 return STATUS_INVALID_PARAMETER; 00473 } 00474 00475 // 00476 // If SupportedRanges aren't sorted, sort them and get the 00477 // number of ranges for each type 00478 // 00479 00480 if (!SupportedRanges->Sorted) { 00481 SupportedRanges->NoIO = IopSortRanges (&SupportedRanges->IO); 00482 SupportedRanges->NoMemory = IopSortRanges (&SupportedRanges->Memory); 00483 SupportedRanges->NoPrefetchMemory = IopSortRanges (&SupportedRanges->PrefetchMemory); 00484 SupportedRanges->NoDma = IopSortRanges (&SupportedRanges->Dma); 00485 SupportedRanges->Sorted = TRUE; 00486 } 00487 00488 icnt = IopSortRanges (InterruptRange); 00489 00490 InCompleteList = IoResourceList; 00491 len = InCompleteList->ListSize; 00492 00493 // 00494 // Scan input list - verify revision #'s, and increase len varible 00495 // by amount output list may increase. 00496 // 00497 00498 i = 0; 00499 InResourceList = InCompleteList->List; 00500 for (alt=0; alt < InCompleteList->AlternativeLists; alt++) { 00501 if (InResourceList->Version != 1 || InResourceList->Revision < 1) { 00502 return STATUS_INVALID_PARAMETER; 00503 } 00504 00505 Pos.InDesc = InResourceList->Descriptors; 00506 for (cnt = InResourceList->Count; cnt; cnt--) { 00507 switch (Pos.InDesc->Type) { 00508 case CmResourceTypeInterrupt: i += icnt; break; 00509 case CmResourceTypePort: i += SupportedRanges->NoIO; break; 00510 case CmResourceTypeDma: i += SupportedRanges->NoDma; break; 00511 00512 case CmResourceTypeMemory: 00513 i += SupportedRanges->NoMemory; 00514 if (Pos.InDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) { 00515 i += SupportedRanges->NoPrefetchMemory; 00516 } 00517 break; 00518 00519 default: 00520 return STATUS_INVALID_PARAMETER; 00521 } 00522 00523 // take one off for the original which is already accounted for in 'len' 00524 i -= 1; 00525 00526 // Next descriptor 00527 Pos.InDesc++; 00528 } 00529 00530 // Next Resource List 00531 InResourceList = (PIO_RESOURCE_LIST) Pos.InDesc; 00532 } 00533 len += i * sizeof (IO_RESOURCE_DESCRIPTOR); 00534 00535 // 00536 // Allocate output list 00537 // 00538 00539 OutCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) 00540 ExAllocatePool (PagedPool, len); 00541 00542 if (!OutCompleteList) { 00543 return STATUS_INSUFFICIENT_RESOURCES; 00544 } 00545 00546 RtlZeroMemory (OutCompleteList, len); 00547 00548 // 00549 // Walk each ResourceList and build output structure 00550 // 00551 00552 InResourceList = InCompleteList->List; 00553 *OutCompleteList = *InCompleteList; 00554 OutResourceList = OutCompleteList->List; 00555 ListCount = InCompleteList->AlternativeLists; 00556 00557 for (alt=0; alt < InCompleteList->AlternativeLists; alt++) { 00558 OutResourceList->Version = 1; 00559 OutResourceList->Revision = 1; 00560 00561 Pos.InDesc = InResourceList->Descriptors; 00562 Pos.OutDesc = OutResourceList->Descriptors; 00563 HeadOutDesc = Pos.OutDesc; 00564 00565 for (cnt = InResourceList->Count; cnt; cnt--) { 00566 00567 // 00568 // Limit desctiptor to be with the buses supported ranges 00569 // 00570 00571 Pos.DescOpt = Pos.InDesc->Option | IO_RESOURCE_PREFERRED; 00572 Pos.AnotherListPending = FALSE; 00573 00574 switch (Pos.InDesc->Type) { 00575 case CmResourceTypePort: 00576 00577 // 00578 // Get supported IO ranges 00579 // 00580 00581 Pos.CurrentPosition = &SupportedRanges->IO; 00582 do { 00583 status = IopGetNextSupportedRange ( 00584 Pos.InDesc->u.Port.MinimumAddress.QuadPart, 00585 Pos.InDesc->u.Port.MaximumAddress.QuadPart, 00586 &Pos, 00587 &SetDesc 00588 ); 00589 if (NT_SUCCESS(status)) { 00590 if (SetDesc) { 00591 SetDesc->u.Port.MinimumAddress.QuadPart = Pos.Base; 00592 SetDesc->u.Port.MaximumAddress.QuadPart = Pos.Limit; 00593 } 00594 } else { 00595 goto skipCurrentList; 00596 } 00597 } while (SetDesc) ; 00598 break; 00599 00600 case CmResourceTypeInterrupt: 00601 // 00602 // Get supported Interrupt ranges 00603 // 00604 00605 Pos.CurrentPosition = InterruptRange; 00606 do { 00607 status = IopGetNextSupportedRange ( 00608 Pos.InDesc->u.Interrupt.MinimumVector, 00609 Pos.InDesc->u.Interrupt.MaximumVector, 00610 &Pos, 00611 &SetDesc 00612 ); 00613 00614 if (NT_SUCCESS(status)) { 00615 if (SetDesc) { 00616 SetDesc->u.Interrupt.MinimumVector = (ULONG) Pos.Base; 00617 SetDesc->u.Interrupt.MaximumVector = (ULONG) Pos.Limit; 00618 } 00619 } else { 00620 goto skipCurrentList; 00621 } 00622 } while (SetDesc) ; 00623 break; 00624 00625 case CmResourceTypeMemory: 00626 // 00627 // Get supported memory ranges 00628 // 00629 00630 if (Pos.InDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) { 00631 00632 // 00633 // This is a Prefetchable range. 00634 // First add in any supported prefetchable ranges, then 00635 // add in any regualer supported ranges 00636 // 00637 00638 Pos.AnotherListPending = TRUE; 00639 Pos.CurrentPosition = &SupportedRanges->PrefetchMemory; 00640 00641 do { 00642 status = IopGetNextSupportedRange ( 00643 Pos.InDesc->u.Memory.MinimumAddress.QuadPart, 00644 Pos.InDesc->u.Memory.MaximumAddress.QuadPart, 00645 &Pos, 00646 &SetDesc 00647 ); 00648 00649 if (NT_SUCCESS(status)) { 00650 if (SetDesc) { 00651 SetDesc->u.Memory.MinimumAddress.QuadPart = Pos.Base; 00652 SetDesc->u.Memory.MaximumAddress.QuadPart = Pos.Limit; 00653 SetDesc->Option |= IO_RESOURCE_PREFERRED; 00654 } 00655 } else { 00656 goto skipCurrentList; 00657 } 00658 } while (SetDesc) ; 00659 00660 Pos.AnotherListPending = FALSE; 00661 } 00662 00663 // 00664 // Add in supported bus memory ranges 00665 // 00666 00667 Pos.CurrentPosition = &SupportedRanges->Memory; 00668 do { 00669 status = IopGetNextSupportedRange ( 00670 Pos.InDesc->u.Memory.MinimumAddress.QuadPart, 00671 Pos.InDesc->u.Memory.MaximumAddress.QuadPart, 00672 &Pos, 00673 &SetDesc 00674 ); 00675 if (NT_SUCCESS(status)) { 00676 if (SetDesc) { 00677 SetDesc->u.Memory.MinimumAddress.QuadPart = Pos.Base; 00678 SetDesc->u.Memory.MaximumAddress.QuadPart = Pos.Limit; 00679 } 00680 } else { 00681 goto skipCurrentList; 00682 } 00683 } while (SetDesc); 00684 break; 00685 00686 case CmResourceTypeDma: 00687 // 00688 // Get supported DMA ranges 00689 // 00690 00691 Pos.CurrentPosition = &SupportedRanges->Dma; 00692 do { 00693 status = IopGetNextSupportedRange ( 00694 Pos.InDesc->u.Dma.MinimumChannel, 00695 Pos.InDesc->u.Dma.MaximumChannel, 00696 &Pos, 00697 &SetDesc 00698 ); 00699 00700 if (NT_SUCCESS(status)) { 00701 if (SetDesc) { 00702 SetDesc->u.Dma.MinimumChannel = (ULONG) Pos.Base; 00703 SetDesc->u.Dma.MaximumChannel = (ULONG) Pos.Limit; 00704 } 00705 } else { 00706 goto skipCurrentList; 00707 } 00708 } while (SetDesc) ; 00709 break; 00710 00711 #if DBG 00712 default: 00713 DbgPrint ("HalAdjustResourceList: Unkown resource type\n"); 00714 break; 00715 #endif 00716 } 00717 00718 // 00719 // Next descriptor 00720 // 00721 00722 Pos.InDesc++; 00723 } 00724 00725 OutResourceList->Count = Pos.OutDesc - HeadOutDesc; 00726 00727 // 00728 // Next Resource List 00729 // 00730 00731 InResourceList = (PIO_RESOURCE_LIST) Pos.InDesc; 00732 OutResourceList = (PIO_RESOURCE_LIST) Pos.OutDesc; 00733 continue; 00734 00735 skipCurrentList: 00736 InResourceList = (PIO_RESOURCE_LIST) (InResourceList->Descriptors + InResourceList->Count); 00737 ListCount--; 00738 } 00739 00740 // 00741 // Return output list 00742 // 00743 00744 if (ListCount == 0) { 00745 ExFreePool(OutCompleteList); 00746 return STATUS_UNSUCCESSFUL; 00747 } else { 00748 OutCompleteList->ListSize = (ULONG) ((PUCHAR) OutResourceList - (PUCHAR) OutCompleteList); 00749 OutCompleteList->AlternativeLists = ListCount; 00750 *ReturnedList = OutCompleteList; 00751 return STATUS_SUCCESS; 00752 } 00753 } 00754 00755 NTSTATUS 00756 IopGetNextSupportedRange ( 00757 IN LONGLONG MinimumAddress, 00758 IN LONGLONG MaximumAddress, 00759 IN OUT PNRPARAMS Pos, 00760 OUT PIO_RESOURCE_DESCRIPTOR *IoDescriptor 00761 ) 00762 /*++ 00763 00764 Routine Description: 00765 00766 Support function for IopAdjustResourceListRange. 00767 Returns the next supported range in the area passed in. 00768 00769 Arguments: 00770 00771 MinimumAddress 00772 MaximumAddress - Min & Max address of a range which needs 00773 to be clipped to match that of the supported 00774 ranges of the current bus. 00775 00776 Pos - describes the current postion 00777 00778 IoDescriptor - returns the adjusted resource descriptor 00779 NULL is no more returned ranges 00780 00781 Return Value: 00782 00783 Otherwise, the IO_RESOURCE_DESCRIPTOR which needs to be set 00784 with the matching range returned in Pos. 00785 00786 --*/ 00787 { 00788 LONGLONG Base, Limit; 00789 00790 // 00791 // Find next range which is supported 00792 // 00793 00794 Base = MinimumAddress; 00795 Limit = MaximumAddress; 00796 00797 while (Pos->CurrentPosition) { 00798 Pos->Base = Base; 00799 Pos->Limit = Limit; 00800 00801 // 00802 // Clip to current range 00803 // 00804 00805 if (Pos->Base < Pos->CurrentPosition->Base) { 00806 Pos->Base = Pos->CurrentPosition->Base; 00807 } 00808 00809 if (Pos->Limit > Pos->CurrentPosition->Limit) { 00810 Pos->Limit = Pos->CurrentPosition->Limit; 00811 } 00812 00813 // 00814 // set position to next range 00815 // 00816 00817 Pos->CurrentPosition = Pos->CurrentPosition->Next; 00818 00819 // 00820 // If valid range, return it 00821 // 00822 00823 if (Pos->Base <= Pos->Limit) { 00824 *Pos->OutDesc = *Pos->InDesc; 00825 Pos->OutDesc->Option = Pos->DescOpt; 00826 00827 // 00828 // next descriptor (if any) is an alternative 00829 // to the descriptor being returned now 00830 // 00831 00832 Pos->OutDesc += 1; 00833 Pos->DescOpt |= IO_RESOURCE_ALTERNATIVE; 00834 *IoDescriptor = Pos->OutDesc - 1; 00835 return STATUS_SUCCESS; 00836 } 00837 } 00838 00839 // 00840 // There's no overlapping range. If this descriptor is 00841 // not an alternative and this descriptor is not going to 00842 // be processed by another range list, then return 00843 // failure. 00844 // 00845 00846 if (!(Pos->DescOpt & IO_RESOURCE_ALTERNATIVE) && 00847 Pos->AnotherListPending == FALSE) { 00848 00849 // 00850 // return a bogus descriptor 00851 // 00852 00853 Pos->Base = MinimumAddress; 00854 Pos->Limit = Pos->Base - 1; 00855 if (Pos->Base == 0) { // if wrapped, fix it 00856 Pos->Base = 1; 00857 Pos->Limit = 0; 00858 } 00859 00860 *Pos->OutDesc = *Pos->InDesc; 00861 Pos->OutDesc->Option = Pos->DescOpt; 00862 00863 Pos->OutDesc += 1; 00864 Pos->DescOpt |= IO_RESOURCE_ALTERNATIVE; 00865 *IoDescriptor = Pos->OutDesc - 1; 00866 return STATUS_SUCCESS; 00867 } 00868 00869 // 00870 // No range found (or no more ranges) 00871 // 00872 00873 *IoDescriptor = NULL; 00874 return STATUS_SUCCESS; 00875 } 00876 00877 ULONG 00878 IopSortRanges ( 00879 IN PSUPPORTED_RANGE RangeList 00880 ) 00881 /*++ 00882 00883 Routine Description: 00884 00885 Support function for IopAdjustResourceListRange. 00886 Sorts a supported range list into decending order. 00887 00888 Arguments: 00889 00890 pRange - List to sort 00891 00892 Return Value: 00893 00894 --*/ 00895 { 00896 ULONG cnt; 00897 LONGLONG hldBase, hldLimit; 00898 PSUPPORTED_RANGE Range1, Range2; 00899 00900 // 00901 // Sort it 00902 // 00903 00904 for (Range1 = RangeList; Range1; Range1 = Range1->Next) { 00905 for (Range2 = Range1->Next; Range2; Range2 = Range2->Next) { 00906 00907 if (Range2->Base > Range1->Base) { 00908 hldBase = Range1->Base; 00909 hldLimit = Range1->Limit; 00910 00911 Range1->Base = Range2->Base; 00912 Range1->Limit = Range2->Limit; 00913 00914 Range2->Base = hldBase; 00915 Range2->Limit = hldLimit; 00916 } 00917 } 00918 } 00919 00920 // 00921 // Count the number of ranges 00922 // 00923 00924 cnt = 0; 00925 for (Range1 = RangeList; Range1; Range1 = Range1->Next) { 00926 cnt += 1; 00927 } 00928 00929 return cnt; 00930 } 00931 #endif // _PNP_POWER_

Generated on Sat May 15 19:40:01 2004 for test by doxygen 1.3.7