[ros-diffs] [sir_richard] 48116: Joint patch By sir_richard: [PCIX]: - Implement PciIsSlotPresentInParentMethod for ACPI query, and PcoDecodeEnable utility function. - Implement PciConfigureIdeController based on WDHC Whitepaper "How Windows Switches a Controller to Native Mode". Check for PciEanbleNativeModeATA in registry, InitSafeBootMode, and call the ACPI driver to evaluate if NATA is present on the slot. Only configure the controller if both channels support native mode, as this is a Windows restriction. - Implement PciApplyHacks for enumeration and resource update cases. In the first case, we handle legacy DEC Alpha Intel i82375 and i82378 PCI-to-(E)ISA bridges with invalid class codes. In the second, we configure IDE controllers for Native mode, except the OPTi Viper-M, which is known to cause issues. We also support cards with legacy VGA decodes by telling the arbiter to enable full access to the rangesm and finally we completely disable the decodes on Compaq PCI Hotplug Controllers (Revision 17) on PAE systems, as they have bugs handling 64-bit addresses. Finally, on resource updates, we apply a vendor-specific errata to the IBM 20H2999 PCI Docking Bridge (Hotplug) used on Thinkpad 600 Series laptops, and we attempt to avoid issues that can happen on certain devices that are plugged into an ICH1/2/3/4 Intel Hub when it has been configured to do subtractive decode. Full information on these workarounds can be seen in the comments. Finally, we also enable CardBUS devices for ACPI-compliant mode, by crossing out the LegacyBaseAddress in the CardBUS Type 2 PCI Configuration Header. - Miscelleaneous code cleanups. By eVb: More PciScanBus support, for debug PCI caps that driver use are dump, and detect nonBIOS configure device (spec is said that CacheLineSize != 0, LatencyTimer != 0 (on PCI-X, != 64)), if found NeedsHotPlugConfiguration to be set By eVb: Support PCI_HACK_VIDEO_LEGACY_DECODE (call ario_ApplyBrokenVideoHack, but no arb support to do work)

Mon, 19 Jul 2010 08:16:00 -0700

Author: sir_richard
Date: Mon Jul 19 15:15:39 2010
New Revision: 48116

URL: http://svn.reactos.org/svn/reactos?rev=48116&view=rev
Log:
Joint patch
By sir_richard: [PCIX]: - Implement PciIsSlotPresentInParentMethod for ACPI 
query, and PcoDecodeEnable utility function.
                        - Implement PciConfigureIdeController based on WDHC 
Whitepaper "How Windows Switches a Controller to Native Mode". Check for 
PciEanbleNativeModeATA in registry, InitSafeBootMode, and call the ACPI driver 
to evaluate if NATA is present on the slot. Only configure the controller if 
both channels support native mode, as this is a Windows restriction.
                        - Implement PciApplyHacks for enumeration and resource 
update cases. In the first case, we handle legacy DEC Alpha Intel i82375 and 
i82378 PCI-to-(E)ISA bridges with invalid class codes. In the second, we 
configure IDE controllers for Native mode, except the OPTi Viper-M, which is 
known to cause issues. We also support cards with legacy VGA decodes by telling 
the arbiter to enable full access to the rangesm and finally we completely 
disable the decodes on Compaq PCI Hotplug Controllers (Revision 17) on PAE 
systems, as they have bugs handling 64-bit addresses. Finally, on resource 
updates, we apply a vendor-specific errata to the IBM 20H2999 PCI Docking 
Bridge (Hotplug) used on Thinkpad 600 Series laptops, and we attempt to avoid 
issues that can happen on certain devices that are plugged into an ICH1/2/3/4 
Intel Hub when it has been configured to do subtractive decode. Full 
information on these workarounds can be seen in the comments. Finally, we also 
enable CardBUS devices for ACPI-compliant mode, by crossing out the 
LegacyBaseAddress in the CardBUS Type 2 PCI Configuration Header.
                        - Miscelleaneous code cleanups.
By eVb: More PciScanBus support, for debug PCI caps that driver use are dump, 
and detect nonBIOS configure device (spec is said that CacheLineSize != 0, 
LatencyTimer != 0 (on PCI-X, != 64)), if found NeedsHotPlugConfiguration to be 
set
By eVb: Support PCI_HACK_VIDEO_LEGACY_DECODE (call ario_ApplyBrokenVideoHack, 
but no arb support to do work)

Modified:
    trunk/reactos/drivers/bus/pcix/arb/ar_memio.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/arb/ar_memio.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/arb/ar_memio.c?rev=48116&r1=48115&r2=48116&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/arb/ar_memio.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/arb/ar_memio.c [iso-8859-1] Mon Jul 19 
15:15:39 2010
@@ -91,6 +91,46 @@
     return Status;
 }
 
+VOID
+NTAPI
+ario_ApplyBrokenVideoHack(IN PPCI_FDO_EXTENSION FdoExtension)
+{
+    PPCI_ARBITER_INSTANCE PciArbiter;
+    //PARBITER_INSTANCE CommonInstance;
+    NTSTATUS Status;
+
+    /* Only valid for root FDOs who are being applied the hack for the first 
time */
+    ASSERT(!FdoExtension->BrokenVideoHackApplied);
+    ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
+
+    /* Find the I/O arbiter */
+    PciArbiter = (PVOID)PciFindNextSecondaryExtension(FdoExtension->
+                                                      SecondaryExtension.Next,
+                                                      PciArb_Io);
+    ASSERT(PciArbiter);
+#if 0 // when arb exist
+    /* Get the Arb instance */
+    CommonInstance = &PciArbiter->CommonInstance;
+
+    /* Free the two lists, enabling full VGA access */
+    ArbFreeOrderingList(&CommonInstance->OrderingList);
+    ArbFreeOrderingList(&CommonInstance->ReservedList);
+
+    /* Build the ordering for broken video PCI access */
+    Status = ArbBuildAssignmentOrdering(CommonInstance,
+                                        L"Pci",
+                                        L"BrokenVideo",
+                                        NULL);
+    ASSERT(NT_SUCCESS(Status));
+#else
+    Status = STATUS_SUCCESS;
+    UNIMPLEMENTED;
+    while (TRUE);
+#endif
+    /* Now the hack has been applied */
+    FdoExtension->BrokenVideoHackApplied = TRUE;
+}
+
 NTSTATUS
 NTAPI
 armem_Initializer(IN PVOID Instance)

Modified: trunk/reactos/drivers/bus/pcix/enum.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/enum.c?rev=48116&r1=48115&r2=48116&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] Mon Jul 19 15:15:39 2010
@@ -15,6 +15,429 @@
 /* GLOBALS 
********************************************************************/
 
 /* FUNCTIONS 
******************************************************************/
+
+/*
+ * 7. The IO/MEM/Busmaster decodes are disabled for the device.
+ * 8. The PCI bus driver sets the operating mode bits of the Programming
+ *    Interface byte to switch the controller to native mode.
+ *
+ *    Important: When the controller is set to native mode, it must quiet 
itself
+ *    and must not decode I/O resources or generate interrupts until the 
operating
+ *    system has enabled the ports in the PCI configuration header.
+ *    The IO/MEM/BusMaster bits will be disabled before the mode change, but it
+ *    is not possible to disable interrupts on the device. The device must not
+ *    generate interrupts (either legacy or native mode) while the decodes are
+ *    disabled in the command register.
+ *
+ *    This operation is expected to be instantaneous and the operating system 
does
+ *    not stall afterward. It is also expected that the interrupt pin register 
in
+ *    the PCI Configuration space for this device is accurate. The operating 
system
+ *    re-reads this data after previously ignoring it.
+ */
+BOOLEAN
+NTAPI
+PciConfigureIdeController(IN PPCI_PDO_EXTENSION PdoExtension,
+                          IN PPCI_COMMON_HEADER PciData,
+                          IN BOOLEAN Initial)
+{
+    UCHAR MasterMode, SlaveMode, MasterFixed, SlaveFixed, ProgIf, NewProgIf;
+    BOOLEAN Switched;
+    USHORT Command;
+
+    /* Assume it won't work */
+    Switched = FALSE;
+
+    /* Get master and slave current settings, and programmability flag */
+    ProgIf = PciData->ProgIf;
+    MasterMode = (ProgIf & 1) == 1;
+    MasterFixed = (ProgIf & 2) == 0;
+    SlaveMode = (ProgIf & 4) == 4;
+    SlaveFixed = (ProgIf & 8) == 0;
+
+    /*
+     * [..] In order for Windows XP SP1 and Windows Server 2003 to switch an 
ATA
+     * ATA controller from compatible mode to native mode, the following must 
be
+     * true:
+     *
+     * - The controller must indicate in its programming interface that both 
channels
+     *   can be switched to native mode. Windows XP SP1 and Windows Server 
2003 do
+     *   not support switching only one IDE channel to native mode. See the 
PCI IDE
+     *   Controller Specification Revision 1.0 for details.
+     */
+    if ((MasterMode != SlaveMode) || (MasterFixed != SlaveFixed))
+    {
+        /* Windows does not support this configuration, fail */
+        DPRINT1("PCI: Warning unsupported IDE controller configuration for 
VEN_%04x&DEV_%04x!",
+                PdoExtension->VendorId,
+                PdoExtension->DeviceId);
+        return Switched;
+    }
+
+    /* Check if the controller is already in native mode */
+    if ((MasterMode) && (SlaveMode))
+    {
+        /* Check if I/O decodes should be disabled */
+        if ((Initial) || (PdoExtension->IoSpaceUnderNativeIdeControl))
+        {
+            /* Read the current command */
+            PciReadDeviceConfig(PdoExtension,
+                                &Command,
+                                FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                sizeof(USHORT));
+
+            /* Disable I/O space decode */
+            Command &= ~PCI_ENABLE_IO_SPACE;
+
+            /* Update new command in PCI IDE controller */
+            PciWriteDeviceConfig(PdoExtension,
+                                 &Command,
+                                 FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                 sizeof(USHORT));
+
+            /* Save updated command value */
+            PciData->Command = Command;
+        }
+
+        /* The controller is now in native mode */
+        Switched = TRUE;
+    }
+    else if (!(MasterFixed) &&
+             !(SlaveFixed) &&
+             (PdoExtension->BIOSAllowsIDESwitchToNativeMode) &&
+             !(PdoExtension->HackFlags & PCI_HACK_DISABLE_IDE_NATIVE_MODE))
+    {
+        /* Turn off decodes */
+        PciDecodeEnable(PdoExtension, FALSE, NULL);
+
+        /* Update the current command */
+        PciReadDeviceConfig(PdoExtension,
+                            &PciData->Command,
+                            FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                            sizeof(USHORT));
+
+        /* Enable native mode */
+        ProgIf = PciData->ProgIf | 5;
+        PciWriteDeviceConfig(PdoExtension,
+                             &ProgIf,
+                             FIELD_OFFSET(PCI_COMMON_HEADER, ProgIf),
+                             sizeof(UCHAR));
+
+        /* Verify the setting "stuck" */
+        PciReadDeviceConfig(PdoExtension,
+                            &NewProgIf,
+                            FIELD_OFFSET(PCI_COMMON_HEADER, ProgIf),
+                            sizeof(UCHAR));
+        if (NewProgIf == ProgIf)
+        {
+            /* Update the header and PDO data with the new programming mode */
+            PciData->ProgIf = ProgIf;
+            PdoExtension->ProgIf = NewProgIf;
+
+            /* Clear the first four BARs to reset current BAR setttings */
+            PciData->u.type0.BaseAddresses[0] = 0;
+            PciData->u.type0.BaseAddresses[1] = 0;
+            PciData->u.type0.BaseAddresses[2] = 0;
+            PciData->u.type0.BaseAddresses[3] = 0;
+            PciWriteDeviceConfig(PdoExtension,
+                                 PciData->u.type0.BaseAddresses,
+                                 FIELD_OFFSET(PCI_COMMON_HEADER,
+                                              u.type0.BaseAddresses),
+                                 4 * sizeof(ULONG));
+
+            /* Re-read the BARs to have the latest data for native mode IDE */
+            PciReadDeviceConfig(PdoExtension,
+                                PciData->u.type0.BaseAddresses,
+                                FIELD_OFFSET(PCI_COMMON_HEADER,
+                                             u.type0.BaseAddresses),
+                                4 * sizeof(ULONG));
+
+            /* Re-read the interrupt pin used for native mode IDE */
+            PciReadDeviceConfig(PdoExtension,
+                                &PciData->u.type0.InterruptPin,
+                                FIELD_OFFSET(PCI_COMMON_HEADER,
+                                             u.type0.InterruptPin),
+                                sizeof(UCHAR));
+
+            /* The IDE Controller is now in native mode */
+            Switched = TRUE;
+        }
+        else
+        {
+            /* Settings did not work, fail */
+            DPRINT1("PCI: Warning failed switch to native mode for IDE 
controller VEN_%04x&DEV_%04x!",
+                    PciData->VendorID,
+                    PciData->DeviceID);
+        }
+   }
+
+   /* Return whether or not native mode was enabled on the IDE controller */
+   return Switched;
+}
+
+VOID
+NTAPI
+PciApplyHacks(IN PPCI_FDO_EXTENSION DeviceExtension,
+              IN PPCI_COMMON_HEADER PciData,
+              IN PCI_SLOT_NUMBER SlotNumber,
+              IN ULONG OperationType,
+              PPCI_PDO_EXTENSION PdoExtension)
+{
+    ULONG LegacyBaseAddress;
+    USHORT Command;
+    UCHAR RegValue;
+
+    /* There should always be a PDO extension passed in */
+    ASSERT(PdoExtension);
+
+    /* Check what kind of hack operation this is */
+    switch (OperationType)
+    {
+        /*
+         * This is mostly concerned with fixing up incorrect class data that 
can
+         * exist on certain PCI hardware before the 2.0 spec was ratified.
+         */
+        case PCI_HACK_FIXUP_BEFORE_CONFIGURATION:
+
+            /* Note that the i82375 PCI/EISA and the i82378 PCI/ISA bridges 
that
+             * are present on certain DEC/NT Alpha machines are pre-PCI 2.0 
devices
+             * and appear as non-classified, so their correct class/subclass 
data
+             * is written here instead.
+             */
+            if ((PciData->VendorID == 0x8086) &&
+                ((PciData->DeviceID == 0x482) || (PciData->DeviceID == 0x484)))
+            {
+                /* Note that 0x482 is the i82375 (EISA), 0x484 is the i82378 
(ISA) */
+                PciData->SubClass = PciData->DeviceID == 0x482 ?
+                                    PCI_SUBCLASS_BR_EISA : PCI_SUBCLASS_BR_ISA;
+                PciData->BaseClass = PCI_CLASS_BRIDGE_DEV;
+
+                /*
+                 * Because the software is modifying the actual header data 
from
+                 * the BIOS, this flag tells the driver to ignore failures when
+                 * comparing the original BIOS data with the PCI data.
+                 */
+                if (PdoExtension) PdoExtension->ExpectedWritebackFailure = 
TRUE;
+            }
+
+            /* Note that in this case, an immediate return is issued */
+            return;
+
+        /*
+         * This is concerned with setting up interrupts correctly for native 
IDE
+         * mode, but will also handle broken VGA decoding on older bridges as
+         * well as a PAE-specific hack for certain Compaq Hot-Plug Controllers.
+         */
+        case PCI_HACK_FIXUP_AFTER_CONFIGURATION:
+
+            /*
+             * On the OPTi Viper-M IDE controller, Linux doesn't support 
IDE-DMA
+             * and FreeBSD bug reports indicate that the system crashes when 
the
+             * feature is enabled (so it's disabled on that OS as well). In the
+             * NT PCI Bus Driver, it seems Microsoft too, completely disables
+             * Native IDE functionality on this controller, so it would seem 
OPTi
+             * simply frelled up this controller.
+             */
+            if ((PciData->VendorID == 0x1045) && (PciData->DeviceID != 0xC621))
+            {
+                /* Disable native mode */
+                PciData->ProgIf &= ~5;
+                PciData->u.type0.InterruptPin = 0;
+
+                /*
+                 * Because the software is modifying the actual header data 
from
+                 * the BIOS, this flag tells the driver to ignore failures when
+                 * comparing the original BIOS data with the PCI data.
+                 */
+                PdoExtension->ExpectedWritebackFailure = TRUE;
+            }
+            else if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
+                    (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
+            {
+                /* For other IDE controllers, start out in compatible mode */
+                PdoExtension->BIOSAllowsIDESwitchToNativeMode = FALSE;
+
+                /*
+                 * Registry must have enabled native mode (typically as a 
result
+                 * of an INF file directive part of the IDE controller's 
driver)
+                 * and the system must not be booted in Safe Mode. If that 
checks
+                 * out, then evaluate the ACPI NATA method to see if the 
platform
+                 * supports this. See the section "BIOS and Platform 
Prerequisites
+                 * for Switching a Native-Mode-Capable Controller" in the 
Storage
+                 * section of the Windows Driver Kit for more details:
+                 *
+                 * 5. For each ATA controller enumerated, the PCI bus driver 
checks
+                 *    the Programming Interface register of the IDE controller 
to
+                 *    see if it supports switching both channels to native 
mode.
+                 * 6. The PCI bus driver checks whether the BIOS/platform 
supports
+                 *    switching the controller by checking the NATA method 
described
+                 *    earlier in this article.
+                 *
+                 *    If an ATA controller does not indicate that it is native
+                 *    mode-capable, or if the BIOS NATA control method is 
missing
+                 *    or does not list that device, the PCI bus driver does not
+                 *    switch the controller and it is assigned legacy 
resources.
+                 *
+                 *  If both the controller and the BIOS indicate that the 
controller
+                 *  can be switched, the process of switching the controller 
begins
+                 *  with the next step.
+                 */
+                if ((PciEnableNativeModeATA) &&
+                    !(InitSafeBootMode) &&
+                    (PciIsSlotPresentInParentMethod(PdoExtension, 'ATAN')))
+                {
+                    /* The platform supports it, remember that */
+                    PdoExtension->BIOSAllowsIDESwitchToNativeMode = TRUE;
+
+                    /*
+                     * Now switch the controller into native mode if both 
channels
+                     * support native IDE mode. See "How Windows Switches an 
ATA
+                     * Controller to Native Mode" in the Storage section of the
+                     * Windows Driver Kit for more details.
+                     */
+                    PdoExtension->SwitchedIDEToNativeMode =
+                        PciConfigureIdeController(PdoExtension, PciData, 1);
+                }
+
+                /* Is native mode enabled after all? */
+                if ((PciData->ProgIf & 5) != 5)
+                {
+                    /* Compatible mode, so force ISA-style IRQ14 and IRQ 15 */
+                    PciData->u.type0.InterruptPin = 0;
+                }
+            }
+
+            /* Is this a PCI device with legacy VGA card decodes on the root 
bus? */
+            if ((PdoExtension->HackFlags & PCI_HACK_VIDEO_LEGACY_DECODE) &&
+                (PCI_IS_ROOT_FDO(DeviceExtension)) &&
+                !(DeviceExtension->BrokenVideoHackApplied))
+            {
+                /* Tell the arbiter to apply a hack for these older devices */
+                ario_ApplyBrokenVideoHack(DeviceExtension);
+            }
+
+            /* Is this a Compaq PCI Hotplug Controller (r17) on a PAE system ? 
*/
+            if ((PciData->VendorID == 0xE11) &&
+                (PciData->DeviceID == 0xA0F7) &&
+                (PciData->RevisionID == 17) &&
+                (ExIsProcessorFeaturePresent(PF_PAE_ENABLED)))
+            {
+                /* Turn off the decodes immediately */
+                PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
+                                      PCI_ENABLE_MEMORY_SPACE |
+                                      PCI_ENABLE_BUS_MASTER);
+                PciWriteDeviceConfig(PdoExtension,
+                                     &PciData->Command,
+                                     FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                     sizeof(USHORT));
+
+                /* Do not EVER turn them on again, this will blow up the 
system */
+                PdoExtension->CommandEnables &= ~(PCI_ENABLE_IO_SPACE |
+                                                  PCI_ENABLE_MEMORY_SPACE |
+                                                  PCI_ENABLE_BUS_MASTER);
+                PdoExtension->HackFlags |= PCI_HACK_PRESERVE_COMMAND;
+            }
+            break;
+
+        /*
+         * This is called whenever resources are changed and hardware needs to 
be
+         * updated. It is concerned with two highly specific erratas on an IBM
+         * hot-plug docking bridge used on the Thinkpad 600 Series and on 
Intel's
+         * ICH PCI Bridges.
+         */
+        case PCI_HACK_FIXUP_BEFORE_UPDATE:
+
+            /* Is this an IBM 20H2999 PCI Docking Bridge, used on Thinkpads? */
+            if ((PdoExtension->VendorId == 0x1014) &&
+                (PdoExtension->DeviceId == 0x95))
+            {
+                /* Read the current command */
+                PciReadDeviceConfig(PdoExtension,
+                                    &Command,
+                                    FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                    sizeof(USHORT));
+
+                /* Turn off the decodes */
+                PciDecodeEnable(PdoExtension, FALSE, &Command);
+
+                /* Apply the required IBM workaround */
+                PciReadDeviceConfig(PdoExtension, &RegValue, 0xE0, 
sizeof(UCHAR));
+                RegValue &= ~2;
+                RegValue |= 1;
+                PciWriteDeviceConfig(PdoExtension, &RegValue, 0xE0, 
sizeof(UCHAR));
+
+                /* Restore the command to its original value */
+                PciWriteDeviceConfig(PdoExtension,
+                                     &Command,
+                                     FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                     sizeof(USHORT));
+
+            }
+
+            /*
+             * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the 
i810,
+             * i820, i840, i845 Chipsets) that have subtractive decode enabled,
+             * and whose hack flags do not specifiy that this support is 
broken.
+             */
+            if ((PdoExtension->HeaderType == PCI_BRIDGE_TYPE) &&
+                (PdoExtension->Dependent.type1.SubtractiveDecode) &&
+                ((PdoExtension->VendorId == 0x8086) &&
+                 ((PdoExtension->DeviceId == 0x2418) ||
+                  (PdoExtension->DeviceId == 0x2428) ||
+                  (PdoExtension->DeviceId == 0x244E) ||
+                  (PdoExtension->DeviceId == 0x2448))) &&
+               !(PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
+            {
+                /*
+                 * The positive decode window shouldn't be used, these values 
are
+                 * normally all read-only or initialized to 0 by the BIOS, but
+                 * it appears Intel doesn't do this, so the PCI Bus Driver will
+                 * do it in software instead. Note that this is used to prevent
+                 * certain non-compliant PCI devices from breaking down due to 
the
+                 * fact that these ICH bridges have a known "quirk" (which 
Intel
+                 * documents as a known "erratum", although it's not not really
+                 * an ICH bug since the PCI specification does allow for it) in
+                 * that they will sometimes send non-zero addresses during 
special
+                 * cycles (ie: non-zero data during the address phase). These
+                 * broken PCI cards will mistakenly attempt to claim the 
special
+                 * cycle and corrupt their I/O and RAM ranges. Again, in 
Intel's
+                 * defense, the PCI specification only requires stable data, 
not
+                 * necessarily zero data, during the address phase.
+                 */
+                PciData->u.type1.MemoryBase = 0xFFFF;
+                PciData->u.type1.PrefetchBase = 0xFFFF;
+                PciData->u.type1.IOBase = 0xFF;
+                PciData->u.type1.IOLimit = 0;
+                PciData->u.type1.MemoryLimit = 0;
+                PciData->u.type1.PrefetchLimit = 0;
+                PciData->u.type1.PrefetchBaseUpper32 = 0;
+                PciData->u.type1.PrefetchLimitUpper32 = 0;
+                PciData->u.type1.IOBaseUpper16 = 0;
+                PciData->u.type1.IOLimitUpper16 = 0;
+            }
+            break;
+
+        default:
+            return;
+    }
+
+    /* Finally, also check if this is this a CardBUS device? */
+    if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
+    {
+        /*
+         * At offset 44h the LegacyBaseAddress is stored, which is cleared by
+         * ACPI-aware versions of Windows, to disable legacy-mode I/O access to
+         * CardBus controllers. For more information, see "Supporting CardBus
+         * Controllers under ACPI" in the "CardBus Controllers and Windows"
+         * Whitepaper on WHDC.
+         */
+        LegacyBaseAddress = 0;
+        PciWriteDeviceConfig(PdoExtension,
+                             &LegacyBaseAddress,
+                             sizeof(PCI_COMMON_HEADER) + sizeof(ULONG),
+                             sizeof(ULONG));
+    }
+}
+
 
 BOOLEAN
 NTAPI
@@ -250,7 +673,8 @@
 {
     ULONG MaxDevice = PCI_MAX_DEVICES;
     BOOLEAN ProcessFlag = FALSE;
-    ULONG i, j, k;
+    ULONG i, j, k, Size;
+    USHORT CapOffset, TempOffset;
     LONGLONG HackFlags;
     PDEVICE_OBJECT DeviceObject;
     UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
@@ -258,11 +682,13 @@
     PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
     PPCI_COMMON_HEADER BiosData = (PVOID)BiosBuffer;
     PCI_SLOT_NUMBER PciSlot;
+    PCHAR Name;
     NTSTATUS Status;
     PPCI_PDO_EXTENSION PdoExtension, NewExtension;
     PPCI_PDO_EXTENSION* BridgeExtension;
     PWCHAR DescriptionText;
     USHORT SubVendorId, SubSystemId;
+    PCI_CAPABILITIES_HEADER CapHeader, PcixCapHeader;
     DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
             DeviceExtension, DeviceExtension->BaseBus);
 
@@ -302,6 +728,13 @@
                               &PciData->DeviceID,
                               sizeof(USHORT),
                               PCI_COMMON_HDR_LENGTH - sizeof(USHORT));
+
+            /* Apply any hacks before even analyzing the configuration header 
*/
+            PciApplyHacks(DeviceExtension,
+                          PciData,
+                          PciSlot,
+                          PCI_HACK_FIXUP_BEFORE_CONFIGURATION,
+                          NULL);
 
             /* Dump device that was found */
             DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
@@ -373,8 +806,15 @@
                 HackFlags |= PCI_HACK_CRITICAL_DEVICE;
             }
 
-            /* Also skip devices that should not be enumerated */
-            if (PciSkipThisFunction(PciData, PciSlot, 1, HackFlags)) continue;
+            /* Check if the device should be skipped for whatever reason */
+            if (PciSkipThisFunction(PciData,
+                                    PciSlot,
+                                    PCI_SKIP_DEVICE_ENUMERATION,
+                                    HackFlags))
+            {
+                /* Skip this device */
+                continue;
+            }
 
             /* Check if a PDO has already been created for this device */
             PdoExtension = PciFindPdoByFunction(DeviceExtension,
@@ -500,6 +940,13 @@
             /* Power up the device */
             PciSetPowerManagedDevicePowerState(NewExtension, PowerDeviceD0, 
FALSE);
 
+            /* Apply any device hacks required for enumeration */
+            PciApplyHacks(DeviceExtension,
+                          PciData,
+                          PciSlot,
+                          PCI_HACK_FIXUP_AFTER_CONFIGURATION,
+                          NewExtension);
+
             /* Save interrupt pin */
             NewExtension->InterruptPin = PciData->u.type0.InterruptPin;
 
@@ -520,6 +967,81 @@
                 /* Set the subsystem information to zero instead */
                 NewExtension->SubsystemVendorId = 0;
                 NewExtension->SubsystemId = 0;
+            }
+
+            /* Scan all capabilities */
+            CapOffset = NewExtension->CapabilitiesPtr;
+            while (CapOffset)
+            {
+                /* Read this header */
+                TempOffset = PciReadDeviceCapability(NewExtension,
+                                                     CapOffset,
+                                                     0,
+                                                     &CapHeader,
+                                                     
sizeof(PCI_CAPABILITIES_HEADER));
+                if (TempOffset != CapOffset)
+                {
+                    /* This is a strange issue that shouldn't happen normally 
*/
+                    DPRINT1("PCI - Failed to read PCI capability at offset 
0x%02x\n",
+                            CapOffset);
+                    ASSERT(TempOffset == CapOffset);
+                }
+
+                /* Check for capabilities that this driver cares about */
+                switch (CapHeader.CapabilityID)
+                {
+                    /* Power management capability is heavily used by the bus 
*/
+                    case PCI_CAPABILITY_ID_POWER_MANAGEMENT:
+
+                        /* Dump the capability */
+                        Name = "POWER";
+                        Size = sizeof(PCI_PM_CAPABILITY);
+                        break;
+
+                    /* AGP capability is required for AGP bus functionality */
+                    case PCI_CAPABILITY_ID_AGP:
+
+                        /* Dump the capability */
+                        Name = "AGP";
+                        Size = sizeof(PCI_AGP_CAPABILITY);
+                        break;
+
+                    /* This driver doesn't really use anything other than that 
*/
+                    default:
+
+                        /* Windows prints this, we could do a translation 
later */
+                        Name = "UNKNOWN CAPABILITY";
+                        Size = 0;
+                        break;
+                }
+
+                /* Check if this is a capability that should be dumped */
+                if (Size)
+                {
+                    /* Read the whole capability data */
+                    TempOffset = PciReadDeviceCapability(NewExtension,
+                                                         CapOffset,
+                                                         
CapHeader.CapabilityID,
+                                                         &CapHeader,
+                                                         Size);
+
+                    if (TempOffset != CapOffset)
+                    {
+                        /* Again, a strange issue that shouldn't be seen */
+                        DPRINT1("- Failed to read capability data. ***\n");
+                        ASSERT(TempOffset == CapOffset);
+                    }
+                }
+
+                /* Dump this capability */
+                DPRINT1("CAP @%02x ID %02x (%s)\n",
+                        CapOffset, CapHeader.CapabilityID, Name);
+                for (i = 0; i < Size; i += 2)
+                    DPRINT1("  %04x\n", *(PUSHORT)((ULONG_PTR)&CapHeader + i));
+                DPRINT1("\n");
+
+                /* Check the next capability */
+                CapOffset = CapHeader.Next;
             }
 
             /* Check for IDE controllers */
@@ -544,6 +1066,39 @@
             {
                 /* Do not allow these legacy bridges to be powered down */
                 NewExtension->DisablePowerDown = TRUE;
+            }
+
+            /* Check if the BIOS did not configure a cache line size */
+            if (!PciData->CacheLineSize)
+            {
+                /* Check if the device is disabled */
+                if (!(NewExtension->CommandEnables & (PCI_ENABLE_IO_SPACE |
+                                                      PCI_ENABLE_MEMORY_SPACE |
+                                                      PCI_ENABLE_BUS_MASTER)))
+                {
+                    /* Check if this is a PCI-X device*/
+                    TempOffset = PciReadDeviceCapability(NewExtension,
+                                                         
NewExtension->CapabilitiesPtr,
+                                                         
PCI_CAPABILITY_ID_PCIX,
+                                                         &PcixCapHeader,
+                                                         
sizeof(PCI_CAPABILITIES_HEADER));
+
+                    /*
+                     * A device with default cache line size and latency timer
+                     * settings is considered to be unconfigured. Note that on
+                     * PCI-X, the reset value of the latency timer field in the
+                     * header is 64, not 0, hence why the check for PCI-X caps
+                     * was required, and the value used here below.
+                     */
+                    if (!(PciData->LatencyTimer) ||
+                        ((TempOffset) && (PciData->LatencyTimer == 64)))
+                    {
+                        /* Keep track of the fact that it needs configuration 
*/
+                        DPRINT1("PCI - ScanBus, PDOx %x found unconfigured\n",
+                                NewExtension);
+                        NewExtension->NeedsHotPlugConfiguration = TRUE;
+                    }
+                }
             }
 
             /* Save latency and cache size information */

Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev=48116&r1=48115&r2=48116&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Mon Jul 19 15:15:39 2010
@@ -63,6 +63,13 @@
 #define PCI_SKIP_RESOURCE_ENUMERATION       0x02
 
 //
+// PCI Apply Hack Flags
+//
+#define PCI_HACK_FIXUP_BEFORE_CONFIGURATION 0x00
+#define PCI_HACK_FIXUP_AFTER_CONFIGURATION  0x01
+#define PCI_HACK_FIXUP_BEFORE_UPDATE        0x03
+
+//
 // PCI Debugging Device Support
 //
 #define MAX_DEBUGGING_DEVICES_SUPPORTED     0x04
@@ -71,7 +78,7 @@
 // PCI Driver Verifier Failures
 //
 #define PCI_VERIFIER_CODES                  0x04
- 
+
 //
 // Device Extension, Interface, Translator and Arbiter Signatures
 //
@@ -974,6 +981,21 @@
     IN BOOLEAN ForPowerDown
 );
 
+BOOLEAN
+NTAPI
+PciIsSlotPresentInParentMethod(
+    IN PPCI_PDO_EXTENSION PdoExtension,
+    IN ULONG Method
+);
+
+VOID
+NTAPI
+PciDecodeEnable(
+    IN PPCI_PDO_EXTENSION PdoExtension,
+    IN BOOLEAN Enable,
+    OUT PUSHORT Command
+);
+
 //
 // Configuration Routines
 //
@@ -1232,6 +1254,12 @@
     IN USHORT Version,
     IN USHORT Size,
     IN PINTERFACE Interface
+);
+
+VOID
+NTAPI
+ario_ApplyBrokenVideoHack(
+    IN PPCI_FDO_EXTENSION FdoExtension
 );
 
 NTSTATUS
@@ -1342,5 +1370,9 @@
 extern PDRIVER_OBJECT PciDriverObject;
 extern PWATCHDOG_TABLE WdTable;
 extern PPCI_HACK_ENTRY PciHackTable;
+extern BOOLEAN PciEnableNativeModeATA;
+
+/* Exported by NTOS, should this go in the NDK? */
+extern NTSYSAPI BOOLEAN InitSafeBootMode;
 
 /* EOF */

Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?rev=48116&r1=48115&r2=48116&view=diff
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Mon Jul 19 15:15:39 2010
@@ -1041,4 +1041,117 @@
     return !(HackFlags & PCI_HACK_NO_PM_CAPS);
 }
 
+BOOLEAN
+NTAPI
+PciIsSlotPresentInParentMethod(IN PPCI_PDO_EXTENSION PdoExtension,
+                               IN ULONG Method)
+{
+    BOOLEAN FoundSlot;
+    PACPI_METHOD_ARGUMENT Argument;
+    ACPI_EVAL_INPUT_BUFFER InputBuffer;
+    PACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
+    ULONG i, Length;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Assume slot is not part of the parent method */
+    FoundSlot = FALSE;
+
+    /* Allocate a 2KB buffer for the method return parameters */
+    Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 2048;
+    OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, 'BicP');
+    if (OutputBuffer)
+    {
+        /* Clear out the output buffer */
+        RtlZeroMemory(OutputBuffer, Length);
+
+        /* Initialize the input buffer with the method requested */
+        InputBuffer.Signature = 0;
+        *(PULONG)InputBuffer.MethodName = Method;
+        InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
+
+        /* Send it to the ACPI driver */
+        Status = 
PciSendIoctl(PdoExtension->ParentFdoExtension->PhysicalDeviceObject,
+                              IOCTL_ACPI_EVAL_METHOD,
+                              &InputBuffer,
+                              sizeof(ACPI_EVAL_INPUT_BUFFER),
+                              OutputBuffer,
+                              Length);
+        if (NT_SUCCESS(Status))
+        {
+            /* Scan all output arguments */
+            for (i = 0; i < OutputBuffer->Count; i++)
+            {
+                /* Make sure it's an integer */
+                Argument = &OutputBuffer->Argument[i];
+                if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) continue;
+
+                /* Check if the argument matches this PCI slot structure */
+                if (Argument->Argument == 
((PdoExtension->Slot.u.bits.DeviceNumber) |
+                                           
((PdoExtension->Slot.u.bits.FunctionNumber) << 16)))
+                {
+                    /* This slot has been found, return it */
+                    FoundSlot = TRUE;
+                    break;
+                }
+            }
+        }
+
+        /* Finished with the buffer, free it */
+        ExFreePoolWithTag(OutputBuffer, 0);
+    }
+
+    /* Return if the slot was found */
+    return FoundSlot;
+}
+
+VOID
+NTAPI
+PciDecodeEnable(IN PPCI_PDO_EXTENSION PdoExtension,
+                IN BOOLEAN Enable,
+                OUT PUSHORT Command)
+{
+    USHORT CommandValue;
+
+    /*
+     * If decodes are being disabled, make sure it's allowed, and in both 
cases,
+     * make sure that a hackflag isn't preventing touching the decodes at all.
+     */
+    if (((Enable) || (PciCanDisableDecodes(PdoExtension, 0, 0, 0))) &&
+        !(PdoExtension->HackFlags & PCI_HACK_PRESERVE_COMMAND))
+    {
+        /* Did the caller already have a command word? */
+        if (Command)
+        {
+            /* Use the caller's */
+            CommandValue = *Command;
+        }
+        else
+        {
+            /* Otherwise, read the current command */
+            PciReadDeviceConfig(PdoExtension,
+                                &Command,
+                                FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                                sizeof(USHORT));
+        }
+
+        /* Turn off decodes by default */
+        CommandValue &= ~(PCI_ENABLE_IO_SPACE |
+                          PCI_ENABLE_MEMORY_SPACE |
+                          PCI_ENABLE_BUS_MASTER);
+
+        /* If requested, enable the decodes that were enabled at init time */
+        if (Enable) CommandValue |= PdoExtension->CommandEnables &
+                                    (PCI_ENABLE_IO_SPACE |
+                                     PCI_ENABLE_MEMORY_SPACE |
+                                     PCI_ENABLE_BUS_MASTER);
+
+        /* Update the command word */
+        PciWriteDeviceConfig(PdoExtension,
+                             &CommandValue,
+                             FIELD_OFFSET(PCI_COMMON_HEADER, Command),
+                             sizeof(USHORT));
+    }
+}
+
 /* EOF */


Reply via email to