- IRP_MN_QUERY_RESOURCES support for PDO (PciQueryResources, PciAllocateCmResourceLis...
authorevb <evb@svn.reactos.org>
Sat, 14 Aug 2010 17:33:10 +0000 (17:33 +0000)
committerevb <evb@svn.reactos.org>
Sat, 14 Aug 2010 17:33:10 +0000 (17:33 +0000)
svn path=/trunk/; revision=48549

reactos/drivers/bus/pcix/enum.c
reactos/drivers/bus/pcix/utils.c

index 3caa988..37bf55b 100644 (file)
@@ -49,14 +49,190 @@ PCI_CONFIGURATOR PciConfigurators[] =
 
 /* FUNCTIONS ******************************************************************/
 
+PCM_RESOURCE_LIST
+NTAPI
+PciAllocateCmResourceList(IN ULONG Count,
+                          IN ULONG BusNumber)
+{
+    SIZE_T Size;
+    PCM_RESOURCE_LIST ResourceList;
+
+    /* Calculate the final size of the list, including each descriptor */
+    Size = sizeof(CM_RESOURCE_LIST);
+    if (Count > 1) Size = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (Count - 1) +
+                          sizeof(CM_RESOURCE_LIST);
+
+    /* Allocate the list */
+    ResourceList = ExAllocatePoolWithTag(PagedPool, Size, 'BicP');
+    if (!ResourceList) return NULL;
+
+    /* Initialize it */
+    RtlZeroMemory(ResourceList, Size);
+    ResourceList->Count = 1;
+    ResourceList->List[0].BusNumber = BusNumber;
+    ResourceList->List[0].InterfaceType = PCIBus;
+    ResourceList->List[0].PartialResourceList.Version = 1;
+    ResourceList->List[0].PartialResourceList.Revision = 1;
+    ResourceList->List[0].PartialResourceList.Count = Count;
+
+    /* Return it */
+    return ResourceList;
+}
+
 NTSTATUS
 NTAPI
 PciQueryResources(IN PPCI_PDO_EXTENSION PdoExtension,
                   OUT PCM_RESOURCE_LIST *Buffer)
 {
-    /* Not yet implemented */
-    UNIMPLEMENTED;
-    while (TRUE);
+    PPCI_FUNCTION_RESOURCES PciResources;
+    BOOLEAN HaveVga, HaveMemSpace, HaveIoSpace;
+    USHORT BridgeControl, PciCommand;
+    ULONG Count, i;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial, Resource, LastResource;
+    PCM_RESOURCE_LIST ResourceList;
+    UCHAR InterruptLine;
+    PAGED_CODE();
+
+    /* Assume failure */
+    Count = 0;
+    HaveVga = FALSE;
+    *Buffer = NULL;
+
+    /* Make sure there's some resources to query */
+    PciResources = PdoExtension->Resources;
+    if (!PciResources) return STATUS_SUCCESS;
+
+    /* Read the decodes */
+    PciReadDeviceConfig(PdoExtension,
+                        &PciCommand,
+                        FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                        sizeof(USHORT));
+
+    /* Check which ones are turned on */
+    HaveIoSpace = PciCommand & PCI_ENABLE_IO_SPACE;
+    HaveMemSpace = PciCommand & PCI_ENABLE_MEMORY_SPACE;
+
+    /* Loop maximum possible descriptors */
+    for (i = 0; i < 7; i++)
+    {
+        /* Check if the decode for this descriptor is actually turned on */
+        Partial = &PciResources->Current[i];
+        if (((HaveMemSpace) && (Partial->Type == CmResourceTypeMemory)) ||
+            ((HaveIoSpace) && (Partial->Type == CmResourceTypePort)))
+        {
+            /* One more fully active descriptor */
+            Count++;
+        }
+    }
+
+    /* If there's an interrupt pin associated, check at least one decode is on */
+    if ((PdoExtension->InterruptPin) && ((HaveMemSpace) || (HaveIoSpace)))
+    {
+        /* Read the interrupt line for the pin, add a descriptor if it's valid */
+        InterruptLine = PdoExtension->AdjustedInterruptLine;
+        if ((InterruptLine) && (InterruptLine != -1)) Count++;
+    }
+
+    /* Check for PCI bridge */
+    if (PdoExtension->HeaderType == PCI_BRIDGE_TYPE)
+    {
+        /* Read bridge settings, check if VGA is present */
+        PciReadDeviceConfig(PdoExtension,
+                            &BridgeControl,
+                            FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BridgeControl),
+                            sizeof(USHORT));
+        if (BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+        {
+            /* Remember for later */
+            HaveVga = TRUE;
+
+            /* One memory descriptor for 0xA0000, plus the two I/O port ranges */
+            if (HaveMemSpace) Count++;
+            if (HaveIoSpace) Count += 2;
+        }
+    }
+
+    /* If there's no descriptors in use, there's no resources, so return */
+    if (!Count) return STATUS_SUCCESS;
+
+    /* Allocate a resource list to hold the resources */
+    ResourceList = PciAllocateCmResourceList(Count,
+                                             PdoExtension->ParentFdoExtension->BaseBus);
+    if (!ResourceList) return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* This is where the descriptors will be copied into */
+    Resource = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+    LastResource = Resource + Count + 1;
+
+    /* Loop maximum possible descriptors */
+    for (i = 0; i < 7; i++)
+    {
+        /* Check if the decode for this descriptor is actually turned on */
+        Partial = &PciResources->Current[i];
+        if (((HaveMemSpace) && (Partial->Type == CmResourceTypeMemory)) ||
+            ((HaveIoSpace) && (Partial->Type == CmResourceTypePort)))
+        {
+            /* Copy the descriptor into the resource list */
+            *Resource++ = *Partial;
+        }
+    }
+
+    /* Check if earlier the code detected this was a PCI bridge with VGA on it */
+    if (HaveVga)
+    {
+        /* Are the memory decodes enabled? */
+        if (HaveMemSpace)
+        {
+            /* Build a memory descriptor for a 128KB framebuffer at 0xA0000 */
+            Resource->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+            Resource->u.Generic.Start.HighPart = 0;
+            Resource->Type = CmResourceTypeMemory;
+            Resource->u.Generic.Start.LowPart = 0xA0000;
+            Resource->u.Generic.Length = 0x20000;
+            Resource++;
+        }
+
+        /* Are the I/O decodes enabled? */
+        if (HaveIoSpace)
+        {
+            /* Build an I/O descriptor for the graphic ports at 0x3B0 */
+            Resource->Type = CmResourceTypePort;
+            Resource->Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | CM_RESOURCE_PORT_10_BIT_DECODE;
+            Resource->u.Port.Start.QuadPart = 0x3B0u;
+            Resource->u.Port.Length = 0xC;
+            Resource++;
+
+            /* Build an I/O descriptor for the graphic ports at 0x3C0 */
+            Resource->Type = CmResourceTypePort;
+            Resource->Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | CM_RESOURCE_PORT_10_BIT_DECODE;
+            Resource->u.Port.Start.QuadPart = 0x3C0u;
+            Resource->u.Port.Length = 0x20;
+            Resource++;
+        }
+    }
+
+    /* If there's an interrupt pin associated, check at least one decode is on */
+    if ((PdoExtension->InterruptPin) && ((HaveMemSpace) || (HaveIoSpace)))
+    {
+         /* Read the interrupt line for the pin, check if it's valid */
+         InterruptLine = PdoExtension->AdjustedInterruptLine;
+         if ((InterruptLine) && (InterruptLine != -1))
+         {
+             /* Make sure there's still space */
+             ASSERT(Resource < LastResource);
+
+             /* Add the interrupt descriptor */
+             Resource->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+             Resource->Type = CmResourceTypeInterrupt;
+             Resource->ShareDisposition = CmResourceShareShared;
+             Resource->u.Interrupt.Affinity = -1;
+             Resource->u.Interrupt.Level = InterruptLine;
+             Resource->u.Interrupt.Vector = InterruptLine;
+        }
+    }
+
+    /* Return the resouce list */
+    *Buffer = ResourceList;
     return STATUS_SUCCESS;
 }
 
index fa0d91e..031b732 100644 (file)
@@ -1355,7 +1355,7 @@ PciDetermineSlotNumber(IN PPCI_PDO_EXTENSION PdoExtension,
                     SlotInfo->BusNumber,
                     SlotInfo->DeviceNumber,
                     SlotInfo->SlotNumber);
-                    
+
             /* Check if this slot information matches the PDO being queried */
             if ((ParentExtension->BaseBus == SlotInfo->BusNumber) &&
                 (PdoExtension->Slot.u.bits.DeviceNumber == SlotInfo->DeviceNumber >> 3) &&
@@ -1365,7 +1365,7 @@ PciDetermineSlotNumber(IN PPCI_PDO_EXTENSION PdoExtension,
                 *SlotNumber = SlotInfo->SlotNumber;
                 return STATUS_SUCCESS;
             }
-            
+
             /* Try the next slot */
             SlotInfo++;
         }
@@ -1475,7 +1475,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
     DEVICE_CAPABILITIES AttachedCaps;
     DEVICE_POWER_STATE NewPowerState, DevicePowerState, DeviceWakeLevel, DeviceWakeState;
     SYSTEM_POWER_STATE SystemWakeState, DeepestWakeState, CurrentState;
-    
+
     /* Nothing is known at first */
     DeviceWakeState = PowerDeviceUnspecified;
     SystemWakeState = DeepestWakeState = PowerSystemUnspecified;
@@ -1523,7 +1523,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
                       sizeof(DeviceCapability->DeviceState));
         return STATUS_SUCCESS;
     }
-    
+
     /* The PCI Device has power capabilities, so read which ones are supported */
     DeviceCapability->DeviceD1 = PdoExtension->PowerCapabilities.Support.D1;
     DeviceCapability->DeviceD2 = PdoExtension->PowerCapabilities.Support.D2;
@@ -1560,7 +1560,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
         /* Read the current mapping from the attached device */
         DevicePowerState = AttachedCaps.DeviceState[CurrentState];
         NewPowerState = DevicePowerState;
-        
+
         /* The attachee suports D1, but this PDO does not */
         if ((NewPowerState == PowerDeviceD1) &&
             !(PdoExtension->PowerCapabilities.Support.D1))
@@ -1568,7 +1568,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Fall back to D2 */
             NewPowerState = PowerDeviceD2;
         }
-        
+
         /* The attachee supports D2, but this PDO does not */
         if ((NewPowerState == PowerDeviceD2) &&
             !(PdoExtension->PowerCapabilities.Support.D2))
@@ -1576,10 +1576,10 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Fall back to D3 */
             NewPowerState = PowerDeviceD3;
         }
-        
+
         /* Set the mapping based on the best state supported */
         DeviceCapability->DeviceState[CurrentState] = NewPowerState;
-        
+
         /* Check if sleep states are being processed, and a mapping was found */
         if ((CurrentState < PowerSystemHibernate) &&
             (NewPowerState != PowerDeviceUnspecified))
@@ -1587,8 +1587,8 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Save this state as being the deepest one found until now */
             DeepestWakeState = CurrentState;
         }
-        
-        /* 
+
+        /*
          * Finally, check if the computed sleep state is within the states that
          * this device can wake the system from, and if it's higher or equal to
          * the sleep state mapping that came from the attachee, assuming that it
@@ -1618,10 +1618,10 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             DeviceWakeState = NewPowerState;
         }
     }
-    
+
     /* Read the current wake level */
     DeviceWakeLevel = PdoExtension->PowerState.DeviceWakeLevel;
-    
+
     /* Check if the attachee's wake levels are valid, and the PDO's is higher */
     if ((AttachedCaps.SystemWake != PowerSystemUnspecified) &&
         (AttachedCaps.DeviceWake != PowerDeviceUnspecified) &&
@@ -1639,7 +1639,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Bump to D1 */
             DeviceCapability->DeviceWake = PowerDeviceD1;
         }
-        
+
         /* Now check if the wake level is D1, but the PDO doesn't support it */
         if ((DeviceCapability->DeviceWake == PowerDeviceD1) &&
             !(DeviceCapability->WakeFromD1))
@@ -1647,7 +1647,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Bump to D2 */
             DeviceCapability->DeviceWake = PowerDeviceD2;
         }
-    
+
         /* Now check if the wake level is D2, but the PDO doesn't support it */
         if ((DeviceCapability->DeviceWake == PowerDeviceD2) &&
             !(DeviceCapability->WakeFromD2))
@@ -1655,7 +1655,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* Bump it to D3 */
             DeviceCapability->DeviceWake = PowerDeviceD3;
         }
-        
+
         /* Now check if the wake level is D3, but the PDO doesn't support it */
         if ((DeviceCapability->DeviceWake == PowerDeviceD3) &&
             !(DeviceCapability->WakeFromD3))
@@ -1676,12 +1676,12 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
                 /* Use the wake state that had been computed earlier */
                 DeviceCapability->DeviceWake = DeviceWakeState;
                 DeviceCapability->SystemWake = SystemWakeState;
-                
+
                 /* If that state was D3, then the device supports Hot/Cold D3 */
                 if (DeviceWakeState == PowerDeviceD3) DeviceCapability->WakeFromD3 = TRUE;
             }
         }
-        
+
         /*
          * Finally, check for off states (lower than S3, such as hibernate) and
          * make sure that the device both supports waking from D3 as well as
@@ -1694,12 +1694,12 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
             /* It doesn't, so pick the computed lowest wake state from earlier */
             DeviceCapability->SystemWake = DeepestWakeState;
         }
-        
+
         /* Set the PCI Specification mandated maximum latencies for transitions */
         DeviceCapability->D1Latency = 0;
         DeviceCapability->D2Latency = 2;
         DeviceCapability->D3Latency = 100;
-        
+
         /* Sanity check */
         ASSERT(DeviceCapability->DeviceState[PowerSystemWorking] == PowerDeviceD0);
     }
@@ -1710,7 +1710,7 @@ PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
         DeviceCapability->D2Latency = 0;
         DeviceCapability->D3Latency = 0;
     }
-    
+
     /* This function always succeeds, even without power management support */
     return STATUS_SUCCESS;
 }