test: assign.c Source File

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