Beispiel #1
0
INIT_FUNCTION
BOOLEAN
NTAPI
HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData)
{
    /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
    return (((PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE) &&
             (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
             (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)) ||
            ((PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) &&
             (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
             (PciData->SubClass == PCI_SUBCLASS_BR_CARDBUS)));
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
INIT_FUNCTION
BOOLEAN
NTAPI
HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,
                     IN PCI_SLOT_NUMBER Slot)
{
    UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
    PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer;
    ULONG i;
    ULONG_PTR Address;

    /* Read the PCI header */
    HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH);

    /* Make sure it's a valid device */
    if ((PciHeader->VendorID == PCI_INVALID_VENDORID) ||
        (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE))
    {
        /* Bail out */
        return FALSE;
    }

    /* Make sure interrupt numbers make sense */
    if (((PciHeader->u.type0.InterruptPin) &&
         (PciHeader->u.type0.InterruptPin > 4)) ||
        (PciHeader->u.type0.InterruptLine & 0x70))
    {
        /* Bail out */
        return FALSE;
    }

    /* Now scan PCI BARs */
    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
    {
        /* Check what kind of address it is */
        Address = PciHeader->u.type0.BaseAddresses[i];
        if (Address & PCI_ADDRESS_IO_SPACE)
        {
            /* Highest I/O port is 65535 */
            if (Address > 0xFFFF) return FALSE;
        }
        else
        {
            /* MMIO should be higher than 0x80000 */
            if ((Address > 0xF) && (Address < 0x80000)) return FALSE;
        }

        /* Is this a 64-bit address? */
        if (!(Address & PCI_ADDRESS_IO_SPACE) &&
            ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
        {
            /* Check the next-next entry, since this one 64-bits wide */
            i++;
        }
    }

    /* Header, interrupt and address data all make sense */
    return TRUE;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}
Beispiel #7
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
}
Beispiel #8
0
INIT_FUNCTION
BOOLEAN
NTAPI
HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
                     IN PPCI_COMMON_CONFIG PciData,
                     IN ULONG Flags)
{
    ULONG ElementCount, i;
    PPCI_CARD_DESCRIPTOR CardDescriptor;

    /* How many PCI Cards that we know about? */
    ElementCount = PciRegistryInfo->ElementCount;
    if (!ElementCount) return FALSE;

    /* Loop all descriptors */
    CardDescriptor = &PciRegistryInfo->CardList[0];
    for (i = 0; i < ElementCount; i++, CardDescriptor++)
    {
        /* Check for flag match */
        if (CardDescriptor->Flags != Flags) continue;

        /* Check for VID-PID match */
        if ((CardDescriptor->VendorID != PciData->VendorID) ||
            (CardDescriptor->DeviceID != PciData->DeviceID))
        {
            /* Skip */
            continue;
        }

        /* Check for revision match, if requested */
        if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
            (CardDescriptor->RevisionID != PciData->RevisionID))
        {
            /* Skip */
            continue;
        }

        /* Check what kind of device this is */
        switch (PCI_CONFIGURATION_TYPE(PciData))
        {
            /* CardBUS Bridge */
            case PCI_CARDBUS_BRIDGE_TYPE:

                /* This means the real device header is in the device-specific data */
                PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;

            /* Normal PCI device */
            case PCI_DEVICE_TYPE:

                /* Check for subvendor match, if requested */
                if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
                    (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
                {
                    /* Skip */
                    continue;
                }

                /* Check for subsystem match, if requested */
                if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
                    (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
                {
                    /* Skip */
                    continue;
                }

                /* You made it! */
                return TRUE;

            /* PCI Bridge -- don't bother */
            case PCI_BRIDGE_TYPE:
            default:

                /* Recognize it */
                return TRUE;
        }
    }

    /* This means the card isn't recognized */
    return FALSE;
}