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
);
82 if (IoDesc
->u
.Memory
.Alignment
== 0) IoDesc
->u
.Memory
.Alignment
= 1;
84 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
85 Start
<= IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
86 Start
+= IoDesc
->u
.Memory
.Alignment
)
88 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
89 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
91 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
93 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+
94 ConflictingDesc
.u
.Memory
.Length
;
108 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
109 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
112 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
114 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
115 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
118 if (IoDesc
->u
.Port
.Alignment
== 0) IoDesc
->u
.Port
.Alignment
= 1;
120 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
121 Start
<= IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
122 Start
+= IoDesc
->u
.Port
.Alignment
)
124 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
125 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
127 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
129 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
143 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
144 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
148 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
149 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
151 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
152 Channel
<= IoDesc
->u
.Dma
.MaximumChannel
;
155 CmDesc
->u
.Dma
.Channel
= Channel
;
156 CmDesc
->u
.Dma
.Port
= 0;
158 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
167 IopFindInterruptResource(
168 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
169 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
173 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
174 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
176 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
177 Vector
<= IoDesc
->u
.Interrupt
.MaximumVector
;
180 CmDesc
->u
.Interrupt
.Vector
= Vector
;
181 CmDesc
->u
.Interrupt
.Level
= Vector
;
182 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
184 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
193 IopCreateResourceListFromRequirements(
194 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
195 OUT PCM_RESOURCE_LIST
*ResourceList
)
198 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
200 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
201 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
203 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
204 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
205 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
208 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
210 return STATUS_INSUFFICIENT_RESOURCES
;
212 (*ResourceList
)->Count
= 1;
213 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
214 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
215 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
216 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
217 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
219 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
221 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
223 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
224 for (ii
= 0; ii
< ResList
->Count
; ii
++)
226 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
227 BOOLEAN FoundResource
= TRUE
;
229 /* FIXME: Handle alternate ranges */
230 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
233 ResDesc
->Type
= ReqDesc
->Type
;
234 ResDesc
->Flags
= ReqDesc
->Flags
;
235 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
237 switch (ReqDesc
->Type
)
239 case CmResourceTypeInterrupt
:
240 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
242 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
243 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
245 if (ReqDesc
->Option
== 0)
247 ExFreePool(*ResourceList
);
248 *ResourceList
= NULL
;
249 return STATUS_CONFLICTING_ADDRESSES
;
252 FoundResource
= FALSE
;
256 case CmResourceTypePort
:
257 if (!IopFindPortResource(ReqDesc
, ResDesc
))
259 DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
260 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
261 ReqDesc
->u
.Port
.Length
);
263 if (ReqDesc
->Option
== 0)
265 ExFreePool(*ResourceList
);
266 *ResourceList
= NULL
;
267 return STATUS_CONFLICTING_ADDRESSES
;
270 FoundResource
= FALSE
;
274 case CmResourceTypeMemory
:
275 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
277 DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
278 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
279 ReqDesc
->u
.Memory
.Length
);
281 if (ReqDesc
->Option
== 0)
283 ExFreePool(*ResourceList
);
284 *ResourceList
= NULL
;
285 return STATUS_CONFLICTING_ADDRESSES
;
288 FoundResource
= FALSE
;
292 case CmResourceTypeBusNumber
:
293 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
295 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
296 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
297 ReqDesc
->u
.BusNumber
.Length
);
299 if (ReqDesc
->Option
== 0)
301 ExFreePool(*ResourceList
);
302 *ResourceList
= NULL
;
303 return STATUS_CONFLICTING_ADDRESSES
;
306 FoundResource
= FALSE
;
310 case CmResourceTypeDma
:
311 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
313 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
314 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
316 if (ReqDesc
->Option
== 0)
318 ExFreePool(*ResourceList
);
319 *ResourceList
= NULL
;
320 return STATUS_CONFLICTING_ADDRESSES
;
323 FoundResource
= FALSE
;
328 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
329 FoundResource
= FALSE
;
335 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
341 return STATUS_SUCCESS
;
346 IopCheckResourceDescriptor(
347 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
348 IN PCM_RESOURCE_LIST ResourceList
,
350 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
353 BOOLEAN Result
= FALSE
;
355 for (i
= 0; i
< ResourceList
->Count
; i
++)
357 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
358 for (ii
= 0; ii
< ResList
->Count
; ii
++)
360 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
362 /* We don't care about shared resources */
363 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
364 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
367 /* Make sure we're comparing the same types */
368 if (ResDesc
->Type
!= ResDesc2
->Type
)
371 switch (ResDesc
->Type
)
373 case CmResourceTypeMemory
:
374 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
375 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
376 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
377 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
378 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
382 DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
383 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
384 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
385 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
394 case CmResourceTypePort
:
395 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
396 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
397 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
398 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
399 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
403 DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
404 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
405 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
406 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
415 case CmResourceTypeInterrupt
:
416 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
420 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
421 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
422 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
431 case CmResourceTypeBusNumber
:
432 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
433 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
434 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
435 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
436 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
440 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
441 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
442 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
443 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
452 case CmResourceTypeDma
:
453 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
457 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
458 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
459 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
473 if (Result
&& ConflictingDescriptor
)
475 RtlCopyMemory(ConflictingDescriptor
,
477 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
485 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode
)
487 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
488 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
489 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
490 HANDLE EnumKey
, InstanceKey
, ControlKey
;
492 OBJECT_ATTRIBUTES ObjectAttributes
;
494 /* Open the Enum key */
495 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
496 if (!NT_SUCCESS(Status
))
499 /* Open the instance key (eg. Root\PNP0A03) */
500 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
503 if (!NT_SUCCESS(Status
))
506 /* Create/Open the Control key */
507 InitializeObjectAttributes(&ObjectAttributes
,
509 OBJ_CASE_INSENSITIVE
,
512 Status
= ZwCreateKey(&ControlKey
,
519 ZwClose(InstanceKey
);
521 if (!NT_SUCCESS(Status
))
524 /* Write the resource list */
525 Status
= ZwSetValueKey(ControlKey
,
529 DeviceNode
->ResourceList
,
530 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
533 if (!NT_SUCCESS(Status
))
536 return STATUS_SUCCESS
;
541 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode
)
543 IO_STACK_LOCATION Stack
;
544 IO_STATUS_BLOCK IoStatusBlock
;
547 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
549 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
550 Status
= IopInitiatePnpIrp(
551 DeviceNode
->PhysicalDeviceObject
,
553 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
555 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
557 DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
560 else if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
562 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
565 return STATUS_SUCCESS
;
570 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
574 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
575 UNICODE_STRING KeyName
;
576 OBJECT_ATTRIBUTES ObjectAttributes
;
578 RtlInitUnicodeString(&KeyName
,
579 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
580 InitializeObjectAttributes(&ObjectAttributes
,
582 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
585 Status
= ZwCreateKey(&ResourceMapKey
,
592 if (!NT_SUCCESS(Status
))
595 RtlInitUnicodeString(&KeyName
, Level1Key
);
596 InitializeObjectAttributes(&ObjectAttributes
,
598 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
601 Status
= ZwCreateKey(&PnpMgrLevel1
,
608 ZwClose(ResourceMapKey
);
609 if (!NT_SUCCESS(Status
))
612 RtlInitUnicodeString(&KeyName
, Level2Key
);
613 InitializeObjectAttributes(&ObjectAttributes
,
615 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
618 Status
= ZwCreateKey(&PnpMgrLevel2
,
625 ZwClose(PnpMgrLevel1
);
626 if (!NT_SUCCESS(Status
))
629 if (DeviceNode
->ResourceList
)
631 UNICODE_STRING NameU
;
632 UNICODE_STRING RawSuffix
, TranslatedSuffix
;
635 ASSERT(DeviceNode
->ResourceListTranslated
);
637 RtlInitUnicodeString(&TranslatedSuffix
, L
".Translated");
638 RtlInitUnicodeString(&RawSuffix
, L
".Raw");
640 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
641 DevicePropertyPhysicalDeviceObjectName
,
645 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
649 NameU
.Buffer
= ExAllocatePool(PagedPool
, OldLength
+ TranslatedSuffix
.Length
);
652 ZwClose(PnpMgrLevel2
);
653 return STATUS_INSUFFICIENT_RESOURCES
;
657 NameU
.MaximumLength
= (USHORT
)OldLength
+ TranslatedSuffix
.Length
;
659 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
660 DevicePropertyPhysicalDeviceObjectName
,
664 if (!NT_SUCCESS(Status
))
666 ZwClose(PnpMgrLevel2
);
667 ExFreePool(NameU
.Buffer
);
671 else if (!NT_SUCCESS(Status
))
674 ZwClose(PnpMgrLevel2
);
679 /* This should never happen */
683 NameU
.Length
= (USHORT
)OldLength
;
685 RtlAppendUnicodeStringToString(&NameU
, &RawSuffix
);
687 Status
= ZwSetValueKey(PnpMgrLevel2
,
691 DeviceNode
->ResourceList
,
692 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
693 if (!NT_SUCCESS(Status
))
695 ZwClose(PnpMgrLevel2
);
696 ExFreePool(NameU
.Buffer
);
700 /* "Remove" the suffix by setting the length back to what it used to be */
701 NameU
.Length
= (USHORT
)OldLength
;
703 RtlAppendUnicodeStringToString(&NameU
, &TranslatedSuffix
);
705 Status
= ZwSetValueKey(PnpMgrLevel2
,
709 DeviceNode
->ResourceListTranslated
,
710 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
711 ZwClose(PnpMgrLevel2
);
712 ExFreePool(NameU
.Buffer
);
714 if (!NT_SUCCESS(Status
))
719 ZwClose(PnpMgrLevel2
);
722 return STATUS_SUCCESS
;
726 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
728 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
733 IopTranslateDeviceResources(
734 IN PDEVICE_NODE DeviceNode
)
736 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
737 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
738 ULONG i
, j
, ListSize
;
741 if (!DeviceNode
->ResourceList
)
743 DeviceNode
->ResourceListTranslated
= NULL
;
744 return STATUS_SUCCESS
;
747 /* That's easy to translate a resource list. Just copy the
748 * untranslated one and change few fields in the copy
750 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
752 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
753 if (!DeviceNode
->ResourceListTranslated
)
755 Status
= STATUS_NO_MEMORY
;
758 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
760 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
762 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
763 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
765 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
766 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
767 switch (DescriptorRaw
->Type
)
769 case CmResourceTypePort
:
771 ULONG AddressSpace
= 1; /* IO space */
772 if (!HalTranslateBusAddress(
773 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
774 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
775 DescriptorRaw
->u
.Port
.Start
,
777 &DescriptorTranslated
->u
.Port
.Start
))
779 Status
= STATUS_UNSUCCESSFUL
;
780 DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Port
.Start
.QuadPart
);
784 if (AddressSpace
== 0)
786 DPRINT1("Guessed incorrect address space: 1 -> 0\n");
788 /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
789 * invalid for this state but I'm not 100% sure */
790 DescriptorRaw
->Flags
=
791 DescriptorTranslated
->Flags
= CM_RESOURCE_PORT_MEMORY
;
795 case CmResourceTypeInterrupt
:
797 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
798 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
799 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
800 DescriptorRaw
->u
.Interrupt
.Level
,
801 DescriptorRaw
->u
.Interrupt
.Vector
,
802 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
803 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
805 if (!DescriptorTranslated
->u
.Interrupt
.Vector
)
807 Status
= STATUS_UNSUCCESSFUL
;
808 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw
->u
.Interrupt
.Vector
,
809 DescriptorRaw
->u
.Interrupt
.Level
);
814 case CmResourceTypeMemory
:
816 ULONG AddressSpace
= 0; /* Memory space */
817 if (!HalTranslateBusAddress(
818 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
819 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
820 DescriptorRaw
->u
.Memory
.Start
,
822 &DescriptorTranslated
->u
.Memory
.Start
))
824 Status
= STATUS_UNSUCCESSFUL
;
825 DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Memory
.Start
.QuadPart
);
829 if (AddressSpace
!= 0)
831 DPRINT1("Guessed incorrect address space: 0 -> 1\n");
833 /* This should never happen for memory space */
838 case CmResourceTypeDma
:
839 case CmResourceTypeBusNumber
:
840 case CmResourceTypeDeviceSpecific
:
844 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
845 Status
= STATUS_NOT_IMPLEMENTED
;
850 return STATUS_SUCCESS
;
853 /* Yes! Also delete ResourceList because ResourceList and
854 * ResourceListTranslated should be a pair! */
855 ExFreePool(DeviceNode
->ResourceList
);
856 DeviceNode
->ResourceList
= NULL
;
857 if (DeviceNode
->ResourceListTranslated
)
859 ExFreePool(DeviceNode
->ResourceListTranslated
);
860 DeviceNode
->ResourceList
= NULL
;
867 IopAssignDeviceResources(
868 IN PDEVICE_NODE DeviceNode
)
873 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
875 Status
= IopFilterResourceRequirements(DeviceNode
);
876 if (!NT_SUCCESS(Status
))
879 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
881 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
882 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
884 /* No resource needed for this device */
885 DeviceNode
->ResourceList
= NULL
;
886 DeviceNode
->ResourceListTranslated
= NULL
;
888 return STATUS_SUCCESS
;
891 /* Fill DeviceNode->ResourceList
892 * FIXME: the PnP arbiter should go there!
893 * Actually, use the BootResources if provided, else the resource requirements
896 if (DeviceNode
->BootResources
)
898 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
900 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
901 if (!DeviceNode
->ResourceList
)
903 Status
= STATUS_NO_MEMORY
;
906 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
908 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
909 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
911 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
913 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
920 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
921 ExFreePool(DeviceNode
->ResourceList
);
922 DeviceNode
->ResourceList
= NULL
;
926 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
927 &DeviceNode
->ResourceList
);
928 if (!NT_SUCCESS(Status
))
930 DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode
->InstancePath
);
934 /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
935 ASSERT(IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
) != STATUS_CONFLICTING_ADDRESSES
);
938 Status
= IopTranslateDeviceResources(DeviceNode
);
939 if (!NT_SUCCESS(Status
))
941 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode
->InstancePath
);
945 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
946 if (!NT_SUCCESS(Status
))
949 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
950 if (!NT_SUCCESS(Status
))
953 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
955 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
957 return STATUS_SUCCESS
;
960 if (DeviceNode
->ResourceList
)
962 ExFreePool(DeviceNode
->ResourceList
);
963 DeviceNode
->ResourceList
= NULL
;
966 DeviceNode
->ResourceListTranslated
= NULL
;
968 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
975 IopCheckForResourceConflict(
976 IN PCM_RESOURCE_LIST ResourceList1
,
977 IN PCM_RESOURCE_LIST ResourceList2
,
979 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
982 BOOLEAN Result
= FALSE
;
984 for (i
= 0; i
< ResourceList1
->Count
; i
++)
986 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
987 for (ii
= 0; ii
< ResList
->Count
; ii
++)
989 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
991 Result
= IopCheckResourceDescriptor(ResDesc
,
994 ConflictingDescriptor
);
995 if (Result
) goto ByeBye
;
1005 IopDetectResourceConflict(
1006 IN PCM_RESOURCE_LIST ResourceList
,
1008 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1010 OBJECT_ATTRIBUTES ObjectAttributes
;
1011 UNICODE_STRING KeyName
;
1012 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1013 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1014 PKEY_BASIC_INFORMATION KeyInformation
;
1015 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1016 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1017 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1020 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1021 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1022 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1023 if (!NT_SUCCESS(Status
))
1025 /* The key is missing which means we are the first device */
1026 return STATUS_SUCCESS
;
1031 Status
= ZwEnumerateKey(ResourceMapKey
,
1033 KeyBasicInformation
,
1037 if (Status
== STATUS_NO_MORE_ENTRIES
)
1039 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1041 KeyInformationLength
= RequiredLength
;
1042 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1043 if (!KeyInformation
)
1045 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1049 Status
= ZwEnumerateKey(ResourceMapKey
,
1051 KeyBasicInformation
,
1053 KeyInformationLength
,
1059 if (!NT_SUCCESS(Status
))
1062 KeyName
.Buffer
= KeyInformation
->Name
;
1063 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1064 InitializeObjectAttributes(&ObjectAttributes
,
1066 OBJ_CASE_INSENSITIVE
,
1069 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1070 ExFreePool(KeyInformation
);
1071 if (!NT_SUCCESS(Status
))
1076 Status
= ZwEnumerateKey(ChildKey2
,
1078 KeyBasicInformation
,
1082 if (Status
== STATUS_NO_MORE_ENTRIES
)
1084 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1086 KeyInformationLength
= RequiredLength
;
1087 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1088 if (!KeyInformation
)
1090 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1094 Status
= ZwEnumerateKey(ChildKey2
,
1096 KeyBasicInformation
,
1098 KeyInformationLength
,
1104 if (!NT_SUCCESS(Status
))
1107 KeyName
.Buffer
= KeyInformation
->Name
;
1108 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1109 InitializeObjectAttributes(&ObjectAttributes
,
1111 OBJ_CASE_INSENSITIVE
,
1114 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1115 ExFreePool(KeyInformation
);
1116 if (!NT_SUCCESS(Status
))
1121 Status
= ZwEnumerateValueKey(ChildKey3
,
1123 KeyValuePartialInformation
,
1127 if (Status
== STATUS_NO_MORE_ENTRIES
)
1129 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1131 KeyValueInformationLength
= RequiredLength
;
1132 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1133 if (!KeyValueInformation
)
1135 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1139 Status
= ZwEnumerateValueKey(ChildKey3
,
1141 KeyValuePartialInformation
,
1142 KeyValueInformation
,
1143 KeyValueInformationLength
,
1148 if (!NT_SUCCESS(Status
))
1151 Status
= ZwEnumerateValueKey(ChildKey3
,
1153 KeyValueBasicInformation
,
1157 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1159 KeyNameInformationLength
= RequiredLength
;
1160 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1161 if (!KeyNameInformation
)
1163 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1167 Status
= ZwEnumerateValueKey(ChildKey3
,
1169 KeyValueBasicInformation
,
1171 KeyNameInformationLength
,
1179 if (!NT_SUCCESS(Status
))
1182 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1184 /* Skip translated entries */
1185 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1187 ExFreePool(KeyNameInformation
);
1191 ExFreePool(KeyNameInformation
);
1193 if (IopCheckForResourceConflict(ResourceList
,
1194 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1196 ConflictingDescriptor
))
1198 ExFreePool(KeyValueInformation
);
1199 Status
= STATUS_CONFLICTING_ADDRESSES
;
1203 ExFreePool(KeyValueInformation
);
1209 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1210 ZwClose(ResourceMapKey
);
1211 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1213 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1216 if (Status
== STATUS_NO_MORE_ENTRIES
)
1217 Status
= STATUS_SUCCESS
;