示例#1
0
文件: pcibus.c 项目: RareHare/reactos
BOOLEAN
NTAPI
HalpValidPCISlot(IN PBUS_HANDLER BusHandler,
                 IN PCI_SLOT_NUMBER Slot)
{
    PCI_SLOT_NUMBER MultiSlot;
    PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
    UCHAR HeaderType;
    //ULONG Device;

    /* Simple validation */
    if (Slot.u.bits.Reserved) return FALSE;
    if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE;

    /* Function 0 doesn't need checking */
    if (!Slot.u.bits.FunctionNumber) return TRUE;

    /* Functions 0+ need Multi-Function support, so check the slot */
    //Device = Slot.u.bits.DeviceNumber;
    MultiSlot = Slot;
    MultiSlot.u.bits.FunctionNumber = 0;

    /* Send function 0 request to get the header back */
    HalpReadPCIConfig(BusHandler,
                      MultiSlot,
                      &HeaderType,
                      FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType),
                      sizeof(UCHAR));

    /* Now make sure the header is multi-function */
    if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE;
    return TRUE;
}
示例#2
0
文件: bussupp.c 项目: Moteesh/reactos
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;
}
示例#3
0
文件: bussupp.c 项目: Moteesh/reactos
INIT_FUNCTION
BOOLEAN
NTAPI
HalpGetPciBridgeConfig(IN ULONG PciType,
                       IN PUCHAR BusCount)
{
    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;

    /* Loop PCI buses */
    PciSlot.u.bits.Reserved = 0;
    for (i = 0; i < *BusCount; i++)
    {
        /* Get the bus handler */
        BusHandler = HalHandlerForBus(PCIBus, i);

        /* Loop every device */
        for (j = 0; j < PCI_MAX_DEVICES; j++)
        {
            /* Loop every function */
            PciSlot.u.bits.DeviceNumber = j;
            for (k = 0; k < PCI_MAX_FUNCTION; 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;

                /* Make sure that this is a PCI bridge or a cardbus bridge */
                if (!HalpIsBridgeDevice(PciData)) continue;

                /* Not supported */
                if (!WarningsGiven[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
                continue;
            }
        }
    }

    /* If we exited the loop, then there's no bridge to worry about */
    return FALSE;
}
示例#4
0
文件: pcibus.c 项目: RareHare/reactos
ULONG
NTAPI
HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
                           IN ULONG BusNumber,
                           IN PCI_SLOT_NUMBER SlotNumber,
                           IN PVOID Buffer,
                           IN ULONG Offset,
                           IN ULONG Length)
{
    BUS_HANDLER BusHandler;

    /* Setup fake PCI Bus handler */
    RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
    BusHandler.BusNumber = BusNumber;

    /* Read configuration data */
    HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);

    /* Return length */
    return Length;
}
示例#5
0
BOOLEAN
HalpGetPciBridgeConfig (
    IN ULONG            HwType,
    IN PUCHAR           MaxPciBus
    )
/*++

Routine Description:

    Scan the devices on all known pci buses trying to locate any
    pci to pci bridges.  Record the hierarchy for the buses, and
    which buses have what addressing limits.

Arguments:

    HwType      - Configuration type.
    MaxPciBus   - # of PCI buses reported by the bios

--*/
{
    PBUS_HANDLER        ChildBus;
    PPCIPBUSDATA        ChildBusData;
    ULONG               d, f, i, j, BusNo;
    UCHAR               Rescan;
    BOOLEAN             FoundDisabledBridge;
    CONFIGBRIDGE        CB;

    Rescan = 0;
    FoundDisabledBridge = FALSE;

    //
    // Find each bus on a bridge and initialize it's base and limit information
    //

    CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
    CB.SlotNumber.u.bits.Reserved = 0;
    for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {

        CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
        CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;

        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;

                //
                // Read PCI configuration information
                //

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

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

                if (!IsPciBridge (CB.PciData)) {
                    // not a PCI-PCI bridge, next function
                    continue;
                }

                if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
                    // this PCI bridge is not enabled - skip it for now
                    FoundDisabledBridge = TRUE;
                    continue;
                }

                if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
                    CB.BusHandler->BusNumber) {

                    DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
                    // what to do?
                }

                //
                // Found a PCI-PCI brdige. Determine the PIRQ to bus number
                // mappings and store them in the HalpPCIBusToPirqTable[].
                //

                for (i = CB.PciData->u.type1.SecondaryBus;
                        i <= CB.PciData->u.type1.SubordinateBus;
                           i++) {

                    HalpPCIBusToPirqTable[i] = HalpPCIPinToLineTable[d];

                }

                //
                // Found a PCI-PCI bridge.  Determine it's parent child
                // relationships
                //

                ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
                if (!ChildBus) {
                    DBGMSG ("HAL GetPciData: found configured pci bridge\n");

                    // up the number of buses
                    if (CB.PciData->u.type1.SecondaryBus > Rescan) {
                        Rescan = CB.PciData->u.type1.SecondaryBus;
                    }
                    continue;
                }

                ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
                if (ChildBusData->BridgeConfigRead) {
                    // this child buses releationships already processed
                    continue;
                }

                //
                // Remember the limits which are programmed into this bridge
                //

                ChildBusData->BridgeConfigRead = TRUE;
                HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
                ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
                ChildBusData->CommonData.ParentSlot = CB.SlotNumber;

                ChildBus->BusAddresses->IO.Base =
                            PciBridgeIO2Base(
                                CB.PciData->u.type1.IOBase,
                                CB.PciData->u.type1.IOBaseUpper16
                                );

                ChildBus->BusAddresses->IO.Limit =
                            PciBridgeIO2Limit(
                                CB.PciData->u.type1.IOLimit,
                                CB.PciData->u.type1.IOLimitUpper16
                                );

                //
                // Special VGA address remapping occuring on this bridge?
                //

                if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA  &&
                    ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
                    DBGMSG("HAL: VGA mode enable in bridge\n");
                    HalpSetPciBridgedVgaCronk (
                        ChildBus->BusNumber,
                        (ULONG) ChildBus->BusAddresses->IO.Base,
                        (ULONG) ChildBus->BusAddresses->IO.Limit
                    );
                }

                //
                // If supported I/O ranges on this bus are limitied to
                // 256bytes on every 1K aligned boundry within the
                // range, then redo supported IO BusAddresses to match
                //

                if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA  &&
                    ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
                    DBGMSG("HAL: ISA mode enable in bridge\n");
                    // assume Base is 1K aligned
                    i = (ULONG) ChildBus->BusAddresses->IO.Base;
                    j = (ULONG) ChildBus->BusAddresses->IO.Limit;

                    // convert head entry
                    ChildBus->BusAddresses->IO.Limit = i + 256;
                    i += 1024;

                    // add remaining ranges
                    while (i < j) {
                        HalpAddRange (
                            &ChildBus->BusAddresses->IO,
                            1,          // address space
                            0,          // system base
                            i,          // bus address
                            i + 256     // bus limit
                            );

                        // next range
                        i += 1024;
                    }
                }

                ChildBus->BusAddresses->Memory.Base =
                        PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);

                ChildBus->BusAddresses->Memory.Limit =
                        PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);

                // On x86 it's ok to clip Prefetch to 32 bits

                if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
                    ChildBus->BusAddresses->PrefetchMemory.Base =
                            PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);


                    ChildBus->BusAddresses->PrefetchMemory.Limit =
                            PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);

                    if (CB.PciData->u.type1.PrefetchLimitUpper32) {
                        ChildBus->BusAddresses->PrefetchMemory.Limit = (ULONGLONG)0xffffffff;
                    }
                }

                // should call HalpAssignPCISlotResources to assign
                // baseaddresses, etc...
            }
        }
    }

    if (Rescan) {
        *MaxPciBus = Rescan;
        return TRUE;
    }

    if (!FoundDisabledBridge) {
        return FALSE;
    }

    DBGMSG ("HAL GetPciData: found disabled pci bridge\n");

    return FALSE;

}
示例#6
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);
}
示例#7
0
NTSTATUS
HalpAdjustPCIResourceList (
    IN PBUS_HANDLER BusHandler,
    IN PBUS_HANDLER RootHandler,
    IN OUT PIO_RESOURCE_REQUIREMENTS_LIST   *pResourceList
    )
/*++
    Rewrite the callers requested resource list to fit within
    the supported ranges of this bus
--*/
{
    NTSTATUS                Status;
    PPCIPBUSDATA            BusData;
    PCI_SLOT_NUMBER         PciSlot;
    PSUPPORTED_RANGE        Interrupt;
    PSUPPORTED_RANGE        Range;
    PSUPPORTED_RANGES       SupportedRanges;
    PPCI_COMMON_CONFIG      PciData, PciOrigData;
    UCHAR                   buffer[PCI_COMMON_HDR_LENGTH];
    UCHAR                   buffer2[PCI_COMMON_HDR_LENGTH];
    BOOLEAN                 UseBusRanges;
    ULONG                   i, j, RomIndex, length, ebit;
    ULONG                   Base[PCI_TYPE0_ADDRESSES + 1];
    PULONG                  BaseAddress[PCI_TYPE0_ADDRESSES + 1];


    BusData = (PPCIPBUSDATA) BusHandler->BusData;
    PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);

    //
    // Determine PCI device's interrupt restrictions
    //

    Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);

    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    SupportedRanges = NULL;
    UseBusRanges    = TRUE;
    Status          = STATUS_INSUFFICIENT_RESOURCES;

    if (HalpPciLockSettings) {

        PciData = (PPCI_COMMON_CONFIG) buffer;
        PciOrigData = (PPCI_COMMON_CONFIG) buffer2;
        HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);

        //
        // If this is a device, and it current has its decodes enabled,
        // then use the currently programmed ranges only
        //

        if (PCI_CONFIG_TYPE(PciData) == 0 &&
            (PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {

            //
            // Save current settings
            //

            RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);


            for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
                BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
            }
            BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
            RomIndex = j;

            //
            // Write all one-bits to determine lengths for each address
            //

            for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
                Base[j] = *BaseAddress[j];
                *BaseAddress[j] = 0xFFFFFFFF;
            }

            PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
            *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
            HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
            HalpReadPCIConfig  (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);

            //
            // restore original settings
            //

            HalpWritePCIConfig (
                BusHandler,
                PciSlot,
                &PciOrigData->Status,
                FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
                PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
                );

            HalpWritePCIConfig (
                BusHandler,
                PciSlot,
                PciOrigData,
                0,
                FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
                );

            //
            // Build a memory & io range list of just the ranges already
            // programmed into the device
            //

            UseBusRanges    = FALSE;
            SupportedRanges = HalpAllocateNewRangeList();
            if (!SupportedRanges) {
                goto CleanUp;
            }

            *BaseAddress[RomIndex] &= ~PCI_ADDRESS_IO_SPACE;
            for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {

                i = *BaseAddress[j];

                if (i & PCI_ADDRESS_IO_SPACE) {
                    length = 1 << 2;
                    Range  = &SupportedRanges->IO;
                    ebit   = PCI_ENABLE_IO_SPACE;

                } else {
                    length = 1 << 4;
                    Range  = &SupportedRanges->Memory;
                    ebit   = PCI_ENABLE_MEMORY_SPACE;

                    if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
                        Range = &SupportedRanges->PrefetchMemory;
                    }
                }

                Base[j] &= ~(length-1);
                while (!(i & length)  &&  length) {
                    length <<= 1;
                }

                if (j == RomIndex &&
                    !(PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)) {

                    // range not enabled, don't use it
                    length = 0;
                }

                if (length) {
                    if (!(PciOrigData->Command & ebit)) {
                        // range not enabled, don't use preprogrammed values
                        UseBusRanges = TRUE;
                    }

                    if (Range->Limit >= Range->Base) {
                        Range->Next = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
                        Range = Range->Next;
                        if (!Range) {
                            goto CleanUp;
                        }

                        Range->Next = NULL;
                    }

                    Range->Base  = Base[j];
                    Range->Limit = Base[j] + length - 1;
                }

                if (Is64BitBaseAddress(i)) {
                    // skip upper half of 64 bit address since this processor
                    // only supports 32 bits of address space
                    j++;
                }
            }
        }
    }

    //
    // Adjust resources
    //

    Status = HaliAdjustResourceListRange (
                UseBusRanges ? BusHandler->BusAddresses : SupportedRanges,
                Interrupt,
                pResourceList
                );

CleanUp:
    if (SupportedRanges) {
        HalpFreeRangeList (SupportedRanges);
    }

    ExFreePool (Interrupt);
    return Status;
}
示例#8
0
BOOLEAN
HalpGetPciBridgeConfig (
    IN ULONG            HwType,
    IN PUCHAR           MaxPciBus
    )
/*++

Routine Description:

    Scan the devices on all known pci buses trying to locate any
    pci to pci bridges.  Record the hierarchy for the buses, and
    which buses have what addressing limits.

Arguments:

    HwType      - Configuration type.
    MaxPciBus   - # of PCI buses reported by the bios

--*/
{
    PBUS_HANDLER        ChildBus;
    PPCIPBUSDATA        ChildBusData;
    ULONG               d, f, i, j, BusNo;
    UCHAR               Rescan;
    BOOLEAN             FoundDisabledBridge;
    CONFIGBRIDGE        CB;

    Rescan = 0;
    FoundDisabledBridge = FALSE;

    //
    // Find each bus on a bridge and initialize it's base and limit information
    //

    CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
    CB.SlotNumber.u.bits.Reserved = 0;
    for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {

        CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
        CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;

        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;

                //
                // Read PCI configuration information
                //

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

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

                if (!IsPciBridge (CB.PciData)) {
                    // not a PCI-PCI bridge, next function
                    continue;
                }

                if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
                    // this PCI bridge is not enabled - skip it for now
                    FoundDisabledBridge = TRUE;
                    continue;
                }

                if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
                    CB.BusHandler->BusNumber) {

                    DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
                    // what to do?
                }

                //
                // Found a PCI-PCI bridge.  Determine it's parent child
                // releationships
                //

                ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
                if (!ChildBus) {
                    DBGMSG ("HAL GetPciData: found configured pci bridge\n");

                    // up the number of buses
                    if (CB.PciData->u.type1.SecondaryBus > Rescan) {
                        //Rescan = CB.PciData->u.type1.SecondaryBus;     JAKETEMP
                        Rescan = CB.PciData->u.type1.SecondaryBus + 1;
                    }
                    continue;
                }

                ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
                if (ChildBusData->BridgeConfigRead) {
                    // this child buses releationships already processed
                    continue;
                }

                //
                // Remember the limits which are programmed into this bridge
                //

                ChildBusData->BridgeConfigRead = TRUE;
                HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
                ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
                ChildBusData->CommonData.ParentSlot = CB.SlotNumber;

                ChildBus->BusAddresses->IO.Base =
                            PciBridgeIO2Base(
                                CB.PciData->u.type1.IOBase,
                                CB.PciData->u.type1.IOBaseUpper16
                                );

                ChildBus->BusAddresses->IO.Limit =
                            PciBridgeIO2Limit(
                                CB.PciData->u.type1.IOLimit,
                                CB.PciData->u.type1.IOLimitUpper16
                                );

                //
                // Special VGA address remapping occuring on this bridge?
                //

                if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA  &&
                    ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {

                    HalpSetPciBridgedVgaCronk (
                        ChildBus->BusNumber,
                        (ULONG) ChildBus->BusAddresses->IO.Base,
                        (ULONG) ChildBus->BusAddresses->IO.Limit
                    );
                }

                //
                // If supported I/O ranges on this bus are limitied to
                // 256bytes on every 1K aligned boundry within the
                // range, then redo supported IO BusAddresses to match
                //

                if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA  &&
                    ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {

                    // assume Base is 1K aligned
                    i = (ULONG) ChildBus->BusAddresses->IO.Base;
                    j = (ULONG) ChildBus->BusAddresses->IO.Limit;

                    // convert head entry
                    ChildBus->BusAddresses->IO.Limit = i + 256;
                    i += 1024;

                    // add remaining ranges
                    while (i < j) {
                        HalpAddRange (
                            &ChildBus->BusAddresses->IO,
                            1,          // address space
                            0,          // system base
                            i,          // bus address
                            i + 256     // bus limit
                            );

                        // next range
                        i += 1024;
                    }
                }

                ChildBus->BusAddresses->Memory.Base =
                        PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);

                ChildBus->BusAddresses->Memory.Limit =
                        PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);

                // On x86 it's ok to clip Prefetch to 32 bits
                //  BUGBUG  This is OK on existing PPCs too, but this may have to change
                //          on later implementations.

                if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
                    ChildBus->BusAddresses->PrefetchMemory.Base =
                            PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);


                    ChildBus->BusAddresses->PrefetchMemory.Limit =
                            PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);

                    if (CB.PciData->u.type1.PrefetchLimitUpper32) {
                        ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
                    }
                }

                // should call HalpAssignPCISlotResources to assign
                // baseaddresses, etc...
            }
        }
    }

    if (Rescan) {
        *MaxPciBus = Rescan;
        return TRUE;
    }

    if (!FoundDisabledBridge) {
        return FALSE;
    }

    DBGMSG ("HAL GetPciData: found disabled pci bridge\n");

#ifdef INIT_PCI_BRIDGE
    //
    //  We've calculated all the parent's buses known bases & limits.
    //  While doing this a pci-pci bus was found that the bios didn't
    //  configure.  This is not expected, and we'll make some guesses
    //  at a configuration here and enable it.
    //
    //  (this code is primarily for testing the above code since
    //   currently no system bioses actually configure the child buses)
    //

    for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {

        CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
        CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;

        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)) {
                    // not a PCI-PCI bridge
                    continue;
                }

                if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
                    // this PCI bridge is enabled
                    continue;
                }

                //
                // We have a disabled bus - assign it a number, then
                // determine all the requirements of all devices
                // on the other side of this bridge
                //

                CB.BusNo = BusNo;
                HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
            }
        }
    }
    // preform Rescan
    return TRUE;

#else

    return FALSE;

#endif

}
示例#9
0
文件: pcibus.c 项目: RareHare/reactos
NTSTATUS
NTAPI
HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
                           IN PBUS_HANDLER RootHandler,
                           IN PUNICODE_STRING RegistryPath,
                           IN PUNICODE_STRING DriverClassName OPTIONAL,
                           IN PDRIVER_OBJECT DriverObject,
                           IN PDEVICE_OBJECT DeviceObject OPTIONAL,
                           IN ULONG Slot,
                           IN OUT PCM_RESOURCE_LIST *AllocatedResources)
{
    PCI_COMMON_CONFIG PciConfig;
    SIZE_T Address;
    ULONG ResourceCount;
    ULONG Size[PCI_TYPE0_ADDRESSES];
    NTSTATUS Status = STATUS_SUCCESS;
    UCHAR Offset;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
    PCI_SLOT_NUMBER SlotNumber;
    ULONG WriteBuffer;
    DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n");

    /* FIXME: Should handle 64-bit addresses */

    /* Read configuration data */
    SlotNumber.u.AsULONG = Slot;
    HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH);

    /* Check if we read it correctly */
    if (PciConfig.VendorID == PCI_INVALID_VENDORID)
        return STATUS_NO_SUCH_DEVICE;

    /* Read the PCI configuration space for the device and store base address and
    size information in temporary storage. Count the number of valid base addresses */
    ResourceCount = 0;
    for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
    {
        if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
            PciConfig.u.type0.BaseAddresses[Address] = 0;

        /* Memory resource */
        if (0 != PciConfig.u.type0.BaseAddresses[Address])
        {
            ResourceCount++;

            Offset = (UCHAR)FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);

            /* Write 0xFFFFFFFF there */
            WriteBuffer = 0xffffffff;
            HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG));

            /* Read that figure back from the config space */
            HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG));

            /* Write back initial value */
            HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG));
        }
    }

    /* Interrupt resource */
    if (0 != PciConfig.u.type0.InterruptPin &&
        0 != PciConfig.u.type0.InterruptLine &&
        0xFF != PciConfig.u.type0.InterruptLine)
        ResourceCount++;

    /* Allocate output buffer and initialize */
    *AllocatedResources = ExAllocatePoolWithTag(
        PagedPool,
        sizeof(CM_RESOURCE_LIST) +
        (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
        TAG_HAL);

    if (NULL == *AllocatedResources)
        return STATUS_NO_MEMORY;

    (*AllocatedResources)->Count = 1;
    (*AllocatedResources)->List[0].InterfaceType = PCIBus;
    (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber;
    (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
    (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
    (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
    Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;

    /* Store configuration information */
    for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
    {
        if (0 != PciConfig.u.type0.BaseAddresses[Address])
        {
            if (PCI_ADDRESS_MEMORY_SPACE ==
                (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
            {
                Descriptor->Type = CmResourceTypeMemory;
                Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
                Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;             /* FIXME Just a guess */
                Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
                Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK);
            }
            else if (PCI_ADDRESS_IO_SPACE ==
                (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
            {
                Descriptor->Type = CmResourceTypePort;
                Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
                Descriptor->Flags = CM_RESOURCE_PORT_IO;                       /* FIXME Just a guess */
                Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK;
                Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff);
            }
            else
            {
                ASSERT(FALSE);
                return STATUS_UNSUCCESSFUL;
            }
            Descriptor++;
        }
    }

    if (0 != PciConfig.u.type0.InterruptPin &&
        0 != PciConfig.u.type0.InterruptLine &&
        0xFF != PciConfig.u.type0.InterruptLine)
    {
        Descriptor->Type = CmResourceTypeInterrupt;
        Descriptor->ShareDisposition = CmResourceShareShared;          /* FIXME Just a guess */
        Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;     /* FIXME Just a guess */
        Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
        Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
        Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;

        Descriptor++;
    }

    ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);

    /* FIXME: Should store the resources in the registry resource map */

    return Status;
}
示例#10
0
文件: pcibus.c 项目: RareHare/reactos
ULONG
NTAPI
HalpSetPCIData(IN PBUS_HANDLER BusHandler,
               IN PBUS_HANDLER RootHandler,
               IN PCI_SLOT_NUMBER Slot,
               IN PVOID Buffer,
               IN ULONG Offset,
               IN ULONG Length)
{
    UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
    PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
    ULONG Len = 0;

#ifdef SARCH_XBOX
    /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
     * hang the Xbox. Also, the device number doesn't seem to be decoded for the
     * video card, so it appears to be present on 1:0:0 - 1:31:0.
     * We hack around these problems by indicating "device not present" for devices
     * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
    if ((0 == BusHandler->BusNumber && 0 == Slot.u.bits.DeviceNumber &&
         (1 == Slot.u.bits.FunctionNumber || 2 == Slot.u.bits.FunctionNumber)) ||
        (1 == BusHandler->BusNumber && 0 != Slot.u.bits.DeviceNumber))
    {
        DPRINT1("Trying to set data on blacklisted PCI slot\n");
        return 0;
    }
#endif

    /* Normalize the length */
    if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);

    /* Check if this is a vendor-specific read */
    if (Offset >= PCI_COMMON_HDR_LENGTH)
    {
        /* Read the header */
        HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));

        /* Make sure the vendor is valid */
        if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
    }
    else
    {
        /* Read the entire header and validate the vendor ID */
        Len = PCI_COMMON_HDR_LENGTH;
        HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
        if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;

        /* Return what's after the offset and normalize */
        Len -= Offset;
        if (Len > Length) Len = Length;

        /* Copy the specific caller data */
        RtlMoveMemory(PciBuffer + Offset, Buffer, Len);

        /* Write the actual configuration data */
        HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len);

        /* Update buffer and offset, decrement total length */
        Offset += Len;
        Buffer = (PVOID)((ULONG_PTR)Buffer + Len);
        Length -= Len;
    }

    /* Now we still have something to copy */
    if (Length)
    {
        /* Check if it's vendor-specific data */
        if (Offset >= PCI_COMMON_HDR_LENGTH)
        {
            /* Read it now */
            HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
            Len += Length;
        }
    }

    /* Update the total length read */
    return Len;
}
示例#11
0
文件: bussupp.c 项目: Moteesh/reactos
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
}