2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpres.c
5 * PURPOSE: Resource handling code
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 * ReactOS Portable Systems Group
17 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
19 CM_RESOURCE_LIST CmList
;
23 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
24 CmList
.List
[0].BusNumber
= 0;
25 CmList
.List
[0].PartialResourceList
.Version
= 1;
26 CmList
.List
[0].PartialResourceList
.Revision
= 1;
27 CmList
.List
[0].PartialResourceList
.Count
= 1;
28 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
30 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
31 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
39 IopFindBusNumberResource(
40 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
41 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
44 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
46 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
47 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
49 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
50 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
53 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
54 CmDesc
->u
.BusNumber
.Start
= Start
;
56 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
58 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
71 IopFindMemoryResource(
72 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
73 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
76 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
78 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
79 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
81 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
82 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
85 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
86 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
88 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
90 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
104 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
105 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
108 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
110 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
111 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
113 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
114 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
117 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
118 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
120 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
122 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
136 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
137 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
141 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
142 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
144 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
145 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
148 CmDesc
->u
.Dma
.Channel
= Channel
;
149 CmDesc
->u
.Dma
.Port
= 0;
151 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
160 IopFindInterruptResource(
161 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
162 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
166 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
167 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
169 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
170 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
173 CmDesc
->u
.Interrupt
.Vector
= Vector
;
174 CmDesc
->u
.Interrupt
.Level
= Vector
;
175 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
177 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
186 IopCreateResourceListFromRequirements(
187 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
188 OUT PCM_RESOURCE_LIST
*ResourceList
)
191 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
193 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
194 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
196 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
197 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
198 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
201 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
203 return STATUS_INSUFFICIENT_RESOURCES
;
205 (*ResourceList
)->Count
= 1;
206 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
207 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
208 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
209 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
210 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
212 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
214 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
216 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
217 for (ii
= 0; ii
< ResList
->Count
; ii
++)
219 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
220 BOOLEAN FoundResource
= TRUE
;
222 /* FIXME: Handle alternate ranges */
223 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
226 ResDesc
->Type
= ReqDesc
->Type
;
227 ResDesc
->Flags
= ReqDesc
->Flags
;
228 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
230 switch (ReqDesc
->Type
)
232 case CmResourceTypeInterrupt
:
233 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
235 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
236 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
238 if (ReqDesc
->Option
== 0)
240 ExFreePool(*ResourceList
);
241 *ResourceList
= NULL
;
242 return STATUS_CONFLICTING_ADDRESSES
;
245 FoundResource
= FALSE
;
249 case CmResourceTypePort
:
250 if (!IopFindPortResource(ReqDesc
, ResDesc
))
252 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
253 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
254 ReqDesc
->u
.Port
.Length
);
256 if (ReqDesc
->Option
== 0)
258 ExFreePool(*ResourceList
);
259 *ResourceList
= NULL
;
260 return STATUS_CONFLICTING_ADDRESSES
;
263 FoundResource
= FALSE
;
267 case CmResourceTypeMemory
:
268 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
270 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
271 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
272 ReqDesc
->u
.Memory
.Length
);
274 if (ReqDesc
->Option
== 0)
276 ExFreePool(*ResourceList
);
277 *ResourceList
= NULL
;
278 return STATUS_CONFLICTING_ADDRESSES
;
281 FoundResource
= FALSE
;
285 case CmResourceTypeBusNumber
:
286 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
288 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
289 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
290 ReqDesc
->u
.BusNumber
.Length
);
292 if (ReqDesc
->Option
== 0)
294 ExFreePool(*ResourceList
);
295 *ResourceList
= NULL
;
296 return STATUS_CONFLICTING_ADDRESSES
;
299 FoundResource
= FALSE
;
303 case CmResourceTypeDma
:
304 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
306 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
307 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
309 if (ReqDesc
->Option
== 0)
311 ExFreePool(*ResourceList
);
312 *ResourceList
= NULL
;
313 return STATUS_CONFLICTING_ADDRESSES
;
316 FoundResource
= FALSE
;
321 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
322 FoundResource
= FALSE
;
328 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
334 return STATUS_SUCCESS
;
339 IopCheckResourceDescriptor(
340 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
341 IN PCM_RESOURCE_LIST ResourceList
,
343 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
346 BOOLEAN Result
= FALSE
;
348 for (i
= 0; i
< ResourceList
->Count
; i
++)
350 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
351 for (ii
= 0; ii
< ResList
->Count
; ii
++)
353 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
355 /* We don't care about shared resources */
356 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
357 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
360 /* Make sure we're comparing the same types */
361 if (ResDesc
->Type
!= ResDesc2
->Type
)
364 switch (ResDesc
->Type
)
366 case CmResourceTypeMemory
:
367 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
368 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
369 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
370 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
371 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
375 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
376 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
377 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
378 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
387 case CmResourceTypePort
:
388 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
389 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
390 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
391 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
392 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
396 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
397 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
398 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
399 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
408 case CmResourceTypeInterrupt
:
409 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
413 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
414 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
415 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
424 case CmResourceTypeBusNumber
:
425 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
426 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
427 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
428 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
429 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
433 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
434 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
435 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
436 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
445 case CmResourceTypeDma
:
446 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
450 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
451 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
452 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
466 if (Result
&& ConflictingDescriptor
)
468 RtlCopyMemory(ConflictingDescriptor
,
470 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
478 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode
)
480 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
481 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
482 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
483 HANDLE EnumKey
, InstanceKey
, ControlKey
;
485 OBJECT_ATTRIBUTES ObjectAttributes
;
487 /* Open the Enum key */
488 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
489 if (!NT_SUCCESS(Status
))
492 /* Open the instance key (eg. Root\PNP0A03) */
493 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
496 if (!NT_SUCCESS(Status
))
499 /* Create/Open the Control key */
500 InitializeObjectAttributes(&ObjectAttributes
,
502 OBJ_CASE_INSENSITIVE
,
505 Status
= ZwCreateKey(&ControlKey
,
512 ZwClose(InstanceKey
);
514 if (!NT_SUCCESS(Status
))
517 /* Write the resource list */
518 Status
= ZwSetValueKey(ControlKey
,
522 DeviceNode
->ResourceList
,
523 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
526 if (!NT_SUCCESS(Status
))
529 return STATUS_SUCCESS
;
534 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode
)
536 IO_STACK_LOCATION Stack
;
537 IO_STATUS_BLOCK IoStatusBlock
;
540 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
542 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
543 Status
= IopInitiatePnpIrp(
544 DeviceNode
->PhysicalDeviceObject
,
546 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
548 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
550 DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
553 else if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
555 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
558 return STATUS_SUCCESS
;
563 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
567 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
568 UNICODE_STRING KeyName
;
569 OBJECT_ATTRIBUTES ObjectAttributes
;
571 RtlInitUnicodeString(&KeyName
,
572 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
573 InitializeObjectAttributes(&ObjectAttributes
,
575 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
578 Status
= ZwCreateKey(&ResourceMapKey
,
585 if (!NT_SUCCESS(Status
))
588 RtlInitUnicodeString(&KeyName
, Level1Key
);
589 InitializeObjectAttributes(&ObjectAttributes
,
591 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
594 Status
= ZwCreateKey(&PnpMgrLevel1
,
601 ZwClose(ResourceMapKey
);
602 if (!NT_SUCCESS(Status
))
605 RtlInitUnicodeString(&KeyName
, Level2Key
);
606 InitializeObjectAttributes(&ObjectAttributes
,
608 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
611 Status
= ZwCreateKey(&PnpMgrLevel2
,
618 ZwClose(PnpMgrLevel1
);
619 if (!NT_SUCCESS(Status
))
622 if (DeviceNode
->ResourceList
)
624 UNICODE_STRING NameU
;
625 UNICODE_STRING RawSuffix
, TranslatedSuffix
;
628 ASSERT(DeviceNode
->ResourceListTranslated
);
630 RtlInitUnicodeString(&TranslatedSuffix
, L
".Translated");
631 RtlInitUnicodeString(&RawSuffix
, L
".Raw");
633 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
634 DevicePropertyPhysicalDeviceObjectName
,
638 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
642 NameU
.Buffer
= ExAllocatePool(PagedPool
, OldLength
+ TranslatedSuffix
.Length
);
645 ZwClose(PnpMgrLevel2
);
646 return STATUS_INSUFFICIENT_RESOURCES
;
650 NameU
.MaximumLength
= OldLength
+ TranslatedSuffix
.Length
;
652 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
653 DevicePropertyPhysicalDeviceObjectName
,
657 if (!NT_SUCCESS(Status
))
659 ZwClose(PnpMgrLevel2
);
660 ExFreePool(NameU
.Buffer
);
664 else if (!NT_SUCCESS(Status
))
667 ZwClose(PnpMgrLevel2
);
672 /* This should never happen */
676 NameU
.Length
= OldLength
;
678 RtlAppendUnicodeStringToString(&NameU
, &RawSuffix
);
680 Status
= ZwSetValueKey(PnpMgrLevel2
,
684 DeviceNode
->ResourceList
,
685 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
686 if (!NT_SUCCESS(Status
))
688 ZwClose(PnpMgrLevel2
);
689 ExFreePool(NameU
.Buffer
);
693 /* "Remove" the suffix by setting the length back to what it used to be */
694 NameU
.Length
= OldLength
;
696 RtlAppendUnicodeStringToString(&NameU
, &TranslatedSuffix
);
698 Status
= ZwSetValueKey(PnpMgrLevel2
,
702 DeviceNode
->ResourceListTranslated
,
703 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
704 ZwClose(PnpMgrLevel2
);
705 ExFreePool(NameU
.Buffer
);
707 if (!NT_SUCCESS(Status
))
712 ZwClose(PnpMgrLevel2
);
715 return STATUS_SUCCESS
;
719 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
721 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
726 IopTranslateDeviceResources(
727 IN PDEVICE_NODE DeviceNode
)
729 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
730 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
731 ULONG i
, j
, ListSize
;
734 if (!DeviceNode
->ResourceList
)
736 DeviceNode
->ResourceListTranslated
= NULL
;
737 return STATUS_SUCCESS
;
740 /* That's easy to translate a resource list. Just copy the
741 * untranslated one and change few fields in the copy
743 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
745 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
746 if (!DeviceNode
->ResourceListTranslated
)
748 Status
= STATUS_NO_MEMORY
;
751 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
753 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
755 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
756 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
758 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
759 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
760 switch (DescriptorRaw
->Type
)
762 case CmResourceTypePort
:
764 ULONG AddressSpace
= 1; /* IO space */
765 if (!HalTranslateBusAddress(
766 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
767 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
768 DescriptorRaw
->u
.Port
.Start
,
770 &DescriptorTranslated
->u
.Port
.Start
))
772 Status
= STATUS_UNSUCCESSFUL
;
773 DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Port
.Start
.QuadPart
);
777 if (AddressSpace
== 0)
779 /* This is actually a memory resource */
780 DescriptorRaw
->Type
= CmResourceTypeMemory
;
781 DescriptorTranslated
->Type
= CmResourceTypeMemory
;
785 case CmResourceTypeInterrupt
:
787 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
788 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
789 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
790 DescriptorRaw
->u
.Interrupt
.Level
,
791 DescriptorRaw
->u
.Interrupt
.Vector
,
792 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
793 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
795 if (!DescriptorTranslated
->u
.Interrupt
.Vector
)
797 Status
= STATUS_UNSUCCESSFUL
;
798 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw
->u
.Interrupt
.Vector
,
799 DescriptorRaw
->u
.Interrupt
.Level
);
804 case CmResourceTypeMemory
:
806 ULONG AddressSpace
= 0; /* Memory space */
807 if (!HalTranslateBusAddress(
808 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
809 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
810 DescriptorRaw
->u
.Memory
.Start
,
812 &DescriptorTranslated
->u
.Memory
.Start
))
814 Status
= STATUS_UNSUCCESSFUL
;
815 DPRINT1("Failed to translate memory resource (Start: 0xI64x)\n", DescriptorRaw
->u
.Memory
.Start
.QuadPart
);
819 if (AddressSpace
!= 0)
821 /* This is actually an I/O port resource */
822 DescriptorRaw
->Type
= CmResourceTypePort
;
823 DescriptorTranslated
->Type
= CmResourceTypePort
;
827 case CmResourceTypeDma
:
828 case CmResourceTypeBusNumber
:
829 case CmResourceTypeDeviceSpecific
:
833 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
834 Status
= STATUS_NOT_IMPLEMENTED
;
839 return STATUS_SUCCESS
;
842 /* Yes! Also delete ResourceList because ResourceList and
843 * ResourceListTranslated should be a pair! */
844 ExFreePool(DeviceNode
->ResourceList
);
845 DeviceNode
->ResourceList
= NULL
;
846 if (DeviceNode
->ResourceListTranslated
)
848 ExFreePool(DeviceNode
->ResourceListTranslated
);
849 DeviceNode
->ResourceList
= NULL
;
856 IopAssignDeviceResources(
857 IN PDEVICE_NODE DeviceNode
)
862 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
864 Status
= IopFilterResourceRequirements(DeviceNode
);
865 if (!NT_SUCCESS(Status
))
868 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
870 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
871 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
873 /* No resource needed for this device */
874 DeviceNode
->ResourceList
= NULL
;
875 DeviceNode
->ResourceListTranslated
= NULL
;
877 return STATUS_SUCCESS
;
880 /* Fill DeviceNode->ResourceList
881 * FIXME: the PnP arbiter should go there!
882 * Actually, use the BootResources if provided, else the resource requirements
885 if (DeviceNode
->BootResources
)
887 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
889 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
890 if (!DeviceNode
->ResourceList
)
892 Status
= STATUS_NO_MEMORY
;
895 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
897 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
898 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
900 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
902 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
909 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
910 ExFreePool(DeviceNode
->ResourceList
);
911 DeviceNode
->ResourceList
= NULL
;
915 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
916 &DeviceNode
->ResourceList
);
917 if (!NT_SUCCESS(Status
))
919 DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode
->InstancePath
);
923 /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
924 ASSERT(IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
) != STATUS_CONFLICTING_ADDRESSES
);
927 Status
= IopTranslateDeviceResources(DeviceNode
);
928 if (!NT_SUCCESS(Status
))
930 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode
->InstancePath
);
934 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
935 if (!NT_SUCCESS(Status
))
938 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
939 if (!NT_SUCCESS(Status
))
942 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
944 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
946 return STATUS_SUCCESS
;
949 if (DeviceNode
->ResourceList
)
951 ExFreePool(DeviceNode
->ResourceList
);
952 DeviceNode
->ResourceList
= NULL
;
955 DeviceNode
->ResourceListTranslated
= NULL
;
957 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
964 IopCheckForResourceConflict(
965 IN PCM_RESOURCE_LIST ResourceList1
,
966 IN PCM_RESOURCE_LIST ResourceList2
,
968 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
971 BOOLEAN Result
= FALSE
;
973 for (i
= 0; i
< ResourceList1
->Count
; i
++)
975 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
976 for (ii
= 0; ii
< ResList
->Count
; ii
++)
978 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
980 Result
= IopCheckResourceDescriptor(ResDesc
,
983 ConflictingDescriptor
);
984 if (Result
) goto ByeBye
;
995 IopDetectResourceConflict(
996 IN PCM_RESOURCE_LIST ResourceList
,
998 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1000 OBJECT_ATTRIBUTES ObjectAttributes
;
1001 UNICODE_STRING KeyName
;
1002 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1003 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1004 PKEY_BASIC_INFORMATION KeyInformation
;
1005 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1006 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1007 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1010 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1011 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1012 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1013 if (!NT_SUCCESS(Status
))
1015 /* The key is missing which means we are the first device */
1016 return STATUS_SUCCESS
;
1021 Status
= ZwEnumerateKey(ResourceMapKey
,
1023 KeyBasicInformation
,
1027 if (Status
== STATUS_NO_MORE_ENTRIES
)
1029 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1031 KeyInformationLength
= RequiredLength
;
1032 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1033 if (!KeyInformation
)
1035 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1039 Status
= ZwEnumerateKey(ResourceMapKey
,
1041 KeyBasicInformation
,
1043 KeyInformationLength
,
1049 if (!NT_SUCCESS(Status
))
1052 KeyName
.Buffer
= KeyInformation
->Name
;
1053 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1054 InitializeObjectAttributes(&ObjectAttributes
,
1056 OBJ_CASE_INSENSITIVE
,
1059 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1060 ExFreePool(KeyInformation
);
1061 if (!NT_SUCCESS(Status
))
1066 Status
= ZwEnumerateKey(ChildKey2
,
1068 KeyBasicInformation
,
1072 if (Status
== STATUS_NO_MORE_ENTRIES
)
1074 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1076 KeyInformationLength
= RequiredLength
;
1077 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1078 if (!KeyInformation
)
1080 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1084 Status
= ZwEnumerateKey(ChildKey2
,
1086 KeyBasicInformation
,
1088 KeyInformationLength
,
1094 if (!NT_SUCCESS(Status
))
1097 KeyName
.Buffer
= KeyInformation
->Name
;
1098 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1099 InitializeObjectAttributes(&ObjectAttributes
,
1101 OBJ_CASE_INSENSITIVE
,
1104 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1105 ExFreePool(KeyInformation
);
1106 if (!NT_SUCCESS(Status
))
1111 Status
= ZwEnumerateValueKey(ChildKey3
,
1113 KeyValuePartialInformation
,
1117 if (Status
== STATUS_NO_MORE_ENTRIES
)
1119 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1121 KeyValueInformationLength
= RequiredLength
;
1122 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1123 if (!KeyValueInformation
)
1125 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1129 Status
= ZwEnumerateValueKey(ChildKey3
,
1131 KeyValuePartialInformation
,
1132 KeyValueInformation
,
1133 KeyValueInformationLength
,
1138 if (!NT_SUCCESS(Status
))
1141 Status
= ZwEnumerateValueKey(ChildKey3
,
1143 KeyValueBasicInformation
,
1147 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1149 KeyNameInformationLength
= RequiredLength
;
1150 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1151 if (!KeyNameInformation
)
1153 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1157 Status
= ZwEnumerateValueKey(ChildKey3
,
1159 KeyValueBasicInformation
,
1161 KeyNameInformationLength
,
1169 if (!NT_SUCCESS(Status
))
1172 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1174 /* Skip translated entries */
1175 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1177 ExFreePool(KeyNameInformation
);
1181 ExFreePool(KeyNameInformation
);
1183 if (IopCheckForResourceConflict(ResourceList
,
1184 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1186 ConflictingDescriptor
))
1188 ExFreePool(KeyValueInformation
);
1189 Status
= STATUS_CONFLICTING_ADDRESSES
;
1193 ExFreePool(KeyValueInformation
);
1199 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1200 ZwClose(ResourceMapKey
);
1201 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1203 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1206 if (Status
== STATUS_NO_MORE_ENTRIES
)
1207 Status
= STATUS_SUCCESS
;