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

assign.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 assign.c 00008 00009 Abstract: 00010 00011 IoAssignResources 00012 00013 Author: 00014 00015 Ken Reneris 00016 00017 Environment: 00018 EDIT IN 110 COLUMN MODE 00019 00020 Revision History: 00021 00022 Add PnP support - shielint 00023 00024 --*/ 00025 00026 #include "iop.h" 00027 00028 #define IDBG DBG 00029 #define PAGED 1 00030 #define INLINE __inline 00031 #define STATIC static 00032 00033 //#define IDBG 1 00034 //#define DBG 1 00035 //#define PAGED 00036 //#define INLINE 00037 //#define STATIC 00038 00039 00040 /* 00041 * IDBG - Internal debugging. Turn on for runtime DbgPrints of calls to IoAssignResources 00042 * PAGED - Declare functions as pageable or not. (usefull for debugging) 00043 * INLINE - Inline functions 00044 * STATIC - internal functions to this module which are static 00045 * 00046 */ 00047 00048 00049 extern WCHAR IopWstrOtherDrivers[]; 00050 extern WCHAR IopWstrAssignedResources[]; 00051 extern WCHAR IopWstrRequestedResources[]; 00052 extern WCHAR IopWstrSystemResources[]; 00053 extern WCHAR IopWstrReservedResources[]; 00054 extern WCHAR IopWstrAssignmentOrdering[]; 00055 extern WCHAR IopWstrBusValues[]; 00056 extern WCHAR IopWstrTranslated[]; 00057 extern WCHAR IopWstrBusTranslated[]; 00058 00059 #define HRESOURCE_MAP 0 00060 #define HDEVICE_STORAGE 1 00061 #define HCURRENT_CONTROL_SET 2 00062 #define HSYSTEMRESOURCES 3 00063 #define HORDERING 4 00064 #define HRESERVEDRESOURCES 5 00065 #define HBUSVALUES 6 00066 #define HOWNER_MAP 7 00067 #define MAX_REG_HANDLES 8 00068 00069 #define INVALID_HANDLE (HANDLE) -1 00070 00071 #define BUFFERSIZE (2048 + sizeof( KEY_FULL_INFORMATION )) 00072 #define MAX_ENTRIES 50 00073 #define SCONFLICT 5 00074 00075 // 00076 // Wrapper structures around IO_RESOURCE lists 00077 // 00078 00079 // owner of TENTRY 00080 typedef struct { 00081 LIST_ENTRY InConflict; 00082 UNICODE_STRING KeyName; 00083 UNICODE_STRING DeviceName; 00084 WCHAR UnicodeBuffer[1]; // Must be last! 00085 } *POWNER; 00086 00087 // translated entry 00088 typedef struct { 00089 LONGLONG BAddr; // Beginning address 00090 LONGLONG EAddr; // Ending address 00091 KAFFINITY Affinity; // Processor affinity of resource 00092 POWNER Owner; // Owner of this resource 00093 #if IDBG 00094 ULONG na[2]; 00095 #endif 00096 } TENTRY, *PTENTRY; // Translated resource 00097 00098 #define DoesTEntryCollide(a,b) \ 00099 ( (a).EAddr >= (b).BAddr && (a).BAddr <= (b).EAddr && ((a).Affinity & (b).Affinity) ) 00100 00101 00102 // list of translated entries 00103 typedef struct _LTENTRY { 00104 struct _LTENTRY *Next; // Allocated table size 00105 ULONG CurEntries; // No entries in table 00106 ULONG na[2]; 00107 TENTRY Table[MAX_ENTRIES]; 00108 } LTENTRY, *PLTENTRY; // List of translated resources 00109 00110 // list of translated entries by CmResourceType 00111 typedef struct { 00112 PLTENTRY ByType[CmResourceTypeMaximum]; 00113 } TENTRIESBYTYPE, *PTENTRIESBYTYPE; 00114 00115 // information about conflict 00116 typedef struct { 00117 ULONG NoConflicts; // # of BAddrs 00118 struct { 00119 UCHAR Type; 00120 LONGLONG BAddr; 00121 POWNER Owner; 00122 } EasyConflict[SCONFLICT]; 00123 00124 LIST_ENTRY OtherConflicts; 00125 } IO_TRACK_CONFLICT, *PIO_TRACK_CONFLICT; 00126 00127 // a required resource with it's alternatives 00128 typedef struct { 00129 // work in progress... 00130 ULONG CurLoc; // Which IoResourceDescriptor 00131 ULONG RunLen; // length of alternative run 00132 ULONG PassNo; 00133 00134 // current bus specific ordering location 00135 ULONG CurBusLoc; // Current Bus descriptor location 00136 LONGLONG CurBusMin; // Current bus desc min 00137 LONGLONG CurBusMax; // Current bus desc max 00138 00139 // raw selection being considered... 00140 UCHAR Type; // type of descriptor 00141 ULONG CurBLoc; 00142 LONGLONG CurBAddr; // bus native BAddr 00143 00144 // the raw selection's translation 00145 UCHAR TType; // Translated type 00146 TENTRY Trans; // Translated info 00147 00148 LONG BestPref; // only has meaning on first pass 00149 LONG CurPref; // Prefernce of current selection 00150 00151 // Phase 3 00152 ULONG PrefCnt; // # of times this level skipped 00153 ULONG Pass2HoldCurLoc; // CurBLoc of best selection so far 00154 LONGLONG Pass2HoldBAddr; // CurBAddr of best selection so far 00155 00156 // resource options 00157 ULONG NoAlternatives; // entries in IoResourceDescriptor 00158 PIO_RESOURCE_DESCRIPTOR IoResourceDescriptor[1]; // MUST BE LAST ENTRY 00159 } DIR_REQUIRED_RESOURCE, *PDIR_REQUIRED_RESOURCE; 00160 00161 // a list of required resources for the alternative list 00162 typedef struct _DIR_RESOURCE_LIST { 00163 struct _DIR_RESOURCE_LIST *Next; // next alternative list 00164 PDIR_REQUIRED_RESOURCE ResourceByType[CmResourceTypeMaximum]; // catagorized list 00165 LONG CurPref; 00166 ULONG LastLevel; // last level tried 00167 ULONG FailedLevel; // which level had conflict 00168 IO_TRACK_CONFLICT Conflict; // pass3 00169 PIO_RESOURCE_LIST IoResourceList; // this IO_RESOURCE_LIST 00170 ULONG NoRequiredResources; // entries in RequiredResource 00171 PDIR_REQUIRED_RESOURCE RequiredResource[1]; // MUST BE LAST ENTRY 00172 } DIR_RESOURCE_LIST, *PDIR_RESOURCE_LIST; 00173 00174 // top level structure 00175 typedef struct _DIR_RESREQ_LIST { 00176 HANDLE RegHandle[MAX_REG_HANDLES]; // handles to different registry locations 00177 struct _DIR_RESREQ_LIST *UserDir; 00178 struct _DIR_RESREQ_LIST *BusDir; 00179 struct _DIR_RESREQ_LIST *FreeResReqList; // other DIR_RESREQ_LIST which need freed 00180 SINGLE_LIST_ENTRY AllocatedHeap; // heap which needs freed 00181 TENTRIESBYTYPE InUseResources; 00182 TENTRIESBYTYPE InUseSharableResources; 00183 TENTRIESBYTYPE ReservedSharableResources; 00184 PIO_RESOURCE_REQUIREMENTS_LIST IoResourceReq; // this IO_RESOURCES_REQUIREMENTS_LIST 00185 PDIR_RESOURCE_LIST Alternative; // list of alternatives 00186 PWCHAR Buffer; // Scratch memory 00187 } DIR_RESREQ_LIST, *PDIR_RESREQ_LIST; 00188 00189 // a list of heap which was allocated 00190 typedef struct { 00191 SINGLE_LIST_ENTRY FreeLink; // List of heap to free 00192 PVOID FreeHeap; // pointer to heap to free 00193 } USED_HEAP, *PUSED_HEAP; 00194 00195 // 00196 // Internal prototypes 00197 // 00198 00199 PIO_RESOURCE_REQUIREMENTS_LIST 00200 IopGetResourceReqRegistryValue ( 00201 IN PDIR_RESREQ_LIST Dir, 00202 IN HANDLE KeyHandle, 00203 IN PWSTR ValueName 00204 ); 00205 00206 NTSTATUS 00207 IopAssignResourcesPhase1 ( 00208 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources, 00209 IN PIO_RESOURCE_REQUIREMENTS_LIST *CopiedList 00210 ); 00211 00212 NTSTATUS 00213 IopAssignResourcesPhase2 ( 00214 IN PDIR_RESREQ_LIST Dir, 00215 IN PUNICODE_STRING DriverClassName, 00216 IN PDRIVER_OBJECT DriverObject, 00217 IN PDEVICE_OBJECT DeviceObject 00218 ); 00219 00220 PDIR_RESOURCE_LIST 00221 IopAssignResourcesPhase3 ( 00222 IN PDIR_RESREQ_LIST Dir 00223 ); 00224 00225 PCM_RESOURCE_LIST 00226 IopAssignResourcesPhase4 ( 00227 IN PDIR_RESREQ_LIST Dir, 00228 IN PDIR_RESOURCE_LIST CurList, 00229 OUT PULONG Length 00230 ); 00231 00232 STATIC VOID 00233 IopLogConflict ( 00234 IN PDRIVER_OBJECT DriverObject, 00235 IN PDIR_RESREQ_LIST Dir, 00236 IN NTSTATUS FinalStatus 00237 ); 00238 00239 STATIC PVOID 00240 IopAllocateDirPool ( 00241 IN PDIR_RESREQ_LIST Dir, 00242 IN ULONG Length 00243 ); 00244 00245 INLINE PTENTRY 00246 IopNewTransEntry ( 00247 IN PDIR_RESREQ_LIST Dir, 00248 IN PTENTRIESBYTYPE pTypes, 00249 IN ULONG Type 00250 ); 00251 00252 STATIC NTSTATUS 00253 IopAddCmDescriptorToInUseList ( 00254 IN PDIR_RESREQ_LIST Dir, 00255 IN PTENTRIESBYTYPE pTypes, 00256 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, 00257 IN POWNER Owner 00258 ); 00259 00260 ULONG 00261 IopFindCollisionInTList ( 00262 IN PTENTRY SEntry, 00263 IN PLTENTRY List 00264 ); 00265 00266 VOID 00267 IopPickupCollisionInTList ( 00268 IN PDIR_RESOURCE_LIST CurList, 00269 IN UCHAR Type, 00270 IN LONGLONG BAddr, 00271 IN PTENTRY SEntry, 00272 IN PLTENTRY List 00273 ); 00274 00275 NTSTATUS 00276 IopBuildResourceDir ( 00277 IN PDIR_RESREQ_LIST ParentDir, 00278 IN PDIR_RESREQ_LIST *DirResourceList, 00279 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources 00280 ); 00281 00282 VOID 00283 IopFreeResourceDir ( 00284 IN PDIR_RESREQ_LIST DirResourceList 00285 ); 00286 00287 VOID 00288 IopSortDescriptors ( 00289 IN OUT PDIR_RESREQ_LIST Dir 00290 ); 00291 00292 NTSTATUS 00293 IopCatagorizeDescriptors ( 00294 IN OUT PDIR_RESREQ_LIST Dir 00295 ); 00296 00297 ULONG 00298 IopDescriptorSortingWeight ( 00299 IN PIO_RESOURCE_DESCRIPTOR Descriptor 00300 ); 00301 00302 BOOLEAN 00303 IopGenNextValidResourceList ( 00304 IN ULONG level, 00305 IN PDIR_RESOURCE_LIST CurList, 00306 IN PDIR_RESREQ_LIST Dir 00307 ); 00308 00309 BOOLEAN 00310 IopGenNextValidDescriptor ( 00311 IN ULONG level, 00312 IN PDIR_RESOURCE_LIST CurList, 00313 IN PDIR_RESREQ_LIST Dir, 00314 IN PULONG collisionlevel 00315 ); 00316 00317 BOOLEAN 00318 IopSlotResourceOwner ( 00319 IN PDIR_RESREQ_LIST Dir, 00320 IN PDRIVER_OBJECT DriverObject, 00321 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 00322 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources, 00323 IN BOOLEAN AddOwner 00324 ); 00325 00326 #if IDBG 00327 VOID 00328 IopDumpIoResourceDir ( 00329 IN PDIR_RESREQ_LIST Dir 00330 ); 00331 00332 VOID 00333 IopDumpIoResourceDescriptor ( 00334 IN PUCHAR Indent, 00335 IN PIO_RESOURCE_DESCRIPTOR Desc 00336 ); 00337 #endif 00338 00339 #if DBG 00340 #define CHECK_STATUS(a,b) { if(!NT_SUCCESS(a)) { DebugString = b; goto Exit; } } 00341 #else 00342 #define CHECK_STATUS(a,b) { if(!NT_SUCCESS(a)) goto Exit; } 00343 #endif 00344 00345 #if DBG 00346 #define DBGMSG(a) DbgPrint(a) 00347 #else 00348 #define DBGMSG(a) 00349 #endif 00350 00351 #if IDBG 00352 #define IDBGMSG(a) DbgPrint(a) 00353 #else 00354 #define IDBGMSG(a) 00355 #endif 00356 00357 #ifdef PAGED 00358 #ifdef ALLOC_PRAGMA 00359 00360 #pragma alloc_text(PAGE,IoAssignResources) 00361 #pragma alloc_text(PAGE,IopAssignResourcesPhase1) 00362 #pragma alloc_text(PAGE,IopAssignResourcesPhase2) 00363 #pragma alloc_text(PAGE,IopAssignResourcesPhase3) 00364 #pragma alloc_text(PAGE,IopAssignResourcesPhase4) 00365 #pragma alloc_text(PAGE,IopLogConflict) 00366 #pragma alloc_text(PAGE,IopGenNextValidResourceList) 00367 #pragma alloc_text(PAGE,IopGenNextValidDescriptor) 00368 #pragma alloc_text(PAGE,IopFindCollisionInTList) 00369 #pragma alloc_text(PAGE,IopPickupCollisionInTList) 00370 #pragma alloc_text(PAGE,IopAllocateDirPool) 00371 #pragma alloc_text(PAGE,IopGetResourceReqRegistryValue) 00372 #pragma alloc_text(PAGE,IopBuildResourceDir) 00373 #pragma alloc_text(PAGE,IopFreeResourceDir) 00374 #pragma alloc_text(PAGE,IopCatagorizeDescriptors) 00375 #pragma alloc_text(PAGE,IopSortDescriptors) 00376 #pragma alloc_text(PAGE,IopAddCmDescriptorToInUseList) 00377 #pragma alloc_text(PAGE,IopSlotResourceOwner) 00378 #if IDBG 00379 #pragma alloc_text(PAGE,IopDumpIoResourceDir) 00380 #pragma alloc_text(PAGE,IopDumpIoResourceDescriptor) 00381 #endif 00382 00383 #ifndef INLINE 00384 #pragma alloc_text(PAGE,IO_DESC_MIN) 00385 #pragma alloc_text(PAGE,IO_DESC_MAX) 00386 #pragma alloc_text(PAGE,IopDescriptorSortingWeight) 00387 #pragma alloc_text(PAGE,IopNewTransEntry) 00388 #endif // INLINE 00389 00390 #endif // ALLOC_PRAGMA 00391 #endif // PAGED 00392 00393 NTSTATUS 00394 IoAssignResources ( 00395 IN PUNICODE_STRING RegistryPath, 00396 IN PUNICODE_STRING DriverClassName OPTIONAL, 00397 IN PDRIVER_OBJECT DriverObject, 00398 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 00399 IN PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, 00400 IN OUT PCM_RESOURCE_LIST *pAllocatedResources 00401 ) 00402 /*++ 00403 00404 Routine Description: 00405 00406 This routine takes an input request of RequestedResources, and returned 00407 allocated resources in pAllocatedResources. The allocated resources are 00408 automatically recorded in the registry under the ResourceMap for the 00409 DriverClassName/DriverObject/DeviceObject requestor. 00410 00411 Arguments: 00412 00413 RegistryPath 00414 For a simple driver, this would be the value passed to the drivers 00415 initialization function. For drivers call IoAssignResources with 00416 multiple DeviceObjects are responsible for passing in a unique 00417 RegistryPath for each object. 00418 00419 The registry path is checked for: 00420 RegitryPath: 00421 AssignedSystemResources. 00422 00423 AssignSystemResources is of type REG_RESOURCE_REQUIREMENTS_LIST 00424 00425 If present, IoAssignResources will attempt to use these settings to 00426 satisify the requested resources. If the listed settings do 00427 not conform to the resource requirements, then IoAssignResources 00428 will fail. 00429 00430 Note: IoAssignResources may store other internal binary information 00431 in the supplied RegisteryPath. 00432 00433 DriverObject: 00434 The driver object of the caller. 00435 00436 DeviceObject: 00437 If non-null, then requested resoruce list refers to this device. 00438 If null, the requested resource list refers to the driver. 00439 00440 DriverClassName 00441 Used to partition allocated resources into different device classes. 00442 00443 RequestedResources 00444 A list of resources to allocate. 00445 00446 Allocated resources may be appended or freed by re-invoking 00447 IoAssignResources with the same RegistryPath, DriverObject and 00448 DeviceObject. (editing requirements on a resource list by using 00449 sucessive calls is not preferred driver behaviour). 00450 00451 AllocatedResources 00452 Returns the allocated resources for the requested resource list. 00453 00454 Note that the driver is responsible for passing in a pointer to 00455 an uninitialized pointer. IoAssignResources will initialize the 00456 pointer to point to the allocated CM_RESOURCE_LIST. The driver 00457 is responisble for returning the memory back to pool when it is 00458 done with them structure. 00459 00460 Return Value: 00461 00462 The status returned is the final completion status of the operation. 00463 00464 --*/ 00465 { 00466 if (DeviceObject) { 00467 00468 if ( DeviceObject->DeviceObjectExtension->DeviceNode && 00469 !(((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)) { 00470 00471 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, PNP_ERR_INVALID_PDO, (ULONG_PTR)DeviceObject, 0, 0); 00472 00473 } 00474 00475 } 00476 00477 if (RequestedResources) { 00478 00479 if (RequestedResources->AlternativeLists == 0 || 00480 RequestedResources->List[0].Count == 0) { 00481 00482 RequestedResources = NULL; 00483 00484 } 00485 } 00486 00487 if (pAllocatedResources) { 00488 00489 *pAllocatedResources = NULL; 00490 00491 } 00492 00493 return IopLegacyResourceAllocation ( ArbiterRequestLegacyAssigned, 00494 DriverObject, 00495 DeviceObject, 00496 RequestedResources, 00497 pAllocatedResources); 00498 } 00499 #if 0 00500 BOOLEAN 00501 IopSlotResourceOwner ( 00502 IN PDIR_RESREQ_LIST Dir, 00503 IN PDRIVER_OBJECT DriverObject, 00504 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 00505 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources, 00506 IN BOOLEAN AddOwner 00507 ) 00508 { 00509 ULONG busflags, len, i; 00510 PWCHAR KeyName; 00511 UNICODE_STRING KeyString, ValueString; 00512 POBJECT_NAME_INFORMATION ObjectName; 00513 PKEY_VALUE_PARTIAL_INFORMATION PartInf; 00514 BOOLEAN Match; 00515 NTSTATUS status; 00516 00517 PAGED_CODE(); 00518 00519 KeyName = ExAllocatePool (PagedPool, BUFFERSIZE * 2); 00520 if (!KeyName) { 00521 return FALSE; 00522 } 00523 00524 ObjectName = (POBJECT_NAME_INFORMATION) ((PCHAR)KeyName + BUFFERSIZE); 00525 Match = TRUE; 00526 00527 // 00528 // Find bus specific ordering 00529 // 00530 00531 status = IopLookupBusStringFromID ( 00532 Dir->RegHandle[HBUSVALUES], 00533 IoResources->InterfaceType, 00534 KeyName, 00535 BUFFERSIZE-40, 00536 &busflags 00537 ); 00538 00539 // 00540 // Does this bus have unique SlotNumber ownership? 00541 // 00542 00543 if (NT_SUCCESS(status) && (busflags & 0x1)) { 00544 00545 // 00546 // Build keyname 00547 // 00548 00549 for (i=0; KeyName[i]; i++) ; 00550 swprintf (KeyName+i, L"_%d_%x", IoResources->BusNumber, IoResources->SlotNumber); 00551 RtlInitUnicodeString( &KeyString, KeyName ); 00552 00553 // 00554 // Build valuename 00555 // 00556 00557 status = ObQueryNameString( 00558 DeviceObject ? (PVOID) DeviceObject : (PVOID) DriverObject, 00559 ObjectName, 00560 BUFFERSIZE, 00561 &len 00562 ); 00563 00564 if (NT_SUCCESS(status)) { 00565 00566 // 00567 // Look it up 00568 // 00569 00570 PartInf = (PKEY_VALUE_PARTIAL_INFORMATION) Dir->Buffer; 00571 status = ZwQueryValueKey ( 00572 Dir->RegHandle[HOWNER_MAP], 00573 &KeyString, 00574 KeyValuePartialInformation, 00575 Dir->Buffer, 00576 BUFFERSIZE, 00577 &len 00578 ); 00579 00580 if (!NT_SUCCESS(status)) { 00581 00582 // 00583 // No owner listed, see if we should add ourselves 00584 // 00585 00586 if (AddOwner) { 00587 // 00588 // Add the key 00589 // 00590 00591 ZwSetValueKey ( 00592 Dir->RegHandle[HOWNER_MAP], 00593 &KeyString, 00594 0L, 00595 REG_SZ, 00596 ObjectName->Name.Buffer, 00597 ObjectName->Name.Length 00598 ); 00599 } 00600 00601 } else { 00602 00603 // 00604 // Owner is listed, see if it's us 00605 // 00606 00607 ValueString.Buffer = (PWCHAR) PartInf->Data; 00608 ValueString.Length = (USHORT) len - (USHORT) FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); 00609 ValueString.MaximumLength = ValueString.Length; 00610 00611 Match = RtlEqualUnicodeString (&ObjectName->Name, &ValueString, TRUE); 00612 if (Match && !AddOwner) { 00613 00614 // 00615 // Free ownership 00616 // 00617 00618 ZwDeleteValueKey( Dir->RegHandle[HOWNER_MAP], &KeyString); 00619 } 00620 } 00621 } 00622 } 00623 00624 ExFreePool (KeyName); 00625 return Match; 00626 } 00627 00628 /*++ 00629 00630 Routine Description: 00631 00632 IO_DESC_MIN - Returns the descriptor's MIN,MAX or ALIGMENT requirements 00633 IO_DESC_MAX 00634 00635 --*/ 00636 00637 INLINE LONGLONG 00638 IO_DESC_MIN ( 00639 IN PIO_RESOURCE_DESCRIPTOR Desc 00640 ) 00641 { 00642 LONGLONG li; 00643 00644 switch (Desc->Type) { 00645 case CmResourceTypePort: 00646 li = Desc->u.Port.MinimumAddress.QuadPart; 00647 break; 00648 00649 case CmResourceTypeMemory: 00650 li = Desc->u.Memory.MinimumAddress.QuadPart; 00651 break; 00652 00653 case CmResourceTypeInterrupt: 00654 li = Desc->u.Interrupt.MinimumVector; 00655 break; 00656 00657 case CmResourceTypeDma: 00658 li = Desc->u.Dma.MinimumChannel; 00659 break; 00660 } 00661 00662 return li; 00663 } 00664 00665 INLINE LONGLONG 00666 IO_DESC_MAX ( 00667 IN PIO_RESOURCE_DESCRIPTOR Desc 00668 ) 00669 /*++ 00670 00671 Routine Description: 00672 00673 Returns the IO_RESORUCE_DESCRIPTOR's maximum value 00674 00675 --*/ 00676 { 00677 LONGLONG li; 00678 00679 switch (Desc->Type) { 00680 case CmResourceTypePort: 00681 li = Desc->u.Port.MaximumAddress.QuadPart; 00682 break; 00683 00684 case CmResourceTypeMemory: 00685 li = Desc->u.Memory.MaximumAddress.QuadPart; 00686 break; 00687 00688 case CmResourceTypeInterrupt: 00689 li = Desc->u.Interrupt.MaximumVector; 00690 break; 00691 00692 case CmResourceTypeDma: 00693 li = Desc->u.Dma.MaximumChannel; 00694 break; 00695 } 00696 00697 return li; 00698 } 00699 00700 00701 BOOLEAN 00702 IopGenNextValidResourceList ( 00703 IN ULONG level, 00704 IN PDIR_RESOURCE_LIST CurList, 00705 IN PDIR_RESREQ_LIST Dir 00706 ) 00707 /*++ 00708 00709 Routine Description: 00710 Attempts to find a setting for every required resource in the CurList 00711 00712 Arguments: 00713 00714 level - Index to which required resource list to start finding resources from 00715 CurList - List of required resources being processed 00716 Dir - The top directory of resources 00717 00718 PassNo - The pass # 00719 1 - Preferred settings only 00720 2 - Available settings 00721 3 - Available settings, find conflict to report 00722 00723 Return Value 00724 00725 TRUE if all required resources found available settings 00726 00727 --*/ 00728 { 00729 ULONG collisionlevel; 00730 BOOLEAN flag; 00731 00732 do { 00733 if (level > CurList->LastLevel) { 00734 CurList->LastLevel = level; 00735 } 00736 00737 flag = IopGenNextValidDescriptor ( 00738 level, 00739 CurList, 00740 Dir, 00741 &collisionlevel 00742 ); 00743 00744 if (flag == FALSE) { 00745 // 00746 // Could not generate a valid descriptor setting 00747 // 00748 00749 if (level == 0 || collisionlevel == -1) { 00750 // 00751 // No more settings 00752 // 00753 00754 CurList->FailedLevel = level; 00755 return FALSE; 00756 } 00757 00758 // 00759 // Backup to the collision level and try anew 00760 // 00761 00762 while (level > collisionlevel) { 00763 CurList->RequiredResource[level]->CurLoc = 0; 00764 CurList->RequiredResource[level]->RunLen = 0; 00765 level--; 00766 } 00767 continue; 00768 } 00769 00770 if (CurList->RequiredResource[level]->PassNo == 1 && 00771 CurList->RequiredResource[level]->CurPref < 00772 CurList->RequiredResource[level]->BestPref) { 00773 00774 // 00775 // First time through don't mess with unpreferred settings, continue 00776 // looking at this level 00777 // 00778 00779 continue; 00780 } 00781 00782 // 00783 // Go to next level 00784 // 00785 00786 level++; 00787 } while (level < CurList->NoRequiredResources); 00788 00789 // 00790 // Determine list's preference 00791 // (only used on PassNo > 1 since PassNo == 1 only suceedes when 00792 // preferred settings are used) 00793 // 00794 00795 CurList->CurPref = 0; 00796 for (level = 0; level < CurList->NoRequiredResources; level++) { 00797 CurList->CurPref += CurList->RequiredResource[level]->CurPref; 00798 } 00799 00800 // 00801 // Got a setting for each requested resource, return TRUE 00802 // 00803 00804 return TRUE; 00805 } 00806 00807 00808 00809 BOOLEAN 00810 IopGenNextValidDescriptor ( 00811 IN ULONG level, 00812 IN PDIR_RESOURCE_LIST CurList, 00813 IN PDIR_RESREQ_LIST Dir, 00814 OUT PULONG collisionlevel 00815 ) 00816 /*++ 00817 00818 Routine Description: 00819 00820 Arguments: 00821 00822 Return Value 00823 00824 TRUE if descriptor setting was found 00825 FALSE if no setting found 00826 00827 --*/ 00828 { 00829 PDIR_REQUIRED_RESOURCE Res, CRes; 00830 PIO_RESOURCE_DESCRIPTOR *Desc, DescTmp; 00831 LONGLONG BAddr, EAddr; 00832 LONGLONG NBAddr; 00833 LONGLONG DescMax, MinAddr, LiILen, LiELen, LiTmp; 00834 LONGLONG NAddr, BusMax, BusMin, PBAddr; 00835 ULONG indx, j, k, NBLoc; 00836 ULONG DescLen, Align, len; 00837 BOOLEAN NBSet, flag, flag2; 00838 LONG Preference, NPref; 00839 UCHAR TType, NTType; 00840 TENTRY Trans, NTrans; 00841 00842 Res = CurList->RequiredResource[level]; 00843 00844 *collisionlevel = (ULONG) -1; // assume no collision 00845 NBSet = FALSE; 00846 00847 do { 00848 Desc = &Res->IoResourceDescriptor[Res->CurLoc]; 00849 00850 if (!Res->RunLen) { 00851 00852 if (Res->CurLoc >= Res->NoAlternatives) { 00853 // 00854 // No more runs 00855 // 00856 return FALSE; 00857 } 00858 00859 // 00860 // Get number of alternatives which are of the same type 00861 // (alternatives have been sorted into types). 00862 // 00863 00864 Res->Type = Desc[0]->Type; 00865 for (j=Res->CurLoc; j < Res->NoAlternatives; j++) { 00866 if (Res->Type != Res->IoResourceDescriptor[j]->Type) { 00867 break; 00868 } 00869 } 00870 00871 Res->RunLen = j - Res->CurLoc; 00872 if (!Res->RunLen) { 00873 // 00874 // Out of alternatives for this resource 00875 // 00876 00877 return FALSE; 00878 } 00879 00880 // 00881 // Start at beginning of bus options 00882 // 00883 00884 Res->CurBusLoc = 0; 00885 00886 DescTmp = Dir->BusDir->Alternative->ResourceByType[Res->Type]->IoResourceDescriptor[0]; 00887 00888 if (!DescTmp) { 00889 // 00890 // There are no bus settings for this type of resource 00891 // 00892 00893 return FALSE; 00894 } 00895 00896 Res->CurBusMin = IO_DESC_MIN (DescTmp); 00897 Res->CurBusMax = IO_DESC_MAX (DescTmp); 00898 NAddr = Res->CurBusMax; 00899 00900 } else { 00901 00902 // 00903 // Decrease current value by one - this will cause this 00904 // function to find the next acceptable value. 00905 // 00906 00907 NAddr = Res->CurBAddr - 1; 00908 } 00909 00910 // 00911 // Return the next available address from NAddr 00912 // 00913 00914 DescLen = Res->RunLen; 00915 BusMax = Res->CurBusMax; 00916 BusMin = Res->CurBusMin; 00917 00918 NBAddr = 0; 00919 00920 for (; ;) { 00921 00922 // 00923 // Loop for each descriptor in this run and pick the numerical highest 00924 // value available for this resource 00925 // 00926 00927 for (indx=0; indx < DescLen ; indx++) { 00928 00929 // 00930 // Set len, Align, MinAddr, DescMax 00931 // 00932 00933 DescTmp = Desc[indx]; 00934 switch (DescTmp->Type) { 00935 case CmResourceTypePort: 00936 len = DescTmp->u.Port.Length; 00937 Align = DescTmp->u.Port.Alignment; 00938 MinAddr = DescTmp->u.Port.MinimumAddress.QuadPart; 00939 DescMax = DescTmp->u.Port.MaximumAddress.QuadPart; 00940 break; 00941 00942 case CmResourceTypeMemory: 00943 len = DescTmp->u.Memory.Length; 00944 Align = DescTmp->u.Memory.Alignment; 00945 MinAddr = DescTmp->u.Memory.MinimumAddress.QuadPart; 00946 DescMax = DescTmp->u.Memory.MaximumAddress.QuadPart; 00947 break; 00948 00949 case CmResourceTypeInterrupt: 00950 len = 1; 00951 Align = 1; 00952 MinAddr = DescTmp->u.Interrupt.MinimumVector; 00953 DescMax = DescTmp->u.Interrupt.MaximumVector; 00954 break; 00955 00956 case CmResourceTypeDma: 00957 len = 1; 00958 Align = 1; 00959 MinAddr = DescTmp->u.Dma.MinimumChannel; 00960 DescMax = DescTmp->u.Dma.MaximumChannel; 00961 break; 00962 00963 } 00964 00965 // 00966 // MinAddr is the largest of Descriptor-MinAddr, Bus-MinAddr, or 00967 // NextBest-MinAddr. Don't go below the last MinAddr (NBAddr). 00968 // So the search is from NAddr -to-> NBAddr 00969 // 00970 00971 if (BusMin > MinAddr) { 00972 MinAddr = BusMin; 00973 } 00974 00975 if (NBAddr > MinAddr) { 00976 MinAddr = NBAddr; 00977 } 00978 00979 BAddr = NAddr; 00980 LiELen = len; // Exclusive length 00981 LiILen = len - 1; // Inclusive length 00982 00983 // 00984 // Set initial preference 00985 // 00986 00987 Preference = 0; 00988 if (Res->PassNo == 1) { 00989 if (DescTmp->Option & IO_RESOURCE_PREFERRED) { 00990 // Account for device's preference durning first pass 00991 Preference = 1; 00992 00993 } else if (Res->BestPref) { 00994 // Some resource in this list has a prefernce, but it's not 00995 // this one. Since this is the PassNo == 1 skip non-preferred. 00996 continue; 00997 } 00998 } 00999 01000 01001 // 01002 // Loop while BAddr being tested is above MinAddr 01003 // 01004 01005 while (BAddr >= MinAddr) { 01006 01007 EAddr = BAddr + LiILen; 01008 if (EAddr > DescMax) { 01009 // 01010 // The ending address is above the requested limit 01011 // compute the best possible beginning address 01012 // 01013 01014 BAddr = DescMax - LiILen; 01015 continue; 01016 } 01017 01018 if (EAddr > BusMax) { 01019 // 01020 // The ending address is above the bus'es limit 01021 // compute best possible beginning address 01022 // 01023 01024 BAddr = BusMax - LiILen; 01025 continue; 01026 } 01027 01028 // 01029 // Verify selection is within any user supplied requirements 01030 // (this is from RegistryPath\AssignResources) 01031 // 01032 01033 if (Dir->UserDir) { 01034 CRes = Dir->UserDir->Alternative->ResourceByType[Res->Type]; 01035 flag = FALSE; 01036 PBAddr = -1; 01037 01038 for (j=0; j < CRes->NoAlternatives; j++) { 01039 LiTmp = IO_DESC_MIN (CRes->IoResourceDescriptor[j]); 01040 01041 if (BAddr < LiTmp) { 01042 // 01043 // Beginning address is before user's range, check 01044 // next descriptor 01045 // 01046 01047 continue; 01048 } 01049 01050 LiTmp = IO_DESC_MAX (CRes->IoResourceDescriptor[j]); 01051 if (EAddr > LiTmp) { 01052 01053 // 01054 // Ending address is above user's range. 01055 // Check for new BAddr to continue from 01056 // 01057 01058 LiTmp = LiTmp - LiILen; 01059 if (LiTmp > PBAddr && LiTmp < BAddr) { 01060 01061 // 01062 // Update next possible setting 01063 // 01064 01065 PBAddr = LiTmp; 01066 } 01067 continue; 01068 } 01069 01070 // 01071 // Within user's requested range 01072 // 01073 01074 flag = TRUE; 01075 break; 01076 } 01077 01078 if (!flag) { 01079 BAddr = PBAddr; 01080 continue; 01081 } 01082 } 01083 01084 // 01085 // So far resource looks good - translate it to system global 01086 // settings and verify resource is available 01087 // 01088 01089 LiTmp = 0; 01090 switch (Res->Type) { 01091 case CmResourceTypePort: 01092 case CmResourceTypeMemory: 01093 j = k = Res->Type == CmResourceTypePort ? 1 : 0; 01094 flag = HalTranslateBusAddress ( 01095 Dir->IoResourceReq->InterfaceType, 01096 Dir->IoResourceReq->BusNumber, 01097 *((PPHYSICAL_ADDRESS) &BAddr), 01098 &j, 01099 (PPHYSICAL_ADDRESS) &Trans.BAddr 01100 ); 01101 01102 // precheck alignment on first half 01103 if (Align > 1 && (Trans.BAddr & 0xffffffff00000000) == 0) { 01104 RtlEnlargedUnsignedDivide ( 01105 *((PULARGE_INTEGER) &Trans.BAddr), Align, (PULONG) &LiTmp); 01106 01107 if (LiTmp & 0xffffffff) { 01108 break; // alignment is off - don't bother with second translation 01109 } 01110 } 01111 01112 flag2 = HalTranslateBusAddress ( 01113 Dir->IoResourceReq->InterfaceType, 01114 Dir->IoResourceReq->BusNumber, 01115 *((PPHYSICAL_ADDRESS) &EAddr), 01116 &k, 01117 (PPHYSICAL_ADDRESS) &Trans.EAddr 01118 ); 01119 01120 TType = j == 1 ? CmResourceTypePort : CmResourceTypeMemory; 01121 Trans.Affinity = (KAFFINITY) -1; 01122 01123 if (flag == FALSE || flag2 == FALSE || j != k) { 01124 // HalAdjustResourceList should ensure that the returned range 01125 // for the bus is within the bus limits and no translation 01126 // within those limits should ever fail 01127 01128 DBGMSG ("IopGenNextValidDescriptor: Error return for HalTranslateBusAddress\n"); 01129 return FALSE; 01130 } 01131 break; 01132 01133 case CmResourceTypeInterrupt: 01134 TType = CmResourceTypeInterrupt; 01135 01136 Trans.Affinity = 0; 01137 Trans.BAddr = HalGetInterruptVector ( 01138 Dir->IoResourceReq->InterfaceType, 01139 Dir->IoResourceReq->BusNumber, 01140 (ULONG) BAddr, // bus level 01141 (ULONG) BAddr, // bus vector 01142 (PKIRQL) &j, // translated level 01143 &Trans.Affinity 01144 ); 01145 01146 Trans.EAddr = Trans.BAddr; 01147 01148 if (Trans.Affinity == 0) { 01149 // skip vectors which can not be translated 01150 LiTmp = 1; 01151 } 01152 break; 01153 01154 case CmResourceTypeDma: 01155 TType = CmResourceTypeDma; 01156 Trans.BAddr = BAddr; 01157 Trans.EAddr = EAddr; 01158 Trans.Affinity = (KAFFINITY) -1; 01159 break; 01160 01161 default: 01162 DBGMSG ("IopGenNextValidDescriptor: Invalid resource type\n"); 01163 return FALSE; 01164 } 01165 01166 // 01167 // Check bias from translation 01168 // 01169 01170 if (LiTmp != 0) { 01171 01172 // move to next address 01173 BAddr = BAddr - LiTmp; 01174 continue; 01175 } 01176 01177 // 01178 // Check alignment restrictions 01179 // 01180 01181 if (Align > 1) { 01182 if ((Trans.BAddr & 0xffffffff00000000) == 0) { 01183 RtlEnlargedUnsignedDivide ( 01184 *((PULARGE_INTEGER) &Trans.BAddr), Align, (PULONG) &LiTmp); 01185 } else { 01186 RtlExtendedLargeIntegerDivide ( 01187 *((PLARGE_INTEGER) &Trans.BAddr), Align, (PULONG) &LiTmp); 01188 01189 } 01190 01191 if (LiTmp != 0) { 01192 // 01193 // Starting address not on proper alignment, move to next 01194 // aligned address 01195 // 01196 01197 BAddr = BAddr - LiTmp; 01198 continue; 01199 } 01200 } 01201 01202 // 01203 // Check for collision with other settings being considered 01204 // 01205 01206 for (j=0; j < level; j++) { 01207 if (CurList->RequiredResource[j]->TType == TType) { 01208 CRes = CurList->RequiredResource[j]; 01209 if (DoesTEntryCollide (Trans, CRes->Trans)) { 01210 // collision 01211 break; 01212 } 01213 } 01214 } 01215 01216 if (j < level) { 01217 // 01218 // Current BAddr - EAddr collides with CRes selection 01219 // 01220 01221 if (j < *collisionlevel) { 01222 01223 // 01224 // If we fail, back up to this level 01225 // 01226 01227 *collisionlevel = j; 01228 } 01229 01230 // 01231 // Try BAddr just best address before collision range 01232 // 01233 01234 BAddr = CRes->CurBAddr - LiELen; 01235 continue; 01236 } 01237 01238 // 01239 // Check InUse system resources to verify this range is available. 01240 // 01241 01242 j = IopFindCollisionInTList (&Trans, Dir->InUseResources.ByType[TType]); 01243 if (j) { 01244 if (Res->PassNo == 3) { 01245 // 01246 // Track this collision 01247 // 01248 01249 IopPickupCollisionInTList ( 01250 CurList, 01251 Res->Type, 01252 BAddr, 01253 &Trans, 01254 Dir->InUseResources.ByType[TType] 01255 ); 01256 } 01257 01258 // 01259 // This range collides with a resource which is already in use. 01260 // Moving begining address to next possible setting 01261 // 01262 01263 BAddr = BAddr - j; 01264 continue; 01265 } 01266 01267 // 01268 // Check to see if this resource selection is being shared 01269 // 01270 01271 j = IopFindCollisionInTList (&Trans, Dir->InUseSharableResources.ByType[TType]); 01272 if (j) { 01273 // 01274 // Current range collided with a resource which is already in use, 01275 // but is sharable. If the current required resource is not sharable, 01276 // then skip this range; otherwise, reduce the preference for this setting. 01277 // 01278 01279 if (Res->PassNo == 1 || Desc[indx]->ShareDisposition != CmResourceShareShared) { 01280 if (Res->PassNo == 3) { 01281 // 01282 // Track this collision 01283 // 01284 01285 IopPickupCollisionInTList ( 01286 CurList, 01287 Res->Type, 01288 BAddr, 01289 &Trans, 01290 Dir->InUseSharableResources.ByType[TType] 01291 ); 01292 } 01293 01294 // required resource can't be shared, move to next possible setting or 01295 // this is the Pass#1 and we don't bother with non-preferred settings 01296 01297 BAddr = BAddr - j; 01298 continue; 01299 } 01300 01301 Preference -= 4; 01302 } 01303 01304 // 01305 // Check to see if this resource reserved, but sharable 01306 // 01307 01308 j = IopFindCollisionInTList (&Trans, Dir->ReservedSharableResources.ByType[TType]); 01309 if (j) { 01310 // 01311 // Current range collosided with a resource which is in the 01312 // ReservedResource list, but is marked sharable. These resources 01313 // are treated as non-preferred regions. 01314 // 01315 01316 if (Res->PassNo == 1) { 01317 // don't bother with non-preferred settings on the first pass. 01318 01319 BAddr = BAddr - j; 01320 continue; 01321 } 01322 01323 Preference -= 2; 01324 } 01325 01326 // 01327 // BAddr - EAddr is a good selection 01328 // (BAddr is greater than NBAddr) 01329 // 01330 01331 NBSet = TRUE; 01332 NBAddr = BAddr; 01333 01334 NTType = TType; 01335 NTrans = Trans; 01336 NPref = Preference; 01337 NBLoc = Res->CurLoc + indx; 01338 break; // check next selector in run 01339 01340 } // next BAddr 01341 } // next descriptor in run 01342 01343 if (NBSet) { 01344 // SUCCESS We have a hit 01345 break; 01346 } 01347 01348 // 01349 // No setting so far, move to next bus ordering descriptor 01350 // 01351 01352 Res->CurBusLoc++; 01353 CRes = Dir->BusDir->Alternative->ResourceByType[Res->Type]; 01354 01355 if (Res->CurBusLoc >= CRes->NoAlternatives) { 01356 // 01357 // no more bus ordering descriptors, move to next ResRun 01358 // 01359 01360 Res->CurLoc += Res->RunLen; 01361 Res->RunLen = 0; 01362 break; 01363 } 01364 01365 DescTmp = CRes->IoResourceDescriptor[Res->CurBusLoc]; 01366 Res->CurBusMin = IO_DESC_MIN (DescTmp); 01367 Res->CurBusMax = IO_DESC_MAX (DescTmp); 01368 BusMin = Res->CurBusMin; 01369 BusMax = Res->CurBusMax; 01370 NAddr = Res->CurBusMax; 01371 } // next bus ordering descriptor 01372 01373 } while (!NBSet); 01374 01375 // 01376 // We have a setting for this resource. Remember it and return. 01377 // 01378 01379 Res->TType = NTType; // used to detect internal conflicts of translated values 01380 Res->Trans = NTrans; // " 01381 01382 Res->CurPref = NPref; // Return prefernce of setting 01383 Res->CurBAddr = NBAddr; // Return raw BAddr of resource (used by Phase3&4) 01384 Res->CurBLoc = NBLoc; // Return location of resource (used by Phase3&4) 01385 return TRUE; 01386 } 01387 01388 01389 ULONG 01390 IopFindCollisionInTList ( 01391 IN PTENTRY SEntry, 01392 IN PLTENTRY List 01393 ) 01394 /*++ 01395 01396 Routine Description: 01397 01398 Checks to see if there's a collision between the source TENTRY and the list 01399 of TENTRIES passed by PLTENTRY. 01400 01401 Arguments: 01402 01403 Return Value 01404 01405 Returns the skew amount required to continue searching for next possible 01406 setting and a pointer to the conflicted entry. 01407 A zero skew means no collision occured. 01408 01409 --*/ 01410 { 01411 LONGLONG LiTmp; 01412 TENTRY Source; 01413 ULONG i, j; 01414 01415 Source = *SEntry; 01416 while (List) { 01417 j = List->CurEntries; 01418 for (i=0; i < j; i++) { 01419 SEntry = List->Table+i; 01420 if (DoesTEntryCollide (Source, *SEntry)) { 01421 01422 LiTmp = Source.EAddr - SEntry->BAddr; 01423 return (ULONG) LiTmp + 1; 01424 } 01425 } 01426 List = List->Next; 01427 } 01428 return 0; 01429 } 01430 01431 VOID 01432 IopPickupCollisionInTList ( 01433 IN PDIR_RESOURCE_LIST CurList, 01434 IN UCHAR Type, 01435 IN LONGLONG BAddr, 01436 IN PTENTRY SEntry, 01437 IN PLTENTRY List 01438 ) 01439 { 01440 TENTRY Source; 01441 ULONG i, j, conflicts; 01442 01443 Source = *SEntry; 01444 01445 // 01446 // If resource already listed in easy collision list, skip it 01447 // 01448 01449 j = CurList->Conflict.NoConflicts; 01450 if (j > SCONFLICT) { 01451 j = SCONFLICT; 01452 } 01453 01454 for (i=0; i < j; i++) { 01455 if (CurList->Conflict.EasyConflict[i].BAddr == BAddr && 01456 CurList->Conflict.EasyConflict[i].Type == Type) { 01457 return ; 01458 } 01459 } 01460 01461 // 01462 // Add valid, but conflicting, resource setting to failed list 01463 // 01464 01465 conflicts = CurList->Conflict.NoConflicts; 01466 if (conflicts < SCONFLICT) { 01467 CurList->Conflict.EasyConflict[conflicts].Type = Type; 01468 CurList->Conflict.EasyConflict[conflicts].BAddr = BAddr; 01469 } 01470 01471 // 01472 // Find collision 01473 // 01474 01475 while (List) { 01476 j = List->CurEntries; 01477 for (i=0; i < j; i++) { 01478 SEntry = List->Table+i; 01479 if (DoesTEntryCollide (Source, *SEntry)) { 01480 01481 if (SEntry->Owner) { 01482 if (conflicts < SCONFLICT) { 01483 CurList->Conflict.EasyConflict[conflicts].Owner = SEntry->Owner; 01484 SEntry->Owner->InConflict.Flink = (PVOID) -1; 01485 } 01486 01487 if (SEntry->Owner->InConflict.Flink == NULL) { 01488 // 01489 // Add owner of this conflict to list of colliding owners 01490 // 01491 01492 InsertTailList (&CurList->Conflict.OtherConflicts, &SEntry->Owner->InConflict); 01493 } 01494 01495 } 01496 01497 CurList->Conflict.NoConflicts += 1; 01498 return ; 01499 } 01500 } 01501 List = List->Next; 01502 } 01503 } 01504 01505 01506 STATIC PVOID 01507 IopAllocateDirPool ( 01508 IN PDIR_RESREQ_LIST Dir, 01509 IN ULONG Length 01510 ) 01511 /*++ 01512 01513 Routine Description: 01514 01515 Allocates pool and links the allocation to the DIR_RESREQ_LIST structure so it will be freed 01516 when the DIR_RESRES_LIST is freed. 01517 01518 WARNING: Just like ExAllocatePool this function needs to return memory aligned on 8 byte 01519 boundaries. 01520 01521 --*/ 01522 { 01523 PUSED_HEAP ph; 01524 01525 ph = (PUSED_HEAP) ExAllocatePool (PagedPool, Length+sizeof(USED_HEAP)); 01526 if (!ph) { 01527 return NULL; 01528 } 01529 01530 ph->FreeHeap = (PVOID) ph; 01531 PushEntryList (&Dir->AllocatedHeap, &ph->FreeLink); 01532 return (PVOID) (ph+1); 01533 } 01534 01535 01536 01537 PIO_RESOURCE_REQUIREMENTS_LIST 01538 IopGetResourceReqRegistryValue ( 01539 IN PDIR_RESREQ_LIST Dir, 01540 IN HANDLE KeyHandle, 01541 IN PWSTR ValueName 01542 ) 01543 /*++ 01544 01545 Routine Description: 01546 01547 Looks up the setting for ValueKey in KeyHandle and returns the 01548 data or NULL. If non-null, the memory was obtained via pool. 01549 01550 Arguments: 01551 01552 Return Value: 01553 01554 --*/ 01555 { 01556 PKEY_VALUE_FULL_INFORMATION KeyInformation; 01557 NTSTATUS status; 01558 PUCHAR Data; 01559 ULONG DataLength, Type; 01560 PIO_RESOURCE_REQUIREMENTS_LIST p; 01561 01562 for (; ;) { 01563 status = IopGetRegistryValue (KeyHandle, ValueName, &KeyInformation); 01564 if (!NT_SUCCESS(status)) { 01565 return NULL; 01566 } 01567 01568 // 01569 // Get pointer to data & length 01570 // 01571 01572 Type = KeyInformation->Type; 01573 Data = ((PUCHAR) KeyInformation + KeyInformation->DataOffset); 01574 DataLength = KeyInformation->DataLength; 01575 01576 // 01577 // Copy data to aligned paged pool buffer, and free non-paged pool 01578 // 01579 01580 p = (PIO_RESOURCE_REQUIREMENTS_LIST) IopAllocateDirPool (Dir, DataLength + sizeof (WCHAR)); 01581 if (!p) { 01582 ExFreePool (KeyInformation); 01583 return NULL; 01584 } 01585 01586 RtlCopyMemory (p, Data, DataLength); 01587 ExFreePool (KeyInformation); 01588 01589 if (Type == REG_SZ) { 01590 // 01591 // Forward to different entry - Need to copy name in order to get 01592 // space at the end to add the NULL terminator 01593 // 01594 01595 ValueName = (PWSTR) p; 01596 ValueName [DataLength / sizeof (WCHAR)] = 0; 01597 continue; 01598 } 01599 01600 // verify registry entry is of expected type 01601 if (Type != REG_RESOURCE_REQUIREMENTS_LIST) { 01602 return NULL; 01603 } 01604 01605 p->ListSize = DataLength; 01606 return p; 01607 } 01608 } 01609 01610 #endif 01611 01612 #if 0 01613 NTSTATUS 01614 IopAssignResourcesPhase1 ( 01615 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources, 01616 IN PIO_RESOURCE_REQUIREMENTS_LIST *pCopiedList 01617 ) 01618 /*++ 01619 01620 Routine Description: 01621 01622 Copies the callers supplied resource list and passes it to the HAL. The HAL 01623 then adjusts the requested resource list to be within any bus/system requirements 01624 the system may have. 01625 01626 Arguments: 01627 IoResources - Callers requested resource list 01628 *pCopiedList - Returned resource list (allocated from heap) 01629 01630 01631 --*/ 01632 { 01633 PIO_RESOURCE_LIST ResourceList; 01634 NTSTATUS status; 01635 ULONG cnt, length; 01636 PUCHAR FirstAddress, LastAddress; 01637 01638 PAGED_CODE(); 01639 01640 01641 // 01642 // Verify Version & Revision of data structure is set correctly 01643 // 01644 01645 if (IoResources->AlternativeLists == 0 || 01646 IoResources->Reserved[0] != 0 || 01647 IoResources->Reserved[1] != 0 || 01648 IoResources->Reserved[2] != 0) { 01649 DBGMSG ("IopAssignResourcesPhase1: Bad structure format\n"); 01650 return STATUS_INVALID_PARAMETER; 01651 } 01652 01653 // 01654 // Pass a copy of the list to the HAL for any adjustments 01655 // 01656 01657 // 01658 // Simple sanity check for size of callers RequestedResource list 01659 // 01660 01661 ResourceList = IoResources->List; 01662 FirstAddress = (PUCHAR) ResourceList; 01663 LastAddress = (PUCHAR) IoResources + IoResources->ListSize; 01664 01665 for (cnt=0; cnt < IoResources->AlternativeLists; cnt++) { 01666 if (ResourceList->Version != 1 || ResourceList->Revision < 1) { 01667 DBGMSG ("IopAssignResourcesPhase1: Invalid version #\n"); 01668 return STATUS_INVALID_PARAMETER; 01669 } 01670 01671 ResourceList = (PIO_RESOURCE_LIST) 01672 (&ResourceList->Descriptors[ResourceList->Count]); 01673 01674 01675 if ((PUCHAR) ResourceList < FirstAddress || 01676 (PUCHAR) ResourceList > LastAddress) { 01677 DBGMSG ("IopAssignResourcesPhase1: IO_RESOURCE_LIST.ListSize too small\n"); 01678 return STATUS_INVALID_PARAMETER; 01679 } 01680 } 01681 01682 length = (ULONG) ((PUCHAR) ResourceList - (PUCHAR) IoResources); 01683 01684 // 01685 // Copy user's passed in list 01686 // 01687 01688 *pCopiedList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (PagedPool, length); 01689 01690 if (!*pCopiedList) { 01691 return STATUS_INSUFFICIENT_RESOURCES; 01692 } 01693 01694 RtlCopyMemory (*pCopiedList, IoResources, length); 01695 (*pCopiedList)->ListSize = length; 01696 01697 // 01698 // Let hal adjust the requested list 01699 // 01700 01701 status = HalAdjustResourceList (pCopiedList); 01702 if (!NT_SUCCESS(status)) { 01703 DBGMSG ("IopAssignResourcesPhase1: HalAdjustResourceList failed\n"); 01704 ExFreePool (*pCopiedList); 01705 return status; 01706 } 01707 01708 return STATUS_SUCCESS; 01709 } 01710 01711 01712 NTSTATUS 01713 IopAssignResourcesPhase2 ( 01714 IN PDIR_RESREQ_LIST Dir, 01715 IN PUNICODE_STRING DriverClassName, 01716 IN PDRIVER_OBJECT DriverObject, 01717 IN PDEVICE_OBJECT DeviceObject 01718 ) 01719 /* 01720 01721 Routine Description: 01722 01723 Reads the ResourceMap in the registry and builds a canonical list of 01724 all in use resources ranges by resource type. 01725 01726 Arguments: 01727 01728 Dir - InUseResources & InUseShareableResources are filled in by this call. 01729 01730 */ 01731 { 01732 HANDLE ResourceMap, ClassKeyHandle, DriverKeyHandle; 01733 ULONG ClassKeyIndex, DriverKeyIndex, DriverValueIndex, Index; 01734 POBJECT_NAME_INFORMATION ObNameInfo; 01735 PCM_RESOURCE_LIST CmResList; 01736 PCM_FULL_RESOURCE_DESCRIPTOR CmFResDesc; 01737 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc; 01738 UNICODE_STRING unicodeString; 01739 UNICODE_STRING KeyName, TranslatedName, DriverName, DClassName; 01740 PVOID p2; 01741 ULONG BufferSize; 01742 union { 01743 PVOID Buffer; 01744 PKEY_BASIC_INFORMATION KeyBInf; 01745 PKEY_FULL_INFORMATION KeyFInf; 01746 PKEY_VALUE_FULL_INFORMATION VKeyFInf; 01747 } U; 01748 PUCHAR LastAddr; 01749 ULONG junk, Length, i, j, TranslatedStrLen, BusTranslatedStrLen; 01750 PWSTR pw; 01751 NTSTATUS status; 01752 BOOLEAN sameClass, sameDriver; 01753 BOOLEAN flag; 01754 POWNER Owner; 01755 LONGLONG li; 01756 01757 PAGED_CODE(); 01758 01759 // 01760 // Allocate a scratch buffer. Use BUFFSERSIZE or the sizeof the largest 01761 // value in SystemResources\ReservedResources 01762 // 01763 01764 U.Buffer = Dir->Buffer; 01765 U.KeyFInf->MaxValueNameLen = U.KeyFInf->MaxValueDataLen = 0; 01766 ZwQueryKey( Dir->RegHandle[HRESERVEDRESOURCES], 01767 KeyFullInformation, 01768 U.KeyFInf, 01769 BUFFERSIZE, 01770 &junk ); 01771 01772 Length = sizeof( KEY_VALUE_FULL_INFORMATION ) + 01773 U.KeyFInf->MaxValueNameLen + U.KeyFInf->MaxValueDataLen + sizeof(UNICODE_NULL); 01774 01775 BufferSize = Length > BUFFERSIZE ? Length : BUFFERSIZE; 01776 U.Buffer = ExAllocatePool (PagedPool, BufferSize); 01777 if (!U.Buffer) { 01778 return STATUS_INSUFFICIENT_RESOURCES; 01779 } 01780 01781 // 01782 // Build translated registry name to watch for 01783 // 01784 01785 ObNameInfo = (POBJECT_NAME_INFORMATION) Dir->Buffer; 01786 if (DeviceObject) { 01787 status = ObQueryNameString (DeviceObject, ObNameInfo, BUFFERSIZE, &Length); 01788 if (!NT_SUCCESS(status)) { 01789 return status; 01790 } 01791 } else { 01792 ObNameInfo->Name.Length = 0; 01793 ObNameInfo->Name.Buffer = (PVOID) ((PUCHAR) Dir->Buffer + sizeof(OBJECT_NAME_INFORMATION)); 01794 } 01795 01796 // 01797 // Handle the case when the DeviceObject was created 01798 // without a name 01799 // 01800 if (ObNameInfo->Name.Buffer == NULL) { 01801 ObNameInfo->Name.Length = 0; 01802 ObNameInfo->Name.Buffer = (PVOID) ((PUCHAR) Dir->Buffer + sizeof(OBJECT_NAME_INFORMATION)); 01803 } 01804 01805 ObNameInfo->Name.MaximumLength = BUFFERSIZE - sizeof(OBJECT_NAME_INFORMATION); 01806 RtlAppendUnicodeToString (&ObNameInfo->Name, IopWstrTranslated); 01807 01808 TranslatedName.Length = ObNameInfo->Name.Length; 01809 TranslatedName.MaximumLength = ObNameInfo->Name.Length; 01810 TranslatedName.Buffer = IopAllocateDirPool (Dir, TranslatedName.Length); 01811 if (!TranslatedName.Buffer) { 01812 return STATUS_INSUFFICIENT_RESOURCES; 01813 } 01814 RtlCopyMemory (TranslatedName.Buffer, ObNameInfo->Name.Buffer, TranslatedName.Length); 01815 for (TranslatedStrLen=0; IopWstrTranslated[TranslatedStrLen]; TranslatedStrLen++) ; 01816 for (BusTranslatedStrLen=0; IopWstrBusTranslated[BusTranslatedStrLen]; BusTranslatedStrLen++) ; 01817 TranslatedStrLen *= sizeof (WCHAR); 01818 BusTranslatedStrLen *= sizeof (WCHAR); 01819 01820 // 01821 // Build driver name to watch for 01822 // 01823 01824 status = ObQueryNameString (DriverObject, ObNameInfo, BUFFERSIZE, &Length); 01825 if (!NT_SUCCESS(status)) { 01826 return status; 01827 } 01828 01829 i = 0; 01830 pw = ObNameInfo->Name.Buffer; 01831 while (*pw) { 01832 if (*pw++ == OBJ_NAME_PATH_SEPARATOR) { 01833 i = pw - ObNameInfo->Name.Buffer; 01834 } 01835 } 01836 01837 Length = ObNameInfo->Name.Length - i * sizeof (WCHAR); 01838 DriverName.Length = (USHORT) Length; 01839 DriverName.MaximumLength = (USHORT) Length; 01840 DriverName.Buffer = IopAllocateDirPool (Dir, Length); 01841 if (!DriverName.Buffer) { 01842 return STATUS_INSUFFICIENT_RESOURCES; 01843 } 01844 RtlCopyMemory (DriverName.Buffer, ObNameInfo->Name.Buffer + i, Length); 01845 01846 // 01847 // If no give driver class, use default 01848 // 01849 01850 if (!DriverClassName) { 01851 RtlInitUnicodeString( &DClassName, IopWstrOtherDrivers ); 01852 DriverClassName = &DClassName; 01853 } 01854 01855 // 01856 // Walk resource map and collect any inuse resources 01857 // 01858 01859 ResourceMap = Dir->RegHandle[HRESOURCE_MAP]; 01860 ClassKeyIndex = 0; 01861 01862 ClassKeyHandle = INVALID_HANDLE; 01863 DriverKeyHandle = INVALID_HANDLE; 01864 01865 while (NT_SUCCESS(status)) { 01866 01867 // 01868 // Get the class information 01869 // 01870 01871 status = ZwEnumerateKey( ResourceMap, 01872 ClassKeyIndex++, 01873 KeyBasicInformation, 01874 U.KeyBInf, 01875 BufferSize, 01876 &junk ); 01877 01878 if (!NT_SUCCESS( status )) { 01879 break; 01880 } 01881 01882 01883 // 01884 // Create a UNICODE_STRING using the counted string passed back to 01885 // us in the information structure, and open the class key. 01886 // 01887 01888 KeyName.Buffer = (PWSTR) U.KeyBInf->Name; 01889 KeyName.Length = (USHORT) U.KeyBInf->NameLength; 01890 KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength; 01891 01892 status = IopOpenRegistryKey( &ClassKeyHandle, 01893 ResourceMap, 01894 &KeyName, 01895 KEY_READ, 01896 FALSE ); 01897 01898 if (!NT_SUCCESS( status )) { 01899 break; 01900 } 01901 01902 // 01903 // Check if we are in the same call node. 01904 // 01905 01906 sameClass = RtlEqualUnicodeString( DriverClassName, &KeyName, TRUE ); 01907 01908 DriverKeyIndex = 0; 01909 while (NT_SUCCESS (status)) { 01910 01911 // 01912 // Get the class information 01913 // 01914 01915 status = ZwEnumerateKey( ClassKeyHandle, 01916 DriverKeyIndex++, 01917 KeyBasicInformation, 01918 U.KeyBInf, 01919 BufferSize, 01920 &junk ); 01921 01922 if (!NT_SUCCESS( status )) { 01923 break; 01924 } 01925 01926 // 01927 // Create a UNICODE_STRING using the counted string passed back to 01928 // us in the information structure, and open the class key. 01929 // 01930 // This is read from the key we created, and the name 01931 // was NULL terminated. 01932 // 01933 01934 KeyName.Buffer = (PWSTR) IopAllocateDirPool (Dir, U.KeyBInf->NameLength); 01935 if (!KeyName.Buffer) { 01936 status = STATUS_INSUFFICIENT_RESOURCES; 01937 break; 01938 } 01939 01940 RtlCopyMemory (KeyName.Buffer, U.KeyBInf->Name, U.KeyBInf->NameLength); 01941 KeyName.Length = (USHORT) U.KeyBInf->NameLength; 01942 KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength; 01943 01944 status = IopOpenRegistryKey( &DriverKeyHandle, 01945 ClassKeyHandle, 01946 &KeyName, 01947 KEY_READ, 01948 FALSE ); 01949 01950 if (!NT_SUCCESS( status )) { 01951 break; 01952 } 01953 // 01954 // Check if we are in the same call node. 01955 // 01956 01957 sameDriver = sameClass && RtlEqualUnicodeString( &DriverName, &KeyName, TRUE ); 01958 01959 // 01960 // Get full information for that key so we can get the 01961 // information about the data stored in the key. 01962 // 01963 01964 status = ZwQueryKey( DriverKeyHandle, 01965 KeyFullInformation, 01966 U.KeyFInf, 01967 BufferSize, 01968 &junk ); 01969 01970 if (!NT_SUCCESS( status )) { 01971 break; 01972 } 01973 01974 Length = sizeof( KEY_VALUE_FULL_INFORMATION ) + 01975 U.KeyFInf->MaxValueNameLen + U.KeyFInf->MaxValueDataLen + sizeof(UNICODE_NULL); 01976 01977 if (Length > BufferSize) { 01978 01979 // 01980 // Get a larger buffer 01981 // 01982 01983 p2 = ExAllocatePool (PagedPool, Length); 01984 if (!p2) { 01985 status = STATUS_INSUFFICIENT_RESOURCES; 01986 break; 01987 } 01988 01989 ExFreePool (U.Buffer); 01990 U.Buffer = p2; 01991 BufferSize = Length; 01992 } 01993 01994 DriverValueIndex = 0; 01995 for (; ;) { 01996 status = ZwEnumerateValueKey( DriverKeyHandle, 01997 DriverValueIndex++, 01998 KeyValueFullInformation, 01999 U.VKeyFInf, 02000 BufferSize, 02001 &junk ); 02002 02003 if (!NT_SUCCESS( status )) { 02004 break; 02005 } 02006 02007 // 02008 // If this is not a translated resource list, skip it. 02009 // 02010 02011 i = U.VKeyFInf->NameLength; 02012 if (i < TranslatedStrLen || 02013 RtlCompareMemory ( 02014 ((PUCHAR) U.VKeyFInf->Name) + i - TranslatedStrLen, 02015 IopWstrTranslated, 02016 TranslatedStrLen 02017 ) != TranslatedStrLen 02018 ) { 02019 // does not end in IopWstrTranslated 02020 continue; 02021 } 02022 02023 // 02024 // If this is a bus translated resource list, ???? 02025 // 02026 02027 if (i >= BusTranslatedStrLen && 02028 RtlCompareMemory ( 02029 ((PUCHAR) U.VKeyFInf->Name) + i - BusTranslatedStrLen, 02030 IopWstrBusTranslated, 02031 BusTranslatedStrLen 02032 ) == BusTranslatedStrLen 02033 ) { 02034 02035 // ends in IopWstrBusTranslated 02036 continue; 02037 } 02038 02039 // 02040 // If these used resources are from the caller, then skip them 02041 // 02042 02043 if (sameDriver) { 02044 unicodeString.Buffer = (PWSTR) U.VKeyFInf->Name; 02045 unicodeString.Length = (USHORT) U.VKeyFInf->NameLength; 02046 unicodeString.MaximumLength = (USHORT) U.VKeyFInf->NameLength; 02047 if (RtlEqualUnicodeString (&unicodeString, &TranslatedName, TRUE)) { 02048 // it's the current allocated resources for this caller. 02049 // skip this entry. 02050 continue; 02051 } 02052 } 02053 02054 // 02055 // Build Owner structure for TLIST entries 02056 // 02057 02058 Owner = IopAllocateDirPool (Dir, sizeof (*Owner) + U.VKeyFInf->NameLength); 02059 if (!Owner) { 02060 status = STATUS_INSUFFICIENT_RESOURCES; 02061 break; 02062 } 02063 02064 Owner->InConflict.Flink = NULL; 02065 Owner->DeviceName.Buffer = NULL; 02066 02067 Owner->KeyName.Buffer = KeyName.Buffer; 02068 Owner->KeyName.Length = KeyName.Length; 02069 Owner->KeyName.MaximumLength = KeyName.MaximumLength; 02070 02071 if (U.VKeyFInf->Name[0] != L'.') { 02072 // strip off the .Translated part of the string 02073 U.VKeyFInf->NameLength -= TranslatedStrLen; 02074 02075 Owner->DeviceName.Buffer = Owner->UnicodeBuffer; 02076 Owner->DeviceName.Length = (USHORT) U.VKeyFInf->NameLength; 02077 Owner->DeviceName.MaximumLength = (USHORT) U.VKeyFInf->NameLength; 02078 RtlCopyMemory (Owner->UnicodeBuffer, U.VKeyFInf->Name, U.VKeyFInf->NameLength); 02079 } 02080 02081 // 02082 // Run the CmResourceList and save each InUse resource 02083 // 02084 02085 CmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) U.VKeyFInf + U.VKeyFInf->DataOffset); 02086 LastAddr = (PUCHAR) CmResList + U.VKeyFInf->DataLength; 02087 02088 CmFResDesc = CmResList->List; 02089 for (i=0; i < CmResList->Count && NT_SUCCESS(status) ; i++) { 02090 CmDesc = CmFResDesc->PartialResourceList.PartialDescriptors; 02091 if ((PUCHAR) (CmDesc+1) > LastAddr) { 02092 if (i) { 02093 DBGMSG ("IopAssignResourcesPhase2: a. CmResourceList in regitry too short\n"); 02094 } 02095 break; 02096 } 02097 02098 for (j=0; j < CmFResDesc->PartialResourceList.Count && NT_SUCCESS(status); j++) { 02099 if ((PUCHAR) (CmDesc+1) > LastAddr) { 02100 i = CmResList->Count; 02101 DBGMSG ("IopAssignResourcesPhase2: b. CmResourceList in regitry too short\n"); 02102 break; 02103 } 02104 02105 // 02106 // Add this CmDesc to the InUse list 02107 // 02108 02109 if (CmDesc->ShareDisposition == CmResourceShareShared) { 02110 status = IopAddCmDescriptorToInUseList ( 02111 Dir, 02112 &Dir->InUseSharableResources, 02113 CmDesc, 02114 Owner 02115 ); 02116 } else { 02117 status = IopAddCmDescriptorToInUseList ( 02118 Dir, 02119 &Dir->InUseResources, 02120 CmDesc, 02121 Owner 02122 ); 02123 02124 } 02125 CmDesc++; 02126 } 02127 02128 CmFResDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) CmDesc; 02129 } 02130 02131 } // next DriverValueIndex 02132 02133 if (DriverKeyHandle != INVALID_HANDLE) { 02134 ZwClose (DriverKeyHandle); 02135 DriverKeyHandle = INVALID_HANDLE; 02136 } 02137 02138 if (status == STATUS_NO_MORE_ENTRIES) { 02139 status = STATUS_SUCCESS; 02140 } 02141 02142 if (!NT_SUCCESS(status)) { 02143 break; 02144 } 02145 } // next DriverKeyIndex 02146 02147 if (ClassKeyHandle != INVALID_HANDLE) { 02148 ZwClose (ClassKeyHandle); 02149 ClassKeyHandle = INVALID_HANDLE; 02150 } 02151 02152 if (status == STATUS_NO_MORE_ENTRIES) { 02153 status = STATUS_SUCCESS; 02154 } 02155 02156 } // next ClassKeyIndex 02157 02158 if (status == STATUS_NO_MORE_ENTRIES) { 02159 status = STATUS_SUCCESS; 02160 } 02161 02162 02163 // 02164 // All reported resources are read in. 02165 // Now read in ...SystemResources\ReservedResources 02166 // (note: this infomration could easily be cached if needed) 02167 // 02168 02169 // 02170 // Build owner for all ResevedResources 02171 // 02172 02173 Owner = IopAllocateDirPool (Dir, sizeof (*Owner) + U.VKeyFInf->NameLength); 02174 if (Owner) { 02175 Owner->InConflict.Flink = NULL; 02176 Owner->DeviceName.Buffer = NULL; 02177 RtlInitUnicodeString (&Owner->KeyName, IopWstrReservedResources); 02178 } 02179 02180 Index = 0; 02181 while (NT_SUCCESS (status)) { 02182 status = ZwEnumerateValueKey( Dir->RegHandle[HRESERVEDRESOURCES], 02183 Index++, 02184 KeyValueFullInformation, 02185 U.VKeyFInf, 02186 BufferSize, 02187 &junk ); 02188 02189 if (!NT_SUCCESS( status )) { 02190 break; 02191 } 02192 02193 // 02194 // Run the CmResourceList and save each InUse resource 02195 // 02196 02197 CmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) U.VKeyFInf + U.VKeyFInf->DataOffset); 02198 LastAddr = (PUCHAR) CmResList + U.VKeyFInf->DataLength; 02199 02200 CmFResDesc = CmResList->List; 02201 for (i=0; i < CmResList->Count && NT_SUCCESS(status) ; i++) { 02202 CmDesc = CmFResDesc->PartialResourceList.PartialDescriptors; 02203 if ((PUCHAR) (CmDesc+1) > LastAddr) { 02204 DBGMSG ("IopAssignResourcesPhase2: c. CmResourceList in regitry too short\n"); 02205 break; 02206 } 02207 02208 for (j=0; j < CmFResDesc->PartialResourceList.Count && NT_SUCCESS(status); j++) { 02209 if ((PUCHAR) (CmDesc+1) > LastAddr) { 02210 i = CmResList->Count; 02211 DBGMSG ("IopAssignResourcesPhase2: d. CmResourceList in regitry too short\n"); 02212 break; 02213 } 02214 02215 // 02216 // Translate this descriptor to it's TRANSLATED values 02217 // 02218 02219 switch (CmDesc->Type) { 02220 case CmResourceTypePort: 02221 case CmResourceTypeMemory: 02222 junk = CmDesc->Type == CmResourceTypePort ? 1 : 0; 02223 li = *((LONGLONG UNALIGNED *) &CmDesc->u.Port.Start); 02224 flag = HalTranslateBusAddress ( 02225 CmFResDesc->InterfaceType, 02226 CmFResDesc->BusNumber, 02227 *((PPHYSICAL_ADDRESS) &li), 02228 &junk, 02229 (PPHYSICAL_ADDRESS) &li 02230 ); 02231 *((LONGLONG UNALIGNED *) &CmDesc->u.Port.Start) = li; 02232 CmDesc->Type = junk == 1 ? CmResourceTypePort : CmResourceTypeMemory; 02233 break; 02234 02235 case CmResourceTypeInterrupt: 02236 CmDesc->u.Interrupt.Vector = HalGetInterruptVector ( 02237 CmFResDesc->InterfaceType, 02238 CmFResDesc->BusNumber, 02239 CmDesc->u.Interrupt.Vector, // bus level 02240 CmDesc->u.Interrupt.Vector, // bus vector 02241 (PKIRQL) &junk, // translated level 02242 &CmDesc->u.Interrupt.Affinity 02243 ); 02244 flag = CmDesc->u.Interrupt.Affinity == 0 ? FALSE : TRUE; 02245 break; 02246 02247 case CmResourceTypeDma: 02248 // no translation 02249 flag = TRUE; 02250 break; 02251 02252 default: 02253 flag = FALSE; 02254 break; 02255 } 02256 02257 if (flag) { 02258 02259 // 02260 // Add it to the appropiate tlist 02261 // 02262 02263 if (CmDesc->ShareDisposition == CmResourceShareShared) { 02264 status = IopAddCmDescriptorToInUseList ( 02265 Dir, 02266 &Dir->ReservedSharableResources, 02267 CmDesc, 02268 Owner 02269 ); 02270 } else { 02271 status = IopAddCmDescriptorToInUseList ( 02272 Dir, 02273 &Dir->InUseResources, 02274 CmDesc, 02275 Owner 02276 ); 02277 } 02278 } 02279 02280 CmDesc++; 02281 } 02282 02283 CmFResDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) CmDesc; 02284 } 02285 02286 } // Next ReservedResource 02287 02288 if (status == STATUS_NO_MORE_ENTRIES) { 02289 status = STATUS_SUCCESS; 02290 } 02291 02292 ExFreePool (U.Buffer); 02293 return status; 02294 } 02295 02296 #if 0 02297 PDIR_RESOURCE_LIST 02298 IopAssignResourcesPhase3 ( 02299 IN PDIR_RESREQ_LIST Dir 02300 ) 02301 /*++ 02302 02303 Routine Description: 02304 02305 All the information to process the requested resource assignments has 02306 been read in & parsed. Phase3 cranks out the resource assignments. 02307 02308 Arguments: 02309 02310 --*/ 02311 { 02312 PDIR_RESOURCE_LIST CurList, BestList; 02313 PDIR_REQUIRED_RESOURCE ReqRes; 02314 ULONG level, i, j; 02315 LONG BestPref, Pref; 02316 02317 // 02318 // Run each list as pass 1 02319 // 02320 02321 PAGED_CODE(); 02322 02323 for (CurList = Dir->Alternative; CurList; CurList = CurList->Next) { 02324 02325 // set to pass 1 02326 for (i=0; i < CurList->NoRequiredResources; i++) { 02327 CurList->RequiredResource[i]->PassNo = 1; 02328 } 02329 02330 // find resouce settings for this list 02331 if (IopGenNextValidResourceList (0, CurList, Dir)) { 02332 02333 // found good settings, return them 02334 return CurList; 02335 } 02336 } 02337 02338 // 02339 // Try again - set last checked resource in any given list to pass2 to see if that will 02340 // unclog the problem. 02341 // 02342 02343 IDBGMSG ("First pass attempt at resource settings failed\n"); 02344 02345 for (CurList = Dir->Alternative; CurList; CurList = CurList->Next) { 02346 for (; ;) { 02347 // 02348 // Reset last level tried to look for any settings 02349 // 02350 02351 level = CurList->LastLevel; 02352 ReqRes = CurList->RequiredResource[level]; 02353 if (ReqRes->PassNo != 1) { 02354 // already trying pass 2 on this level 02355 break; 02356 } 02357 02358 ReqRes->PassNo = 2; 02359 for (j=0; j < ReqRes->NoAlternatives; j++) { 02360 ReqRes->IoResourceDescriptor[j]->Option &= ~IO_RESOURCE_PREFERRED; 02361 } 02362 02363 // 02364 // Back up to failed level and see if this list can now be satisfied 02365 // 02366 02367 level = CurList->NoRequiredResources; 02368 while (level > CurList->FailedLevel) { 02369 level--; 02370 CurList->RequiredResource[level]->CurLoc = 0; 02371 CurList->RequiredResource[level]->RunLen = 0; 02372 } 02373 02374 if (IopGenNextValidResourceList (level, CurList, Dir)) { 02375 // found good settings, return them 02376 return CurList; 02377 } 02378 02379 } // loop and clear next failed level 02380 } // loop and try next list 02381 02382 // 02383 // Try again, this time allow for a complete search. Clear all preferred settings and 02384 // move all levels to Pass2 02385 // 02386 02387 IDBGMSG ("Pass 2 attempt at resource settings failed\n"); 02388 02389 for (CurList = Dir->Alternative; CurList; CurList = CurList->Next) { 02390 for (i=0; i < CurList->NoRequiredResources; i++) { 02391 ReqRes = CurList->RequiredResource[i]; 02392 ReqRes->CurLoc = 0; 02393 ReqRes->RunLen = 0; 02394 ReqRes->PassNo = 2; 02395 02396 for (j=0; j < ReqRes->NoAlternatives; j++) { 02397 ReqRes->IoResourceDescriptor[j]->Option &= ~IO_RESOURCE_PREFERRED; 02398 } 02399 } 02400 } 02401 02402 BestPref = -999999; 02403 BestList = NULL; 02404 CurList = Dir->Alternative; 02405 level = 0; 02406 02407 while (CurList) { 02408 02409 // find resouce settings for this list 02410 if (IopGenNextValidResourceList (level, CurList, Dir)) { 02411 02412 // 02413 // We have useable settings, check to see how useable 02414 // 02415 02416 if (CurList->CurPref >= 0) { 02417 // 02418 // Nothing wrong with these settings, go use them 02419 // 02420 02421 IDBGMSG ("Pass3: Good hit\n"); 02422 return CurList; 02423 } 02424 02425 if (CurList->CurPref > BestPref) { 02426 02427 // 02428 // These are the best so far, remember them 02429 // 02430 02431 BestPref = CurList->CurPref; 02432 BestList = CurList; 02433 02434 for (i = 0; i < CurList->NoRequiredResources; i++) { 02435 ReqRes = CurList->RequiredResource[i]; 02436 ReqRes->Pass2HoldCurLoc = ReqRes->CurBLoc; 02437 ReqRes->Pass2HoldBAddr = ReqRes->CurBAddr; 02438 } 02439 } 02440 02441 // 02442 // Determine which level to back up too to continue searching from 02443 // 02444 02445 Pref = CurList->CurPref; 02446 level = CurList->NoRequiredResources; 02447 while (level && Pref <= BestPref) { 02448 level--; 02449 Pref -= CurList->RequiredResource[level]->CurPref; 02450 CurList->RequiredResource[level]->CurLoc = 0; 02451 CurList->RequiredResource[level]->RunLen = 0; 02452 } 02453 02454 if (CurList->RequiredResource[level]->PrefCnt > 16) { 02455 while (level && CurList->RequiredResource[level]->PrefCnt > 16) { 02456 level--; 02457 Pref -= CurList->RequiredResource[level]->CurPref; 02458 CurList->RequiredResource[level]->CurLoc = 0; 02459 CurList->RequiredResource[level]->RunLen = 0; 02460 } 02461 02462 if (level == 0) { 02463 // go with best setting so far 02464 break; 02465 } 02466 } 02467 02468 CurList->RequiredResource[level]->PrefCnt++; 02469 continue ; 02470 } 02471 02472 // no (more) valid settings found on this list, try the next 02473 CurList = CurList->Next; 02474 level = 0; 02475 } 02476 02477 if (!BestList) { 02478 // failure 02479 IDBGMSG ("Pass3: No settings found\n"); 02480 return NULL; 02481 } 02482 02483 // 02484 // Return best settings which were found 02485 // 02486 02487 for (i = 0; i < BestList->NoRequiredResources; i++) { 02488 ReqRes = BestList->RequiredResource[i]; 02489 ReqRes->CurBLoc = ReqRes->Pass2HoldCurLoc; 02490 ReqRes->CurBAddr = ReqRes->Pass2HoldBAddr; 02491 } 02492 02493 return BestList; 02494 } 02495 02496 PCM_RESOURCE_LIST 02497 IopAssignResourcesPhase4 ( 02498 IN PDIR_RESREQ_LIST Dir, 02499 IN PDIR_RESOURCE_LIST CurList, 02500 OUT PULONG Length 02501 ) 02502 /*++ 02503 02504 Routine Description: 02505 02506 The callers request for resources has been calculated. Phase 4 builds 02507 a CM_RESOURCE_LIST of the allocated resources. 02508 02509 This functions need CurDesc->CurBLoc & CurDesc->CurBAddr as passed from Phase3. 02510 02511 Arguments: 02512 02513 --*/ 02514 { 02515 PCM_RESOURCE_LIST CmRes; 02516 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc; 02517 PDIR_REQUIRED_RESOURCE DirDesc, *pDirDesc; 02518 PIO_RESOURCE_DESCRIPTOR IoDesc; 02519 ULONG i, cnt, len; 02520 02521 PAGED_CODE(); 02522 02523 cnt = CurList->NoRequiredResources; 02524 len = sizeof (CM_RESOURCE_LIST) + cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR); 02525 *Length = len; 02526 02527 CmRes = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, len); 02528 if (!CmRes) { 02529 return NULL; 02530 } 02531 02532 RtlZeroMemory (CmRes, len); 02533 02534 CmRes->Count = 1; 02535 CmRes->List[0].InterfaceType = Dir->IoResourceReq->InterfaceType; 02536 CmRes->List[0].BusNumber = Dir->IoResourceReq->BusNumber; 02537 CmRes->List[0].PartialResourceList.Count = CurList->NoRequiredResources; 02538 02539 CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors; 02540 pDirDesc = CurList->RequiredResource; // return resources in same order they 02541 // where requested 02542 #if IDBG 02543 DbgPrint ("Acquired Resourses - %d\n", CurList->NoRequiredResources); 02544 #endif 02545 02546 for (i=0; i < cnt; i++, CmDesc++, pDirDesc++) { 02547 DirDesc = *pDirDesc; 02548 IoDesc = DirDesc->IoResourceDescriptor[DirDesc->CurBLoc]; 02549 02550 CmDesc->Type = IoDesc->Type; 02551 CmDesc->ShareDisposition = IoDesc->ShareDisposition; 02552 CmDesc->Flags = IoDesc->Flags; 02553 02554 switch (CmDesc->Type) { 02555 case CmResourceTypePort: 02556 CmDesc->u.Port.Start.QuadPart = DirDesc->CurBAddr; 02557 CmDesc->u.Port.Length = IoDesc->u.Port.Length; 02558 #if IDBG 02559 DbgPrint (" IO Start %x:%08x, Len %x\n", 02560 CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart, 02561 CmDesc->u.Port.Length ); 02562 #endif 02563 break; 02564 02565 case CmResourceTypeMemory: 02566 CmDesc->u.Memory.Start.QuadPart = DirDesc->CurBAddr; 02567 CmDesc->u.Memory.Length = IoDesc->u.Memory.Length; 02568 #if IDBG 02569 DbgPrint (" MEM Start %x:%08x, Len %x\n", 02570 CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart, 02571 CmDesc->u.Memory.Length ); 02572 #endif 02573 break; 02574 02575 case CmResourceTypeInterrupt: 02576 CmDesc->u.Interrupt.Level = (ULONG) DirDesc->CurBAddr; 02577 CmDesc->u.Interrupt.Vector = (ULONG) DirDesc->CurBAddr; 02578 #if IDBG 02579 DbgPrint (" INT Level %x, Vector %x\n", 02580 CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector ); 02581 #endif 02582 break; 02583 02584 case CmResourceTypeDma: 02585 CmDesc->u.Dma.Channel = (ULONG) DirDesc->CurBAddr; 02586 #if IDBG 02587 DbgPrint (" DMA Channel %x\n", CmDesc->u.Dma.Channel); 02588 #endif 02589 break; 02590 02591 default: 02592 ExFreePool (CmRes); 02593 return NULL; 02594 } 02595 } 02596 02597 return CmRes; 02598 } 02599 02600 STATIC VOID 02601 IopLogConflict ( 02602 IN PDRIVER_OBJECT DriverObject, 02603 IN PDIR_RESREQ_LIST Dir, 02604 IN NTSTATUS FinalStatus 02605 ) 02606 /*++ 02607 02608 Routine Description: 02609 02610 Resource settings could not be satisfied. Locate first resource 02611 which can not be assigned and report the conflict. 02612 02613 Arguments: 02614 02615 --*/ 02616 { 02617 PIO_ERROR_LOG_PACKET ErrLog; 02618 PDIR_RESOURCE_LIST CurList; 02619 PDIR_REQUIRED_RESOURCE ReqRes; 02620 ULONG i, j; 02621 ULONG len, ErrorLogNumber, ErrLogBufferLeft; 02622 ULONG ConflictLevel; 02623 UCHAR s[8]; 02624 PWCHAR pLog; 02625 POWNER Owner; 02626 02627 PAGED_CODE(); 02628 02629 IDBGMSG ("\n****\n"); 02630 IDBGMSG ("Failed to satisfy the following required resource\n"); 02631 02632 ErrLog = NULL; 02633 ErrorLogNumber = 0; 02634 02635 // 02636 // There's a conflict in each alternative list 02637 // 02638 02639 for (CurList = Dir->Alternative; CurList; CurList = CurList->Next) { 02640 02641 // 02642 // Clear position (already on pass 2) 02643 // 02644 02645 for (i=0; i < CurList->NoRequiredResources; i++) { 02646 CurList->RequiredResource[i]->CurLoc = 0; 02647 CurList->RequiredResource[i]->RunLen = 0; 02648 CurList->RequiredResource[i]->PassNo = 2; 02649 } 02650 02651 // 02652 // Look for settings - set ConflictLevel to pass 3 to track where the problem is 02653 // 02654 02655 ConflictLevel = CurList->FailedLevel; 02656 CurList->RequiredResource[ConflictLevel]->PassNo = 3; 02657 02658 InitializeListHead (&CurList->Conflict.OtherConflicts); 02659 02660 if (IopGenNextValidResourceList (0, CurList, Dir)) { 02661 IDBGMSG ("IopLogConflict: internal error\n"); 02662 continue ; 02663 } 02664 02665 #if IDBG 02666 if (CurList != Dir->Alternative) { 02667 DbgPrint ("the following alternate resource also failed\n"); 02668 } 02669 02670 s[0] = s[1] = s[2] = s[3] = ' '; 02671 s[4] = 0; 02672 02673 ReqRes = CurList->RequiredResource[ConflictLevel]; 02674 for (j=0; j < ReqRes->NoAlternatives; j++) { 02675 IopDumpIoResourceDescriptor (s, ReqRes->IoResourceDescriptor[j]); 02676 } 02677 02678 02679 i = CurList->Conflict.NoConflicts; 02680 if (i > SCONFLICT) { 02681 i = SCONFLICT; 02682 } 02683 for (j=0; j < i; j++) { 02684 DbgPrint (" Conflict # %d. ", j+1); 02685 switch (CurList->Conflict.EasyConflict[j].Type) { 02686 case CmResourceTypePort: 02687 DbgPrint ("IO Base %08x", (ULONG) CurList->Conflict.EasyConflict[j].BAddr); 02688 break; 02689 02690 case CmResourceTypeMemory: 02691 DbgPrint ("MEM Base %08x", (ULONG) CurList->Conflict.EasyConflict[j].BAddr); 02692 break; 02693 02694 case CmResourceTypeInterrupt: 02695 DbgPrint ("INT Line %x", (ULONG) CurList->Conflict.EasyConflict[j].BAddr); 02696 break; 02697 02698 case CmResourceTypeDma: 02699 DbgPrint ("DMA Channel %x", (ULONG) CurList->Conflict.EasyConflict[j].BAddr); 02700 break; 02701 } 02702 02703 DbgPrint (" with '%wZ' ", &CurList->Conflict.EasyConflict[j].Owner->KeyName); 02704 if (CurList->Conflict.EasyConflict[j].Owner->DeviceName.Buffer) { 02705 DbgPrint ("'%wZ'", &CurList->Conflict.EasyConflict[j].Owner->DeviceName); 02706 } 02707 DbgPrint ("\n"); 02708 } 02709 02710 if (CurList->Conflict.NoConflicts > SCONFLICT) { 02711 DbgPrint (" ...\n"); 02712 DbgPrint ("Total Conflicts = %d\n", CurList->Conflict.NoConflicts); 02713 } 02714 02715 if (!IsListEmpty (&CurList->Conflict.OtherConflicts)) { 02716 DbgPrint ("Possible settings also conflicts with the following list\n"); 02717 // bugbug - not done 02718 } 02719 #endif 02720 02721 // 02722 // Loop for each easy conflict 02723 // 02724 02725 i = CurList->Conflict.NoConflicts; 02726 if (i > SCONFLICT) { 02727 i = SCONFLICT; 02728 } 02729 02730 for (j=0; j < i; j++) { 02731 if (ErrorLogNumber >= 3) { 02732 // 02733 // only add n logs for a given problem 02734 // 02735 break; 02736 } 02737 02738 // 02739 // Allocate a new error log structure 02740 // 02741 02742 ErrorLogNumber += 1; 02743 ErrLog = IoAllocateErrorLogEntry (DriverObject, ERROR_LOG_MAXIMUM_SIZE); 02744 if (!ErrLog) { 02745 break; 02746 } 02747 02748 // 02749 // Initialize errorlog field and counts to append strings 02750 // 02751 02752 RtlZeroMemory (ErrLog, sizeof (*ErrLog)); 02753 ErrLog->FinalStatus = FinalStatus; 02754 ErrLog->UniqueErrorValue = ErrorLogNumber; 02755 ErrLog->NumberOfStrings = 2; 02756 pLog = (PWCHAR) ErrLog->DumpData; 02757 ErrLog->StringOffset = (USHORT) ( ((PUCHAR) pLog) - ((PUCHAR) ErrLog) ); 02758 ErrLogBufferLeft = (ERROR_LOG_MAXIMUM_SIZE - ErrLog->StringOffset) / sizeof(WCHAR); 02759 02760 switch (CurList->Conflict.EasyConflict[j].Type) { 02761 case CmResourceTypePort: 02762 ErrLog->ErrorCode = IO_ERR_PORT_RESOURCE_CONFLICT; 02763 break; 02764 02765 case CmResourceTypeMemory: 02766 ErrLog->ErrorCode = IO_ERR_MEMORY_RESOURCE_CONFLICT; 02767 break; 02768 02769 case CmResourceTypeInterrupt: 02770 ErrLog->ErrorCode = IO_ERR_INTERRUPT_RESOURCE_CONFLICT; 02771 break; 02772 02773 case CmResourceTypeDma: 02774 ErrLog->ErrorCode = IO_ERR_DMA_RESOURCE_CONFLICT; 02775 break; 02776 } 02777 02778 if (CurList->Conflict.EasyConflict[j].BAddr & 0xffffffff00000000) { 02779 len = swprintf (pLog, L"%X:%08X", 02780 (ULONG) (CurList->Conflict.EasyConflict[j].BAddr >> 32), 02781 (ULONG) CurList->Conflict.EasyConflict[j].BAddr 02782 ); 02783 } else { 02784 len = swprintf (pLog, L"%X", (ULONG) CurList->Conflict.EasyConflict[j].BAddr); 02785 } 02786 02787 len += 1; // include null 02788 pLog += len; 02789 ErrLogBufferLeft -= len; 02790 02791 Owner = CurList->Conflict.EasyConflict[j].Owner; 02792 02793 len = Owner->KeyName.Length / sizeof(WCHAR); 02794 if (len > ErrLogBufferLeft) { 02795 len = ErrLogBufferLeft; 02796 } 02797 02798 RtlCopyMemory (pLog, Owner->KeyName.Buffer, len * sizeof(WCHAR) ); 02799 pLog += len; 02800 ErrLogBufferLeft -= len; 02801 02802 if (Owner->DeviceName.Buffer && ErrLogBufferLeft > 11) { 02803 len = Owner->DeviceName.Length / sizeof(WCHAR); 02804 if (len > ErrLogBufferLeft) { 02805 len = ErrLogBufferLeft; 02806 } 02807 02808 *(pLog++) = ' '; 02809 RtlCopyMemory (pLog, Owner->DeviceName.Buffer, len * sizeof(WCHAR)); 02810 pLog += len; 02811 ErrLogBufferLeft -= len; 02812 } 02813 02814 *(pLog++) = 0; // null terminate 02815 02816 IoWriteErrorLogEntry ( ErrLog ); 02817 } 02818 } 02819 02820 IDBGMSG ("****\n"); 02821 } 02822 #endif 02823 02824 02825 STATIC PTENTRY 02826 IopNewTransEntry ( 02827 IN PDIR_RESREQ_LIST Dir, 02828 IN PTENTRIESBYTYPE pTypes, 02829 IN ULONG Type 02830 ) 02831 { 02832 PLTENTRY LEntry, NewTable; 02833 02834 LEntry = pTypes->ByType[Type]; 02835 02836 if (!LEntry || LEntry->CurEntries == MAX_ENTRIES) { 02837 // 02838 // Build a new table 02839 // 02840 02841 NewTable = IopAllocateDirPool (Dir, sizeof (LTENTRY)); 02842 02843 if (!NewTable) { 02844 return NULL; 02845 } 02846 02847 pTypes->ByType[Type] = NewTable; 02848 NewTable->Next = LEntry; 02849 NewTable->CurEntries = 0; 02850 02851 LEntry = NewTable; 02852 } 02853 02854 return LEntry->Table + (LEntry->CurEntries++); 02855 } 02856 02857 02858 STATIC NTSTATUS 02859 IopAddCmDescriptorToInUseList ( 02860 IN PDIR_RESREQ_LIST Dir, 02861 IN PTENTRIESBYTYPE pTypes, 02862 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, 02863 IN POWNER Owner 02864 ) 02865 /*++ 02866 02867 Routine Description: 02868 02869 Adds Translated CmDescriptor to TLIST. 02870 02871 Arguments: 02872 02873 Return Value: 02874 02875 --*/ 02876 { 02877 PTENTRY Trans; 02878 LONGLONG li; 02879 02880 if ((CmDesc->Type == CmResourceTypePort && CmDesc->u.Port.Length == 0) || 02881 (CmDesc->Type == CmResourceTypeMemory && CmDesc->u.Memory.Length == 0)) { 02882 // no length? 02883 IDBGMSG ("IopAddCmDescriptor: Skipping zero length descriptor\n"); 02884 return STATUS_SUCCESS; 02885 } 02886 02887 // 02888 // Get a new Trans entry in the InUseResource list or the 02889 // InUseSharableResource list 02890 // 02891 02892 Trans = IopNewTransEntry (Dir, pTypes, CmDesc->Type); 02893 if (!Trans) { 02894 return STATUS_INSUFFICIENT_RESOURCES; 02895 } 02896 02897 // 02898 // Fill in the Trans structure 02899 // 02900 02901 // NOTE: turning TEntries into a splay tree would speed up the collision 02902 // detect process. 02903 02904 Trans->Owner = Owner; 02905 switch (CmDesc->Type) { 02906 case CmResourceTypePort: 02907 li = CmDesc->u.Port.Length - 1; 02908 Trans->BAddr = *((LONGLONG UNALIGNED *) &CmDesc->u.Port.Start); 02909 Trans->EAddr = Trans->BAddr + li; 02910 Trans->Affinity = (KAFFINITY) -1; 02911 break; 02912 02913 case CmResourceTypeMemory: 02914 li = CmDesc->u.Memory.Length - 1; 02915 Trans->BAddr = *((LONGLONG UNALIGNED *) &CmDesc->u.Memory.Start); 02916 Trans->EAddr = Trans->BAddr + li; 02917 Trans->Affinity = (KAFFINITY) -1; 02918 break; 02919 02920 case CmResourceTypeInterrupt: 02921 Trans->BAddr = CmDesc->u.Interrupt.Vector; 02922 Trans->EAddr = CmDesc->u.Interrupt.Vector; 02923 Trans->Affinity = CmDesc->u.Interrupt.Affinity; 02924 break; 02925 02926 case CmResourceTypeDma: 02927 Trans->BAddr = CmDesc->u.Dma.Channel; 02928 Trans->EAddr = CmDesc->u.Dma.Channel; 02929 Trans->Affinity = (KAFFINITY) -1; 02930 break; 02931 } 02932 return STATUS_SUCCESS; 02933 } 02934 02935 NTSTATUS 02936 IopBuildResourceDir ( 02937 IN PDIR_RESREQ_LIST ParentDir, 02938 IN PDIR_RESREQ_LIST *pDir, 02939 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResources 02940 ) 02941 /*++ 02942 02943 Routine Description: 02944 02945 Takes an IO_RESOURCE_REQUIREMENTS list and builds a directory for 02946 it's contents. 02947 02948 Arguments: 02949 02950 Return Value: 02951 02952 --*/ 02953 { 02954 PDIR_RESREQ_LIST Dir; 02955 PIO_RESOURCE_LIST ResourceList; 02956 PIO_RESOURCE_DESCRIPTOR Descriptor, ADescriptor; 02957 PDIR_RESOURCE_LIST DirResourceList, *AltListTail; 02958 PDIR_REQUIRED_RESOURCE ReqRes; 02959 ULONG i, j, alt, cnt, acnt; 02960 PUCHAR FirstAddress, LastAddress; 02961 02962 // 02963 // Allocate and initialize DIR structure 02964 // 02965 02966 Dir = (PDIR_RESREQ_LIST) ExAllocatePool (PagedPool, sizeof(DIR_RESREQ_LIST)); 02967 *pDir = Dir; 02968 if (!Dir) { 02969 return STATUS_INSUFFICIENT_RESOURCES; 02970 } 02971 02972 RtlZeroMemory (Dir, sizeof (DIR_RESREQ_LIST)); 02973 for (i=0; i < MAX_REG_HANDLES; i++) { 02974 Dir->RegHandle[i] = INVALID_HANDLE; 02975 } 02976 02977 if (ParentDir) { 02978 Dir->FreeResReqList = ParentDir->FreeResReqList; 02979 ParentDir->FreeResReqList = Dir; 02980 } 02981 02982 // 02983 // If no IoResources to process, the Dir structure is done 02984 // 02985 02986 if (!IoResources) { 02987 return STATUS_SUCCESS; 02988 } 02989 02990 // 02991 // Verify ResourceList does not exceede ListSize 02992 // 02993 02994 ResourceList = IoResources->List; 02995 FirstAddress = (PUCHAR) ResourceList; 02996 LastAddress = (PUCHAR) IoResources + IoResources->ListSize; 02997 for (cnt=0; cnt < IoResources->AlternativeLists; cnt++) { 02998 ResourceList = (PIO_RESOURCE_LIST) 02999 (&ResourceList->Descriptors[ResourceList->Count]); 03000 03001 if ((PUCHAR) ResourceList < FirstAddress || 03002 (PUCHAR) ResourceList > LastAddress) { 03003 DBGMSG ("IopBuildResourceDir: IO_RESOURCE_LIST.ListSize too small\n"); 03004 return STATUS_INVALID_PARAMETER; 03005 } 03006 } 03007 03008 // 03009 // Build a directory of the block stlye structure IO_RESOURCE_REQUIREMENTS_LIST 03010 // 03011 03012 Dir->IoResourceReq = IoResources; 03013 AltListTail = &Dir->Alternative; 03014 ResourceList = IoResources->List; 03015 03016 for (alt=0; alt < IoResources->AlternativeLists; alt++) { 03017 03018 // 03019 // Count number of non-alternative descriptors on this 03020 // alternative list 03021 // 03022 03023 cnt = 0; 03024 Descriptor = ResourceList->Descriptors; 03025 for (i = ResourceList->Count; i; i--) { 03026 if (!(Descriptor->Option & IO_RESOURCE_ALTERNATIVE)) { 03027 cnt++; 03028 } 03029 Descriptor++; 03030 } 03031 03032 // 03033 // Build alternative list structure 03034 // 03035 03036 i = sizeof (DIR_RESOURCE_LIST) + cnt * sizeof(PVOID) * 2; 03037 DirResourceList = (PDIR_RESOURCE_LIST) IopAllocateDirPool (Dir, i); 03038 03039 if (!DirResourceList) { 03040 return STATUS_INSUFFICIENT_RESOURCES; 03041 } 03042 03043 // 03044 // Initialize structure 03045 // 03046 03047 RtlZeroMemory (DirResourceList, i); 03048 DirResourceList->IoResourceList = ResourceList; 03049 03050 // add to tail of single linked list 03051 *(AltListTail) = DirResourceList; 03052 AltListTail = &DirResourceList->Next; 03053 03054 Descriptor = ResourceList->Descriptors; 03055 for (i = ResourceList->Count; i; i--) { 03056 if (!(Descriptor->Option & IO_RESOURCE_ALTERNATIVE)) { 03057 // 03058 // Count number of alternative descriptors 03059 // 03060 03061 acnt = 1; 03062 ADescriptor = Descriptor + 1; 03063 while (acnt < i && ADescriptor->Option & IO_RESOURCE_ALTERNATIVE) { 03064 ADescriptor++; 03065 acnt++; 03066 } 03067 03068 // 03069 // Allocate a required resource list 03070 // 03071 03072 ReqRes = (PDIR_REQUIRED_RESOURCE) IopAllocateDirPool (Dir, 03073 sizeof (DIR_REQUIRED_RESOURCE) + acnt * sizeof(PVOID)); 03074 03075 if (!ReqRes) { 03076 return STATUS_INSUFFICIENT_RESOURCES; 03077 } 03078 03079 RtlZeroMemory (ReqRes, sizeof (DIR_REQUIRED_RESOURCE)); 03080 DirResourceList->RequiredResource[DirResourceList->NoRequiredResources] = ReqRes; 03081 DirResourceList->NoRequiredResources++; 03082 03083 // 03084 // Fill in all the alternatives for this required resource 03085 // 03086 03087 ReqRes->NoAlternatives = acnt; 03088 ADescriptor = Descriptor; 03089 for (j=0; j < acnt; j++) { 03090 ReqRes->IoResourceDescriptor[j] = ADescriptor; 03091 if (ADescriptor->Option & IO_RESOURCE_PREFERRED) { 03092 ReqRes->BestPref = 1; 03093 } 03094 ADescriptor++; 03095 } 03096 } 03097 03098 // 03099 // Next descriptor 03100 // 03101 Descriptor++; 03102 } 03103 03104 03105 // 03106 // Next alternative resource list 03107 // 03108 03109 ResourceList = (PIO_RESOURCE_LIST) Descriptor; 03110 } 03111 return STATUS_SUCCESS; 03112 } 03113 03114 VOID 03115 IopFreeResourceDir ( 03116 IN PDIR_RESREQ_LIST DirResourceList 03117 ) 03118 /*++ 03119 03120 Routine Description: 03121 03122 Frees pool used to track a DIR_RESREQ_LIST and other assiocated 03123 resources. Also free's all pool for DIR_RESREQ_LIST's on a 03124 free list. 03125 03126 Arguments: 03127 03128 Return Value: 03129 03130 --*/ 03131 { 03132 PDIR_RESREQ_LIST NextResourceList; 03133 ULONG i; 03134 PSINGLE_LIST_ENTRY pe; 03135 PUSED_HEAP ph; 03136 03137 // 03138 // Free any allocated lists 03139 // 03140 03141 while (DirResourceList) { 03142 NextResourceList = DirResourceList->FreeResReqList; 03143 03144 // 03145 // Free any allocated heap 03146 // 03147 03148 while (DirResourceList->AllocatedHeap.Next) { 03149 pe = PopEntryList (&DirResourceList->AllocatedHeap); 03150 ph = CONTAINING_RECORD(pe, USED_HEAP, FreeLink); 03151 ExFreePool (ph->FreeHeap); 03152 } 03153 03154 // 03155 // Close any opened handles 03156 // 03157 03158 for (i=0; i< MAX_REG_HANDLES; i++) { 03159 if (DirResourceList->RegHandle[i] != INVALID_HANDLE) { 03160 ZwClose (DirResourceList->RegHandle[i]); 03161 } 03162 } 03163 03164 03165 // 03166 // Free header 03167 // 03168 03169 ExFreePool (DirResourceList); 03170 03171 // 03172 // Next list 03173 // 03174 03175 DirResourceList = NextResourceList; 03176 } 03177 } 03178 03179 #if IDBG 03180 VOID 03181 IopDumpIoResourceDir ( 03182 IN PDIR_RESREQ_LIST Dir 03183 ) 03184 { 03185 PDIR_RESOURCE_LIST ResourceList; 03186 PIO_RESOURCE_DESCRIPTOR Desc; 03187 PDIR_REQUIRED_RESOURCE ReqRes; 03188 ULONG alt, i, j; 03189 UCHAR s[10]; 03190 03191 03192 alt = 0; 03193 for (ResourceList = Dir->Alternative; ResourceList; ResourceList = ResourceList->Next) { 03194 DbgPrint ("Alternative #%d - %d required resources\n", 03195 alt++, ResourceList->NoRequiredResources ); 03196 03197 for (i=0; i < ResourceList->NoRequiredResources; i++) { 03198 ReqRes = ResourceList->RequiredResource[i]; 03199 for (j=0; j < ReqRes->NoAlternatives; j++) { 03200 Desc = ReqRes->IoResourceDescriptor[j]; 03201 if (j == 0) { 03202 s[0] = s[1] = s[2] = '*'; 03203 s[3] = ' '; 03204 } else { 03205 s[0] = s[1] = s[2] = s[3] = ' '; 03206 } 03207 03208 s[4] = Desc->Option & IO_RESOURCE_PREFERRED ? 'P' : ' '; 03209 s[5] = ' '; 03210 s[6] = 0; 03211 03212 IopDumpIoResourceDescriptor (s, Desc); 03213 } 03214 } 03215 } 03216 } 03217 03218 VOID 03219 IopDumpIoResourceDescriptor ( 03220 IN PUCHAR Indent, 03221 IN PIO_RESOURCE_DESCRIPTOR Desc 03222 ) 03223 { 03224 switch (Desc->Type) { 03225 case CmResourceTypePort: 03226 DbgPrint ("%sIO Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n", 03227 Indent, 03228 Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart, 03229 Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart, 03230 Desc->u.Port.Alignment, 03231 Desc->u.Port.Length 03232 ); 03233 break; 03234 03235 case CmResourceTypeMemory: 03236 DbgPrint ("%sMEM Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n", 03237 Indent, 03238 Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart, 03239 Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart, 03240 Desc->u.Memory.Alignment, 03241 Desc->u.Memory.Length 03242 ); 03243 break; 03244 03245 case CmResourceTypeInterrupt: 03246 DbgPrint ("%sINT Min: %x, Max: %x\n", 03247 Indent, 03248 Desc->u.Interrupt.MinimumVector, 03249 Desc->u.Interrupt.MaximumVector 03250 ); 03251 break; 03252 03253 case CmResourceTypeDma: 03254 DbgPrint ("%sDMA Min: %x, Max: %x\n", 03255 Indent, 03256 Desc->u.Dma.MinimumChannel, 03257 Desc->u.Dma.MaximumChannel 03258 ); 03259 break; 03260 } 03261 } 03262 03263 03264 #endif 03265 03266 NTSTATUS 03267 IopCatagorizeDescriptors ( 03268 IN OUT PDIR_RESREQ_LIST Dir 03269 ) 03270 /*++ 03271 03272 Routine Description: 03273 03274 Takes a DIR_RESREQ_LIST and returns a list of resources by 03275 catagory. It is assumed that such a directory has one list 03276 of alternative descriptors per resource type. 03277 03278 Arguments: 03279 03280 Return Value: 03281 03282 --*/ 03283 { 03284 PDIR_RESOURCE_LIST DirResourceList; 03285 PDIR_REQUIRED_RESOURCE ReqRes; 03286 ULONG i, j, acnt; 03287 CM_RESOURCE_TYPE type; 03288 03289 if (!Dir->Alternative || Dir->Alternative->Next) { 03290 // there can only be one list 03291 DBGMSG ("IopCatagorizeDescriptors: too many altenative lists\n"); 03292 return STATUS_INVALID_PARAMETER_MIX; 03293 } 03294 03295 DirResourceList = Dir->Alternative; 03296 for (i=0; i < DirResourceList->NoRequiredResources; i++) { 03297 ReqRes = DirResourceList->RequiredResource[i]; 03298 03299 acnt = ReqRes->NoAlternatives; 03300 if (!acnt) { 03301 // shouldn't have a zero count 03302 DBGMSG ("IopCatagorizeDescriptors: no entries\n"); 03303 return STATUS_INVALID_PARAMETER_MIX; 03304 } 03305 03306 type = ReqRes->IoResourceDescriptor[0]->Type; 03307 03308 // verify all entries in this list are of the same type 03309 for (j=1; j < acnt; j++) { 03310 if (ReqRes->IoResourceDescriptor[j]->Type != type) { 03311 DBGMSG ("IopCatagorizeDescriptors: mixed types in alternatives\n"); 03312 return STATUS_INVALID_PARAMETER_MIX; 03313 } 03314 } 03315 03316 if (type >= CmResourceTypeMaximum) { 03317 // unkown catagory 03318 continue; 03319 } 03320 03321 if (DirResourceList->ResourceByType[type]) { 03322 // should only have one list per type 03323 DBGMSG ("IopCatagorizeDescriptors: multiple lists per resource type\n"); 03324 return STATUS_INVALID_PARAMETER_MIX; 03325 } 03326 03327 DirResourceList->ResourceByType[type] = ReqRes; 03328 } 03329 03330 return STATUS_SUCCESS; 03331 } 03332 03333 03334 03335 INLINE ULONG 03336 IopDescriptorSortingWeight ( 03337 IN PIO_RESOURCE_DESCRIPTOR Descriptor 03338 ) 03339 /*++ 03340 03341 Routine Description: 03342 Used by IopSortDescriptors 03343 03344 --*/ 03345 { 03346 ULONG w; 03347 03348 switch (Descriptor->Type) { 03349 case CmResourceTypeMemory: w = 4; break; 03350 case CmResourceTypeInterrupt: w = 3; break; 03351 case CmResourceTypeDma: w = 2; break; 03352 case CmResourceTypePort: w = 1; break; 03353 default: w = 0; break; 03354 } 03355 03356 return w; 03357 } 03358 03359 03360 VOID 03361 IopSortDescriptors ( 03362 IN OUT PDIR_RESREQ_LIST Dir 03363 ) 03364 /*++ 03365 03366 Routine Description: 03367 03368 Sorts the directory entries for each decsriptor such that they 03369 descriptors are order by resource type. 03370 03371 Arguments: 03372 03373 Return Value: 03374 03375 --*/ 03376 { 03377 PIO_RESOURCE_DESCRIPTOR Descriptor; 03378 PDIR_RESOURCE_LIST DirResourceList; 03379 PDIR_REQUIRED_RESOURCE ReqRes; 03380 ULONG i, j, k, acnt; 03381 ULONG w1, w2; 03382 03383 // 03384 // Sort each require resource list by descriptor type 03385 // 03386 03387 for (DirResourceList = Dir->Alternative; DirResourceList; DirResourceList = DirResourceList->Next) { 03388 03389 // 03390 // Sort the descriptors by type 03391 // 03392 03393 for (k=0; k < DirResourceList->NoRequiredResources; k++) { 03394 ReqRes = DirResourceList->RequiredResource[k]; 03395 03396 acnt = ReqRes->NoAlternatives; 03397 for (i=0; i < acnt; i++) { 03398 w1 = IopDescriptorSortingWeight (ReqRes->IoResourceDescriptor[i]); 03399 03400 for (j = i+1; j < acnt; j++) { 03401 w2 = IopDescriptorSortingWeight (ReqRes->IoResourceDescriptor[j]); 03402 03403 if (w2 > w1) { 03404 Descriptor = ReqRes->IoResourceDescriptor[i]; 03405 ReqRes->IoResourceDescriptor[i] = ReqRes->IoResourceDescriptor[j]; 03406 ReqRes->IoResourceDescriptor[j] = Descriptor; 03407 w1 = w2; 03408 } 03409 } 03410 } 03411 } 03412 } 03413 } 03414 #endif

Generated on Sat May 15 19:39:17 2004 for test by doxygen 1.3.7