Support PCI device resource dicsovery for limit and current now, so bridge + device...
authorevb <evb@svn.reactos.org>
Mon, 9 Aug 2010 19:07:52 +0000 (19:07 +0000)
committerevb <evb@svn.reactos.org>
Mon, 9 Aug 2010 19:07:52 +0000 (19:07 +0000)
PciScanBus second pass enabled: PciProcessBus, most stubs now until VGA/ISA system tested
PciClassifyDeviceType implement as helper function
PCI Enumeration 100% complete!

svn path=/trunk/; revision=48492

reactos/drivers/bus/pcix/device.c
reactos/drivers/bus/pcix/enum.c
reactos/drivers/bus/pcix/pci.h
reactos/drivers/bus/pcix/utils.c

index 05d307d..4dbd16b 100644 (file)
@@ -20,32 +20,238 @@ VOID
 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 @@ Device_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context,
                                         IN PPCI_COMMON_HEADER PciData,
                                         IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
 {
+    /* Not yet implemented */
     UNIMPLEMENTED;
     while (TRUE);
 }
@@ -62,6 +269,7 @@ VOID
 NTAPI
 Device_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
+    /* Not yet implemented */
     UNIMPLEMENTED;
     while (TRUE);
 }
@@ -70,6 +278,7 @@ VOID
 NTAPI
 Device_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
+    /* Not yet implemented */
     UNIMPLEMENTED;
     while (TRUE);
 }
index dc771f2..a4d53dd 100644 (file)
@@ -32,7 +32,7 @@ PCI_CONFIGURATOR PciConfigurators[] =
         PPBridge_SaveCurrentSettings,
         PPBridge_ChangeResourceSettings,
         PPBridge_GetAdditionalResourceDescriptors,
-        PPBridge_ResetDevice  
+        PPBridge_ResetDevice
     },
     {
         Cardbus_MassageHeaderForLimitsDetermination,
@@ -44,7 +44,7 @@ PCI_CONFIGURATOR PciConfigurators[] =
         Cardbus_ResetDevice
     }
 };
+
 /* FUNCTIONS ******************************************************************/
 
 /*
@@ -715,10 +715,10 @@ PciWriteLimitsAndRestoreCurrent(IN PVOID Reserved,
 
     /* 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 @@ PciWriteLimitsAndRestoreCurrent(IN PVOID Reserved,
 
     /* 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);
 }
@@ -917,6 +917,62 @@ PciGetFunctionLimits(IN PPCI_PDO_EXTENSION PdoExtension,
     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
 NTAPI
 PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
@@ -1363,7 +1419,8 @@ PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
         }
     }
 
-    /* Enumeration is completed */
+    /* Enumeration completed, do a final pass now that all devices are found */
+    if (ProcessFlag) PciProcessBus(DeviceExtension);
     return STATUS_SUCCESS;
 }
 
index 306265f..93a5f14 100644 (file)
@@ -102,6 +102,18 @@ typedef enum _PCI_SIGNATURE
     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 @@ PciCanDisableDecodes(
     IN BOOLEAN ForPowerDown
 );
 
+PCI_DEVICE_TYPES
+NTAPI
+PciClassifyDeviceType(
+    IN PPCI_PDO_EXTENSION PdoExtension
+);
+
 ULONG_PTR
 NTAPI
 PciExecuteCriticalSystemRoutine(
@@ -1607,6 +1625,7 @@ extern PCI_INTERFACE TranslatorInterfaceInterrupt;
 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? */
index 94f411b..f450a26 100644 (file)
@@ -1041,6 +1041,24 @@ PciCanDisableDecodes(IN PPCI_PDO_EXTENSION DeviceExtension,
     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)