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 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
25 CM_RESOURCE_LIST CmList
;
29 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
30 CmList
.List
[0].BusNumber
= 0;
31 CmList
.List
[0].PartialResourceList
.Version
= 1;
32 CmList
.List
[0].PartialResourceList
.Revision
= 1;
33 CmList
.List
[0].PartialResourceList
.Count
= 1;
34 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
36 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
37 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
45 IopFindBusNumberResource(
46 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
47 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
50 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
52 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
53 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
55 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
56 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
59 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
60 CmDesc
->u
.BusNumber
.Start
= Start
;
62 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
64 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
77 IopFindMemoryResource(
78 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
79 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
82 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
84 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
85 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
87 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
88 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
91 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
92 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
94 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
96 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
110 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
111 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
114 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
116 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
117 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
119 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
120 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
123 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
124 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
126 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
128 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
142 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
143 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
147 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
148 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
150 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
151 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
154 CmDesc
->u
.Dma
.Channel
= Channel
;
155 CmDesc
->u
.Dma
.Port
= 0;
157 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
166 IopFindInterruptResource(
167 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
168 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
172 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
173 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
175 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
176 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
179 CmDesc
->u
.Interrupt
.Vector
= Vector
;
180 CmDesc
->u
.Interrupt
.Level
= Vector
;
181 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
183 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
192 IopCreateResourceListFromRequirements(
193 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
194 OUT PCM_RESOURCE_LIST
*ResourceList
)
197 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
199 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
200 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
202 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
203 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
204 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
207 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
209 return STATUS_INSUFFICIENT_RESOURCES
;
211 (*ResourceList
)->Count
= 1;
212 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
213 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
214 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
215 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
216 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
218 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
220 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
222 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
223 for (ii
= 0; ii
< ResList
->Count
; ii
++)
225 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
227 /* FIXME: Handle alternate ranges */
228 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
231 ResDesc
->Type
= ReqDesc
->Type
;
232 ResDesc
->Flags
= ReqDesc
->Flags
;
233 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
235 switch (ReqDesc
->Type
)
237 case CmResourceTypeInterrupt
:
238 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
240 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
241 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
243 if (ReqDesc
->Option
== 0)
245 ExFreePool(*ResourceList
);
246 *ResourceList
= NULL
;
247 return STATUS_CONFLICTING_ADDRESSES
;
252 case CmResourceTypePort
:
253 if (!IopFindPortResource(ReqDesc
, ResDesc
))
255 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
256 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
257 ReqDesc
->u
.Port
.Length
);
259 if (ReqDesc
->Option
== 0)
261 ExFreePool(*ResourceList
);
262 *ResourceList
= NULL
;
263 return STATUS_CONFLICTING_ADDRESSES
;
268 case CmResourceTypeMemory
:
269 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
271 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
272 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
273 ReqDesc
->u
.Memory
.Length
);
275 if (ReqDesc
->Option
== 0)
277 ExFreePool(*ResourceList
);
278 *ResourceList
= NULL
;
279 return STATUS_CONFLICTING_ADDRESSES
;
284 case CmResourceTypeBusNumber
:
285 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
287 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
288 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
289 ReqDesc
->u
.BusNumber
.Length
);
291 if (ReqDesc
->Option
== 0)
293 ExFreePool(*ResourceList
);
294 *ResourceList
= NULL
;
295 return STATUS_CONFLICTING_ADDRESSES
;
300 case CmResourceTypeDma
:
301 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
303 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
304 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
306 if (ReqDesc
->Option
== 0)
308 ExFreePool(*ResourceList
);
309 *ResourceList
= NULL
;
310 return STATUS_CONFLICTING_ADDRESSES
;
316 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
320 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
325 return STATUS_SUCCESS
;
330 IopCheckResourceDescriptor(
331 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
332 IN PCM_RESOURCE_LIST ResourceList
,
334 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
337 BOOLEAN Result
= FALSE
;
339 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
342 for (i
= 0; i
< ResourceList
->Count
; i
++)
344 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
345 for (ii
= 0; ii
< ResList
->Count
; ii
++)
347 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
349 /* We don't care about shared resources */
350 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
351 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
354 /* Make sure we're comparing the same types */
355 if (ResDesc
->Type
!= ResDesc2
->Type
)
358 switch (ResDesc
->Type
)
360 case CmResourceTypeMemory
:
361 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
362 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
363 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
364 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
365 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
369 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
370 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
371 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
372 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
381 case CmResourceTypePort
:
382 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
383 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
384 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
385 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
386 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
390 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
391 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
392 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
393 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
402 case CmResourceTypeInterrupt
:
403 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
407 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
408 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
409 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
418 case CmResourceTypeBusNumber
:
419 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
420 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
421 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
422 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
423 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
427 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
428 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
429 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
430 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
439 case CmResourceTypeDma
:
440 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
444 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
445 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
446 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
460 if (Result
&& ConflictingDescriptor
)
462 RtlCopyMemory(ConflictingDescriptor
,
464 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
472 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode
)
474 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
475 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
476 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
477 HANDLE EnumKey
, InstanceKey
, ControlKey
;
479 OBJECT_ATTRIBUTES ObjectAttributes
;
481 /* Open the Enum key */
482 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
483 if (!NT_SUCCESS(Status
))
486 /* Open the instance key (eg. Root\PNP0A03) */
487 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
490 if (!NT_SUCCESS(Status
))
493 /* Create/Open the Control key */
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_CASE_INSENSITIVE
,
499 Status
= ZwCreateKey(&ControlKey
,
506 ZwClose(InstanceKey
);
508 if (!NT_SUCCESS(Status
))
511 /* Write the resource list */
512 Status
= ZwSetValueKey(ControlKey
,
516 DeviceNode
->ResourceList
,
517 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
520 if (!NT_SUCCESS(Status
))
523 return STATUS_SUCCESS
;
528 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode
)
530 IO_STACK_LOCATION Stack
;
531 IO_STATUS_BLOCK IoStatusBlock
;
534 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
536 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
537 Status
= IopInitiatePnpIrp(
538 DeviceNode
->PhysicalDeviceObject
,
540 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
542 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
544 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
547 else if (NT_SUCCESS(Status
))
549 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
552 return STATUS_SUCCESS
;
557 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
561 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
562 UNICODE_STRING KeyName
;
563 OBJECT_ATTRIBUTES ObjectAttributes
;
565 RtlInitUnicodeString(&KeyName
,
566 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
567 InitializeObjectAttributes(&ObjectAttributes
,
569 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
572 Status
= ZwCreateKey(&ResourceMapKey
,
579 if (!NT_SUCCESS(Status
))
582 RtlInitUnicodeString(&KeyName
, Level1Key
);
583 InitializeObjectAttributes(&ObjectAttributes
,
585 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
588 Status
= ZwCreateKey(&PnpMgrLevel1
,
595 ZwClose(ResourceMapKey
);
596 if (!NT_SUCCESS(Status
))
599 RtlInitUnicodeString(&KeyName
, Level2Key
);
600 InitializeObjectAttributes(&ObjectAttributes
,
602 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
605 Status
= ZwCreateKey(&PnpMgrLevel2
,
612 ZwClose(PnpMgrLevel1
);
613 if (!NT_SUCCESS(Status
))
616 if (DeviceNode
->ResourceList
)
618 PWCHAR DeviceName
= NULL
;
619 UNICODE_STRING NameU
;
620 UNICODE_STRING Suffix
;
623 ASSERT(DeviceNode
->ResourceListTranslated
);
625 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
626 DevicePropertyPhysicalDeviceObjectName
,
630 if ((OldLength
!= 0) && (Status
== STATUS_BUFFER_TOO_SMALL
))
632 DeviceName
= ExAllocatePool(NonPagedPool
, OldLength
);
635 IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
636 DevicePropertyPhysicalDeviceObjectName
,
641 RtlInitUnicodeString(&NameU
, DeviceName
);
646 ASSERT(!NT_SUCCESS(Status
));
650 RtlInitUnicodeString(&Suffix
, L
".Raw");
651 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
653 Status
= ZwSetValueKey(PnpMgrLevel2
,
657 DeviceNode
->ResourceList
,
658 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
659 if (!NT_SUCCESS(Status
))
661 ZwClose(PnpMgrLevel2
);
665 /* "Remove" the suffix by setting the length back to what it used to be */
666 NameU
.Length
= (USHORT
)OldLength
;
668 RtlInitUnicodeString(&Suffix
, L
".Translated");
669 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
671 Status
= ZwSetValueKey(PnpMgrLevel2
,
675 DeviceNode
->ResourceListTranslated
,
676 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
677 ZwClose(PnpMgrLevel2
);
679 ExFreePool(DeviceName
);
680 if (!NT_SUCCESS(Status
))
685 ZwClose(PnpMgrLevel2
);
688 return STATUS_SUCCESS
;
692 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
694 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
699 IopTranslateDeviceResources(
700 IN PDEVICE_NODE DeviceNode
)
702 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
703 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
704 ULONG i
, j
, ListSize
;
707 if (!DeviceNode
->ResourceList
)
709 DeviceNode
->ResourceListTranslated
= NULL
;
710 return STATUS_SUCCESS
;
713 /* That's easy to translate a resource list. Just copy the
714 * untranslated one and change few fields in the copy
716 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
718 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
719 if (!DeviceNode
->ResourceListTranslated
)
721 Status
=STATUS_NO_MEMORY
;
724 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
726 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
728 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
729 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
731 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
732 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
733 switch (DescriptorRaw
->Type
)
735 case CmResourceTypePort
:
737 ULONG AddressSpace
= 1; /* IO space */
738 if (!HalTranslateBusAddress(
739 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
740 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
741 DescriptorRaw
->u
.Port
.Start
,
743 &DescriptorTranslated
->u
.Port
.Start
))
745 Status
= STATUS_UNSUCCESSFUL
;
750 case CmResourceTypeInterrupt
:
752 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
753 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
754 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
755 DescriptorRaw
->u
.Interrupt
.Level
,
756 DescriptorRaw
->u
.Interrupt
.Vector
,
757 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
758 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
761 case CmResourceTypeMemory
:
763 ULONG AddressSpace
= 0; /* Memory space */
764 if (!HalTranslateBusAddress(
765 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
766 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
767 DescriptorRaw
->u
.Memory
.Start
,
769 &DescriptorTranslated
->u
.Memory
.Start
))
771 Status
= STATUS_UNSUCCESSFUL
;
776 case CmResourceTypeDma
:
777 case CmResourceTypeBusNumber
:
778 case CmResourceTypeDeviceSpecific
:
782 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
783 Status
= STATUS_NOT_IMPLEMENTED
;
788 return STATUS_SUCCESS
;
791 /* Yes! Also delete ResourceList because ResourceList and
792 * ResourceListTranslated should be a pair! */
793 ExFreePool(DeviceNode
->ResourceList
);
794 DeviceNode
->ResourceList
= NULL
;
795 if (DeviceNode
->ResourceListTranslated
)
797 ExFreePool(DeviceNode
->ResourceListTranslated
);
798 DeviceNode
->ResourceList
= NULL
;
805 IopAssignDeviceResources(
806 IN PDEVICE_NODE DeviceNode
)
811 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
813 Status
= IopFilterResourceRequirements(DeviceNode
);
814 if (!NT_SUCCESS(Status
))
817 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
819 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
820 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
822 /* No resource needed for this device */
823 DeviceNode
->ResourceList
= NULL
;
824 DeviceNode
->ResourceListTranslated
= NULL
;
826 return STATUS_SUCCESS
;
829 /* Fill DeviceNode->ResourceList
830 * FIXME: the PnP arbiter should go there!
831 * Actually, use the BootResources if provided, else the resource requirements
834 if (DeviceNode
->BootResources
)
836 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
838 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
839 if (!DeviceNode
->ResourceList
)
841 Status
= STATUS_NO_MEMORY
;
844 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
846 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
847 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
849 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
851 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
858 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
859 ExFreePool(DeviceNode
->ResourceList
);
860 DeviceNode
->ResourceList
= NULL
;
864 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
865 &DeviceNode
->ResourceList
);
866 if (!NT_SUCCESS(Status
))
869 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
870 if (!NT_SUCCESS(Status
))
874 Status
= IopTranslateDeviceResources(DeviceNode
);
875 if (!NT_SUCCESS(Status
))
878 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
879 if (!NT_SUCCESS(Status
))
882 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
883 if (!NT_SUCCESS(Status
))
886 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
888 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
890 return STATUS_SUCCESS
;
893 if (DeviceNode
->ResourceList
)
895 ExFreePool(DeviceNode
->ResourceList
);
896 DeviceNode
->ResourceList
= NULL
;
899 DeviceNode
->ResourceListTranslated
= NULL
;
901 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
908 IopCheckForResourceConflict(
909 IN PCM_RESOURCE_LIST ResourceList1
,
910 IN PCM_RESOURCE_LIST ResourceList2
,
912 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
915 BOOLEAN Result
= FALSE
;
917 for (i
= 0; i
< ResourceList1
->Count
; i
++)
919 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
920 for (ii
= 0; ii
< ResList
->Count
; ii
++)
922 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
924 Result
= IopCheckResourceDescriptor(ResDesc
,
927 ConflictingDescriptor
);
928 if (Result
) goto ByeBye
;
939 IopDetectResourceConflict(
940 IN PCM_RESOURCE_LIST ResourceList
,
942 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
944 OBJECT_ATTRIBUTES ObjectAttributes
;
945 UNICODE_STRING KeyName
;
946 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
947 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
948 PKEY_BASIC_INFORMATION KeyInformation
;
949 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
950 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
951 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
954 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
955 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
956 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
957 if (!NT_SUCCESS(Status
))
959 /* The key is missing which means we are the first device */
960 return STATUS_SUCCESS
;
965 Status
= ZwEnumerateKey(ResourceMapKey
,
971 if (Status
== STATUS_NO_MORE_ENTRIES
)
973 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
975 KeyInformationLength
= RequiredLength
;
976 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
979 Status
= STATUS_INSUFFICIENT_RESOURCES
;
983 Status
= ZwEnumerateKey(ResourceMapKey
,
987 KeyInformationLength
,
993 if (!NT_SUCCESS(Status
))
996 KeyName
.Buffer
= KeyInformation
->Name
;
997 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
998 InitializeObjectAttributes(&ObjectAttributes
,
1000 OBJ_CASE_INSENSITIVE
,
1003 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1004 ExFreePool(KeyInformation
);
1005 if (!NT_SUCCESS(Status
))
1010 Status
= ZwEnumerateKey(ChildKey2
,
1012 KeyBasicInformation
,
1016 if (Status
== STATUS_NO_MORE_ENTRIES
)
1018 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1020 KeyInformationLength
= RequiredLength
;
1021 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1022 if (!KeyInformation
)
1024 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1028 Status
= ZwEnumerateKey(ChildKey2
,
1030 KeyBasicInformation
,
1032 KeyInformationLength
,
1038 if (!NT_SUCCESS(Status
))
1041 KeyName
.Buffer
= KeyInformation
->Name
;
1042 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1043 InitializeObjectAttributes(&ObjectAttributes
,
1045 OBJ_CASE_INSENSITIVE
,
1048 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1049 ExFreePool(KeyInformation
);
1050 if (!NT_SUCCESS(Status
))
1055 Status
= ZwEnumerateValueKey(ChildKey3
,
1057 KeyValuePartialInformation
,
1061 if (Status
== STATUS_NO_MORE_ENTRIES
)
1063 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1065 KeyValueInformationLength
= RequiredLength
;
1066 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1067 if (!KeyValueInformation
)
1069 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1073 Status
= ZwEnumerateValueKey(ChildKey3
,
1075 KeyValuePartialInformation
,
1076 KeyValueInformation
,
1077 KeyValueInformationLength
,
1082 if (!NT_SUCCESS(Status
))
1085 Status
= ZwEnumerateValueKey(ChildKey3
,
1087 KeyValueBasicInformation
,
1091 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1093 KeyNameInformationLength
= RequiredLength
;
1094 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1095 if (!KeyNameInformation
)
1097 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1101 Status
= ZwEnumerateValueKey(ChildKey3
,
1103 KeyValueBasicInformation
,
1105 KeyNameInformationLength
,
1113 if (!NT_SUCCESS(Status
))
1116 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1118 /* Skip translated entries */
1119 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1121 ExFreePool(KeyNameInformation
);
1125 ExFreePool(KeyNameInformation
);
1127 if (IopCheckForResourceConflict(ResourceList
,
1128 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1130 ConflictingDescriptor
))
1132 ExFreePool(KeyValueInformation
);
1133 Status
= STATUS_CONFLICTING_ADDRESSES
;
1137 ExFreePool(KeyValueInformation
);
1143 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1144 ZwClose(ResourceMapKey
);
1145 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1147 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1150 if (Status
== STATUS_NO_MORE_ENTRIES
)
1151 Status
= STATUS_SUCCESS
;