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
];
221 /* FIXME: Handle alternate ranges */
222 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
225 ResDesc
->Type
= ReqDesc
->Type
;
226 ResDesc
->Flags
= ReqDesc
->Flags
;
227 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
229 switch (ReqDesc
->Type
)
231 case CmResourceTypeInterrupt
:
232 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
234 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
235 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
237 if (ReqDesc
->Option
== 0)
239 ExFreePool(*ResourceList
);
240 *ResourceList
= NULL
;
241 return STATUS_CONFLICTING_ADDRESSES
;
246 case CmResourceTypePort
:
247 if (!IopFindPortResource(ReqDesc
, ResDesc
))
249 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
250 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
251 ReqDesc
->u
.Port
.Length
);
253 if (ReqDesc
->Option
== 0)
255 ExFreePool(*ResourceList
);
256 *ResourceList
= NULL
;
257 return STATUS_CONFLICTING_ADDRESSES
;
262 case CmResourceTypeMemory
:
263 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
265 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
266 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
267 ReqDesc
->u
.Memory
.Length
);
269 if (ReqDesc
->Option
== 0)
271 ExFreePool(*ResourceList
);
272 *ResourceList
= NULL
;
273 return STATUS_CONFLICTING_ADDRESSES
;
278 case CmResourceTypeBusNumber
:
279 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
281 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
282 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
283 ReqDesc
->u
.BusNumber
.Length
);
285 if (ReqDesc
->Option
== 0)
287 ExFreePool(*ResourceList
);
288 *ResourceList
= NULL
;
289 return STATUS_CONFLICTING_ADDRESSES
;
294 case CmResourceTypeDma
:
295 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
297 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
298 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
300 if (ReqDesc
->Option
== 0)
302 ExFreePool(*ResourceList
);
303 *ResourceList
= NULL
;
304 return STATUS_CONFLICTING_ADDRESSES
;
310 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
314 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
319 return STATUS_SUCCESS
;
324 IopCheckResourceDescriptor(
325 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
326 IN PCM_RESOURCE_LIST ResourceList
,
328 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
331 BOOLEAN Result
= FALSE
;
333 for (i
= 0; i
< ResourceList
->Count
; i
++)
335 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
336 for (ii
= 0; ii
< ResList
->Count
; ii
++)
338 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
340 /* We don't care about shared resources */
341 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
342 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
345 /* Make sure we're comparing the same types */
346 if (ResDesc
->Type
!= ResDesc2
->Type
)
349 switch (ResDesc
->Type
)
351 case CmResourceTypeMemory
:
352 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
353 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
354 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
355 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
356 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
360 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
361 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
362 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
363 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
372 case CmResourceTypePort
:
373 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
374 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
375 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
376 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
377 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
381 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
382 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
383 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
384 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
393 case CmResourceTypeInterrupt
:
394 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
398 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
399 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
400 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
409 case CmResourceTypeBusNumber
:
410 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
411 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
412 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
413 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
414 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
418 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
419 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
420 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
421 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
430 case CmResourceTypeDma
:
431 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
435 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
436 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
437 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
451 if (Result
&& ConflictingDescriptor
)
453 RtlCopyMemory(ConflictingDescriptor
,
455 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
463 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode
)
465 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
466 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
467 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
468 HANDLE EnumKey
, InstanceKey
, ControlKey
;
470 OBJECT_ATTRIBUTES ObjectAttributes
;
472 /* Open the Enum key */
473 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
474 if (!NT_SUCCESS(Status
))
477 /* Open the instance key (eg. Root\PNP0A03) */
478 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
481 if (!NT_SUCCESS(Status
))
484 /* Create/Open the Control key */
485 InitializeObjectAttributes(&ObjectAttributes
,
487 OBJ_CASE_INSENSITIVE
,
490 Status
= ZwCreateKey(&ControlKey
,
497 ZwClose(InstanceKey
);
499 if (!NT_SUCCESS(Status
))
502 /* Write the resource list */
503 Status
= ZwSetValueKey(ControlKey
,
507 DeviceNode
->ResourceList
,
508 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
511 if (!NT_SUCCESS(Status
))
514 return STATUS_SUCCESS
;
519 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode
)
521 IO_STACK_LOCATION Stack
;
522 IO_STATUS_BLOCK IoStatusBlock
;
525 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
527 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
528 Status
= IopInitiatePnpIrp(
529 DeviceNode
->PhysicalDeviceObject
,
531 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
533 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
535 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
538 else if (NT_SUCCESS(Status
))
540 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
543 return STATUS_SUCCESS
;
548 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
552 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
553 UNICODE_STRING KeyName
;
554 OBJECT_ATTRIBUTES ObjectAttributes
;
556 RtlInitUnicodeString(&KeyName
,
557 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
558 InitializeObjectAttributes(&ObjectAttributes
,
560 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
563 Status
= ZwCreateKey(&ResourceMapKey
,
570 if (!NT_SUCCESS(Status
))
573 RtlInitUnicodeString(&KeyName
, Level1Key
);
574 InitializeObjectAttributes(&ObjectAttributes
,
576 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
579 Status
= ZwCreateKey(&PnpMgrLevel1
,
586 ZwClose(ResourceMapKey
);
587 if (!NT_SUCCESS(Status
))
590 RtlInitUnicodeString(&KeyName
, Level2Key
);
591 InitializeObjectAttributes(&ObjectAttributes
,
593 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
596 Status
= ZwCreateKey(&PnpMgrLevel2
,
603 ZwClose(PnpMgrLevel1
);
604 if (!NT_SUCCESS(Status
))
607 if (DeviceNode
->ResourceList
)
609 UNICODE_STRING NameU
;
610 UNICODE_STRING RawSuffix
, TranslatedSuffix
;
613 ASSERT(DeviceNode
->ResourceListTranslated
);
615 RtlInitUnicodeString(&TranslatedSuffix
, L
".Translated");
616 RtlInitUnicodeString(&RawSuffix
, L
".Raw");
618 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
619 DevicePropertyPhysicalDeviceObjectName
,
623 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
627 NameU
.Buffer
= ExAllocatePool(PagedPool
, OldLength
+ TranslatedSuffix
.Length
);
630 ZwClose(PnpMgrLevel2
);
631 return STATUS_INSUFFICIENT_RESOURCES
;
635 NameU
.MaximumLength
= OldLength
+ TranslatedSuffix
.Length
;
637 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
638 DevicePropertyPhysicalDeviceObjectName
,
642 if (!NT_SUCCESS(Status
))
644 ZwClose(PnpMgrLevel2
);
645 ExFreePool(NameU
.Buffer
);
649 else if (!NT_SUCCESS(Status
))
652 ZwClose(PnpMgrLevel2
);
657 /* This should never happen */
661 NameU
.Length
= OldLength
;
663 RtlAppendUnicodeStringToString(&NameU
, &RawSuffix
);
665 Status
= ZwSetValueKey(PnpMgrLevel2
,
669 DeviceNode
->ResourceList
,
670 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
671 if (!NT_SUCCESS(Status
))
673 ZwClose(PnpMgrLevel2
);
674 ExFreePool(NameU
.Buffer
);
678 /* "Remove" the suffix by setting the length back to what it used to be */
679 NameU
.Length
= OldLength
;
681 RtlAppendUnicodeStringToString(&NameU
, &TranslatedSuffix
);
683 Status
= ZwSetValueKey(PnpMgrLevel2
,
687 DeviceNode
->ResourceListTranslated
,
688 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
689 ZwClose(PnpMgrLevel2
);
690 ExFreePool(NameU
.Buffer
);
692 if (!NT_SUCCESS(Status
))
697 ZwClose(PnpMgrLevel2
);
700 return STATUS_SUCCESS
;
704 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
706 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
711 IopTranslateDeviceResources(
712 IN PDEVICE_NODE DeviceNode
)
714 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
715 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
716 ULONG i
, j
, ListSize
;
719 if (!DeviceNode
->ResourceList
)
721 DeviceNode
->ResourceListTranslated
= NULL
;
722 return STATUS_SUCCESS
;
725 /* That's easy to translate a resource list. Just copy the
726 * untranslated one and change few fields in the copy
728 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
730 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
731 if (!DeviceNode
->ResourceListTranslated
)
733 Status
= STATUS_NO_MEMORY
;
736 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
738 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
740 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
741 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
743 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
744 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
745 switch (DescriptorRaw
->Type
)
747 case CmResourceTypePort
:
749 ULONG AddressSpace
= 1; /* IO space */
750 if (!HalTranslateBusAddress(
751 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
752 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
753 DescriptorRaw
->u
.Port
.Start
,
755 &DescriptorTranslated
->u
.Port
.Start
))
757 Status
= STATUS_UNSUCCESSFUL
;
758 DPRINT1("Failed to translate port resource (Start: 0xI64x)\n", DescriptorRaw
->u
.Port
.Start
.QuadPart
);
763 case CmResourceTypeInterrupt
:
765 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
766 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
767 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
768 DescriptorRaw
->u
.Interrupt
.Level
,
769 DescriptorRaw
->u
.Interrupt
.Vector
,
770 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
771 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
773 if (!DescriptorTranslated
->u
.Interrupt
.Vector
)
775 Status
= STATUS_UNSUCCESSFUL
;
776 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw
->u
.Interrupt
.Vector
,
777 DescriptorRaw
->u
.Interrupt
.Level
);
782 case CmResourceTypeMemory
:
784 ULONG AddressSpace
= 0; /* Memory space */
785 if (!HalTranslateBusAddress(
786 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
787 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
788 DescriptorRaw
->u
.Memory
.Start
,
790 &DescriptorTranslated
->u
.Memory
.Start
))
792 Status
= STATUS_UNSUCCESSFUL
;
793 DPRINT1("Failed to translate memory resource (Start: 0xI64x)\n", DescriptorRaw
->u
.Memory
.Start
.QuadPart
);
798 case CmResourceTypeDma
:
799 case CmResourceTypeBusNumber
:
800 case CmResourceTypeDeviceSpecific
:
804 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
805 Status
= STATUS_NOT_IMPLEMENTED
;
810 return STATUS_SUCCESS
;
813 /* Yes! Also delete ResourceList because ResourceList and
814 * ResourceListTranslated should be a pair! */
815 ExFreePool(DeviceNode
->ResourceList
);
816 DeviceNode
->ResourceList
= NULL
;
817 if (DeviceNode
->ResourceListTranslated
)
819 ExFreePool(DeviceNode
->ResourceListTranslated
);
820 DeviceNode
->ResourceList
= NULL
;
827 IopAssignDeviceResources(
828 IN PDEVICE_NODE DeviceNode
)
833 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
835 Status
= IopFilterResourceRequirements(DeviceNode
);
836 if (!NT_SUCCESS(Status
))
839 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
841 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
842 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
844 /* No resource needed for this device */
845 DeviceNode
->ResourceList
= NULL
;
846 DeviceNode
->ResourceListTranslated
= NULL
;
848 return STATUS_SUCCESS
;
851 /* Fill DeviceNode->ResourceList
852 * FIXME: the PnP arbiter should go there!
853 * Actually, use the BootResources if provided, else the resource requirements
856 if (DeviceNode
->BootResources
)
858 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
860 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
861 if (!DeviceNode
->ResourceList
)
863 Status
= STATUS_NO_MEMORY
;
866 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
868 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
869 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
871 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
873 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
880 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
881 ExFreePool(DeviceNode
->ResourceList
);
882 DeviceNode
->ResourceList
= NULL
;
886 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
887 &DeviceNode
->ResourceList
);
888 if (!NT_SUCCESS(Status
))
890 DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode
->InstancePath
);
894 /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
895 ASSERT(IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
) != STATUS_CONFLICTING_ADDRESSES
);
898 Status
= IopTranslateDeviceResources(DeviceNode
);
899 if (!NT_SUCCESS(Status
))
901 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode
->InstancePath
);
905 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
906 if (!NT_SUCCESS(Status
))
909 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
910 if (!NT_SUCCESS(Status
))
913 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
915 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
917 return STATUS_SUCCESS
;
920 if (DeviceNode
->ResourceList
)
922 ExFreePool(DeviceNode
->ResourceList
);
923 DeviceNode
->ResourceList
= NULL
;
926 DeviceNode
->ResourceListTranslated
= NULL
;
928 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
935 IopCheckForResourceConflict(
936 IN PCM_RESOURCE_LIST ResourceList1
,
937 IN PCM_RESOURCE_LIST ResourceList2
,
939 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
942 BOOLEAN Result
= FALSE
;
944 for (i
= 0; i
< ResourceList1
->Count
; i
++)
946 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
947 for (ii
= 0; ii
< ResList
->Count
; ii
++)
949 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
951 Result
= IopCheckResourceDescriptor(ResDesc
,
954 ConflictingDescriptor
);
955 if (Result
) goto ByeBye
;
966 IopDetectResourceConflict(
967 IN PCM_RESOURCE_LIST ResourceList
,
969 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
971 OBJECT_ATTRIBUTES ObjectAttributes
;
972 UNICODE_STRING KeyName
;
973 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
974 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
975 PKEY_BASIC_INFORMATION KeyInformation
;
976 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
977 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
978 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
981 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
982 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
983 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
984 if (!NT_SUCCESS(Status
))
986 /* The key is missing which means we are the first device */
987 return STATUS_SUCCESS
;
992 Status
= ZwEnumerateKey(ResourceMapKey
,
998 if (Status
== STATUS_NO_MORE_ENTRIES
)
1000 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1002 KeyInformationLength
= RequiredLength
;
1003 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1004 if (!KeyInformation
)
1006 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1010 Status
= ZwEnumerateKey(ResourceMapKey
,
1012 KeyBasicInformation
,
1014 KeyInformationLength
,
1020 if (!NT_SUCCESS(Status
))
1023 KeyName
.Buffer
= KeyInformation
->Name
;
1024 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1025 InitializeObjectAttributes(&ObjectAttributes
,
1027 OBJ_CASE_INSENSITIVE
,
1030 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1031 ExFreePool(KeyInformation
);
1032 if (!NT_SUCCESS(Status
))
1037 Status
= ZwEnumerateKey(ChildKey2
,
1039 KeyBasicInformation
,
1043 if (Status
== STATUS_NO_MORE_ENTRIES
)
1045 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1047 KeyInformationLength
= RequiredLength
;
1048 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1049 if (!KeyInformation
)
1051 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1055 Status
= ZwEnumerateKey(ChildKey2
,
1057 KeyBasicInformation
,
1059 KeyInformationLength
,
1065 if (!NT_SUCCESS(Status
))
1068 KeyName
.Buffer
= KeyInformation
->Name
;
1069 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1070 InitializeObjectAttributes(&ObjectAttributes
,
1072 OBJ_CASE_INSENSITIVE
,
1075 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1076 ExFreePool(KeyInformation
);
1077 if (!NT_SUCCESS(Status
))
1082 Status
= ZwEnumerateValueKey(ChildKey3
,
1084 KeyValuePartialInformation
,
1088 if (Status
== STATUS_NO_MORE_ENTRIES
)
1090 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1092 KeyValueInformationLength
= RequiredLength
;
1093 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1094 if (!KeyValueInformation
)
1096 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1100 Status
= ZwEnumerateValueKey(ChildKey3
,
1102 KeyValuePartialInformation
,
1103 KeyValueInformation
,
1104 KeyValueInformationLength
,
1109 if (!NT_SUCCESS(Status
))
1112 Status
= ZwEnumerateValueKey(ChildKey3
,
1114 KeyValueBasicInformation
,
1118 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1120 KeyNameInformationLength
= RequiredLength
;
1121 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1122 if (!KeyNameInformation
)
1124 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1128 Status
= ZwEnumerateValueKey(ChildKey3
,
1130 KeyValueBasicInformation
,
1132 KeyNameInformationLength
,
1140 if (!NT_SUCCESS(Status
))
1143 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1145 /* Skip translated entries */
1146 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1148 ExFreePool(KeyNameInformation
);
1152 ExFreePool(KeyNameInformation
);
1154 if (IopCheckForResourceConflict(ResourceList
,
1155 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1157 ConflictingDescriptor
))
1159 ExFreePool(KeyValueInformation
);
1160 Status
= STATUS_CONFLICTING_ADDRESSES
;
1164 ExFreePool(KeyValueInformation
);
1170 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1171 ZwClose(ResourceMapKey
);
1172 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1174 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1177 if (Status
== STATUS_NO_MORE_ENTRIES
)
1178 Status
= STATUS_SUCCESS
;