Beispiel #1
0
NTSTATUS
NTAPI
HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler,
                          IN PBUS_HANDLER RootHandler,
                          IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList)
{
    PPCIPBUSDATA BusData;
    PCI_SLOT_NUMBER SlotNumber;
    PSUPPORTED_RANGE Interrupt;
    NTSTATUS Status;

    /* Get PCI bus data */
    BusData = BusHandler->BusData;
    SlotNumber.u.AsULONG = (*pResourceList)->SlotNumber;

    /* Get the IRQ supported range */
    Status = BusData->GetIrqRange(BusHandler, RootHandler, SlotNumber, &Interrupt);
    if (!NT_SUCCESS(Status)) return Status;
#ifndef _MINIHAL_
    /* Handle the /PCILOCK feature */
    if (HalpPciLockSettings)
    {
        /* /PCILOCK is not yet supported */
        UNIMPLEMENTED_DBGBREAK("/PCILOCK boot switch is not yet supported.");
    }
#endif
    /* Now create the correct resource list based on the supported bus ranges */
#if 0
    Status = HaliAdjustResourceListRange(BusHandler->BusAddresses,
                                         Interrupt,
                                         pResourceList);
#else
    DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n");
    Status = STATUS_SUCCESS;
#endif

    /* Return to caller */
    ExFreePool(Interrupt);
    return Status;
}
Beispiel #2
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;
}