Example #1
0
VOID
HalpGetPciBridgeNeeds (
    IN ULONG            HwType,
    IN PUCHAR           MaxPciBus,
    IN PCONFIGBRIDGE    Current
    )
{
    ACCESS_MASK                     DesiredAccess;
    UNICODE_STRING                  unicodeString;
    PUCHAR                          buffer;
    HANDLE                          handle;
    OBJECT_ATTRIBUTES               objectAttributes;
    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
    PCONFIGURATION_COMPONENT        Component;
    CONFIGBRIDGE                    CB;
    ULONG                           mnum, d, f;
    NTSTATUS                        status;


    buffer = ExAllocatePool (PagedPool, 1024);

    // init
    CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
    CB.SlotNumber.u.bits.Reserved = 0;
    Current->IO = Current->Memory = Current->PFMemory = 0;

    //
    // Assign this bridge an ID, and turn on configuration space
    //

    Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
    Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
    Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
    Current->PciData->u.type1.SecondaryStatus = 0xffff;
    Current->PciData->Status  = 0xffff;
    Current->PciData->Command = 0;

    Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;

    HalpWritePCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        Current->PciData,
        0,
        PCI_COMMON_HDR_LENGTH
        );

    KeStallExecutionProcessor (100);

    Current->PciData->u.type1.BridgeControl = 0;
    HalpWritePCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        Current->PciData,
        0,
        PCI_COMMON_HDR_LENGTH
        );


    KeStallExecutionProcessor (100);

    //
    // Allocate new handler for bus
    //

    CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
    CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
    CB.BusNo = *MaxPciBus;
    *MaxPciBus += 1;

    //
    // Add another PCI bus in the registry
    //

    mnum = 0;
    for (; ;) {
        //
        // Find next available MultiFunctionAdapter key
        //

        DesiredAccess = KEY_READ | KEY_WRITE;
        swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
        RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);

        InitializeObjectAttributes( &objectAttributes,
                                    &unicodeString,
                                    OBJ_CASE_INSENSITIVE,
                                    NULL,
                                    (PSECURITY_DESCRIPTOR) NULL
                                    );

        status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
        if (!NT_SUCCESS(status)) {
            break;
        }

        // already exists, next
        ZwClose (handle);
        mnum += 1;
    }

    ZwCreateKey (&handle,
                   DesiredAccess,
                   &objectAttributes,
                   0,
                   NULL,
                   REG_OPTION_VOLATILE,
                   &d
                );

    //
    // Add needed registry values for this MultifucntionAdapter entry
    //

    RtlInitUnicodeString (&unicodeString, rgzIdentifier);
    ZwSetValueKey (handle,
                   &unicodeString,
                   0L,
                   REG_SZ,
                   L"PCI",
                   sizeof (L"PCI")
                   );

    RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
    Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
    Descriptor->InterfaceType = PCIBus;
    Descriptor->BusNumber = CB.BusNo;
    Descriptor->PartialResourceList.Version = 0;
    Descriptor->PartialResourceList.Revision = 0;
    Descriptor->PartialResourceList.Count = 0;
    ZwSetValueKey (handle,
                   &unicodeString,
                   0L,
                   REG_FULL_RESOURCE_DESCRIPTOR,
                   Descriptor,
                   sizeof (*Descriptor)
                   );


    RtlInitUnicodeString (&unicodeString, L"Component Information");
    Component = (PCONFIGURATION_COMPONENT) buffer;
    RtlZeroMemory (Component, sizeof (*Component));
    Component->AffinityMask = 0xffffffff;
    ZwSetValueKey (handle,
                   &unicodeString,
                   0L,
                   REG_BINARY,
                   Component,
                   FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
                   );

    ZwClose (handle);


    //
    // Since the firmware didn't configure this bridge we'll assume that
    // the PCI interrupts are bridged.
    //

    for (d = 0; d < PCI_MAX_DEVICES; d++) {
        CB.SlotNumber.u.bits.DeviceNumber = d;

        for (f = 0; f < PCI_MAX_FUNCTION; f++) {
            CB.SlotNumber.u.bits.FunctionNumber = f;

            HalpReadPCIConfig (
                    Current->BusHandler,
                    CB.SlotNumber,
                    CB.PciData,
                    0,
                    PCI_COMMON_HDR_LENGTH
                    );

             if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
                    break;
             }

             if (CB.PciData->u.type0.InterruptPin  &&
                    (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE  ||
                     PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {

                    //
                    // Get IRQ value from table since firmware
                    // did not initialize the bridge.
                    //

                    Current->PciData->u.type1.InterruptPin =
                        CB.PciData->u.type0.InterruptPin + (UCHAR)d % 4;

                    Current->PciData->u.type1.InterruptLine =
                        HalpPCIPinToLineTable[(CB.BusNo*8) + CB.SlotNumber.u.bits.DeviceNumber];
             }
        }
    }

    //
    // Look at each device on the bus and determine it's resource needs
    //

    for (d = 0; d < PCI_MAX_DEVICES; d++) {
        CB.SlotNumber.u.bits.DeviceNumber = d;

        for (f = 0; f < PCI_MAX_FUNCTION; f++) {
            CB.SlotNumber.u.bits.FunctionNumber = f;

            HalpReadPCIConfig (
                CB.BusHandler,
                CB.SlotNumber,
                CB.PciData,
                0,
                PCI_COMMON_HDR_LENGTH
                );

            if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
                break;
            }

            if (IsPciBridge (CB.PciData)) {
                // oh look - another bridge ...
                HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
                continue;
            }

            if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
                continue;
            }

            // found a device - figure out the resources it needs
        }
    }

    //
    // Found all sub-buses set SubordinateBus accordingly
    //

    Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;

    HalpWritePCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        Current->PciData,
        0,
        PCI_COMMON_HDR_LENGTH
        );


    //
    // Set the bridges IO, Memory, and Prefetch Memory windows
    //

    // For now just pick some numbers & set everyone the same
    //  IO      0x6000 - 0xFFFF
    //  MEM     0x40000000 - 0x4FFFFFFF
    //  PFMEM   0x50000000 - 0x5FFFFFFF

    Current->PciData->u.type1.IOBase       = 0xD000     >> 12 << 4;
    Current->PciData->u.type1.IOLimit      = 0xffff     >> 12 << 4;
    Current->PciData->u.type1.MemoryBase   = 0x0 >> 20 << 4;
    Current->PciData->u.type1.MemoryLimit  = 0x0 >> 20 << 4;
    Current->PciData->u.type1.PrefetchBase  = 0 >> 20 << 4;
    Current->PciData->u.type1.PrefetchLimit = 0 >> 20 << 4;

    Current->PciData->u.type1.PrefetchBaseUpper32    = 0;
    Current->PciData->u.type1.PrefetchLimitUpper32   = 0;
    Current->PciData->u.type1.IOBaseUpper16         = 0;
    Current->PciData->u.type1.IOLimitUpper16        = 0;
    Current->PciData->u.type1.BridgeControl         =
        PCI_ENABLE_BRIDGE_ISA;

    HalpWritePCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        Current->PciData,
        0,
        PCI_COMMON_HDR_LENGTH
        );

    HalpReadPCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        Current->PciData,
        0,
        PCI_COMMON_HDR_LENGTH
        );

    // enable memory & io decodes

    Current->PciData->Command =
        PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;

    HalpWritePCIConfig (
        Current->BusHandler,
        Current->SlotNumber,
        &Current->PciData->Command,
        FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
        sizeof (Current->PciData->Command)
        );

    ExFreePool (buffer);
}
Example #2
0
INIT_FUNCTION
VOID
NTAPI
HalpInitializePciBus(VOID)
{
#ifndef _MINIHAL_
    PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
    UCHAR PciType;
    PCI_SLOT_NUMBER PciSlot;
    ULONG i, j, k;
    UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
    PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
    PBUS_HANDLER BusHandler;
    ULONG HackFlags;
    BOOLEAN ExtendedAddressDecoding = FALSE;
    NTSTATUS Status;

    /* Query registry information */
    PciRegistryInfo = HalpQueryPciRegistryInfo();
    if (!PciRegistryInfo) return;

    /* Initialize the PCI configuration lock */
    KeInitializeSpinLock(&HalpPCIConfigLock);

    /* Get the type and free the info structure */
    PciType = PciRegistryInfo->HardwareMechanism & 0xF;

    /* Check if this is a type 2 PCI bus with at least one bus */
    if ((PciRegistryInfo->NoBuses) && (PciType == 2))
    {
        /* Setup the PCI slot */
        PciSlot.u.bits.Reserved = 0;
        PciSlot.u.bits.FunctionNumber = 0;

        /* Loop all slots */
        for (i = 0; i < 32; i++)
        {
            /* Try to setup a Type 2 PCI slot */
            PciType = 2;
            BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
            if (!BusHandler) break;

            /* Now check if it's valid */
            if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;

            /* Heh, the BIOS lied... try Type 1 */
            PciType = 1;
            BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
            if (!BusHandler) break;

            /* Now check if it's valid */
            if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;

            /* Keep trying */
            PciType = 2;
        }

        /* Now allocate the correct kind of handler */
        HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
    }

    /* Okay, now loop all PCI bridges */
    do
    {
        /* Loop all PCI buses */
        for (i = 0; i < PciRegistryInfo->NoBuses; i++)
        {
            /* Check if we have a handler for it */
            if (!HalHandlerForBus(PCIBus, i))
            {
                /* Allocate it */
                HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
            }
        }
        /* Go to the next bridge */
    } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));

    /* Now build correct address range informaiton */
    HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);

    /* Loop every bus */
    DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
    PciSlot.u.bits.Reserved = 0;
    for (i = 0; i < PciRegistryInfo->NoBuses; i++)
    {
        /* Get the bus handler */
        BusHandler = HalHandlerForBus(PCIBus, i);

        /* Loop every device */
        for (j = 0; j < 32; j++)
        {
            /* Loop every function */
            PciSlot.u.bits.DeviceNumber = j;
            for (k = 0; k < 8; k++)
            {
                /* Build the final slot structure */
                PciSlot.u.bits.FunctionNumber = k;

                /* Read the configuration information */
                HalpReadPCIConfig(BusHandler,
                                  PciSlot,
                                  PciData,
                                  0,
                                  PCI_COMMON_HDR_LENGTH);

                /* Skip if this is an invalid function */
                if (PciData->VendorID == PCI_INVALID_VENDORID) continue;

                /* Print out the entry */
                HalpDebugPciDumpBus(i, j, k, PciData);

                /* Check if this is a Cardbus bridge */
                if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
                {
                    /* Not supported */
                    DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
                    continue;
                }

                /* Check if this is a PCI device */
                if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
                {
                    /* Check if it has an interrupt pin and line registered */
                    if ((PciData->u.type1.InterruptPin) &&
                        (PciData->u.type1.InterruptLine))
                    {
                        /* Check if this interrupt line is connected to the bus */
                        if (PciData->u.type1.InterruptLine < 16)
                        {
                            /* Is this an IDE device? */
                            if (!HalpIsIdeDevice(PciData))
                            {
                                /* We'll mask out this interrupt then */
                                DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
                                         PciData->u.type1.InterruptLine);
                                HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
                            }
                        }
                    }
                }

                /* Check for broken Intel chips */
                if (PciData->VendorID == 0x8086)
                {
                    /* Check for broken 82830 PCI controller */
                    if ((PciData->DeviceID == 0x04A3) &&
                        (PciData->RevisionID < 0x11))
                    {
                        /* Skip */
                        DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
                        continue;
                    }

                    /* Check for broken 82378 PCI-to-ISA Bridge */
                    if ((PciData->DeviceID == 0x0484) &&
                        (PciData->RevisionID <= 3))
                    {
                        /* Skip */
                        DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
                        continue;
                    }

                    /* Check for broken 82450 PCI Bridge */
                    if ((PciData->DeviceID == 0x84C4) &&
                        (PciData->RevisionID <= 4))
                    {
                        DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
                        continue;
                    }
                }

                /* Do we know this card? */
                if (!ExtendedAddressDecoding)
                {
                    /* Check for it */
                    if (HalpIsRecognizedCard(PciRegistryInfo,
                                             PciData,
                                             HALP_CARD_FEATURE_FULL_DECODE))
                    {
                        /* We'll do chipset checks later */
                        DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
                        ExtendedAddressDecoding = TRUE;
                    }
                }

                /* Now check the registry for chipset hacks */
                Status = HalpGetChipHacks(PciData->VendorID,
                                          PciData->DeviceID,
                                          PciData->RevisionID,
                                          &HackFlags);
                if (NT_SUCCESS(Status))
                {
                    /* Check for broken ACPI routing */
                    if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
                    {
                        DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
                        continue;
                    }

                    /* Check for broken ACPI timer */
                    if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
                    {
                         DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
                         continue;
                    }

                    /* Check for hibernate-disable */
                    if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
                    {
                        DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
                        continue;
                    }

                    /* Check for USB controllers that generate SMIs */
                    if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
                    {
                        DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
                        continue;
                    }
                }

                /* Terminate the entry */
                DbgPrint("\n");
            }
        }
    }

    /* Initialize NMI Crash Flag */
    HalpGetNMICrashFlag();

    /* Free the registry data */
    ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);

    /* Tell PnP if this hard supports correct decoding */
    HalpMarkChipsetDecode(ExtendedAddressDecoding);
    DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
#endif
}