Author: evb
Date: Sat Aug 14 17:33:10 2010
New Revision: 48549
URL:
http://svn.reactos.org/svn/reactos?rev=48549&view=rev
Log:
- IRP_MN_QUERY_RESOURCES support for PDO (PciQueryResources, PciAllocateCmResourceList),
now remain IRP_MN_QUERY_RESOURCE_REQUIREMENTS to last device stack interogration from
PNPMGR
Modified:
trunk/reactos/drivers/bus/pcix/enum.c
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/enum.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/enum.c?re…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] Sat Aug 14 17:33:10 2010
@@ -49,14 +49,190 @@
/* 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;
}
Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Sat Aug 14 17:33:10 2010
@@ -1355,7 +1355,7 @@
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 @@
*SlotNumber = SlotInfo->SlotNumber;
return STATUS_SUCCESS;
}
-
+
/* Try the next slot */
SlotInfo++;
}
@@ -1475,7 +1475,7 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
DeviceCapability->D2Latency = 0;
DeviceCapability->D3Latency = 0;
}
-
+
/* This function always succeeds, even without power management support */
return STATUS_SUCCESS;
}