// // update interrupt line [checked] // VOID PciUpdateInterruptLine(__in PDEVICE_OBJECT Pdo,__in UCHAR LineRegister) { PAGED_CODE(); PPCI_LEGACY_DEVICE_INFO Info = CONTAINING_RECORD(PciLegacyDeviceHead.Next,PCI_LEGACY_DEVICE_INFO,ListEntry); PPCI_PDO_EXTENSION PdoExt = static_cast<PPCI_PDO_EXTENSION>(Pdo->DeviceExtension); while(Info) { if(Info->OwnerDevice == Pdo) { PdoExt = Info->PdoExt; break; } Info = CONTAINING_RECORD(Info->ListEntry.Next,PCI_LEGACY_DEVICE_INFO,ListEntry); } ASSERT(PdoExt->Common.ExtensionType == PciPdoExtensionType); // // set raw/adjusted interrupt line // PdoExt->AdjustedInterruptLine = LineRegister; PdoExt->RawInterruptLine = LineRegister; // // and program hardware // PciWriteDeviceConfig(PdoExt,&LineRegister,FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.InterruptLine),sizeof(LineRegister)); // // update registry data // PCI_COMMON_HEADER BiosConfig; NTSTATUS Status = PciGetBiosConfig(PdoExt,&BiosConfig); ASSERT(NT_SUCCESS(Status)); if(BiosConfig.u.type0.InterruptLine != LineRegister) { Status = PciSaveBiosConfig(PdoExt,&BiosConfig); ASSERT(NT_SUCCESS(Status)); } }
VOID NTAPI PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context) { NTSTATUS Status; PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor; PIO_RESOURCE_DESCRIPTOR IoDescriptor; PPCI_FUNCTION_RESOURCES Resources; PCI_COMMON_HEADER BiosData; PPCI_COMMON_HEADER Current; PPCI_COMMON_CONFIG SavedConfig; ULONG i, Bar, BarMask; PULONG BarArray; PHYSICAL_ADDRESS Limit, Base, Length; BOOLEAN HaveIoLimit, CheckAlignment; PPCI_PDO_EXTENSION PdoExtension; /* Get the pointers from the extension */ PdoExtension = Context->PdoExtension; Resources = PdoExtension->Resources; Current = Context->Current; /* Check if decodes are disabled */ if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) { /* Well, we're going to need them from somewhere, use the registry data */ Status = PciGetBiosConfig(PdoExtension, &BiosData); if (NT_SUCCESS(Status)) Current = &BiosData; } /* Scan all current and limit descriptors for each BAR needed */ BarArray = Current->u.type1.BaseAddresses; for (i = 0; i < 6; i++) { /* Get the current resource descriptor, and the limit requirement */ CmDescriptor = &Resources->Current[i]; IoDescriptor = &Resources->Limit[i]; /* Copy descriptor data, skipping null descriptors */ CmDescriptor->Type = IoDescriptor->Type; if (CmDescriptor->Type == CmResourceTypeNull) continue; CmDescriptor->Flags = IoDescriptor->Flags; CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition; /* Initialize the high-parts to zero, since most stuff is 32-bit only */ Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0; /* Check if we're handling PCI BARs, or the ROM BAR */ if ((i < PCI_TYPE1_ADDRESSES) || (i == 5)) { /* Is this the ROM BAR? */ if (i == 5) { /* Read the correct bar, with the appropriate mask */ Bar = Current->u.type1.ROMBaseAddress; BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK; /* Decode the base address, and write down the length */ Base.LowPart = Bar & BarMask; DPRINT1("ROM BAR Base: %lx\n", Base.LowPart); CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length; } else { /* Otherwise, get the BAR from the array */ Bar = BarArray[i]; /* Is this an I/O BAR? */ if (Bar & PCI_ADDRESS_IO_SPACE) { /* Set the correct mask */ ASSERT(CmDescriptor->Type == CmResourceTypePort); BarMask = PCI_ADDRESS_IO_ADDRESS_MASK; } else { /* This is a memory BAR, set the correct base */ ASSERT(CmDescriptor->Type == CmResourceTypeMemory); BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK; /* IS this a 64-bit BAR? */ if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) { /* Read the next 32-bits as well, ie, the next BAR */ Base.HighPart = BarArray[i + 1]; } } /* Decode the base address, and write down the length */ Base.LowPart = Bar & BarMask; DPRINT1("BAR Base: %lx\n", Base.LowPart); CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length; } } else { /* Reset loop conditions */ HaveIoLimit = FALSE; CheckAlignment = FALSE; /* Check which descriptor is being parsed */ if (i == 2) { /* I/O Port Requirements */ Base.LowPart = PciBridgeIoBase(Current); Limit.LowPart = PciBridgeIoLimit(Current); DPRINT1("Bridge I/O Base and Limit: %lx %lx\n", Base.LowPart, Limit.LowPart); /* Do we have any I/O Port data? */ if (!(Base.LowPart) && (Current->u.type1.IOLimit)) { /* There's a limit */ HaveIoLimit = TRUE; } } else if (i == 3) { /* Memory requirements */ Base.LowPart = PciBridgeMemoryBase(Current); Limit.LowPart = PciBridgeMemoryLimit(Current); /* These should always be there, so check their alignment */ DPRINT1("Bridge MEM Base and Limit: %lx %lx\n", Base.LowPart, Limit.LowPart); CheckAlignment = TRUE; } else if (i == 4) { /* This should only be present for prefetch memory */ ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE); Base = PciBridgePrefetchMemoryBase(Current); Limit = PciBridgePrefetchMemoryLimit(Current); /* If it's there, check the alignment */ DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base, Limit); CheckAlignment = TRUE; } /* Check for invalid base address */ if (Base.QuadPart >= Limit.QuadPart) { /* Assume the descriptor is bogus */ CmDescriptor->Type = CmResourceTypeNull; IoDescriptor->Type = CmResourceTypeNull; continue; } /* Check if there's no memory, and no I/O port either */ if (!(Base.LowPart) && !(HaveIoLimit)) { /* This seems like a bogus requirement, ignore it */ CmDescriptor->Type = CmResourceTypeNull; continue; } /* Set the length to be the limit - the base; should always be 32-bit */ Length.QuadPart = Limit.LowPart - Base.LowPart + 1; ASSERT(Length.HighPart == 0); CmDescriptor->u.Generic.Length = Length.LowPart; /* Check if alignment should be set */ if (CheckAlignment) { /* Compute the required alignment for this length */ ASSERT(CmDescriptor->u.Memory.Length > 0); IoDescriptor->u.Memory.Alignment = PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length); } } /* Now set the base address */ CmDescriptor->u.Generic.Start.LowPart = Base.LowPart; } /* Save PCI settings into the PDO extension for easy access later */ PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus; PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus; PdoExtension->Dependent.type1.SubordinateBus = Current->u.type1.SubordinateBus; /* Check for subtractive decode bridges */ if (PdoExtension->Dependent.type1.SubtractiveDecode) { /* Check if legacy VGA decodes are enabled */ DPRINT1("Subtractive decode bridge\n"); if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) { /* Save this setting for later */ DPRINT1("VGA Bridge\n"); PdoExtension->Dependent.type1.VgaBitSet = TRUE; } /* Legacy ISA decoding is not compatible with subtractive decode */ ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE); } else { /* Check if legacy VGA decodes are enabled */ if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) { /* Save this setting for later */ DPRINT1("VGA Bridge\n"); PdoExtension->Dependent.type1.VgaBitSet = TRUE; /* And on positive decode, we'll also need extra resources locked */ PdoExtension->AdditionalResourceCount = 4; } /* Check if legacy ISA decoding is enabled */ if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA) { /* Save this setting for later */ DPRINT1("ISA Bridge\n"); PdoExtension->Dependent.type1.IsaBitSet = TRUE; } } /* * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810, * i820, i840, i845 Chipsets) that have subtractive decode broken. */ if (((PdoExtension->VendorId == 0x8086) && ((PdoExtension->DeviceId == 0x2418) || (PdoExtension->DeviceId == 0x2428) || (PdoExtension->DeviceId == 0x244E) || (PdoExtension->DeviceId == 0x2448))) || (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE)) { /* Check if subtractive decode is actually enabled */ if (PdoExtension->Dependent.type1.SubtractiveDecode) { /* We're going to need a copy of the configuration for later use */ DPRINT1("apply config save hack to ICH subtractive decode\n"); SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH, 'PciP'); PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig; if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH); } } }