[USB]
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnpres.c
index 71319f8..73272f5 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-NTSTATUS
-IopDetectResourceConflict(
-   IN PCM_RESOURCE_LIST ResourceList,
-   IN BOOLEAN Silent,
-   OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor);
-
 static
 BOOLEAN
 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
@@ -53,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;
@@ -65,6 +59,7 @@ IopFindBusNumberResource(
         }
         else
         {
+            DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start, CmDesc->u.BusNumber.Length);
             return TRUE;
         }
    }
@@ -78,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;
         }
    }
@@ -110,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;
@@ -129,6 +132,7 @@ IopFindPortResource(
         }
         else
         {
+            DPRINT1("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Port.Length);
             return TRUE;
         }
    }
@@ -148,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;
@@ -173,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;
@@ -181,148 +188,298 @@ 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;
 }
 
-static
-NTSTATUS
-IopCreateResourceListFromRequirements(
+NTSTATUS NTAPI
+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;
-
-   ResDesc = &(*ResourceList)->List[0].PartialResourceList.PartialDescriptors[0];
-
-   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];
-
-         /* FIXME: Handle alternate ranges */
-         if (ReqDesc->Option == IO_RESOURCE_ALTERNATIVE)
-             continue;
-
-         ResDesc->Type = ReqDesc->Type;
-         ResDesc->Flags = ReqDesc->Flags;
-         ResDesc->ShareDisposition = ReqDesc->ShareDisposition;
-
-         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);
-
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
-
-            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);
-
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
-
-            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);
-
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              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);
-
-                  if (ReqDesc->Option == 0)
-                  {
-                      ExFreePool(*ResourceList);
-                      *ResourceList = NULL;
-                      return STATUS_CONFLICTING_ADDRESSES;
-                  }
-              }
-              break;
-
-            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);
+    ULONG i;
+    for (i = 0; i < RequirementsList->AlternativeLists; i++)
+    {
+        ULONG ii;
+        PIO_RESOURCE_LIST ResList = &RequirementsList->List[i];
+        BOOLEAN AlternateRequired = FALSE;
+
+        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;
+            
+            /* 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\n");
+
+                if (*ResourceList)
+                {
+                    ExFreePool(*ResourceList);
+                    *ResourceList = NULL;
+                }
+                return STATUS_CONFLICTING_ADDRESSES;
+            }
 
-            default:
-              DPRINT1("Unsupported resource type: %x\n", ReqDesc->Type);
-              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;
+                }
+            }
 
-         (*ResourceList)->List[0].PartialResourceList.Count++;
-         ResDesc++;
-      }
-   }
+            /* 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)
+                {
+                    if (*ResourceList)
+                    {
+                        ExFreePool(*ResourceList);
+                        *ResourceList = NULL;
+                    }
+                    return STATUS_CONFLICTING_ADDRESSES;
+                }
+                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;
+            }
+        }
+    }
 
-   return STATUS_SUCCESS;
+    /* Done */
+    return STATUS_SUCCESS;
 }
 
 static
@@ -336,9 +493,6 @@ IopCheckResourceDescriptor(
    ULONG i, ii;
    BOOLEAN Result = FALSE;
 
-   if (ResDesc->ShareDisposition == CmResourceShareShared)
-       return FALSE;
-
    for (i = 0; i < ResourceList->Count; i++)
    {
       PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList;
@@ -366,7 +520,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);
@@ -387,7 +541,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);
@@ -518,7 +672,7 @@ IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode)
    ZwClose(ControlKey);
 
    if (!NT_SUCCESS(Status))
-       return Status; 
+       return Status;
 
    return STATUS_SUCCESS;
 }
@@ -541,10 +695,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;
    }
@@ -615,40 +769,61 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
 
   if (DeviceNode->ResourceList)
   {
-      PWCHAR DeviceName = NULL;
       UNICODE_STRING NameU;
-      UNICODE_STRING Suffix;
+      UNICODE_STRING RawSuffix, TranslatedSuffix;
       ULONG OldLength = 0;
 
       ASSERT(DeviceNode->ResourceListTranslated);
+      
+      RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
+      RtlInitUnicodeString(&RawSuffix, L".Raw");
 
       Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
                                    DevicePropertyPhysicalDeviceObjectName,
                                    0,
                                    NULL,
                                    &OldLength);
-     if ((OldLength != 0) && (Status == STATUS_BUFFER_TOO_SMALL))
-     {
-        DeviceName = ExAllocatePool(NonPagedPool, OldLength);
-        ASSERT(DeviceName);
-
-        IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
-                            DevicePropertyPhysicalDeviceObjectName,
-                            OldLength,
-                            DeviceName,
-                            &OldLength);
-                            
-        RtlInitUnicodeString(&NameU, DeviceName);
-     }
-     else
-     {
-        /* Some failure */
-        ASSERT(!NT_SUCCESS(Status));
-        return Status;
-     }
-
-      RtlInitUnicodeString(&Suffix, L".Raw");
-      RtlAppendUnicodeStringToString(&NameU, &Suffix);
+      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 = (USHORT)OldLength + TranslatedSuffix.Length;
+          
+          Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
+                                       DevicePropertyPhysicalDeviceObjectName,
+                                       NameU.MaximumLength,
+                                       NameU.Buffer,
+                                       &OldLength);
+          if (!NT_SUCCESS(Status))
+          {
+              ZwClose(PnpMgrLevel2);
+              ExFreePool(NameU.Buffer);
+              return Status;
+          }
+      }
+      else if (!NT_SUCCESS(Status))
+      {
+          /* Some failure */
+          ZwClose(PnpMgrLevel2);
+          return Status;
+      }
+      else
+      {
+          /* This should never happen */
+          ASSERT(FALSE);
+      }
+      
+      NameU.Length = (USHORT)OldLength;
+
+      RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
 
       Status = ZwSetValueKey(PnpMgrLevel2,
                              &NameU,
@@ -659,14 +834,14 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
       if (!NT_SUCCESS(Status))
       {
           ZwClose(PnpMgrLevel2);
+          ExFreePool(NameU.Buffer);
           return Status;
       }
 
       /* "Remove" the suffix by setting the length back to what it used to be */
       NameU.Length = (USHORT)OldLength;
 
-      RtlInitUnicodeString(&Suffix, L".Translated");
-      RtlAppendUnicodeStringToString(&NameU, &Suffix);
+      RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
 
       Status = ZwSetValueKey(PnpMgrLevel2,
                              &NameU,
@@ -675,8 +850,8 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
                              DeviceNode->ResourceListTranslated,
                              PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated));
       ZwClose(PnpMgrLevel2);
-      ASSERT(DeviceName);
-      ExFreePool(DeviceName);
+      ExFreePool(NameU.Buffer);
+
       if (!NT_SUCCESS(Status))
           return Status;
   }
@@ -718,7 +893,7 @@ IopTranslateDeviceResources(
    DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize);
    if (!DeviceNode->ResourceListTranslated)
    {
-      Status =STATUS_NO_MEMORY;
+      Status = STATUS_NO_MEMORY;
       goto cleanup;
    }
    RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize);
@@ -743,8 +918,19 @@ IopTranslateDeviceResources(
                   &DescriptorTranslated->u.Port.Start))
                {
                   Status = STATUS_UNSUCCESSFUL;
+                  DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
                   goto cleanup;
                }
+                
+               if (AddressSpace == 0)
+               {
+                   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;
             }
             case CmResourceTypeInterrupt:
@@ -756,6 +942,14 @@ IopTranslateDeviceResources(
                   DescriptorRaw->u.Interrupt.Vector,
                   (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
                   &DescriptorTranslated->u.Interrupt.Affinity);
+                
+               if (!DescriptorTranslated->u.Interrupt.Vector)
+               {
+                   Status = STATUS_UNSUCCESSFUL;
+                   DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector,
+                                                                                                   DescriptorRaw->u.Interrupt.Level);
+                   goto cleanup;
+               }
                break;
             }
             case CmResourceTypeMemory:
@@ -769,8 +963,17 @@ IopTranslateDeviceResources(
                   &DescriptorTranslated->u.Memory.Start))
                {
                   Status = STATUS_UNSUCCESSFUL;
+                  DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
                   goto cleanup;
                }
+
+               if (AddressSpace != 0)
+               {
+                   DPRINT1("Guessed incorrect address space: 0 -> 1\n");
+
+                   /* This should never happen for memory space */
+                   ASSERT(FALSE);
+               }
             }
 
             case CmResourceTypeDma:
@@ -826,54 +1029,59 @@ 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 fixup a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
        goto ByeBye;
+   }
 
-   Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
-   if (!NT_SUCCESS(Status))
-       goto ByeBye;
+   /* 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))
+   {
+       DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
        goto ByeBye;
+   }
 
    Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
    if (!NT_SUCCESS(Status))
@@ -929,13 +1137,12 @@ IopCheckForResourceConflict(
       }
    }
 
-        
 ByeBye:
 
    return Result;
 }
 
-NTSTATUS
+NTSTATUS NTAPI
 IopDetectResourceConflict(
    IN PCM_RESOURCE_LIST ResourceList,
    IN BOOLEAN Silent,
@@ -980,7 +1187,7 @@ IopDetectResourceConflict(
               goto cleanup;
           }
 
-          Status = ZwEnumerateKey(ResourceMapKey, 
+          Status = ZwEnumerateKey(ResourceMapKey,
                                   ChildKeyIndex1,
                                   KeyBasicInformation,
                                   KeyInformation,
@@ -994,7 +1201,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,
@@ -1007,7 +1214,7 @@ IopDetectResourceConflict(
 
       while (TRUE)
       {
-          Status = ZwEnumerateKey(ChildKey2, 
+          Status = ZwEnumerateKey(ChildKey2,
                                   ChildKeyIndex2,
                                   KeyBasicInformation,
                                   NULL,
@@ -1039,7 +1246,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,