[ros-diffs] [evb] 48298: Add all pci bridge control function (PciBridgeIoBase, PciBridgeIoLimit, PciBridgeMemoryBase, PciBridgeMemoryLimit, PciBridgePrefetchMemoryBase, PciBridgePrefetchMemoryLimit, PciBridgeMemoryWorstCasealignment, PciBridgeIsPositiveDecode, PciBridgeIsSubtractiveDecode) More support ICH0/1/2/3/4 hub Add all PCI2PCI bridge limit/current resource codes (PPBridge_*), now is BAR setup okay, and Device_* must be implement Support ISA+VGA legacy decode, 20+64-bit decode, ROM BAR, prefetch BAR

evb at svn.reactos.org evb at svn.reactos.org
Tue Jul 27 03:24:24 UTC 2010


Author: evb
Date: Tue Jul 27 03:24:24 2010
New Revision: 48298

URL: http://svn.reactos.org/svn/reactos?rev=48298&view=rev
Log:
Add all pci bridge control function (PciBridgeIoBase, PciBridgeIoLimit, PciBridgeMemoryBase, PciBridgeMemoryLimit, PciBridgePrefetchMemoryBase, PciBridgePrefetchMemoryLimit, PciBridgeMemoryWorstCasealignment, PciBridgeIsPositiveDecode, PciBridgeIsSubtractiveDecode)
More support ICH0/1/2/3/4 hub
Add all PCI2PCI bridge limit/current resource codes (PPBridge_*), now is BAR setup okay, and Device_* must be implement
Support ISA+VGA legacy decode, 20+64-bit decode, ROM BAR, prefetch BAR

Modified:
    trunk/reactos/drivers/bus/pcix/pci.h
    trunk/reactos/drivers/bus/pcix/pci/ppbridge.c
    trunk/reactos/drivers/bus/pcix/utils.c

Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev=48298&r1=48297&r2=48298&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -1072,6 +1072,14 @@
 
 BOOLEAN
 NTAPI
+PciCreateIoDescriptorFromBarLimit(
+    PIO_RESOURCE_DESCRIPTOR ResourceDescriptor,
+    IN PULONG BarArray,
+    IN BOOLEAN Rom
+);
+
+BOOLEAN
+NTAPI
 PciIsSlotPresentInParentMethod(
     IN PPCI_PDO_EXTENSION PdoExtension,
     IN ULONG Method

Modified: trunk/reactos/drivers/bus/pcix/pci/ppbridge.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci/ppbridge.c?rev=48298&r1=48297&r2=48298&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -16,36 +16,612 @@
 
 /* FUNCTIONS ******************************************************************/
 
+ULONG
+NTAPI
+PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData)
+{
+    BOOLEAN Is32Bit;
+    ULONG Base, IoBase;
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Get the base */
+    Base = PciData->u.type1.IOLimit;
+
+    /* Low bit specifies 32-bit address, top bits specify the base */
+    Is32Bit = (Base & 0xF) == 1;
+    IoBase = (Base & 0xF0) << 8;
+
+    /* Is it 32-bit? */
+    if (Is32Bit)
+    {
+        /* Read the upper 16-bits from the other register */
+        IoBase |= PciData->u.type1.IOBaseUpper16 << 16;
+        ASSERT(PciData->u.type1.IOLimit & 0x1);
+    }
+
+    /* Return the base address */
+    return IoBase;
+}
+
+ULONG
+NTAPI
+PciBridgeIoLimit(IN PPCI_COMMON_HEADER PciData)
+{
+    BOOLEAN Is32Bit;
+    ULONG Limit, IoLimit;
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Get the limit */
+    Limit = PciData->u.type1.IOLimit;
+
+    /* Low bit specifies 32-bit address, top bits specify the limit */
+    Is32Bit = (Limit & 0xF) == 1;
+    IoLimit = (Limit & 0xF0) << 8;
+
+    /* Is it 32-bit? */
+    if (Is32Bit)
+    {
+        /* Read the upper 16-bits from the other register */
+        IoLimit |= PciData->u.type1.IOLimitUpper16 << 16;
+        ASSERT(PciData->u.type1.IOBase & 0x1);
+    }
+
+    /* Return the I/O limit */
+    return IoLimit | 0xFFF;
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryBase(IN PPCI_COMMON_HEADER PciData)
+{
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Return the memory base */
+    return (PciData->u.type1.MemoryBase << 16);
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryLimit(IN PPCI_COMMON_HEADER PciData)
+{
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Return the memory limit */
+    return (PciData->u.type1.MemoryLimit << 16) | 0xFFFFF;
+}
+
+PHYSICAL_ADDRESS
+NTAPI
+PciBridgePrefetchMemoryBase(IN PPCI_COMMON_HEADER PciData)
+{
+    BOOLEAN Is64Bit;
+    LARGE_INTEGER Base;
+    USHORT PrefetchBase;
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Get the base */
+    PrefetchBase = PciData->u.type1.PrefetchBase;
+
+    /* Low bit specifies 64-bit address, top bits specify the base */
+    Is64Bit = (PrefetchBase & 0xF) == 1;
+    Base.LowPart = ((PrefetchBase & 0xFFF0) << 16);
+
+    /* Is it 64-bit? */
+    if (Is64Bit)
+    {
+        /* Read the upper 32-bits from the other register */
+        Base.HighPart = PciData->u.type1.PrefetchBaseUpper32;
+    }
+
+    /* Return the base */
+    return Base;
+}
+
+PHYSICAL_ADDRESS
+NTAPI
+PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData)
+{
+    BOOLEAN Is64Bit;
+    LARGE_INTEGER Limit;
+    USHORT PrefetchLimit;
+    ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+    /* Get the base */
+    PrefetchLimit = PciData->u.type1.PrefetchLimit;
+
+    /* Low bit specifies 64-bit address, top bits specify the limit */
+    Is64Bit = (PrefetchLimit & 0xF) == 1;
+    Limit.LowPart = (PrefetchLimit << 16) | 0xFFFFF;
+
+    /* Is it 64-bit? */
+    if (Is64Bit)
+    {
+        /* Read the upper 32-bits from the other register */
+        Limit.HighPart = PciData->u.type1.PrefetchLimitUpper32;
+    }
+
+    /* Return the limit */
+    return Limit;
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryWorstCaseAlignment(IN ULONG Length)
+{
+    ULONG Alignment;
+    ASSERT(Length != 0);
+
+    /* Start with highest alignment (2^31) */
+    Alignment = 0x80000000;
+
+    /* Keep dividing until we reach the correct power of two */
+    while (!(Length & Alignment)) Alignment >>= 1;
+
+    /* Return the alignment */
+    return Alignment;
+}
+
+BOOLEAN
+NTAPI
+PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension)
+{
+    /* Undocumented ACPI Method PDEC to get positive decode settings */
+    return PciIsSlotPresentInParentMethod(PdoExtension, 'CEDP');
+}
+
+BOOLEAN
+NTAPI
+PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context)
+{
+    PPCI_COMMON_HEADER Current, PciData;
+    PPCI_PDO_EXTENSION PdoExtension;
+
+    /* Get pointers from context */
+    Current = Context->Current;
+    PciData = Context->PciData;
+    PdoExtension = Context->PdoExtension;
+
+    /* Only valid for PCI-to-PCI bridges */
+    ASSERT((Current->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+           (Current->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));
+
+    /* Check for hacks first, then check the ProgIf of the bridge */
+    if (!(PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE) &&
+         (Current->ProgIf != 1) &&
+         ((PciData->u.type1.IOLimit & 0xF0) == 0xF0))
+    {
+        /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */
+        DPRINT("Subtractive decode does not seem to be enabled\n");
+        return FALSE;
+    }
+
+    /*
+     * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
+     * i820, i840, i845 Chipsets) that have subtractive decode broken.
+     */
+    if (((PdoExtension->VendorId == 0x8086) &&
+         ((PdoExtension->DeviceId == 0x2418) ||
+          (PdoExtension->DeviceId == 0x2428) ||
+          (PdoExtension->DeviceId == 0x244E) ||
+          (PdoExtension->DeviceId == 0x2448))) ||
+        (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
+    {
+        /* Check if the ACPI BIOS says positive decode should be enabled */
+        if (PciBridgeIsPositiveDecode(PdoExtension))
+        {
+            /* Obey ACPI */
+            DPRINT1("Putting bridge in positive decode because of PDEC\n");
+            return FALSE;
+        }
+    }
+
+    /* If we found subtractive decode, we'll need a resource update later */
+    DPRINT1("PCI : Subtractive decode on 0x%x\n", Current->u.type1.SecondaryBus);
+    PdoExtension->UpdateHardware = TRUE;
+    return TRUE;
+}
+
 VOID
 NTAPI
 PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    NTSTATUS Status;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+    PIO_RESOURCE_DESCRIPTOR IoDescriptor;
+    PPCI_FUNCTION_RESOURCES Resources;
+    PCI_COMMON_HEADER BiosData;
+    PPCI_COMMON_HEADER Current;
+    PPCI_COMMON_CONFIG SavedConfig;
+    ULONG i, Bar, BarMask;
+    PULONG BarArray;
+    PHYSICAL_ADDRESS Limit, Base, Length;
+    BOOLEAN HaveIoLimit, CheckAlignment;
+    PPCI_PDO_EXTENSION PdoExtension;
+
+    /* Get the pointers from the extension */
+    PdoExtension = Context->PdoExtension;
+    Resources = PdoExtension->Resources;
+    Current = Context->Current;
+
+    /* Check if decodes are disabled */
+    if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)))
+    {
+        /* Well, we're going to need them from somewhere, use the registry data */
+        Status = PciGetBiosConfig(PdoExtension, &BiosData);
+        if (NT_SUCCESS(Status)) Current = &BiosData;
+    }
+
+    /* Scan all current and limit descriptors for each BAR needed */
+    BarArray = Current->u.type1.BaseAddresses;
+    for (i = 0; i < 6; i++)
+    {
+        /* Get the current resource descriptor, and the limit requirement */
+        CmDescriptor = &Resources->Current[i];
+        IoDescriptor = &Resources->Limit[i];
+
+        /* Copy descriptor data, skipping null descriptors */
+        CmDescriptor->Type = IoDescriptor->Type;
+        if (CmDescriptor->Type == CmResourceTypeNull) continue;
+        CmDescriptor->Flags = IoDescriptor->Flags;
+        CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+
+        /* Initialize the high-parts to zero, since most stuff is 32-bit only */
+        Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0;
+
+        /* Check if we're handling PCI BARs, or the ROM BAR */
+        if ((i < PCI_TYPE1_ADDRESSES) || (i == 5))
+        {
+            /* Is this the ROM BAR? */
+            if (i == 5)
+            {
+                /* Read the correct bar, with the appropriate mask */
+                Bar = Current->u.type1.ROMBaseAddress;
+                BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK;
+
+                /* Decode the base address, and write down the length */
+                Base.LowPart = Bar & BarMask;
+                DPRINT1("ROM BAR Base: %lx\n", Base.LowPart);
+                CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+            }
+            else
+            {
+                /* Otherwise, get the BAR from the array */
+                Bar = BarArray[i];
+
+                /* Is this an I/O BAR? */
+                if (Bar & PCI_ADDRESS_IO_SPACE)
+                {
+                    /* Set the correct mask */
+                    ASSERT(CmDescriptor->Type == CmResourceTypePort);
+                    BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
+                }
+                else
+                {
+                    /* This is a memory BAR, set the correct base */
+                    ASSERT(CmDescriptor->Type == CmResourceTypeMemory);
+                    BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
+
+                    /* IS this a 64-bit BAR? */
+                    if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+                    {
+                        /* Read the next 32-bits as well, ie, the next BAR */
+                        Base.HighPart = BarArray[i + 1];
+                    }
+                }
+
+                /* Decode the base address, and write down the length */
+                Base.LowPart = Bar & BarMask;
+                DPRINT1("BAR Base: %lx\n", Base.LowPart);
+                CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
+            }
+        }
+        else
+        {
+            /* Reset loop conditions */
+            HaveIoLimit = FALSE;
+            CheckAlignment = FALSE;
+
+            /* Check which descriptor is being parsed */
+            if (i == 2)
+            {
+                /* I/O Port Requirements */
+                Base.LowPart = PciBridgeIoBase(Current);
+                Limit.LowPart = PciBridgeIoLimit(Current);
+                DPRINT1("Bridge I/O Base and Limit: %lx %lx\n",
+                         Base.LowPart, Limit.LowPart);
+
+                /* Do we have any I/O Port data? */
+                if (!(Base.LowPart) && (Current->u.type1.IOLimit))
+                {
+                    /* There's a limit */
+                    HaveIoLimit = TRUE;
+                }
+            }
+            else if (i == 3)
+            {
+                /* Memory requirements */
+                Base.LowPart = PciBridgeMemoryBase(Current);
+                Limit.LowPart = PciBridgeMemoryLimit(Current);
+
+                /* These should always be there, so check their alignment */
+                DPRINT1("Bridge MEM Base and Limit: %lx %lx\n",
+                         Base.LowPart, Limit.LowPart);
+                CheckAlignment = TRUE;
+            }
+            else if (i == 4)
+            {
+                /* This should only be present for prefetch memory */
+                ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE);
+                Base = PciBridgePrefetchMemoryBase(Current);
+                Limit = PciBridgePrefetchMemoryLimit(Current);
+
+                /* If it's there, check the alignment */
+                DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base, Limit);
+                CheckAlignment = TRUE;
+            }
+
+            /* Check for invalid base address */
+            if (Base.QuadPart >= Limit.QuadPart)
+            {
+                /* Assume the descriptor is bogus */
+                CmDescriptor->Type = CmResourceTypeNull;
+                IoDescriptor->Type = CmResourceTypeNull;
+                continue;
+            }
+
+            /* Check if there's no memory, and no I/O port either */
+            if (!(Base.LowPart) && !(HaveIoLimit))
+            {
+                /* This seems like a bogus requirement, ignore it */
+                CmDescriptor->Type = CmResourceTypeNull;
+                continue;
+            }
+
+            /* Set the length to be the limit - the base; should always be 32-bit */
+            Length.QuadPart = Limit.LowPart - Base.LowPart + 1;
+            ASSERT(Length.HighPart == 0);
+            CmDescriptor->u.Generic.Length = Length.LowPart;
+
+            /* Check if alignment should be set */
+            if (CheckAlignment)
+            {
+                /* Compute the required alignment for this length */
+                ASSERT(CmDescriptor->u.Memory.Length > 0);
+                IoDescriptor->u.Memory.Alignment =
+                    PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length);
+            }
+        }
+
+        /* Now set the base address */
+        CmDescriptor->u.Generic.Start.LowPart = Base.LowPart;
+    }
+
+    /* Save PCI settings into the PDO extension for easy access later */
+    PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus;
+    PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus;
+    PdoExtension->Dependent.type1.SubordinateBus = Current->u.type1.SubordinateBus;
+
+    /* Check for subtractive decode bridges */
+    if (PdoExtension->Dependent.type1.SubtractiveDecode)
+    {
+        /* Check if legacy VGA decodes are enabled */
+        DPRINT1("Subtractive decode bridge\n");
+        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+        {
+            /* Save this setting for later */
+            DPRINT1("VGA Bridge\n");
+            PdoExtension->Dependent.type1.VgaBitSet = TRUE;
+        }
+
+        /* Legacy ISA decoding is not compatible with subtractive decode */
+        ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE);
+    }
+    else
+    {
+        /* Check if legacy VGA decodes are enabled */
+        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+        {
+            /* Save this setting for later */
+            DPRINT1("VGA Bridge\n");
+            PdoExtension->Dependent.type1.VgaBitSet = TRUE;
+
+            /* And on positive decode, we'll also need extra resources locked */
+            PdoExtension->AdditionalResourceCount = 4;
+        }
+
+        /* Check if legacy ISA decoding is enabled */
+        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA)
+        {
+            /* Save this setting for later */
+            DPRINT1("ISA Bridge\n");
+            PdoExtension->Dependent.type1.IsaBitSet = TRUE;
+        }
+    }
+
+    /*
+     * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
+     * i820, i840, i845 Chipsets) that have subtractive decode broken.
+     */
+    if (((PdoExtension->VendorId == 0x8086) &&
+         ((PdoExtension->DeviceId == 0x2418) ||
+          (PdoExtension->DeviceId == 0x2428) ||
+          (PdoExtension->DeviceId == 0x244E) ||
+          (PdoExtension->DeviceId == 0x2448))) ||
+        (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
+    {
+        /* Check if subtractive decode is actually enabled */
+        if (PdoExtension->Dependent.type1.SubtractiveDecode)
+        {
+            /* We're going to need a copy of the configuration for later use */
+            DPRINT1("apply config save hack to ICH subtractive decode\n");
+            SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH, 'PciP');
+            PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig;
+            if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH);
+        }
+    }
 }
 
 VOID
 NTAPI
 PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    PIO_RESOURCE_DESCRIPTOR Limit;
+    PULONG BarArray;
+    PHYSICAL_ADDRESS MemoryLimit;
+    ULONG i;
+    PPCI_COMMON_HEADER Working;
+    PPCI_PDO_EXTENSION PdoExtension;
+
+    /* Get the pointers from the context */
+    Working = Context->PciData;
+    PdoExtension = Context->PdoExtension;
+
+    /* Scan the BARs into the limit descriptors */
+    BarArray = Working->u.type1.BaseAddresses;
+    Limit = PdoExtension->Resources->Limit;
+
+    /* First of all, loop all the BARs */
+    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+    {
+        /* Create a descriptor for their limits */
+        if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE))
+        {
+            /* This was a 64-bit descriptor, make sure there's space */
+            ASSERT((i + 1) < PCI_TYPE1_ADDRESSES);
+
+            /* Skip the next descriptor since this one is double sized */
+            i++;
+            (&Limit[i])->Type == CmResourceTypeNull;
+        }
+    }
+
+    /* Check if this is a subtractive decode bridge */
+    if (PciBridgeIsSubtractiveDecode(Context))
+    {
+        /* This bridge is subtractive */
+        PdoExtension->Dependent.type1.SubtractiveDecode = TRUE;
+
+        /* Subtractive bridges cannot use legacy ISA or VGA functionality */
+        PdoExtension->Dependent.type1.IsaBitSet = FALSE;
+        PdoExtension->Dependent.type1.VgaBitSet = FALSE;
+    }
+
+    /* For normal decode bridges, we'll need to find the bridge limits too */
+    if (!PdoExtension->Dependent.type1.SubtractiveDecode)
+    {
+        /* Loop the descriptors that are left, to store the bridge limits */
+        for (i = PCI_TYPE1_ADDRESSES; i < 5; i++)
+        {
+            /* No 64-bit memory addresses, and set the address to 0 to begin */
+            MemoryLimit.HighPart = 0;
+            (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
+
+            /* Are we getting the I/O limit? */
+            if (i == 2)
+            {
+                /* There should be one, get it */
+                ASSERT(Working->u.type1.IOLimit != 0);
+                ASSERT((Working->u.type1.IOLimit & 0x0E) == 0);
+                MemoryLimit.LowPart = PciBridgeIoLimit(Working);
+
+                /* Build a descriptor for this limit */
+                (&Limit[i])->Type = CmResourceTypePort;
+                (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE |
+                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
+                (&Limit[i])->u.Port.Alignment = 0x1000;
+                (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
+                (&Limit[i])->u.Port.MaximumAddress = MemoryLimit;
+                (&Limit[i])->u.Port.Length = 0;
+            }
+            else if (i == 3)
+            {
+                /* There should be a valid memory limit, get it */
+                ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0);
+                MemoryLimit.LowPart = PciBridgeMemoryLimit(Working);
+
+                /* Build the descriptor for it */
+                (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+                (&Limit[i])->Type = CmResourceTypeMemory;
+                (&Limit[i])->u.Memory.Alignment = 0x100000;
+                (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
+                (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
+                (&Limit[i])->u.Memory.Length = 0;
+            }
+            else if (Working->u.type1.PrefetchLimit)
+            {
+                /* Get the prefetch memory limit, if there is one */
+                MemoryLimit = PciBridgePrefetchMemoryLimit(Working);
+
+                /* Write out the descriptor for it */
+                (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE;
+                (&Limit[i])->Type = CmResourceTypeMemory;
+                (&Limit[i])->u.Memory.Alignment = 0x100000;
+                (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
+                (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
+                (&Limit[i])->u.Memory.Length = 0;
+            }
+            else
+            {
+                /* Blank descriptor */
+                (&Limit[i])->Type = CmResourceTypeNull;
+            }
+        }
+    }
+
+    /* Does the ROM have its own BAR? */
+    if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)
+    {
+        /* Build a limit for it as well */
+        PciCreateIoDescriptorFromBarLimit(&Limit[i],
+                                          &Working->u.type1.ROMBaseAddress,
+                                          TRUE);
+    }
 }
 
 VOID
 NTAPI
 PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    PPCI_COMMON_HEADER PciData, Current;
+
+    /* Get pointers from context */
+    PciData = Context->PciData;
+    Current = Context->Current;
+
+    /*
+     * Write FFh everywhere so that the PCI bridge ignores what it can't handle.
+     * Based on the bits that were ignored (still 0), this is how we can tell
+     * what the limit is.
+     */
+    RtlFillMemory(PciData->u.type1.BaseAddresses,
+                  FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr) -
+                  FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BaseAddresses),
+                  0xFF);
+
+    /* Copy the saved settings from the current context into the PCI header */
+    PciData->u.type1.PrimaryBus = Current->u.type1.PrimaryBus;
+    PciData->u.type1.SecondaryBus = Current->u.type1.SecondaryBus;
+    PciData->u.type1.SubordinateBus = Current->u.type1.SubordinateBus;
+    PciData->u.type1.SecondaryLatency = Current->u.type1.SecondaryLatency;
+
+    /* No I/O limit or base. The bottom base bit specifies that FIXME */
+    PciData->u.type1.IOBaseUpper16 = 0xFFFE;
+    PciData->u.type1.IOLimitUpper16 = 0xFFFF;
+
+    /* Save secondary status before it gets cleared */
+    Context->SecondaryStatus = Current->u.type1.SecondaryStatus;
+
+    /* Clear secondary status */
+    Current->u.type1.SecondaryStatus = 0;
+    PciData->u.type1.SecondaryStatus = 0;
 }
 
 VOID
 NTAPI
 PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
+    /* Copy back the secondary status register */
+    Context->Current->u.type1.SecondaryStatus = Context->SecondaryStatus;
 }
 
 VOID
@@ -54,24 +630,56 @@
                                           IN PPCI_COMMON_HEADER PciData,
                                           IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
 {
+    /* Does this bridge have VGA decodes on it? */
+    if (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+    {
+        /* Build a private descriptor with 3 entries */
+        IoDescriptor->Type = CmResourceTypeDevicePrivate;
+        IoDescriptor->u.DevicePrivate.Data[0] = 3;
+        IoDescriptor->u.DevicePrivate.Data[1] = 3;
+
+        /* First, the VGA range at 0xA0000 */
+        IoDescriptor[1].Type = CmResourceTypeMemory;
+        IoDescriptor[1].Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+        IoDescriptor[1].u.Port.Length = 0x20000;
+        IoDescriptor[1].u.Port.Alignment = 1;
+        IoDescriptor[1].u.Port.MinimumAddress.QuadPart = 0xA0000;
+        IoDescriptor[1].u.Port.MaximumAddress.QuadPart = 0xBFFFF;
+
+        /* Then, the VGA registers at 0x3B0 */
+        IoDescriptor[2].Type = CmResourceTypePort;
+        IoDescriptor[2].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
+                                CM_RESOURCE_PORT_10_BIT_DECODE;
+        IoDescriptor[2].u.Port.Length = 12;
+        IoDescriptor[2].u.Port.Alignment = 1;
+        IoDescriptor[2].u.Port.MinimumAddress.QuadPart = 0x3B0;
+        IoDescriptor[2].u.Port.MaximumAddress.QuadPart = 0x3BB;
+
+        /* And finally the VGA registers at 0x3C0 */
+        IoDescriptor[3].Type = CmResourceTypePort;
+        IoDescriptor[3].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
+                                CM_RESOURCE_PORT_10_BIT_DECODE;
+        IoDescriptor[3].u.Port.Length = 32;
+        IoDescriptor[3].u.Port.Alignment = 1;
+        IoDescriptor[3].u.Port.MinimumAddress.QuadPart = 0x3C0;
+        IoDescriptor[3].u.Port.MaximumAddress.QuadPart = 0x3DF;
+    }
+}
+
+VOID
+NTAPI
+PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
+{
     UNIMPLEMENTED;
     while (TRUE);
 }
 
 VOID
 NTAPI
-PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
+PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
 {
     UNIMPLEMENTED;
     while (TRUE);
 }
 
-VOID
-NTAPI
-PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
-{
-    UNIMPLEMENTED;
-    while (TRUE);
-}
-
 /* EOF */

Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?rev=48298&r1=48297&r2=48298&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -1130,6 +1130,115 @@
     return FoundSlot;
 }
 
+ULONG
+NTAPI
+PciGetLengthFromBar(IN ULONG Bar)
+{
+    ULONG Length;
+
+    /* I/O addresses vs. memory addresses start differently due to alignment */
+    Length = 1 << ((Bar & PCI_ADDRESS_IO_SPACE) ? 2 : 4);
+
+    /* Keep going until a set bit */
+    while (!(Length & Bar) && (Length)) Length <<= 1;
+
+    /* Return the length (might be 0 on 64-bit because it's the low-word) */
+    if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) != PCI_TYPE_64BIT) ASSERT(Length);
+    return Length;
+}
+
+BOOLEAN
+NTAPI
+PciCreateIoDescriptorFromBarLimit(PIO_RESOURCE_DESCRIPTOR ResourceDescriptor,
+                                  IN PULONG BarArray,
+                                  IN BOOLEAN Rom)
+{
+    ULONG CurrentBar, BarLength, BarMask;
+    BOOLEAN Is64BitBar = FALSE;
+
+    /* Check if the BAR is nor I/O nor memory */
+    CurrentBar = BarArray[0];
+    if (!(CurrentBar & ~PCI_ADDRESS_IO_SPACE))
+    {
+        /* Fail this descriptor */
+        ResourceDescriptor->Type = CmResourceTypeNull;
+        return FALSE;
+    }
+
+    /* Set default flag and clear high words */
+    ResourceDescriptor->Flags = 0;
+    ResourceDescriptor->u.Generic.MaximumAddress.HighPart = 0;
+    ResourceDescriptor->u.Generic.MinimumAddress.LowPart = 0;
+    ResourceDescriptor->u.Generic.MinimumAddress.HighPart = 0;
+
+    /* Check for ROM Address */
+    if (Rom)
+    {
+        /* Clean up the BAR to get just the address */
+        CurrentBar &= PCI_ADDRESS_ROM_ADDRESS_MASK;
+        if (!CurrentBar)
+        {
+            /* Invalid ar, fail this descriptor */
+            ResourceDescriptor->Type = CmResourceTypeNull;
+            return FALSE;
+        }
+
+        /* ROM Addresses are always read only */
+        ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+    }
+
+    /* Compute the length, assume it's the alignment for now */
+    BarLength = PciGetLengthFromBar(CurrentBar);
+    ResourceDescriptor->u.Generic.Length = BarLength;
+    ResourceDescriptor->u.Generic.Alignment = BarLength;
+
+    /* Check what kind of BAR this is */
+    if (CurrentBar & PCI_ADDRESS_IO_SPACE)
+    {
+        /* Use correct mask to decode the address */
+        BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
+
+        /* Set this as an I/O Port descriptor */
+        ResourceDescriptor->Type = CmResourceTypePort;
+        ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+    }
+    else
+    {
+        /* Use correct mask to decode the address */
+        BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
+
+        /* Set this as a memory descriptor */
+        ResourceDescriptor->Type = CmResourceTypeMemory;
+
+        /* Check if it's 64-bit or 20-bit decode */
+        if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+        {
+            /* The next BAR has the high word, read it */
+            ResourceDescriptor->u.Port.MaximumAddress.HighPart = BarArray[1];
+            Is64BitBar = TRUE;
+        }
+        else if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
+        {
+            /* Use the correct mask to decode the address */
+            BarMask = ~0xFFF0000F;
+        }
+
+        /* Check if the BAR is listed as prefetchable memory */
+        if (CurrentBar & PCI_ADDRESS_MEMORY_PREFETCHABLE)
+        {
+            /* Mark the descriptor in the same way */
+            ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+        }
+    }
+
+    /* Now write down the maximum address based on the base + length */
+    ResourceDescriptor->u.Port.MaximumAddress.QuadPart = (CurrentBar & BarMask) +
+                                                         BarLength - 1;
+
+    /* Return if this is a 64-bit BAR, so the loop code knows to skip the next one */
+    return Is64BitBar;
+}
+
 VOID
 NTAPI
 PciDecodeEnable(IN PPCI_PDO_EXTENSION PdoExtension,




More information about the Ros-diffs mailing list