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; }
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; }