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
16 IopDetectResourceConflict(
17 IN PCM_RESOURCE_LIST ResourceList
,
19 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
);
23 IopCalculateResourceListSize(
24 IN PCM_RESOURCE_LIST ResourceList
)
27 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
29 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
30 for (i
= 0; i
< ResourceList
->Count
; i
++)
32 pPartialResourceList
= &ResourceList
->List
[i
].PartialResourceList
;
33 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
) +
34 pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
35 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
37 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
38 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
47 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
49 CM_RESOURCE_LIST CmList
;
53 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
54 CmList
.List
[0].BusNumber
= 0;
55 CmList
.List
[0].PartialResourceList
.Version
= 1;
56 CmList
.List
[0].PartialResourceList
.Revision
= 1;
57 CmList
.List
[0].PartialResourceList
.Count
= 1;
58 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
60 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
61 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
69 IopFindBusNumberResource(
70 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
71 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
74 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
76 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
77 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
79 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
80 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
83 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
84 CmDesc
->u
.BusNumber
.Start
= Start
;
86 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
88 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
101 IopFindMemoryResource(
102 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
103 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
106 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
108 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
109 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
111 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
112 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
115 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
116 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
118 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
120 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
134 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
135 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
138 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
140 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
141 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
143 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
144 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
147 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
148 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
150 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
152 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
166 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
167 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
171 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
172 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
174 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
175 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
178 CmDesc
->u
.Dma
.Channel
= Channel
;
179 CmDesc
->u
.Dma
.Port
= 0;
181 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
190 IopFindInterruptResource(
191 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
192 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
196 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
197 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
199 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
200 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
203 CmDesc
->u
.Interrupt
.Vector
= Vector
;
204 CmDesc
->u
.Interrupt
.Level
= Vector
;
205 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
207 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
216 IopCreateResourceListFromRequirements(
217 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
218 OUT PCM_RESOURCE_LIST
*ResourceList
)
221 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
223 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
224 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
226 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
227 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
228 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
231 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
233 return STATUS_INSUFFICIENT_RESOURCES
;
235 (*ResourceList
)->Count
= 1;
236 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
237 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
238 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
239 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
240 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
242 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
244 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
246 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
247 for (ii
= 0; ii
< ResList
->Count
; ii
++)
249 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
251 /* FIXME: Handle alternate ranges */
252 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
255 ResDesc
->Type
= ReqDesc
->Type
;
256 ResDesc
->Flags
= ReqDesc
->Flags
;
257 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
259 switch (ReqDesc
->Type
)
261 case CmResourceTypeInterrupt
:
262 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
264 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
265 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
267 if (ReqDesc
->Option
== 0)
269 ExFreePool(*ResourceList
);
270 return STATUS_CONFLICTING_ADDRESSES
;
275 case CmResourceTypePort
:
276 if (!IopFindPortResource(ReqDesc
, ResDesc
))
278 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
279 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
280 ReqDesc
->u
.Port
.Length
);
282 if (ReqDesc
->Option
== 0)
284 ExFreePool(*ResourceList
);
285 return STATUS_CONFLICTING_ADDRESSES
;
290 case CmResourceTypeMemory
:
291 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
293 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
294 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
295 ReqDesc
->u
.Memory
.Length
);
297 if (ReqDesc
->Option
== 0)
299 ExFreePool(*ResourceList
);
300 return STATUS_CONFLICTING_ADDRESSES
;
305 case CmResourceTypeBusNumber
:
306 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
308 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
309 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
310 ReqDesc
->u
.BusNumber
.Length
);
312 if (ReqDesc
->Option
== 0)
314 ExFreePool(*ResourceList
);
315 return STATUS_CONFLICTING_ADDRESSES
;
320 case CmResourceTypeDma
:
321 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
323 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
324 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
326 if (ReqDesc
->Option
== 0)
328 ExFreePool(*ResourceList
);
329 return STATUS_CONFLICTING_ADDRESSES
;
335 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
339 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
344 return STATUS_SUCCESS
;
349 IopCheckResourceDescriptor(
350 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
351 IN PCM_RESOURCE_LIST ResourceList
,
353 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
356 BOOLEAN Result
= FALSE
;
358 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
361 for (i
= 0; i
< ResourceList
->Count
; i
++)
363 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
364 for (ii
= 0; ii
< ResList
->Count
; ii
++)
366 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
368 /* We don't care about shared resources */
369 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
370 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
373 /* Make sure we're comparing the same types */
374 if (ResDesc
->Type
!= ResDesc2
->Type
)
377 switch (ResDesc
->Type
)
379 case CmResourceTypeMemory
:
380 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
381 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
382 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
383 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
384 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
388 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
389 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
390 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
391 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
400 case CmResourceTypePort
:
401 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
402 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
403 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
404 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
405 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
409 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
410 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
411 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
412 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
421 case CmResourceTypeInterrupt
:
422 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
426 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
427 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
428 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
437 case CmResourceTypeBusNumber
:
438 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
439 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
440 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
441 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
442 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
446 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
447 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
448 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
449 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
458 case CmResourceTypeDma
:
459 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
463 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
464 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
465 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
479 if (Result
&& ConflictingDescriptor
)
481 RtlCopyMemory(ConflictingDescriptor
,
483 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
491 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode
)
493 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
494 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
495 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
496 HANDLE EnumKey
, InstanceKey
, ControlKey
;
498 OBJECT_ATTRIBUTES ObjectAttributes
;
500 /* Open the Enum key */
501 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
502 if (!NT_SUCCESS(Status
))
505 /* Open the instance key (eg. Root\PNP0A03) */
506 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
509 if (!NT_SUCCESS(Status
))
512 /* Create/Open the Control key */
513 InitializeObjectAttributes(&ObjectAttributes
,
515 OBJ_CASE_INSENSITIVE
,
518 Status
= ZwCreateKey(&ControlKey
,
525 ZwClose(InstanceKey
);
527 if (!NT_SUCCESS(Status
))
530 /* Write the resource list */
531 Status
= ZwSetValueKey(ControlKey
,
535 DeviceNode
->ResourceList
,
536 IopCalculateResourceListSize(DeviceNode
->ResourceList
));
539 if (!NT_SUCCESS(Status
))
542 return STATUS_SUCCESS
;
547 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode
)
549 IO_STACK_LOCATION Stack
;
550 IO_STATUS_BLOCK IoStatusBlock
;
553 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
555 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
556 Status
= IopInitiatePnpIrp(
557 DeviceNode
->PhysicalDeviceObject
,
559 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
561 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
563 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
566 else if (NT_SUCCESS(Status
))
568 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
571 return STATUS_SUCCESS
;
576 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
580 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
581 UNICODE_STRING KeyName
;
582 OBJECT_ATTRIBUTES ObjectAttributes
;
584 RtlInitUnicodeString(&KeyName
,
585 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
586 InitializeObjectAttributes(&ObjectAttributes
,
588 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
591 Status
= ZwCreateKey(&ResourceMapKey
,
598 if (!NT_SUCCESS(Status
))
601 RtlInitUnicodeString(&KeyName
, Level1Key
);
602 InitializeObjectAttributes(&ObjectAttributes
,
604 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
607 Status
= ZwCreateKey(&PnpMgrLevel1
,
614 ZwClose(ResourceMapKey
);
615 if (!NT_SUCCESS(Status
))
618 RtlInitUnicodeString(&KeyName
, Level2Key
);
619 InitializeObjectAttributes(&ObjectAttributes
,
621 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
624 Status
= ZwCreateKey(&PnpMgrLevel2
,
631 ZwClose(PnpMgrLevel1
);
632 if (!NT_SUCCESS(Status
))
635 if (DeviceNode
->ResourceList
)
638 UNICODE_STRING NameU
;
639 UNICODE_STRING Suffix
;
642 ASSERT(DeviceNode
->ResourceListTranslated
);
644 NameU
.Buffer
= NameBuff
;
646 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
648 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
649 DevicePropertyPhysicalDeviceObjectName
,
653 ASSERT(Status
== STATUS_SUCCESS
);
655 NameU
.Length
= (USHORT
)OldLength
;
657 RtlInitUnicodeString(&Suffix
, L
".Raw");
658 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
660 Status
= ZwSetValueKey(PnpMgrLevel2
,
664 DeviceNode
->ResourceList
,
665 IopCalculateResourceListSize(DeviceNode
->ResourceList
));
666 if (!NT_SUCCESS(Status
))
668 ZwClose(PnpMgrLevel2
);
672 /* "Remove" the suffix by setting the length back to what it used to be */
673 NameU
.Length
= (USHORT
)OldLength
;
675 RtlInitUnicodeString(&Suffix
, L
".Translated");
676 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
678 Status
= ZwSetValueKey(PnpMgrLevel2
,
682 DeviceNode
->ResourceListTranslated
,
683 IopCalculateResourceListSize(DeviceNode
->ResourceListTranslated
));
684 ZwClose(PnpMgrLevel2
);
685 if (!NT_SUCCESS(Status
))
690 ZwClose(PnpMgrLevel2
);
693 return STATUS_SUCCESS
;
697 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
699 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
704 IopTranslateDeviceResources(
705 IN PDEVICE_NODE DeviceNode
)
707 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
708 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
709 ULONG i
, j
, ListSize
;
712 if (!DeviceNode
->ResourceList
)
714 DeviceNode
->ResourceListTranslated
= NULL
;
715 return STATUS_SUCCESS
;
718 /* That's easy to translate a resource list. Just copy the
719 * untranslated one and change few fields in the copy
721 ListSize
= IopCalculateResourceListSize(DeviceNode
->ResourceList
);
723 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
724 if (!DeviceNode
->ResourceListTranslated
)
726 Status
=STATUS_NO_MEMORY
;
729 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
731 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
733 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
734 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
736 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
737 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
738 switch (DescriptorRaw
->Type
)
740 case CmResourceTypePort
:
742 ULONG AddressSpace
= 1; /* IO space */
743 if (!HalTranslateBusAddress(
744 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
745 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
746 DescriptorRaw
->u
.Port
.Start
,
748 &DescriptorTranslated
->u
.Port
.Start
))
750 Status
= STATUS_UNSUCCESSFUL
;
755 case CmResourceTypeInterrupt
:
757 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
758 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
759 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
760 DescriptorRaw
->u
.Interrupt
.Level
,
761 DescriptorRaw
->u
.Interrupt
.Vector
,
762 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
763 &DescriptorRaw
->u
.Interrupt
.Affinity
);
766 case CmResourceTypeMemory
:
768 ULONG AddressSpace
= 0; /* Memory space */
769 if (!HalTranslateBusAddress(
770 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
771 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
772 DescriptorRaw
->u
.Memory
.Start
,
774 &DescriptorTranslated
->u
.Memory
.Start
))
776 Status
= STATUS_UNSUCCESSFUL
;
781 case CmResourceTypeDma
:
782 case CmResourceTypeBusNumber
:
783 case CmResourceTypeDeviceSpecific
:
787 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
788 Status
= STATUS_NOT_IMPLEMENTED
;
793 return STATUS_SUCCESS
;
796 /* Yes! Also delete ResourceList because ResourceList and
797 * ResourceListTranslated should be a pair! */
798 ExFreePool(DeviceNode
->ResourceList
);
799 DeviceNode
->ResourceList
= NULL
;
800 if (DeviceNode
->ResourceListTranslated
)
802 ExFreePool(DeviceNode
->ResourceListTranslated
);
803 DeviceNode
->ResourceList
= NULL
;
810 IopAssignDeviceResources(
811 IN PDEVICE_NODE DeviceNode
)
816 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
818 Status
= IopFilterResourceRequirements(DeviceNode
);
819 if (!NT_SUCCESS(Status
))
822 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
824 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
826 /* No resource needed for this device */
827 DeviceNode
->ResourceList
= NULL
;
828 DeviceNode
->ResourceListTranslated
= NULL
;
830 return STATUS_SUCCESS
;
833 /* Fill DeviceNode->ResourceList
834 * FIXME: the PnP arbiter should go there!
835 * Actually, use the BootResources if provided, else the resource requirements
838 if (DeviceNode
->BootResources
)
840 ListSize
= IopCalculateResourceListSize(DeviceNode
->BootResources
);
842 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
843 if (!DeviceNode
->ResourceList
)
845 Status
= STATUS_NO_MEMORY
;
848 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
850 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
851 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
853 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
855 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
862 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
863 ExFreePool(DeviceNode
->ResourceList
);
867 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
868 &DeviceNode
->ResourceList
);
869 if (!NT_SUCCESS(Status
))
872 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
873 if (!NT_SUCCESS(Status
))
877 Status
= IopTranslateDeviceResources(DeviceNode
);
878 if (!NT_SUCCESS(Status
))
881 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
882 if (!NT_SUCCESS(Status
))
885 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
886 if (!NT_SUCCESS(Status
))
889 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
891 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
893 return STATUS_SUCCESS
;
896 if (DeviceNode
->ResourceList
)
898 ExFreePool(DeviceNode
->ResourceList
);
899 DeviceNode
->ResourceList
= NULL
;
902 DeviceNode
->ResourceListTranslated
= NULL
;
904 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
911 IopCheckForResourceConflict(
912 IN PCM_RESOURCE_LIST ResourceList1
,
913 IN PCM_RESOURCE_LIST ResourceList2
,
915 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
918 BOOLEAN Result
= FALSE
;
920 for (i
= 0; i
< ResourceList1
->Count
; i
++)
922 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
923 for (ii
= 0; ii
< ResList
->Count
; ii
++)
925 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
927 Result
= IopCheckResourceDescriptor(ResDesc
,
930 ConflictingDescriptor
);
931 if (Result
) goto ByeBye
;
942 IopDetectResourceConflict(
943 IN PCM_RESOURCE_LIST ResourceList
,
945 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
947 OBJECT_ATTRIBUTES ObjectAttributes
;
948 UNICODE_STRING KeyName
;
949 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
950 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
951 PKEY_BASIC_INFORMATION KeyInformation
;
952 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
953 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
954 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
957 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
958 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
959 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
960 if (!NT_SUCCESS(Status
))
962 /* The key is missing which means we are the first device */
963 return STATUS_SUCCESS
;
968 Status
= ZwEnumerateKey(ResourceMapKey
,
974 if (Status
== STATUS_NO_MORE_ENTRIES
)
976 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
978 KeyInformationLength
= RequiredLength
;
979 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
982 Status
= STATUS_INSUFFICIENT_RESOURCES
;
986 Status
= ZwEnumerateKey(ResourceMapKey
,
990 KeyInformationLength
,
996 if (!NT_SUCCESS(Status
))
999 KeyName
.Buffer
= KeyInformation
->Name
;
1000 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1001 InitializeObjectAttributes(&ObjectAttributes
,
1003 OBJ_CASE_INSENSITIVE
,
1006 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1007 ExFreePool(KeyInformation
);
1008 if (!NT_SUCCESS(Status
))
1013 Status
= ZwEnumerateKey(ChildKey2
,
1015 KeyBasicInformation
,
1019 if (Status
== STATUS_NO_MORE_ENTRIES
)
1021 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1023 KeyInformationLength
= RequiredLength
;
1024 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1025 if (!KeyInformation
)
1027 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1031 Status
= ZwEnumerateKey(ChildKey2
,
1033 KeyBasicInformation
,
1035 KeyInformationLength
,
1041 if (!NT_SUCCESS(Status
))
1044 KeyName
.Buffer
= KeyInformation
->Name
;
1045 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1046 InitializeObjectAttributes(&ObjectAttributes
,
1048 OBJ_CASE_INSENSITIVE
,
1051 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1052 ExFreePool(KeyInformation
);
1053 if (!NT_SUCCESS(Status
))
1058 Status
= ZwEnumerateValueKey(ChildKey3
,
1060 KeyValuePartialInformation
,
1064 if (Status
== STATUS_NO_MORE_ENTRIES
)
1066 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1068 KeyValueInformationLength
= RequiredLength
;
1069 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1070 if (!KeyValueInformation
)
1072 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1076 Status
= ZwEnumerateValueKey(ChildKey3
,
1078 KeyValuePartialInformation
,
1079 KeyValueInformation
,
1080 KeyValueInformationLength
,
1085 if (!NT_SUCCESS(Status
))
1088 Status
= ZwEnumerateValueKey(ChildKey3
,
1090 KeyValueBasicInformation
,
1094 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1096 KeyNameInformationLength
= RequiredLength
;
1097 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1098 if (!KeyNameInformation
)
1100 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1104 Status
= ZwEnumerateValueKey(ChildKey3
,
1106 KeyValueBasicInformation
,
1108 KeyNameInformationLength
,
1116 if (!NT_SUCCESS(Status
))
1119 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1121 /* Skip translated entries */
1122 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1124 ExFreePool(KeyNameInformation
);
1128 ExFreePool(KeyNameInformation
);
1130 if (IopCheckForResourceConflict(ResourceList
,
1131 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1133 ConflictingDescriptor
))
1135 ExFreePool(KeyValueInformation
);
1136 Status
= STATUS_CONFLICTING_ADDRESSES
;
1140 ExFreePool(KeyValueInformation
);
1146 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1147 ZwClose(ResourceMapKey
);
1148 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1150 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1153 if (Status
== STATUS_NO_MORE_ENTRIES
)
1154 Status
= STATUS_SUCCESS
;