* Sync up to trunk head (r64921).
[reactos.git] / ntoskrnl / io / pnpmgr / pnpres.c
index ee0fdca..42e6cfe 100644 (file)
@@ -47,7 +47,7 @@ IopFindBusNumberResource(
    ASSERT(IoDesc->Type == CmResourceTypeBusNumber);
 
    for (Start = IoDesc->u.BusNumber.MinBusNumber;
-        Start < IoDesc->u.BusNumber.MaxBusNumber;
+        Start <= IoDesc->u.BusNumber.MaxBusNumber - IoDesc->u.BusNumber.Length + 1;
         Start++)
    {
         CmDesc->u.BusNumber.Length = IoDesc->u.BusNumber.Length;
@@ -59,6 +59,7 @@ IopFindBusNumberResource(
         }
         else
         {
+            DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start, CmDesc->u.BusNumber.Length);
             return TRUE;
         }
    }
@@ -72,25 +73,30 @@ IopFindMemoryResource(
    IN PIO_RESOURCE_DESCRIPTOR IoDesc,
    OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
 {
-   ULONGLONG Start;
+   LONGLONG Start;
    CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
 
    ASSERT(IoDesc->Type == CmDesc->Type);
    ASSERT(IoDesc->Type == CmResourceTypeMemory);
 
+   /* HACK */
+   if (IoDesc->u.Memory.Alignment == 0) IoDesc->u.Memory.Alignment = 1;
+
    for (Start = IoDesc->u.Memory.MinimumAddress.QuadPart;
-        Start < IoDesc->u.Memory.MaximumAddress.QuadPart;
-        Start++)
+        Start <= IoDesc->u.Memory.MaximumAddress.QuadPart - IoDesc->u.Memory.Length + 1;
+        Start += IoDesc->u.Memory.Alignment)
    {
         CmDesc->u.Memory.Length = IoDesc->u.Memory.Length;
         CmDesc->u.Memory.Start.QuadPart = Start;
 
         if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
         {
-            Start += ConflictingDesc.u.Memory.Start.QuadPart + ConflictingDesc.u.Memory.Length;
+            Start += ConflictingDesc.u.Memory.Start.QuadPart +
+                     ConflictingDesc.u.Memory.Length;
         }
         else
         {
+            DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Memory.Length);
             return TRUE;
         }
    }
@@ -104,15 +110,18 @@ IopFindPortResource(
    IN PIO_RESOURCE_DESCRIPTOR IoDesc,
    OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
 {
-   ULONGLONG Start;
+   LONGLONG Start;
    CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
 
    ASSERT(IoDesc->Type == CmDesc->Type);
    ASSERT(IoDesc->Type == CmResourceTypePort);
 
+   /* HACK */
+   if (IoDesc->u.Port.Alignment == 0) IoDesc->u.Port.Alignment = 1;
+
    for (Start = IoDesc->u.Port.MinimumAddress.QuadPart;
-        Start < IoDesc->u.Port.MaximumAddress.QuadPart;
-        Start++)
+        Start <= IoDesc->u.Port.MaximumAddress.QuadPart - IoDesc->u.Port.Length + 1;
+        Start += IoDesc->u.Port.Alignment)
    {
         CmDesc->u.Port.Length = IoDesc->u.Port.Length;
         CmDesc->u.Port.Start.QuadPart = Start;
@@ -123,6 +132,7 @@ IopFindPortResource(
         }
         else
         {
+            DPRINT1("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Port.Length);
             return TRUE;
         }
    }
@@ -142,14 +152,17 @@ IopFindDmaResource(
    ASSERT(IoDesc->Type == CmResourceTypeDma);
 
    for (Channel = IoDesc->u.Dma.MinimumChannel;
-        Channel < IoDesc->u.Dma.MaximumChannel;
+        Channel <= IoDesc->u.Dma.MaximumChannel;
         Channel++)
    {
         CmDesc->u.Dma.Channel = Channel;
         CmDesc->u.Dma.Port = 0;
 
         if (!IopCheckDescriptorForConflict(CmDesc, NULL))
+        {
+            DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel);
             return TRUE;
+        }
    }
 
    return FALSE;
@@ -167,7 +180,7 @@ IopFindInterruptResource(
    ASSERT(IoDesc->Type == CmResourceTypeInterrupt);
 
    for (Vector = IoDesc->u.Interrupt.MinimumVector;
-        Vector < IoDesc->u.Interrupt.MaximumVector;
+        Vector <= IoDesc->u.Interrupt.MaximumVector;
         Vector++)
    {
         CmDesc->u.Interrupt.Vector = Vector;
@@ -175,148 +188,349 @@ IopFindInterruptResource(
         CmDesc->u.Interrupt.Affinity = (KAFFINITY)-1;
 
         if (!IopCheckDescriptorForConflict(CmDesc, NULL))
+        {
+            DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector);
             return TRUE;
+        }
    }
 
    return FALSE;
 }
 
-
 NTSTATUS NTAPI
-IopCreateResourceListFromRequirements(
+IopFixupResourceListWithRequirements(
    IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
    OUT PCM_RESOURCE_LIST *ResourceList)
 {
-   ULONG i, ii, Size;
-   PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc;
-
-   Size = FIELD_OFFSET(CM_RESOURCE_LIST, List);
-   for (i = 0; i < RequirementsList->AlternativeLists; i++)
-   {
-      PIO_RESOURCE_LIST ResList = &RequirementsList->List[i];
-      Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors)
-        + ResList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
-   }
-
-   *ResourceList = ExAllocatePool(PagedPool, Size);
-   if (!*ResourceList)
-       return STATUS_INSUFFICIENT_RESOURCES;
-
-   (*ResourceList)->Count = 1;
-   (*ResourceList)->List[0].BusNumber = RequirementsList->BusNumber;
-   (*ResourceList)->List[0].InterfaceType = RequirementsList->InterfaceType;
-   (*ResourceList)->List[0].PartialResourceList.Version = 1;
-   (*ResourceList)->List[0].PartialResourceList.Revision = 1;
-   (*ResourceList)->List[0].PartialResourceList.Count = 0;
+    ULONG i, OldCount;
+    BOOLEAN AlternateRequired = FALSE;
+
+    /* Save the initial resource count when we got here so we can restore if an alternate fails */
+    if (*ResourceList != NULL)
+        OldCount = (*ResourceList)->List[0].PartialResourceList.Count;
+    else
+        OldCount = 0;
+
+    for (i = 0; i < RequirementsList->AlternativeLists; i++)
+    {
+        ULONG ii;
+        PIO_RESOURCE_LIST ResList = &RequirementsList->List[i];
+
+        /* We need to get back to where we were before processing the last alternative list */
+        if (OldCount == 0 && *ResourceList != NULL)
+        {
+            /* Just free it and kill the pointer */
+            ExFreePool(*ResourceList);
+            *ResourceList = NULL;
+        }
+        else if (OldCount != 0)
+        {
+            PCM_RESOURCE_LIST NewList;
 
-   ResDesc = &(*ResourceList)->List[0].PartialResourceList.PartialDescriptors[0];
+            /* Let's resize it */
+            (*ResourceList)->List[0].PartialResourceList.Count = OldCount;
 
-   for (i = 0; i < RequirementsList->AlternativeLists; i++)
-   {
-      PIO_RESOURCE_LIST ResList = &RequirementsList->List[i];
-      for (ii = 0; ii < ResList->Count; ii++)
-      {
-         PIO_RESOURCE_DESCRIPTOR ReqDesc = &ResList->Descriptors[ii];
+            /* Allocate the new smaller list */
+            NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList));
+            if (!NewList)
+                return STATUS_NO_MEMORY;
 
-         /* FIXME: Handle alternate ranges */
-         if (ReqDesc->Option == IO_RESOURCE_ALTERNATIVE)
-             continue;
+            /* Copy the old stuff back */
+            RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
 
-         ResDesc->Type = ReqDesc->Type;
-         ResDesc->Flags = ReqDesc->Flags;
-         ResDesc->ShareDisposition = ReqDesc->ShareDisposition;
+            /* Free the old one */
+            ExFreePool(*ResourceList);
 
-         switch (ReqDesc->Type)
-         {
-            case CmResourceTypeInterrupt:
-              if (!IopFindInterruptResource(ReqDesc, ResDesc))
-              {
-                  DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
-                           ReqDesc->u.Interrupt.MinimumVector, ReqDesc->u.Interrupt.MaximumVector);
+            /* Store the pointer to the new one */
+            *ResourceList = NewList;
+        }
 
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
+        for (ii = 0; ii < ResList->Count; ii++)
+        {
+            ULONG iii;
+            PCM_PARTIAL_RESOURCE_LIST PartialList = (*ResourceList) ? &(*ResourceList)->List[0].PartialResourceList : NULL;
+            PIO_RESOURCE_DESCRIPTOR IoDesc = &ResList->Descriptors[ii];
+            BOOLEAN Matched = FALSE;
 
-            case CmResourceTypePort:
-              if (!IopFindPortResource(ReqDesc, ResDesc))
-              {
-                  DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
-                          ReqDesc->u.Port.MinimumAddress.QuadPart, ReqDesc->u.Port.MaximumAddress.QuadPart,
-                          ReqDesc->u.Port.Length);
+            /* Skip alternates if we don't need one */
+            if (!AlternateRequired && (IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
+            {
+                DPRINT("Skipping unneeded alternate\n");
+                continue;
+            }
 
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
+            /* Check if we couldn't satsify a requirement or its alternates */
+            if (AlternateRequired && !(IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
+            {
+                DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
 
-            case CmResourceTypeMemory:
-              if (!IopFindMemoryResource(ReqDesc, ResDesc))
-              {
-                  DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
-                          ReqDesc->u.Memory.MinimumAddress.QuadPart, ReqDesc->u.Memory.MaximumAddress.QuadPart,
-                          ReqDesc->u.Memory.Length);
+                /* Break out of this loop and try the next list */
+                break;
+            }
 
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
+            for (iii = 0; PartialList && iii < PartialList->Count && !Matched; iii++)
+            {
+                PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = &PartialList->PartialDescriptors[iii];
+
+                /* First check types */
+                if (IoDesc->Type != CmDesc->Type)
+                    continue;
+
+                switch (IoDesc->Type)
+                {
+                    case CmResourceTypeInterrupt:
+                        /* Make sure it satisfies our vector range */
+                        if (CmDesc->u.Interrupt.Vector >= IoDesc->u.Interrupt.MinimumVector &&
+                            CmDesc->u.Interrupt.Vector <= IoDesc->u.Interrupt.MaximumVector)
+                        {
+                            /* Found it */
+                            Matched = TRUE;
+                        }
+                        else
+                        {
+                            DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n",
+                                   CmDesc->u.Interrupt.Vector,
+                                   IoDesc->u.Interrupt.MinimumVector,
+                                   IoDesc->u.Interrupt.MaximumVector);
+                        }
+                        break;
+
+                    case CmResourceTypeMemory:
+                    case CmResourceTypePort:
+                        /* Make sure the length matches and it satisfies our address range */
+                        if (CmDesc->u.Memory.Length == IoDesc->u.Memory.Length &&
+                            CmDesc->u.Memory.Start.QuadPart >= IoDesc->u.Memory.MinimumAddress.QuadPart &&
+                            CmDesc->u.Memory.Start.QuadPart + CmDesc->u.Memory.Length - 1 <= IoDesc->u.Memory.MaximumAddress.QuadPart)
+                        {
+                            /* Found it */
+                            Matched = TRUE;
+                        }
+                        else
+                        {
+                            DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n",
+                                   CmDesc->u.Memory.Start.QuadPart,
+                                   CmDesc->u.Memory.Length,
+                                   IoDesc->u.Memory.MinimumAddress.QuadPart,
+                                   IoDesc->u.Memory.MaximumAddress.QuadPart,
+                                   IoDesc->u.Memory.Length);
+                        }
+                        break;
+
+                    case CmResourceTypeBusNumber:
+                        /* Make sure the length matches and it satisfies our bus number range */
+                        if (CmDesc->u.BusNumber.Length == IoDesc->u.BusNumber.Length &&
+                            CmDesc->u.BusNumber.Start >= IoDesc->u.BusNumber.MinBusNumber &&
+                            CmDesc->u.BusNumber.Start + CmDesc->u.BusNumber.Length - 1 <= IoDesc->u.BusNumber.MaxBusNumber)
+                        {
+                            /* Found it */
+                            Matched = TRUE;
+                        }
+                        else
+                        {
+                            DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n",
+                                   CmDesc->u.BusNumber.Start,
+                                   CmDesc->u.BusNumber.Length,
+                                   IoDesc->u.BusNumber.MinBusNumber,
+                                   IoDesc->u.BusNumber.MaxBusNumber,
+                                   IoDesc->u.BusNumber.Length);
+                        }
+                        break;
+
+                    case CmResourceTypeDma:
+                        /* Make sure it fits in our channel range */
+                        if (CmDesc->u.Dma.Channel >= IoDesc->u.Dma.MinimumChannel &&
+                            CmDesc->u.Dma.Channel <= IoDesc->u.Dma.MaximumChannel)
+                        {
+                            /* Found it */
+                            Matched = TRUE;
+                        }
+                        else
+                        {
+                            DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n",
+                                   CmDesc->u.Dma.Channel,
+                                   IoDesc->u.Dma.MinimumChannel,
+                                   IoDesc->u.Dma.MaximumChannel);
+                        }
+                        break;
+
+                    default:
+                        /* Other stuff is fine */
+                        Matched = TRUE;
+                        break;
+                }
+            }
 
-            case CmResourceTypeBusNumber:
-              if (!IopFindBusNumberResource(ReqDesc, ResDesc))
-              {
-                  DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
-                          ReqDesc->u.BusNumber.MinBusNumber, ReqDesc->u.BusNumber.MaxBusNumber,
-                          ReqDesc->u.BusNumber.Length);
+            /* Check if we found a matching descriptor */
+            if (!Matched)
+            {
+                PCM_RESOURCE_LIST NewList;
+                CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc;
+                PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr;
+                BOOLEAN FoundResource = TRUE;
+
+                /* Setup the new CM descriptor */
+                NewDesc.Type = IoDesc->Type;
+                NewDesc.Flags = IoDesc->Flags;
+                NewDesc.ShareDisposition = IoDesc->ShareDisposition;
+
+                /* Let'se see if we can find a resource to satisfy this */
+                switch (IoDesc->Type)
+                {
+                    case CmResourceTypeInterrupt:
+                        /* Find an available interrupt */
+                        if (!IopFindInterruptResource(IoDesc, &NewDesc))
+                        {
+                            DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
+                                    IoDesc->u.Interrupt.MinimumVector, IoDesc->u.Interrupt.MaximumVector);
+
+                            FoundResource = FALSE;
+                        }
+                        break;
+
+                    case CmResourceTypePort:
+                        /* Find an available port range */
+                        if (!IopFindPortResource(IoDesc, &NewDesc))
+                        {
+                            DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
+                                    IoDesc->u.Port.MinimumAddress.QuadPart, IoDesc->u.Port.MaximumAddress.QuadPart,
+                                    IoDesc->u.Port.Length);
+
+                            FoundResource = FALSE;
+                        }
+                        break;
+
+                    case CmResourceTypeMemory:
+                        /* Find an available memory range */
+                        if (!IopFindMemoryResource(IoDesc, &NewDesc))
+                        {
+                            DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
+                                    IoDesc->u.Memory.MinimumAddress.QuadPart, IoDesc->u.Memory.MaximumAddress.QuadPart,
+                                    IoDesc->u.Memory.Length);
+
+                            FoundResource = FALSE;
+                        }
+                        break;
+
+                    case CmResourceTypeBusNumber:
+                        /* Find an available bus address range */
+                        if (!IopFindBusNumberResource(IoDesc, &NewDesc))
+                        {
+                            DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
+                                    IoDesc->u.BusNumber.MinBusNumber, IoDesc->u.BusNumber.MaxBusNumber,
+                                    IoDesc->u.BusNumber.Length);
+
+                            FoundResource = FALSE;
+                        }
+                        break;
+
+                    case CmResourceTypeDma:
+                        /* Find an available DMA channel */
+                        if (!IopFindDmaResource(IoDesc, &NewDesc))
+                        {
+                            DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
+                                    IoDesc->u.Dma.MinimumChannel, IoDesc->u.Dma.MaximumChannel);
+
+                            FoundResource = FALSE;
+                        }
+                        break;
+
+                    default:
+                        DPRINT1("Unsupported resource type: %x\n", IoDesc->Type);
+                        FoundResource = FALSE;
+                        break;
+                }
+
+                /* Check if it's missing and required */
+                if (!FoundResource && IoDesc->Option == 0)
+                {
+                    /* Break out of this loop and try the next list */
+                    DPRINT1("Unable to satisfy required resource in list %lu\n", i);
+                    break;
+                }
+                else if (!FoundResource)
+                {
+                    /* Try an alternate for this preferred descriptor */
+                    AlternateRequired = TRUE;
+                    continue;
+                }
+                else
+                {
+                    /* Move on to the next preferred or required descriptor after this one */
+                    AlternateRequired = FALSE;
+                }
+
+                /* Figure out what we need */
+                if (PartialList == NULL)
+                {
+                    /* We need a new list */
+                    NewList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
+                    if (!NewList)
+                        return STATUS_NO_MEMORY;
+
+                    /* Set it up */
+                    NewList->Count = 1;
+                    NewList->List[0].InterfaceType = RequirementsList->InterfaceType;
+                    NewList->List[0].BusNumber = RequirementsList->BusNumber;
+                    NewList->List[0].PartialResourceList.Version = 1;
+                    NewList->List[0].PartialResourceList.Revision = 1;
+                    NewList->List[0].PartialResourceList.Count = 1;
+
+                    /* Set our pointer */
+                    DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[0];
+                }
+                else
+                {
+                    /* Allocate the new larger list */
+                    NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+                    if (!NewList)
+                        return STATUS_NO_MEMORY;
+
+                    /* Copy the old stuff back */
+                    RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
+
+                    /* Set our pointer */
+                    DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[NewList->List[0].PartialResourceList.Count];
+
+                    /* Increment the descriptor count */
+                    NewList->List[0].PartialResourceList.Count++;
+
+                    /* Free the old list */
+                    ExFreePool(*ResourceList);
+                }
+
+                /* Copy the descriptor in */
+                *DescPtr = NewDesc;
+
+                /* Store the new list */
+                *ResourceList = NewList;
+            }
+        }
 
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
+        /* Check if we need an alternate with no resources left */
+        if (AlternateRequired)
+        {
+            DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
 
-            case CmResourceTypeDma:
-              if (!IopFindDmaResource(ReqDesc, ResDesc))
-              {
-                  DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
-                          ReqDesc->u.Dma.MinimumChannel, ReqDesc->u.Dma.MaximumChannel);
+            /* Try the next alternate list */
+            continue;
+        }
 
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
+        /* We're done because we satisfied one of the alternate lists */
+        return STATUS_SUCCESS;
+    }
 
-            default:
-              DPRINT1("Unsupported resource type: %x\n", ReqDesc->Type);
-              break;
-         }
+    /* We ran out of alternates */
+    DPRINT1("Out of alternate lists!\n");
 
-         (*ResourceList)->List[0].PartialResourceList.Count++;
-         ResDesc++;
-      }
-   }
+    /* Free the list */
+    if (*ResourceList)
+    {
+        ExFreePool(*ResourceList);
+        *ResourceList = NULL;
+    }
 
-   return STATUS_SUCCESS;
+    /* Fail */
+    return STATUS_CONFLICTING_ADDRESSES;
 }
 
 static
@@ -357,7 +571,7 @@ IopCheckResourceDescriptor(
                  {
                       if (!Silent)
                       {
-                          DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
+                          DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
                                   ResDesc->u.Memory.Start.QuadPart, ResDesc->u.Memory.Start.QuadPart +
                                   ResDesc->u.Memory.Length, ResDesc2->u.Memory.Start.QuadPart,
                                   ResDesc2->u.Memory.Start.QuadPart + ResDesc2->u.Memory.Length);
@@ -378,7 +592,7 @@ IopCheckResourceDescriptor(
                  {
                       if (!Silent)
                       {
-                          DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
+                          DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
                                   ResDesc->u.Port.Start.QuadPart, ResDesc->u.Port.Start.QuadPart +
                                   ResDesc->u.Port.Length, ResDesc2->u.Port.Start.QuadPart,
                                   ResDesc2->u.Port.Start.QuadPart + ResDesc2->u.Port.Length);
@@ -509,7 +723,7 @@ IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode)
    ZwClose(ControlKey);
 
    if (!NT_SUCCESS(Status))
-       return Status; 
+       return Status;
 
    return STATUS_SUCCESS;
 }
@@ -532,10 +746,10 @@ IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode)
       &Stack);
    if (!NT_SUCCESS(Status) && Status != STATUS_NOT_SUPPORTED)
    {
-      DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
+      DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
       return Status;
    }
-   else if (NT_SUCCESS(Status))
+   else if (NT_SUCCESS(Status) && IoStatusBlock.Information)
    {
       DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
    }
@@ -554,28 +768,28 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
   OBJECT_ATTRIBUTES ObjectAttributes;
 
   RtlInitUnicodeString(&KeyName,
-                      L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
+               L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
   InitializeObjectAttributes(&ObjectAttributes,
-                            &KeyName,
-                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
-                            0,
-                            NULL);
+                 &KeyName,
+                 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                 0,
+                 NULL);
   Status = ZwCreateKey(&ResourceMapKey,
-                      KEY_ALL_ACCESS,
-                      &ObjectAttributes,
-                      0,
-                      NULL,
-                      REG_OPTION_VOLATILE,
-                      &Disposition);
+               KEY_ALL_ACCESS,
+               &ObjectAttributes,
+               0,
+               NULL,
+               REG_OPTION_VOLATILE,
+               &Disposition);
   if (!NT_SUCCESS(Status))
       return Status;
 
   RtlInitUnicodeString(&KeyName, Level1Key);
   InitializeObjectAttributes(&ObjectAttributes,
-                            &KeyName,
-                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
-                            ResourceMapKey,
-                            NULL);
+                 &KeyName,
+                 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                 ResourceMapKey,
+                 NULL);
   Status = ZwCreateKey(&PnpMgrLevel1,
                        KEY_ALL_ACCESS,
                        &ObjectAttributes,
@@ -589,10 +803,10 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
 
   RtlInitUnicodeString(&KeyName, Level2Key);
   InitializeObjectAttributes(&ObjectAttributes,
-                            &KeyName,
-                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
-                            PnpMgrLevel1,
-                            NULL);
+                 &KeyName,
+                 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                 PnpMgrLevel1,
+                 NULL);
   Status = ZwCreateKey(&PnpMgrLevel2,
                        KEY_ALL_ACCESS,
                        &ObjectAttributes,
@@ -611,7 +825,7 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
       ULONG OldLength = 0;
 
       ASSERT(DeviceNode->ResourceListTranslated);
-      
+
       RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
       RtlInitUnicodeString(&RawSuffix, L".Raw");
 
@@ -623,17 +837,17 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
       if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
       {
           ASSERT(OldLength);
-          
+
           NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length);
           if (!NameU.Buffer)
           {
               ZwClose(PnpMgrLevel2);
               return STATUS_INSUFFICIENT_RESOURCES;
           }
-          
+
           NameU.Length = 0;
-          NameU.MaximumLength = OldLength + TranslatedSuffix.Length;
-          
+          NameU.MaximumLength = (USHORT)OldLength + TranslatedSuffix.Length;
+
           Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
                                        DevicePropertyPhysicalDeviceObjectName,
                                        NameU.MaximumLength,
@@ -657,8 +871,8 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
           /* This should never happen */
           ASSERT(FALSE);
       }
-      
-      NameU.Length = OldLength;
+
+      NameU.Length = (USHORT)OldLength;
 
       RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
 
@@ -676,7 +890,7 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
       }
 
       /* "Remove" the suffix by setting the length back to what it used to be */
-      NameU.Length = OldLength;
+      NameU.Length = (USHORT)OldLength;
 
       RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
 
@@ -758,12 +972,15 @@ IopTranslateDeviceResources(
                   DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
                   goto cleanup;
                }
-                
+
                if (AddressSpace == 0)
                {
-                   /* This is actually a memory resource */
-                   DescriptorRaw->Type = CmResourceTypeMemory;
-                   DescriptorTranslated->Type = CmResourceTypeMemory;
+                   DPRINT1("Guessed incorrect address space: 1 -> 0\n");
+
+                   /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
+                    * invalid for this state but I'm not 100% sure */
+                   DescriptorRaw->Flags =
+                   DescriptorTranslated->Flags = CM_RESOURCE_PORT_MEMORY;
                }
                break;
             }
@@ -776,7 +993,7 @@ IopTranslateDeviceResources(
                   DescriptorRaw->u.Interrupt.Vector,
                   (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
                   &DescriptorTranslated->u.Interrupt.Affinity);
-                
+
                if (!DescriptorTranslated->u.Interrupt.Vector)
                {
                    Status = STATUS_UNSUCCESSFUL;
@@ -797,15 +1014,16 @@ IopTranslateDeviceResources(
                   &DescriptorTranslated->u.Memory.Start))
                {
                   Status = STATUS_UNSUCCESSFUL;
-                  DPRINT1("Failed to translate memory resource (Start: 0xI64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
+                  DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
                   goto cleanup;
                }
 
                if (AddressSpace != 0)
                {
-                   /* This is actually an I/O port resource */
-                   DescriptorRaw->Type = CmResourceTypePort;
-                   DescriptorTranslated->Type = CmResourceTypePort;
+                   DPRINT1("Guessed incorrect address space: 0 -> 1\n");
+
+                   /* This should never happen for memory space */
+                   ASSERT(FALSE);
                }
             }
 
@@ -862,56 +1080,58 @@ IopAssignDeviceResources(
       return STATUS_SUCCESS;
    }
 
-   /* Fill DeviceNode->ResourceList
-    * FIXME: the PnP arbiter should go there!
-    * Actually, use the BootResources if provided, else the resource requirements
-    */
-
    if (DeviceNode->BootResources)
    {
-      ListSize = PnpDetermineResourceListSize(DeviceNode->BootResources);
-
-      DeviceNode->ResourceList = ExAllocatePool(PagedPool, ListSize);
-      if (!DeviceNode->ResourceList)
-      {
-         Status = STATUS_NO_MEMORY;
-         goto ByeBye;
-      }
-      RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, ListSize);
+       ListSize = PnpDetermineResourceListSize(DeviceNode->BootResources);
+
+       DeviceNode->ResourceList = ExAllocatePool(PagedPool, ListSize);
+       if (!DeviceNode->ResourceList)
+       {
+           Status = STATUS_NO_MEMORY;
+           goto ByeBye;
+       }
+
+       RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, ListSize);
+
+       Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+           DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath);
+           ExFreePool(DeviceNode->ResourceList);
+           DeviceNode->ResourceList = NULL;
+       }
+   }
+   else
+   {
+       /* We'll make this from the requirements */
+       DeviceNode->ResourceList = NULL;
+   }
 
-      Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
-      if (NT_SUCCESS(Status) || !DeviceNode->ResourceRequirements)
-      {
-          if (!NT_SUCCESS(Status) && !DeviceNode->ResourceRequirements)
-          {
-              DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
-          }
+   /* No resources requirements */
+   if (!DeviceNode->ResourceRequirements)
+       goto Finish;
 
-          goto Finish;
-      }
-      else
-      {
-          DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath);
-          ExFreePool(DeviceNode->ResourceList);
-          DeviceNode->ResourceList = NULL;
-      }
-   }
+   /* Call HAL to fixup our resource requirements list */
+   HalAdjustResourceList(&DeviceNode->ResourceRequirements);
 
-   Status = IopCreateResourceListFromRequirements(DeviceNode->ResourceRequirements,
-                                                  &DeviceNode->ResourceList);
+   /* Add resource requirements that aren't in the list we already got */
+   Status = IopFixupResourceListWithRequirements(DeviceNode->ResourceRequirements,
+                                                 &DeviceNode->ResourceList);
    if (!NT_SUCCESS(Status))
    {
-       DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
+       DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
+       DeviceNode->Problem = CM_PROB_NORMAL_CONFLICT;
        goto ByeBye;
    }
 
-   /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
+   /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */
    ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES);
 
 Finish:
    Status = IopTranslateDeviceResources(DeviceNode);
    if (!NT_SUCCESS(Status))
    {
+       DeviceNode->Problem = CM_PROB_TRANSLATION_FAILED;
        DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
        goto ByeBye;
    }
@@ -970,7 +1190,6 @@ IopCheckForResourceConflict(
       }
    }
 
-        
 ByeBye:
 
    return Result;
@@ -1021,7 +1240,7 @@ IopDetectResourceConflict(
               goto cleanup;
           }
 
-          Status = ZwEnumerateKey(ResourceMapKey, 
+          Status = ZwEnumerateKey(ResourceMapKey,
                                   ChildKeyIndex1,
                                   KeyBasicInformation,
                                   KeyInformation,
@@ -1035,7 +1254,7 @@ IopDetectResourceConflict(
           goto cleanup;
 
       KeyName.Buffer = KeyInformation->Name;
-      KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength;
+      KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
       InitializeObjectAttributes(&ObjectAttributes,
                                  &KeyName,
                                  OBJ_CASE_INSENSITIVE,
@@ -1048,7 +1267,7 @@ IopDetectResourceConflict(
 
       while (TRUE)
       {
-          Status = ZwEnumerateKey(ChildKey2, 
+          Status = ZwEnumerateKey(ChildKey2,
                                   ChildKeyIndex2,
                                   KeyBasicInformation,
                                   NULL,
@@ -1080,7 +1299,7 @@ IopDetectResourceConflict(
               goto cleanup;
 
           KeyName.Buffer = KeyInformation->Name;
-          KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength;
+          KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
           InitializeObjectAttributes(&ObjectAttributes,
                                      &KeyName,
                                      OBJ_CASE_INSENSITIVE,