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
;
825 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
827 /* No resource needed for this device */
828 DeviceNode
->ResourceList
= NULL
;
829 DeviceNode
->ResourceListTranslated
= NULL
;
831 return STATUS_SUCCESS
;
834 /* Fill DeviceNode->ResourceList
835 * FIXME: the PnP arbiter should go there!
836 * Actually, use the BootResources if provided, else the resource requirements
839 if (DeviceNode
->BootResources
)
841 ListSize
= IopCalculateResourceListSize(DeviceNode
->BootResources
);
843 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
844 if (!DeviceNode
->ResourceList
)
846 Status
= STATUS_NO_MEMORY
;
849 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
851 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
852 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
854 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
856 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
863 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
864 ExFreePool(DeviceNode
->ResourceList
);
868 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
869 &DeviceNode
->ResourceList
);
870 if (!NT_SUCCESS(Status
))
873 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
874 if (!NT_SUCCESS(Status
))
878 Status
= IopTranslateDeviceResources(DeviceNode
);
879 if (!NT_SUCCESS(Status
))
882 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
883 if (!NT_SUCCESS(Status
))
886 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
887 if (!NT_SUCCESS(Status
))
890 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
892 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
894 return STATUS_SUCCESS
;
897 if (DeviceNode
->ResourceList
)
899 ExFreePool(DeviceNode
->ResourceList
);
900 DeviceNode
->ResourceList
= NULL
;
903 DeviceNode
->ResourceListTranslated
= NULL
;
905 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
912 IopCheckForResourceConflict(
913 IN PCM_RESOURCE_LIST ResourceList1
,
914 IN PCM_RESOURCE_LIST ResourceList2
,
916 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
919 BOOLEAN Result
= FALSE
;
921 for (i
= 0; i
< ResourceList1
->Count
; i
++)
923 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
924 for (ii
= 0; ii
< ResList
->Count
; ii
++)
926 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
928 Result
= IopCheckResourceDescriptor(ResDesc
,
931 ConflictingDescriptor
);
932 if (Result
) goto ByeBye
;
943 IopDetectResourceConflict(
944 IN PCM_RESOURCE_LIST ResourceList
,
946 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
948 OBJECT_ATTRIBUTES ObjectAttributes
;
949 UNICODE_STRING KeyName
;
950 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
951 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
952 PKEY_BASIC_INFORMATION KeyInformation
;
953 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
954 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
955 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
958 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
959 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
960 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
961 if (!NT_SUCCESS(Status
))
963 /* The key is missing which means we are the first device */
964 return STATUS_SUCCESS
;
969 Status
= ZwEnumerateKey(ResourceMapKey
,
975 if (Status
== STATUS_NO_MORE_ENTRIES
)
977 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
979 KeyInformationLength
= RequiredLength
;
980 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
983 Status
= STATUS_INSUFFICIENT_RESOURCES
;
987 Status
= ZwEnumerateKey(ResourceMapKey
,
991 KeyInformationLength
,
997 if (!NT_SUCCESS(Status
))
1000 KeyName
.Buffer
= KeyInformation
->Name
;
1001 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1002 InitializeObjectAttributes(&ObjectAttributes
,
1004 OBJ_CASE_INSENSITIVE
,
1007 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1008 ExFreePool(KeyInformation
);
1009 if (!NT_SUCCESS(Status
))
1014 Status
= ZwEnumerateKey(ChildKey2
,
1016 KeyBasicInformation
,
1020 if (Status
== STATUS_NO_MORE_ENTRIES
)
1022 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1024 KeyInformationLength
= RequiredLength
;
1025 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1026 if (!KeyInformation
)
1028 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1032 Status
= ZwEnumerateKey(ChildKey2
,
1034 KeyBasicInformation
,
1036 KeyInformationLength
,
1042 if (!NT_SUCCESS(Status
))
1045 KeyName
.Buffer
= KeyInformation
->Name
;
1046 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1047 InitializeObjectAttributes(&ObjectAttributes
,
1049 OBJ_CASE_INSENSITIVE
,
1052 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1053 ExFreePool(KeyInformation
);
1054 if (!NT_SUCCESS(Status
))
1059 Status
= ZwEnumerateValueKey(ChildKey3
,
1061 KeyValuePartialInformation
,
1065 if (Status
== STATUS_NO_MORE_ENTRIES
)
1067 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1069 KeyValueInformationLength
= RequiredLength
;
1070 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1071 if (!KeyValueInformation
)
1073 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1077 Status
= ZwEnumerateValueKey(ChildKey3
,
1079 KeyValuePartialInformation
,
1080 KeyValueInformation
,
1081 KeyValueInformationLength
,
1086 if (!NT_SUCCESS(Status
))
1089 Status
= ZwEnumerateValueKey(ChildKey3
,
1091 KeyValueBasicInformation
,
1095 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1097 KeyNameInformationLength
= RequiredLength
;
1098 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1099 if (!KeyNameInformation
)
1101 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1105 Status
= ZwEnumerateValueKey(ChildKey3
,
1107 KeyValueBasicInformation
,
1109 KeyNameInformationLength
,
1117 if (!NT_SUCCESS(Status
))
1120 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1122 /* Skip translated entries */
1123 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1125 ExFreePool(KeyNameInformation
);
1129 ExFreePool(KeyNameInformation
);
1131 if (IopCheckForResourceConflict(ResourceList
,
1132 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1134 ConflictingDescriptor
))
1136 ExFreePool(KeyValueInformation
);
1137 Status
= STATUS_CONFLICTING_ADDRESSES
;
1141 ExFreePool(KeyValueInformation
);
1147 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1148 ZwClose(ResourceMapKey
);
1149 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1151 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1154 if (Status
== STATUS_NO_MORE_ENTRIES
)
1155 Status
= STATUS_SUCCESS
;