Author: evb Date: Tue Jul 27 03:24:24 2010 New Revision: 48298
URL: http://svn.reactos.org/svn/reactos?rev=48298&view=rev Log: Add all pci bridge control function (PciBridgeIoBase, PciBridgeIoLimit, PciBridgeMemoryBase, PciBridgeMemoryLimit, PciBridgePrefetchMemoryBase, PciBridgePrefetchMemoryLimit, PciBridgeMemoryWorstCasealignment, PciBridgeIsPositiveDecode, PciBridgeIsSubtractiveDecode) More support ICH0/1/2/3/4 hub Add all PCI2PCI bridge limit/current resource codes (PPBridge_*), now is BAR setup okay, and Device_* must be implement Support ISA+VGA legacy decode, 20+64-bit decode, ROM BAR, prefetch BAR
Modified: trunk/reactos/drivers/bus/pcix/pci.h trunk/reactos/drivers/bus/pcix/pci/ppbridge.c trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/pci.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev=... ============================================================================== --- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original) +++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Tue Jul 27 03:24:24 2010 @@ -1072,6 +1072,14 @@
BOOLEAN NTAPI +PciCreateIoDescriptorFromBarLimit( + PIO_RESOURCE_DESCRIPTOR ResourceDescriptor, + IN PULONG BarArray, + IN BOOLEAN Rom +); + +BOOLEAN +NTAPI PciIsSlotPresentInParentMethod( IN PPCI_PDO_EXTENSION PdoExtension, IN ULONG Method
Modified: trunk/reactos/drivers/bus/pcix/pci/ppbridge.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci/ppbrid... ============================================================================== --- trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] (original) +++ trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] Tue Jul 27 03:24:24 2010 @@ -16,36 +16,612 @@
/* FUNCTIONS ******************************************************************/
+ULONG +NTAPI +PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData) +{ + BOOLEAN Is32Bit; + ULONG Base, IoBase; + ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); + + /* Get the base */ + Base = PciData->u.type1.IOLimit; + + /* Low bit specifies 32-bit address, top bits specify the base */ + Is32Bit = (Base & 0xF) == 1; + IoBase = (Base & 0xF0) << 8; + + /* Is it 32-bit? */ + if (Is32Bit) + { + /* Read the upper 16-bits from the other register */ + IoBase |= PciData->u.type1.IOBaseUpper16 << 16; + ASSERT(PciData->u.type1.IOLimit & 0x1); + } + + /* Return the base address */ + return IoBase; +} + +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; +} + +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); +} + +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; +} + +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; +} + +PHYSICAL_ADDRESS +NTAPI +PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData) +{ + BOOLEAN Is64Bit; + LARGE_INTEGER Limit; + USHORT PrefetchLimit; + ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); + + /* Get the base */ + PrefetchLimit = PciData->u.type1.PrefetchLimit; + + /* Low bit specifies 64-bit address, top bits specify the limit */ + Is64Bit = (PrefetchLimit & 0xF) == 1; + Limit.LowPart = (PrefetchLimit << 16) | 0xFFFFF; + + /* Is it 64-bit? */ + if (Is64Bit) + { + /* Read the upper 32-bits from the other register */ + Limit.HighPart = PciData->u.type1.PrefetchLimitUpper32; + } + + /* Return the limit */ + return Limit; +} + +ULONG +NTAPI +PciBridgeMemoryWorstCaseAlignment(IN ULONG Length) +{ + ULONG Alignment; + ASSERT(Length != 0); + + /* Start with highest alignment (2^31) */ + Alignment = 0x80000000; + + /* Keep dividing until we reach the correct power of two */ + while (!(Length & Alignment)) Alignment >>= 1; + + /* Return the alignment */ + return Alignment; +} + +BOOLEAN +NTAPI +PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension) +{ + /* Undocumented ACPI Method PDEC to get positive decode settings */ + return PciIsSlotPresentInParentMethod(PdoExtension, 'CEDP'); +} + +BOOLEAN +NTAPI +PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context) +{ + PPCI_COMMON_HEADER Current, PciData; + PPCI_PDO_EXTENSION PdoExtension; + + /* Get pointers from context */ + Current = Context->Current; + PciData = Context->PciData; + PdoExtension = Context->PdoExtension; + + /* Only valid for PCI-to-PCI bridges */ + ASSERT((Current->BaseClass == PCI_CLASS_BRIDGE_DEV) && + (Current->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)); + + /* Check for hacks first, then check the ProgIf of the bridge */ + if (!(PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE) && + (Current->ProgIf != 1) && + ((PciData->u.type1.IOLimit & 0xF0) == 0xF0)) + { + /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */ + DPRINT("Subtractive decode does not seem to be enabled\n"); + return FALSE; + } + + /* + * 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 the ACPI BIOS says positive decode should be enabled */ + if (PciBridgeIsPositiveDecode(PdoExtension)) + { + /* Obey ACPI */ + DPRINT1("Putting bridge in positive decode because of PDEC\n"); + return FALSE; + } + } + + /* If we found subtractive decode, we'll need a resource update later */ + DPRINT1("PCI : Subtractive decode on 0x%x\n", Current->u.type1.SecondaryBus); + PdoExtension->UpdateHardware = TRUE; + return TRUE; +} + VOID NTAPI PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context) { - UNIMPLEMENTED; - while (TRUE); + 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); + } + } }
VOID NTAPI PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context) { - UNIMPLEMENTED; - while (TRUE); + PIO_RESOURCE_DESCRIPTOR Limit; + PULONG BarArray; + PHYSICAL_ADDRESS MemoryLimit; + ULONG i; + PPCI_COMMON_HEADER Working; + PPCI_PDO_EXTENSION PdoExtension; + + /* Get the pointers from the context */ + Working = Context->PciData; + PdoExtension = Context->PdoExtension; + + /* Scan the BARs into the limit descriptors */ + BarArray = Working->u.type1.BaseAddresses; + Limit = PdoExtension->Resources->Limit; + + /* First of all, loop all the BARs */ + for (i = 0; i < PCI_TYPE1_ADDRESSES; i++) + { + /* Create a descriptor for their limits */ + if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE)) + { + /* This was a 64-bit descriptor, make sure there's space */ + ASSERT((i + 1) < PCI_TYPE1_ADDRESSES); + + /* Skip the next descriptor since this one is double sized */ + i++; + (&Limit[i])->Type == CmResourceTypeNull; + } + } + + /* Check if this is a subtractive decode bridge */ + if (PciBridgeIsSubtractiveDecode(Context)) + { + /* This bridge is subtractive */ + PdoExtension->Dependent.type1.SubtractiveDecode = TRUE; + + /* Subtractive bridges cannot use legacy ISA or VGA functionality */ + PdoExtension->Dependent.type1.IsaBitSet = FALSE; + PdoExtension->Dependent.type1.VgaBitSet = FALSE; + } + + /* For normal decode bridges, we'll need to find the bridge limits too */ + if (!PdoExtension->Dependent.type1.SubtractiveDecode) + { + /* Loop the descriptors that are left, to store the bridge limits */ + for (i = PCI_TYPE1_ADDRESSES; i < 5; i++) + { + /* No 64-bit memory addresses, and set the address to 0 to begin */ + MemoryLimit.HighPart = 0; + (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; + + /* Are we getting the I/O limit? */ + if (i == 2) + { + /* There should be one, get it */ + ASSERT(Working->u.type1.IOLimit != 0); + ASSERT((Working->u.type1.IOLimit & 0x0E) == 0); + MemoryLimit.LowPart = PciBridgeIoLimit(Working); + + /* Build a descriptor for this limit */ + (&Limit[i])->Type = CmResourceTypePort; + (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE | + CM_RESOURCE_PORT_POSITIVE_DECODE; + (&Limit[i])->u.Port.Alignment = 0x1000; + (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; + (&Limit[i])->u.Port.MaximumAddress = MemoryLimit; + (&Limit[i])->u.Port.Length = 0; + } + else if (i == 3) + { + /* There should be a valid memory limit, get it */ + ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0); + MemoryLimit.LowPart = PciBridgeMemoryLimit(Working); + + /* Build the descriptor for it */ + (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + (&Limit[i])->Type = CmResourceTypeMemory; + (&Limit[i])->u.Memory.Alignment = 0x100000; + (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; + (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; + (&Limit[i])->u.Memory.Length = 0; + } + else if (Working->u.type1.PrefetchLimit) + { + /* Get the prefetch memory limit, if there is one */ + MemoryLimit = PciBridgePrefetchMemoryLimit(Working); + + /* Write out the descriptor for it */ + (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE; + (&Limit[i])->Type = CmResourceTypeMemory; + (&Limit[i])->u.Memory.Alignment = 0x100000; + (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; + (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; + (&Limit[i])->u.Memory.Length = 0; + } + else + { + /* Blank descriptor */ + (&Limit[i])->Type = CmResourceTypeNull; + } + } + } + + /* Does the ROM have its own BAR? */ + if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) + { + /* Build a limit for it as well */ + PciCreateIoDescriptorFromBarLimit(&Limit[i], + &Working->u.type1.ROMBaseAddress, + TRUE); + } }
VOID NTAPI PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context) { - UNIMPLEMENTED; - while (TRUE); + PPCI_COMMON_HEADER PciData, Current; + + /* Get pointers from context */ + PciData = Context->PciData; + Current = Context->Current; + + /* + * Write FFh everywhere so that the PCI bridge ignores what it can't handle. + * Based on the bits that were ignored (still 0), this is how we can tell + * what the limit is. + */ + RtlFillMemory(PciData->u.type1.BaseAddresses, + FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr) - + FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BaseAddresses), + 0xFF); + + /* Copy the saved settings from the current context into the PCI header */ + PciData->u.type1.PrimaryBus = Current->u.type1.PrimaryBus; + PciData->u.type1.SecondaryBus = Current->u.type1.SecondaryBus; + PciData->u.type1.SubordinateBus = Current->u.type1.SubordinateBus; + PciData->u.type1.SecondaryLatency = Current->u.type1.SecondaryLatency; + + /* No I/O limit or base. The bottom base bit specifies that FIXME */ + PciData->u.type1.IOBaseUpper16 = 0xFFFE; + PciData->u.type1.IOLimitUpper16 = 0xFFFF; + + /* Save secondary status before it gets cleared */ + Context->SecondaryStatus = Current->u.type1.SecondaryStatus; + + /* Clear secondary status */ + Current->u.type1.SecondaryStatus = 0; + PciData->u.type1.SecondaryStatus = 0; }
VOID NTAPI PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context) { - UNIMPLEMENTED; - while (TRUE); + /* Copy back the secondary status register */ + Context->Current->u.type1.SecondaryStatus = Context->SecondaryStatus; }
VOID @@ -54,24 +630,56 @@ IN PPCI_COMMON_HEADER PciData, IN PIO_RESOURCE_DESCRIPTOR IoDescriptor) { + /* Does this bridge have VGA decodes on it? */ + if (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) + { + /* Build a private descriptor with 3 entries */ + IoDescriptor->Type = CmResourceTypeDevicePrivate; + IoDescriptor->u.DevicePrivate.Data[0] = 3; + IoDescriptor->u.DevicePrivate.Data[1] = 3; + + /* First, the VGA range at 0xA0000 */ + IoDescriptor[1].Type = CmResourceTypeMemory; + IoDescriptor[1].Flags = CM_RESOURCE_MEMORY_READ_WRITE; + IoDescriptor[1].u.Port.Length = 0x20000; + IoDescriptor[1].u.Port.Alignment = 1; + IoDescriptor[1].u.Port.MinimumAddress.QuadPart = 0xA0000; + IoDescriptor[1].u.Port.MaximumAddress.QuadPart = 0xBFFFF; + + /* Then, the VGA registers at 0x3B0 */ + IoDescriptor[2].Type = CmResourceTypePort; + IoDescriptor[2].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | + CM_RESOURCE_PORT_10_BIT_DECODE; + IoDescriptor[2].u.Port.Length = 12; + IoDescriptor[2].u.Port.Alignment = 1; + IoDescriptor[2].u.Port.MinimumAddress.QuadPart = 0x3B0; + IoDescriptor[2].u.Port.MaximumAddress.QuadPart = 0x3BB; + + /* And finally the VGA registers at 0x3C0 */ + IoDescriptor[3].Type = CmResourceTypePort; + IoDescriptor[3].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | + CM_RESOURCE_PORT_10_BIT_DECODE; + IoDescriptor[3].u.Port.Length = 32; + IoDescriptor[3].u.Port.Alignment = 1; + IoDescriptor[3].u.Port.MinimumAddress.QuadPart = 0x3C0; + IoDescriptor[3].u.Port.MaximumAddress.QuadPart = 0x3DF; + } +} + +VOID +NTAPI +PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context) +{ UNIMPLEMENTED; while (TRUE); }
VOID NTAPI -PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context) +PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context) { UNIMPLEMENTED; while (TRUE); }
-VOID -NTAPI -PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context) -{ - UNIMPLEMENTED; - while (TRUE); -} - /* EOF */
Modified: trunk/reactos/drivers/bus/pcix/utils.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?re... ============================================================================== --- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original) +++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Tue Jul 27 03:24:24 2010 @@ -1130,6 +1130,115 @@ return FoundSlot; }
+ULONG +NTAPI +PciGetLengthFromBar(IN ULONG Bar) +{ + ULONG Length; + + /* I/O addresses vs. memory addresses start differently due to alignment */ + Length = 1 << ((Bar & PCI_ADDRESS_IO_SPACE) ? 2 : 4); + + /* Keep going until a set bit */ + while (!(Length & Bar) && (Length)) Length <<= 1; + + /* Return the length (might be 0 on 64-bit because it's the low-word) */ + if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) != PCI_TYPE_64BIT) ASSERT(Length); + return Length; +} + +BOOLEAN +NTAPI +PciCreateIoDescriptorFromBarLimit(PIO_RESOURCE_DESCRIPTOR ResourceDescriptor, + IN PULONG BarArray, + IN BOOLEAN Rom) +{ + ULONG CurrentBar, BarLength, BarMask; + BOOLEAN Is64BitBar = FALSE; + + /* Check if the BAR is nor I/O nor memory */ + CurrentBar = BarArray[0]; + if (!(CurrentBar & ~PCI_ADDRESS_IO_SPACE)) + { + /* Fail this descriptor */ + ResourceDescriptor->Type = CmResourceTypeNull; + return FALSE; + } + + /* Set default flag and clear high words */ + ResourceDescriptor->Flags = 0; + ResourceDescriptor->u.Generic.MaximumAddress.HighPart = 0; + ResourceDescriptor->u.Generic.MinimumAddress.LowPart = 0; + ResourceDescriptor->u.Generic.MinimumAddress.HighPart = 0; + + /* Check for ROM Address */ + if (Rom) + { + /* Clean up the BAR to get just the address */ + CurrentBar &= PCI_ADDRESS_ROM_ADDRESS_MASK; + if (!CurrentBar) + { + /* Invalid ar, fail this descriptor */ + ResourceDescriptor->Type = CmResourceTypeNull; + return FALSE; + } + + /* ROM Addresses are always read only */ + ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + } + + /* Compute the length, assume it's the alignment for now */ + BarLength = PciGetLengthFromBar(CurrentBar); + ResourceDescriptor->u.Generic.Length = BarLength; + ResourceDescriptor->u.Generic.Alignment = BarLength; + + /* Check what kind of BAR this is */ + if (CurrentBar & PCI_ADDRESS_IO_SPACE) + { + /* Use correct mask to decode the address */ + BarMask = PCI_ADDRESS_IO_ADDRESS_MASK; + + /* Set this as an I/O Port descriptor */ + ResourceDescriptor->Type = CmResourceTypePort; + ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO; + } + else + { + /* Use correct mask to decode the address */ + BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK; + + /* Set this as a memory descriptor */ + ResourceDescriptor->Type = CmResourceTypeMemory; + + /* Check if it's 64-bit or 20-bit decode */ + if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) + { + /* The next BAR has the high word, read it */ + ResourceDescriptor->u.Port.MaximumAddress.HighPart = BarArray[1]; + Is64BitBar = TRUE; + } + else if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT) + { + /* Use the correct mask to decode the address */ + BarMask = ~0xFFF0000F; + } + + /* Check if the BAR is listed as prefetchable memory */ + if (CurrentBar & PCI_ADDRESS_MEMORY_PREFETCHABLE) + { + /* Mark the descriptor in the same way */ + ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; + } + } + + /* Now write down the maximum address based on the base + length */ + ResourceDescriptor->u.Port.MaximumAddress.QuadPart = (CurrentBar & BarMask) + + BarLength - 1; + + /* Return if this is a 64-bit BAR, so the loop code knows to skip the next one */ + return Is64BitBar; +} + VOID NTAPI PciDecodeEnable(IN PPCI_PDO_EXTENSION PdoExtension,