Author: evb
Date: Mon Aug 9 19:07:52 2010
New Revision: 48492
URL: http://svn.reactos.org/svn/reactos?rev=48492&view=rev
Log:
Support PCI device resource dicsovery for limit and current now, so bridge + device BAR functionning
PciScanBus second pass enabled: PciProcessBus, most stubs now until VGA/ISA system tested
PciClassifyDeviceType implement as helper function
PCI Enumeration 100% complete!
Modified:
trunk/reactos/drivers/bus/pcix/device.c
trunk/reactos/drivers/bus/pcix/enum.c
trunk/reactos/drivers/bus/pcix/pci.h
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/device.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/device.c?…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/device.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/device.c [iso-8859-1] Mon Aug 9 19:07:52 2010
@@ -20,32 +20,238 @@
NTAPI
Device_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ PPCI_COMMON_HEADER PciData;
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ PPCI_FUNCTION_RESOURCES Resources;
+ PULONG BarArray;
+ ULONG Bar, BarMask, i;
+
+ /* Get variables from context */
+ PciData = Context->Current;
+ Resources = Context->PdoExtension->Resources;
+
+ /* Loop all the PCI BARs */
+ BarArray = PciData->u.type0.BaseAddresses;
+ for (i = 0; i <= PCI_TYPE0_ADDRESSES; i++)
+ {
+ /* Get the resource descriptor and limit descriptor for this BAR */
+ CmDescriptor = &Resources->Current[i];
+ IoDescriptor = &Resources->Limit[i];
+
+ /* Build the resource descriptor based on the limit descriptor */
+ CmDescriptor->Type = IoDescriptor->Type;
+ if (CmDescriptor->Type == CmResourceTypeNull) continue;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->u.Generic.Start.HighPart = 0;
+ CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
+
+ /* Read the actual BAR value */
+ Bar = BarArray[i];
+
+ /* Check which BAR is being processed now */
+ if (i != PCI_TYPE0_ADDRESSES)
+ {
+ /* Check if this is an I/O BAR */
+ if (Bar & PCI_ADDRESS_IO_SPACE)
+ {
+ /* Use the right mask to get the I/O port base address */
+ ASSERT(CmDescriptor->Type == CmResourceTypePort);
+ BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
+ }
+ else
+ {
+ /* It's a RAM BAR, use the right mask to get the base address */
+ ASSERT(CmDescriptor->Type == CmResourceTypeMemory);
+ BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
+
+ /* Check if it's a 64-bit BAR */
+ if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+ {
+ /* The next BAR value is actually the high 32-bits */
+ CmDescriptor->u.Memory.Start.HighPart = BarArray[i + 1];
+ }
+ else if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
+ {
+ /* Legacy BAR, don't read more than 20 bits of the address */
+ BarMask = 0xFFFF0;
+ }
+ }
+ }
+ else
+ {
+ /* Actually a ROM BAR, so read the correct register */
+ Bar = PciData->u.type0.ROMBaseAddress;
+
+ /* Apply the correct mask for ROM BARs */
+ BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK;
+
+ /* Make sure it's enabled */
+ if (!(Bar & PCI_ROMADDRESS_ENABLED))
+ {
+ /* If it isn't, then a descriptor won't be built for it */
+ CmDescriptor->Type = CmResourceTypeNull;
+ continue;
+ }
+ }
+
+ /* Now we have the right mask, read the actual address from the BAR */
+ Bar &= BarMask;
+ CmDescriptor->u.Memory.Start.LowPart = Bar;
+
+ /* And check for invalid BAR addresses */
+ if (!(CmDescriptor->u.Memory.Start.HighPart | Bar))
+ {
+ /* Skip these descriptors */
+ CmDescriptor->Type = CmResourceTypeNull;
+ DPRINT1("Invalid BAR\n");
+ }
+ }
+
+ /* Also save the sub-IDs that came directly from the PCI header */
+ Context->PdoExtension->SubsystemVendorId = PciData->u.type0.SubVendorID;
+ Context->PdoExtension->SubsystemId = PciData->u.type0.SubSystemID;
}
VOID
NTAPI
Device_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ PPCI_COMMON_HEADER Current, PciData;
+ PPCI_PDO_EXTENSION PdoExtension;
+ PULONG BarArray;
+ PIO_RESOURCE_DESCRIPTOR Limit;
+ ULONG i;
+
+ /* Get pointers from the context */
+ PdoExtension = Context->PdoExtension;
+ Current = Context->Current;
+ PciData = Context->PciData;
+
+ /* And get the array of bARs */
+ BarArray = PciData->u.type0.BaseAddresses;
+
+ /* First, check for IDE controllers that are not in native mode */
+ if ((PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
+ (PdoExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR) &&
+ (PdoExtension->ProgIf & 5) != 5)
+ {
+ /* They should not be using any non-legacy resources */
+ BarArray[0] = 0;
+ BarArray[1] = 0;
+ BarArray[2] = 0;
+ BarArray[3] = 0;
+ }
+ else if ((PdoExtension->VendorId == 0x5333) &&
+ ((PdoExtension->DeviceId == 0x88F0) ||
+ (PdoExtension->DeviceId == 0x8880)))
+ {
+ /*
+ * The problem is caused by the S3 Vision 968/868 video controller which
+ * is used on the Diamond Stealth 64 Video 3000 series, Number Nine 9FX
+ * motion 771, and other popular video cards, all containing a memory bug.
+ * The 968/868 claims to require 32 MB of memory, but it actually decodes
+ * 64 MB of memory.
+ */
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ {
+ /* Find its 32MB RAM BAR */
+ if (BarArray[i] == 0xFE000000)
+ {
+ /* Increase it to 64MB to make sure nobody touches the buffer */
+ BarArray[i] = 0xFC000000;
+ DPRINT1("PCI - Adjusted broken S3 requirement from 32MB to 64MB\n");
+ }
+ }
+ }
+
+ /* Check for Cirrus Logic GD5430/5440 cards */
+ if ((PdoExtension->VendorId == 0x1013) && (PdoExtension->DeviceId == 0xA0))
+ {
+ /* Check for the I/O port requirement */
+ if (BarArray[1] == 0xFC01)
+ {
+ /* Check for completely bogus BAR */
+ if (Current->u.type0.BaseAddresses[1] == 1)
+ {
+ /* Ignore it */
+ BarArray[1] = 0;
+ DPRINT1("PCI - Ignored Cirrus GD54xx broken IO requirement (400 ports)\n");
+ }
+ else
+ {
+ /* Otherwise, this BAR seems okay */
+ DPRINT1("PCI - Cirrus GD54xx 400 port IO requirement has a valid setting (%08x)\n",
+ Current->u.type0.BaseAddresses[1]);
+ }
+ }
+ else if (BarArray[1])
+ {
+ /* Strange, the I/O BAR was not found as expected (or at all) */
+ DPRINT1("PCI - Warning Cirrus Adapter 101300a0 has unexpected resource requirement (%08x)\n",
+ BarArray[1]);
+ }
+ }
+
+ /* Finally, process all the limit descriptors */
+ Limit = PdoExtension->Resources->Limit;
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ {
+ /* And build them based on the BARs */
+ if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE))
+ {
+ /* This function returns TRUE if the BAR was 64-bit, handle this */
+ ASSERT((i + 1) < PCI_TYPE0_ADDRESSES);
+ i++;
+ (&Limit[i])->Type == CmResourceTypeNull;
+ }
+ }
+
+ /* Create the last descriptor based on the ROM address */
+ PciCreateIoDescriptorFromBarLimit(&Limit[i],
+ &PciData->u.type0.ROMBaseAddress,
+ TRUE);
}
VOID
NTAPI
Device_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ PPCI_COMMON_HEADER PciData;
+ PPCI_PDO_EXTENSION PdoExtension;
+ PULONG BarArray;
+ ULONG i = 0;
+
+ /* Get pointers from context data */
+ PdoExtension = Context->PdoExtension;
+ PciData = Context->PciData;
+
+ /* Get the array of BARs */
+ BarArray = PciData->u.type0.BaseAddresses;
+
+ /* Check for IDE controllers that are not in native mode */
+ if ((PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
+ (PdoExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR) &&
+ (PdoExtension->ProgIf & 5) != 5)
+ {
+ /* These controllers only use legacy resources */
+ i = 4;
+ }
+
+ /* Set all the bits on, which will allow us to recover the limit data */
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) BarArray[i] = 0xFFFFFFFF;
+
+ /* Do the same for the PCI ROM BAR */
+ PciData->u.type0.ROMBaseAddress = PCI_ADDRESS_ROM_ADDRESS_MASK;
}
VOID
NTAPI
Device_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ /* Nothing to do for devices */
+ return;
}
VOID
@@ -54,6 +260,7 @@
IN PPCI_COMMON_HEADER PciData,
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
{
+ /* Not yet implemented */
UNIMPLEMENTED;
while (TRUE);
}
@@ -62,6 +269,7 @@
NTAPI
Device_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
+ /* Not yet implemented */
UNIMPLEMENTED;
while (TRUE);
}
@@ -70,6 +278,7 @@
NTAPI
Device_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
+ /* Not yet implemented */
UNIMPLEMENTED;
while (TRUE);
}
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] Mon Aug 9 19:07:52 2010
@@ -32,7 +32,7 @@
PPBridge_SaveCurrentSettings,
PPBridge_ChangeResourceSettings,
PPBridge_GetAdditionalResourceDescriptors,
- PPBridge_ResetDevice
+ PPBridge_ResetDevice
},
{
Cardbus_MassageHeaderForLimitsDetermination,
@@ -44,7 +44,7 @@
Cardbus_ResetDevice
}
};
-
+
/* FUNCTIONS ******************************************************************/
/*
@@ -715,10 +715,10 @@
/* Write the limit discovery header */
PciWriteDeviceConfig(PdoExtension, PciData, 0, PCI_COMMON_HDR_LENGTH);
-
+
/* Now read what the device indicated the limits are */
PciReadDeviceConfig(PdoExtension, PciData, 0, PCI_COMMON_HDR_LENGTH);
-
+
/* Then write back the original configuration header */
PciWriteDeviceConfig(PdoExtension, Current, 0, PCI_COMMON_HDR_LENGTH);
@@ -735,7 +735,7 @@
/* Copy back the original status that was saved as well */
Current->Status = Context->Status;
-
+
/* Call the configurator to restore any other data that might've changed */
Context->Configurator->RestoreCurrent(Context);
}
@@ -915,6 +915,62 @@
/* Enumeration is completed, free the PCI headers and return the status */
ExFreePoolWithTag(PciData, 0);
return Status;
+}
+
+VOID
+NTAPI
+PciProcessBus(IN PPCI_FDO_EXTENSION DeviceExtension)
+{
+ PPCI_PDO_EXTENSION PdoExtension;
+ PDEVICE_OBJECT PhysicalDeviceObject;
+ PAGED_CODE();
+
+ /* Get the PDO Extension */
+ PhysicalDeviceObject = DeviceExtension->PhysicalDeviceObject;
+ PdoExtension = (PPCI_PDO_EXTENSION)PhysicalDeviceObject->DeviceExtension;
+
+ /* Cheeck if this is the root bus */
+ if (!PCI_IS_ROOT_FDO(DeviceExtension))
+ {
+ /* Not really handling this year */
+ UNIMPLEMENTED;
+ while (TRUE);
+
+ /* Check for PCI bridges with the ISA bit set, or required */
+ if ((PdoExtension) &&
+ (PciClassifyDeviceType(PdoExtension) == PciTypePciBridge) &&
+ ((PdoExtension->Dependent.type1.IsaBitRequired) ||
+ (PdoExtension->Dependent.type1.IsaBitSet)))
+ {
+ /* We'll need to do some legacy support */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ }
+ else
+ {
+ /* Scan all of the root bus' children bridges */
+ for (PdoExtension = DeviceExtension->ChildBridgePdoList;
+ PdoExtension;
+ PdoExtension = PdoExtension->NextBridge)
+ {
+ /* Find any that have the VGA decode bit on */
+ if (PdoExtension->Dependent.type1.VgaBitSet)
+ {
+ /* Again, some more legacy support we'll have to do */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ }
+ }
+
+ /* Check for ACPI systems where the OS assigns bus numbers */
+ if (PciAssignBusNumbers)
+ {
+ /* Not yet supported */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
}
NTSTATUS
@@ -1363,7 +1419,8 @@
}
}
- /* Enumeration is completed */
+ /* Enumeration completed, do a final pass now that all devices are found */
+ if (ProcessFlag) PciProcessBus(DeviceExtension);
return STATUS_SUCCESS;
}
Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Mon Aug 9 19:07:52 2010
@@ -101,6 +101,18 @@
PciInterface_AgpTarget = 'icP>',
PciInterface_Location = 'icP?'
} PCI_SIGNATURE, *PPCI_SIGNATURE;
+
+//
+// Driver-handled PCI Device Types
+//
+typedef enum _PCI_DEVICE_TYPES
+{
+ PciTypeInvalid,
+ PciTypeHostBridge,
+ PciTypePciBridge,
+ PciTypeCardbusBridge,
+ PciTypeDevice
+} PCI_DEVICE_TYPES;
//
// Device Extension Logic States
@@ -1064,6 +1076,12 @@
IN BOOLEAN ForPowerDown
);
+PCI_DEVICE_TYPES
+NTAPI
+PciClassifyDeviceType(
+ IN PPCI_PDO_EXTENSION PdoExtension
+);
+
ULONG_PTR
NTAPI
PciExecuteCriticalSystemRoutine(
@@ -1607,6 +1625,7 @@
extern PDRIVER_OBJECT PciDriverObject;
extern PWATCHDOG_TABLE WdTable;
extern PPCI_HACK_ENTRY PciHackTable;
+extern BOOLEAN PciAssignBusNumbers;
extern BOOLEAN PciEnableNativeModeATA;
/* Exported by NTOS, should this go in the NDK? */
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] Mon Aug 9 19:07:52 2010
@@ -1041,6 +1041,24 @@
return !(HackFlags & PCI_HACK_NO_PM_CAPS);
}
+PCI_DEVICE_TYPES
+NTAPI
+PciClassifyDeviceType(IN PPCI_PDO_EXTENSION PdoExtension)
+{
+ ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType);
+
+ /* Differenriate between devices and bridges */
+ if (PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) return PciTypeDevice;
+
+ /* The PCI Bus driver handles only CardBus and PCI bridges (plus host) */
+ if (PdoExtension->SubClass == PCI_SUBCLASS_BR_HOST) return PciTypeHostBridge;
+ if (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) return PciTypePciBridge;
+ if (PdoExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS) return PciTypeCardbusBridge;
+
+ /* Any other kind of bridge is treated like a device */
+ return PciTypeDevice;
+}
+
ULONG_PTR
NTAPI
PciExecuteCriticalSystemRoutine(IN ULONG_PTR IpiContext)