/* GLOBALS ********************************************************************/
+PIO_RESOURCE_REQUIREMENTS_LIST PciZeroIoResourceRequirements;
+
PCI_CONFIGURATOR PciConfigurators[] =
{
{
/* FUNCTIONS ******************************************************************/
+PIO_RESOURCE_REQUIREMENTS_LIST
+NTAPI
+PciAllocateIoRequirementsList(IN ULONG Count,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber)
+{
+ SIZE_T Size;
+ PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+
+ /* Calculate the final size of the list, including each descriptor */
+ Size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ if (Count > 1) Size = sizeof(IO_RESOURCE_DESCRIPTOR) * (Count - 1) +
+ sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+
+ /* Allocate the list */
+ RequirementsList = ExAllocatePoolWithTag(PagedPool, Size, 'BicP');
+ if (!RequirementsList) return NULL;
+
+ /* Initialize it */
+ RtlZeroMemory(RequirementsList, Size);
+ RequirementsList->AlternativeLists = 1;
+ RequirementsList->BusNumber = BusNumber;
+ RequirementsList->SlotNumber = SlotNumber;
+ RequirementsList->InterfaceType = PCIBus;
+ RequirementsList->ListSize = Size;
+ RequirementsList->List[0].Count = Count;
+ RequirementsList->List[0].Version = 1;
+ RequirementsList->List[0].Revision = 1;
+
+ /* Return it */
+ return RequirementsList;
+}
+
+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)
+{
+ 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;
+}
+
+NTSTATUS
+NTAPI
+PciQueryTargetDeviceRelations(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations)
+{
+ PDEVICE_RELATIONS DeviceRelations;
+ PAGED_CODE();
+
+ /* If there were existing relations, free them */
+ if (*pDeviceRelations) ExFreePoolWithTag(*pDeviceRelations, 0);
+
+ /* Allocate a new structure for the relations */
+ DeviceRelations = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DEVICE_RELATIONS),
+ 'BicP');
+ if (!DeviceRelations) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Only one relation: the PDO */
+ DeviceRelations->Count = 1;
+ DeviceRelations->Objects[0] = PdoExtension->PhysicalDeviceObject;
+ ObReferenceObject(DeviceRelations->Objects[0]);
+
+ /* Return the new relations */
+ *pDeviceRelations = DeviceRelations;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryEjectionRelations(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations)
+{
+ /* Not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+}
+
+NTSTATUS
+NTAPI
+PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN PPCI_COMMON_HEADER PciData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST* Buffer)
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+ {
+ /* There aren't, so use the zero descriptor */
+ RequirementsList = PciZeroIoResourceRequirements;
+
+ /* Does it actually exist yet? */
+ if (!PciZeroIoResourceRequirements)
+ {
+ /* Allocate it, and use it for future use */
+ RequirementsList = PciAllocateIoRequirementsList(0, 0, 0);
+ PciZeroIoResourceRequirements = RequirementsList;
+ if (!PciZeroIoResourceRequirements) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Return the zero requirements list to the caller */
+ *Buffer = RequirementsList;
+ DPRINT1("PCI - build resource reqs - early out, 0 resources\n");
+ return STATUS_SUCCESS;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryRequirements(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList)
+{
+ NTSTATUS Status;
+ PCI_COMMON_HEADER PciHeader;
+ PAGED_CODE();
+
+ /* Check if the PDO has any resources, or at least an interrupt pin */
+ if ((PdoExtension->Resources) || (PdoExtension->InterruptPin))
+ {
+ /* Read the current PCI header */
+ PciReadDeviceConfig(PdoExtension, &PciHeader, 0, PCI_COMMON_HDR_LENGTH);
+
+ /* Use it to build a list of requirements */
+ Status = PciBuildRequirementsList(PdoExtension, &PciHeader, RequirementsList);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Is this a Compaq PCI Hotplug Controller (r17) on a PAE system ? */
+ if ((PciHeader.VendorID == 0xE11) &&
+ (PciHeader.DeviceID == 0xA0F7) &&
+ (PciHeader.RevisionID == 17) &&
+ (ExIsProcessorFeaturePresent(PF_PAE_ENABLED)))
+ {
+ /* Have not tested this on eVb's machine yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+
+ /* Check if the requirements are actually the zero list */
+ if (*RequirementsList == PciZeroIoResourceRequirements)
+ {
+ /* A simple NULL will sufficie for the PnP Manager */
+ *RequirementsList = NULL;
+ DPRINT1("Returning NULL requirements list\n");
+ }
+ else
+ {
+ /* Otherwise, print out the requirements list */
+ PciDebugPrintIoResReqList(*RequirementsList);
+ }
+ }
+ else
+ {
+ /* There aren't any resources, so simply return NULL */
+ DPRINT1("PciQueryRequirements returning NULL requirements list\n");
+ *RequirementsList = NULL;
+ }
+
+ /* This call always succeeds (but maybe with no requirements) */
+ return STATUS_SUCCESS;
+}
+
/*
* 7. The IO/MEM/Busmaster decodes are disabled for the device.
* 8. The PCI bus driver sets the operating mode bits of the Programming