ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ppbridge.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS PCI Bus Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            drivers/bus/pci/pci/ppbridge.c
00005  * PURPOSE:         PCI-to-PCI Bridge Support
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <pci.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 /* FUNCTIONS ******************************************************************/
00018 
00019 ULONG
00020 NTAPI
00021 PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData)
00022 {
00023     BOOLEAN Is32Bit;
00024     ULONG Base, IoBase;
00025     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00026 
00027     /* Get the base */
00028     Base = PciData->u.type1.IOLimit;
00029 
00030     /* Low bit specifies 32-bit address, top bits specify the base */
00031     Is32Bit = (Base & 0xF) == 1;
00032     IoBase = (Base & 0xF0) << 8;
00033 
00034     /* Is it 32-bit? */
00035     if (Is32Bit)
00036     {
00037         /* Read the upper 16-bits from the other register */
00038         IoBase |= PciData->u.type1.IOBaseUpper16 << 16;
00039         ASSERT(PciData->u.type1.IOLimit & 0x1);
00040     }
00041 
00042     /* Return the base address */
00043     return IoBase;
00044 }
00045 
00046 ULONG
00047 NTAPI
00048 PciBridgeIoLimit(IN PPCI_COMMON_HEADER PciData)
00049 {
00050     BOOLEAN Is32Bit;
00051     ULONG Limit, IoLimit;
00052     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00053 
00054     /* Get the limit */
00055     Limit = PciData->u.type1.IOLimit;
00056 
00057     /* Low bit specifies 32-bit address, top bits specify the limit */
00058     Is32Bit = (Limit & 0xF) == 1;
00059     IoLimit = (Limit & 0xF0) << 8;
00060 
00061     /* Is it 32-bit? */
00062     if (Is32Bit)
00063     {
00064         /* Read the upper 16-bits from the other register */
00065         IoLimit |= PciData->u.type1.IOLimitUpper16 << 16;
00066         ASSERT(PciData->u.type1.IOBase & 0x1);
00067     }
00068 
00069     /* Return the I/O limit */
00070     return IoLimit | 0xFFF;
00071 }
00072 
00073 ULONG
00074 NTAPI
00075 PciBridgeMemoryBase(IN PPCI_COMMON_HEADER PciData)
00076 {
00077     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00078 
00079     /* Return the memory base */
00080     return (PciData->u.type1.MemoryBase << 16);
00081 }
00082 
00083 ULONG
00084 NTAPI
00085 PciBridgeMemoryLimit(IN PPCI_COMMON_HEADER PciData)
00086 {
00087     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00088 
00089     /* Return the memory limit */
00090     return (PciData->u.type1.MemoryLimit << 16) | 0xFFFFF;
00091 }
00092 
00093 PHYSICAL_ADDRESS
00094 NTAPI
00095 PciBridgePrefetchMemoryBase(IN PPCI_COMMON_HEADER PciData)
00096 {
00097     BOOLEAN Is64Bit;
00098     LARGE_INTEGER Base;
00099     USHORT PrefetchBase;
00100     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00101 
00102     /* Get the base */
00103     PrefetchBase = PciData->u.type1.PrefetchBase;
00104 
00105     /* Low bit specifies 64-bit address, top bits specify the base */
00106     Is64Bit = (PrefetchBase & 0xF) == 1;
00107     Base.LowPart = ((PrefetchBase & 0xFFF0) << 16);
00108 
00109     /* Is it 64-bit? */
00110     if (Is64Bit)
00111     {
00112         /* Read the upper 32-bits from the other register */
00113         Base.HighPart = PciData->u.type1.PrefetchBaseUpper32;
00114     }
00115 
00116     /* Return the base */
00117     return Base;
00118 }
00119 
00120 PHYSICAL_ADDRESS
00121 NTAPI
00122 PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData)
00123 {
00124     BOOLEAN Is64Bit;
00125     LARGE_INTEGER Limit;
00126     USHORT PrefetchLimit;
00127     ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
00128 
00129     /* Get the base */
00130     PrefetchLimit = PciData->u.type1.PrefetchLimit;
00131 
00132     /* Low bit specifies 64-bit address, top bits specify the limit */
00133     Is64Bit = (PrefetchLimit & 0xF) == 1;
00134     Limit.LowPart = (PrefetchLimit << 16) | 0xFFFFF;
00135 
00136     /* Is it 64-bit? */
00137     if (Is64Bit)
00138     {
00139         /* Read the upper 32-bits from the other register */
00140         Limit.HighPart = PciData->u.type1.PrefetchLimitUpper32;
00141     }
00142 
00143     /* Return the limit */
00144     return Limit;
00145 }
00146 
00147 ULONG
00148 NTAPI
00149 PciBridgeMemoryWorstCaseAlignment(IN ULONG Length)
00150 {
00151     ULONG Alignment;
00152     ASSERT(Length != 0);
00153 
00154     /* Start with highest alignment (2^31) */
00155     Alignment = 0x80000000;
00156 
00157     /* Keep dividing until we reach the correct power of two */
00158     while (!(Length & Alignment)) Alignment >>= 1;
00159 
00160     /* Return the alignment */
00161     return Alignment;
00162 }
00163 
00164 BOOLEAN
00165 NTAPI
00166 PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension)
00167 {
00168     /* Undocumented ACPI Method PDEC to get positive decode settings */
00169     return PciIsSlotPresentInParentMethod(PdoExtension, 'CEDP');
00170 }
00171 
00172 BOOLEAN
00173 NTAPI
00174 PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context)
00175 {
00176     PPCI_COMMON_HEADER Current, PciData;
00177     PPCI_PDO_EXTENSION PdoExtension;
00178 
00179     /* Get pointers from context */
00180     Current = Context->Current;
00181     PciData = Context->PciData;
00182     PdoExtension = Context->PdoExtension;
00183 
00184     /* Only valid for PCI-to-PCI bridges */
00185     ASSERT((Current->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
00186            (Current->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));
00187 
00188     /* Check for hacks first, then check the ProgIf of the bridge */
00189     if (!(PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE) &&
00190          (Current->ProgIf != 1) &&
00191          ((PciData->u.type1.IOLimit & 0xF0) == 0xF0))
00192     {
00193         /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */
00194         DPRINT("Subtractive decode does not seem to be enabled\n");
00195         return FALSE;
00196     }
00197 
00198     /*
00199      * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
00200      * i820, i840, i845 Chipsets) that have subtractive decode broken.
00201      */
00202     if (((PdoExtension->VendorId == 0x8086) &&
00203          ((PdoExtension->DeviceId == 0x2418) ||
00204           (PdoExtension->DeviceId == 0x2428) ||
00205           (PdoExtension->DeviceId == 0x244E) ||
00206           (PdoExtension->DeviceId == 0x2448))) ||
00207         (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
00208     {
00209         /* Check if the ACPI BIOS says positive decode should be enabled */
00210         if (PciBridgeIsPositiveDecode(PdoExtension))
00211         {
00212             /* Obey ACPI */
00213             DPRINT1("Putting bridge in positive decode because of PDEC\n");
00214             return FALSE;
00215         }
00216     }
00217 
00218     /* If we found subtractive decode, we'll need a resource update later */
00219     DPRINT1("PCI : Subtractive decode on 0x%x\n", Current->u.type1.SecondaryBus);
00220     PdoExtension->UpdateHardware = TRUE;
00221     return TRUE;
00222 }
00223 
00224 VOID
00225 NTAPI
00226 PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
00227 {
00228     NTSTATUS Status;
00229     PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
00230     PIO_RESOURCE_DESCRIPTOR IoDescriptor;
00231     PPCI_FUNCTION_RESOURCES Resources;
00232     PCI_COMMON_HEADER BiosData;
00233     PPCI_COMMON_HEADER Current;
00234     PPCI_COMMON_CONFIG SavedConfig;
00235     ULONG i, Bar, BarMask;
00236     PULONG BarArray;
00237     PHYSICAL_ADDRESS Limit, Base, Length;
00238     BOOLEAN HaveIoLimit, CheckAlignment;
00239     PPCI_PDO_EXTENSION PdoExtension;
00240 
00241     /* Get the pointers from the extension */
00242     PdoExtension = Context->PdoExtension;
00243     Resources = PdoExtension->Resources;
00244     Current = Context->Current;
00245 
00246     /* Check if decodes are disabled */
00247     if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)))
00248     {
00249         /* Well, we're going to need them from somewhere, use the registry data */
00250         Status = PciGetBiosConfig(PdoExtension, &BiosData);
00251         if (NT_SUCCESS(Status)) Current = &BiosData;
00252     }
00253 
00254     /* Scan all current and limit descriptors for each BAR needed */
00255     BarArray = Current->u.type1.BaseAddresses;
00256     for (i = 0; i < 6; i++)
00257     {
00258         /* Get the current resource descriptor, and the limit requirement */
00259         CmDescriptor = &Resources->Current[i];
00260         IoDescriptor = &Resources->Limit[i];
00261 
00262         /* Copy descriptor data, skipping null descriptors */
00263         CmDescriptor->Type = IoDescriptor->Type;
00264         if (CmDescriptor->Type == CmResourceTypeNull) continue;
00265         CmDescriptor->Flags = IoDescriptor->Flags;
00266         CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
00267 
00268         /* Initialize the high-parts to zero, since most stuff is 32-bit only */
00269         Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0;
00270 
00271         /* Check if we're handling PCI BARs, or the ROM BAR */
00272         if ((i < PCI_TYPE1_ADDRESSES) || (i == 5))
00273         {
00274             /* Is this the ROM BAR? */
00275             if (i == 5)
00276             {
00277                 /* Read the correct bar, with the appropriate mask */
00278                 Bar = Current->u.type1.ROMBaseAddress;
00279                 BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK;
00280 
00281                 /* Decode the base address, and write down the length */
00282                 Base.LowPart = Bar & BarMask;
00283                 DPRINT1("ROM BAR Base: %lx\n", Base.LowPart);
00284                 CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
00285             }
00286             else
00287             {
00288                 /* Otherwise, get the BAR from the array */
00289                 Bar = BarArray[i];
00290 
00291                 /* Is this an I/O BAR? */
00292                 if (Bar & PCI_ADDRESS_IO_SPACE)
00293                 {
00294                     /* Set the correct mask */
00295                     ASSERT(CmDescriptor->Type == CmResourceTypePort);
00296                     BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
00297                 }
00298                 else
00299                 {
00300                     /* This is a memory BAR, set the correct base */
00301                     ASSERT(CmDescriptor->Type == CmResourceTypeMemory);
00302                     BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
00303 
00304                     /* IS this a 64-bit BAR? */
00305                     if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
00306                     {
00307                         /* Read the next 32-bits as well, ie, the next BAR */
00308                         Base.HighPart = BarArray[i + 1];
00309                     }
00310                 }
00311 
00312                 /* Decode the base address, and write down the length */
00313                 Base.LowPart = Bar & BarMask;
00314                 DPRINT1("BAR Base: %lx\n", Base.LowPart);
00315                 CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
00316             }
00317         }
00318         else
00319         {
00320             /* Reset loop conditions */
00321             HaveIoLimit = FALSE;
00322             CheckAlignment = FALSE;
00323 
00324             /* Check which descriptor is being parsed */
00325             if (i == 2)
00326             {
00327                 /* I/O Port Requirements */
00328                 Base.LowPart = PciBridgeIoBase(Current);
00329                 Limit.LowPart = PciBridgeIoLimit(Current);
00330                 DPRINT1("Bridge I/O Base and Limit: %lx %lx\n",
00331                          Base.LowPart, Limit.LowPart);
00332 
00333                 /* Do we have any I/O Port data? */
00334                 if (!(Base.LowPart) && (Current->u.type1.IOLimit))
00335                 {
00336                     /* There's a limit */
00337                     HaveIoLimit = TRUE;
00338                 }
00339             }
00340             else if (i == 3)
00341             {
00342                 /* Memory requirements */
00343                 Base.LowPart = PciBridgeMemoryBase(Current);
00344                 Limit.LowPart = PciBridgeMemoryLimit(Current);
00345 
00346                 /* These should always be there, so check their alignment */
00347                 DPRINT1("Bridge MEM Base and Limit: %lx %lx\n",
00348                          Base.LowPart, Limit.LowPart);
00349                 CheckAlignment = TRUE;
00350             }
00351             else if (i == 4)
00352             {
00353                 /* This should only be present for prefetch memory */
00354                 ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE);
00355                 Base = PciBridgePrefetchMemoryBase(Current);
00356                 Limit = PciBridgePrefetchMemoryLimit(Current);
00357 
00358                 /* If it's there, check the alignment */
00359                 DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base, Limit);
00360                 CheckAlignment = TRUE;
00361             }
00362 
00363             /* Check for invalid base address */
00364             if (Base.QuadPart >= Limit.QuadPart)
00365             {
00366                 /* Assume the descriptor is bogus */
00367                 CmDescriptor->Type = CmResourceTypeNull;
00368                 IoDescriptor->Type = CmResourceTypeNull;
00369                 continue;
00370             }
00371 
00372             /* Check if there's no memory, and no I/O port either */
00373             if (!(Base.LowPart) && !(HaveIoLimit))
00374             {
00375                 /* This seems like a bogus requirement, ignore it */
00376                 CmDescriptor->Type = CmResourceTypeNull;
00377                 continue;
00378             }
00379 
00380             /* Set the length to be the limit - the base; should always be 32-bit */
00381             Length.QuadPart = Limit.LowPart - Base.LowPart + 1;
00382             ASSERT(Length.HighPart == 0);
00383             CmDescriptor->u.Generic.Length = Length.LowPart;
00384 
00385             /* Check if alignment should be set */
00386             if (CheckAlignment)
00387             {
00388                 /* Compute the required alignment for this length */
00389                 ASSERT(CmDescriptor->u.Memory.Length > 0);
00390                 IoDescriptor->u.Memory.Alignment =
00391                     PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length);
00392             }
00393         }
00394 
00395         /* Now set the base address */
00396         CmDescriptor->u.Generic.Start.LowPart = Base.LowPart;
00397     }
00398 
00399     /* Save PCI settings into the PDO extension for easy access later */
00400     PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus;
00401     PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus;
00402     PdoExtension->Dependent.type1.SubordinateBus = Current->u.type1.SubordinateBus;
00403 
00404     /* Check for subtractive decode bridges */
00405     if (PdoExtension->Dependent.type1.SubtractiveDecode)
00406     {
00407         /* Check if legacy VGA decodes are enabled */
00408         DPRINT1("Subtractive decode bridge\n");
00409         if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
00410         {
00411             /* Save this setting for later */
00412             DPRINT1("VGA Bridge\n");
00413             PdoExtension->Dependent.type1.VgaBitSet = TRUE;
00414         }
00415 
00416         /* Legacy ISA decoding is not compatible with subtractive decode */
00417         ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE);
00418     }
00419     else
00420     {
00421         /* Check if legacy VGA decodes are enabled */
00422         if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
00423         {
00424             /* Save this setting for later */
00425             DPRINT1("VGA Bridge\n");
00426             PdoExtension->Dependent.type1.VgaBitSet = TRUE;
00427 
00428             /* And on positive decode, we'll also need extra resources locked */
00429             PdoExtension->AdditionalResourceCount = 4;
00430         }
00431 
00432         /* Check if legacy ISA decoding is enabled */
00433         if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA)
00434         {
00435             /* Save this setting for later */
00436             DPRINT1("ISA Bridge\n");
00437             PdoExtension->Dependent.type1.IsaBitSet = TRUE;
00438         }
00439     }
00440 
00441     /*
00442      * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
00443      * i820, i840, i845 Chipsets) that have subtractive decode broken.
00444      */
00445     if (((PdoExtension->VendorId == 0x8086) &&
00446          ((PdoExtension->DeviceId == 0x2418) ||
00447           (PdoExtension->DeviceId == 0x2428) ||
00448           (PdoExtension->DeviceId == 0x244E) ||
00449           (PdoExtension->DeviceId == 0x2448))) ||
00450         (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
00451     {
00452         /* Check if subtractive decode is actually enabled */
00453         if (PdoExtension->Dependent.type1.SubtractiveDecode)
00454         {
00455             /* We're going to need a copy of the configuration for later use */
00456             DPRINT1("apply config save hack to ICH subtractive decode\n");
00457             SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH, 'PciP');
00458             PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig;
00459             if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH);
00460         }
00461     }
00462 }
00463 
00464 VOID
00465 NTAPI
00466 PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
00467 {
00468     PIO_RESOURCE_DESCRIPTOR Limit;
00469     PULONG BarArray;
00470     PHYSICAL_ADDRESS MemoryLimit;
00471     ULONG i;
00472     PPCI_COMMON_HEADER Working;
00473     PPCI_PDO_EXTENSION PdoExtension;
00474 
00475     /* Get the pointers from the context */
00476     Working = Context->PciData;
00477     PdoExtension = Context->PdoExtension;
00478 
00479     /* Scan the BARs into the limit descriptors */
00480     BarArray = Working->u.type1.BaseAddresses;
00481     Limit = PdoExtension->Resources->Limit;
00482 
00483     /* First of all, loop all the BARs */
00484     for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
00485     {
00486         /* Create a descriptor for their limits */
00487         if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE))
00488         {
00489             /* This was a 64-bit descriptor, make sure there's space */
00490             ASSERT((i + 1) < PCI_TYPE1_ADDRESSES);
00491 
00492             /* Skip the next descriptor since this one is double sized */
00493             i++;
00494             Limit[i].Type = CmResourceTypeNull;
00495         }
00496     }
00497 
00498     /* Check if this is a subtractive decode bridge */
00499     if (PciBridgeIsSubtractiveDecode(Context))
00500     {
00501         /* This bridge is subtractive */
00502         PdoExtension->Dependent.type1.SubtractiveDecode = TRUE;
00503 
00504         /* Subtractive bridges cannot use legacy ISA or VGA functionality */
00505         PdoExtension->Dependent.type1.IsaBitSet = FALSE;
00506         PdoExtension->Dependent.type1.VgaBitSet = FALSE;
00507     }
00508 
00509     /* For normal decode bridges, we'll need to find the bridge limits too */
00510     if (!PdoExtension->Dependent.type1.SubtractiveDecode)
00511     {
00512         /* Loop the descriptors that are left, to store the bridge limits */
00513         for (i = PCI_TYPE1_ADDRESSES; i < 5; i++)
00514         {
00515             /* No 64-bit memory addresses, and set the address to 0 to begin */
00516             MemoryLimit.HighPart = 0;
00517             (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
00518 
00519             /* Are we getting the I/O limit? */
00520             if (i == 2)
00521             {
00522                 /* There should be one, get it */
00523                 ASSERT(Working->u.type1.IOLimit != 0);
00524                 ASSERT((Working->u.type1.IOLimit & 0x0E) == 0);
00525                 MemoryLimit.LowPart = PciBridgeIoLimit(Working);
00526 
00527                 /* Build a descriptor for this limit */
00528                 (&Limit[i])->Type = CmResourceTypePort;
00529                 (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE |
00530                                      CM_RESOURCE_PORT_POSITIVE_DECODE;
00531                 (&Limit[i])->u.Port.Alignment = 0x1000;
00532                 (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
00533                 (&Limit[i])->u.Port.MaximumAddress = MemoryLimit;
00534                 (&Limit[i])->u.Port.Length = 0;
00535             }
00536             else if (i == 3)
00537             {
00538                 /* There should be a valid memory limit, get it */
00539                 ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0);
00540                 MemoryLimit.LowPart = PciBridgeMemoryLimit(Working);
00541 
00542                 /* Build the descriptor for it */
00543                 (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00544                 (&Limit[i])->Type = CmResourceTypeMemory;
00545                 (&Limit[i])->u.Memory.Alignment = 0x100000;
00546                 (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
00547                 (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
00548                 (&Limit[i])->u.Memory.Length = 0;
00549             }
00550             else if (Working->u.type1.PrefetchLimit)
00551             {
00552                 /* Get the prefetch memory limit, if there is one */
00553                 MemoryLimit = PciBridgePrefetchMemoryLimit(Working);
00554 
00555                 /* Write out the descriptor for it */
00556                 (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE;
00557                 (&Limit[i])->Type = CmResourceTypeMemory;
00558                 (&Limit[i])->u.Memory.Alignment = 0x100000;
00559                 (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
00560                 (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
00561                 (&Limit[i])->u.Memory.Length = 0;
00562             }
00563             else
00564             {
00565                 /* Blank descriptor */
00566                 (&Limit[i])->Type = CmResourceTypeNull;
00567             }
00568         }
00569     }
00570 
00571     /* Does the ROM have its own BAR? */
00572     if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)
00573     {
00574         /* Build a limit for it as well */
00575         PciCreateIoDescriptorFromBarLimit(&Limit[i],
00576                                           &Working->u.type1.ROMBaseAddress,
00577                                           TRUE);
00578     }
00579 }
00580 
00581 VOID
00582 NTAPI
00583 PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context)
00584 {
00585     PPCI_COMMON_HEADER PciData, Current;
00586 
00587     /* Get pointers from context */
00588     PciData = Context->PciData;
00589     Current = Context->Current;
00590 
00591     /*
00592      * Write FFh everywhere so that the PCI bridge ignores what it can't handle.
00593      * Based on the bits that were ignored (still 0), this is how we can tell
00594      * what the limit is.
00595      */
00596     RtlFillMemory(PciData->u.type1.BaseAddresses,
00597                   FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr) -
00598                   FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BaseAddresses),
00599                   0xFF);
00600 
00601     /* Copy the saved settings from the current context into the PCI header */
00602     PciData->u.type1.PrimaryBus = Current->u.type1.PrimaryBus;
00603     PciData->u.type1.SecondaryBus = Current->u.type1.SecondaryBus;
00604     PciData->u.type1.SubordinateBus = Current->u.type1.SubordinateBus;
00605     PciData->u.type1.SecondaryLatency = Current->u.type1.SecondaryLatency;
00606 
00607     /* No I/O limit or base. The bottom base bit specifies that FIXME */
00608     PciData->u.type1.IOBaseUpper16 = 0xFFFE;
00609     PciData->u.type1.IOLimitUpper16 = 0xFFFF;
00610 
00611     /* Save secondary status before it gets cleared */
00612     Context->SecondaryStatus = Current->u.type1.SecondaryStatus;
00613 
00614     /* Clear secondary status */
00615     Current->u.type1.SecondaryStatus = 0;
00616     PciData->u.type1.SecondaryStatus = 0;
00617 }
00618 
00619 VOID
00620 NTAPI
00621 PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context)
00622 {
00623     /* Copy back the secondary status register */
00624     Context->Current->u.type1.SecondaryStatus = Context->SecondaryStatus;
00625 }
00626 
00627 VOID
00628 NTAPI
00629 PPBridge_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context,
00630                                           IN PPCI_COMMON_HEADER PciData,
00631                                           IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
00632 {
00633     /* Does this bridge have VGA decodes on it? */
00634     if (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
00635     {
00636         /* Build a private descriptor with 3 entries */
00637         IoDescriptor->Type = CmResourceTypeDevicePrivate;
00638         IoDescriptor->u.DevicePrivate.Data[0] = 3;
00639         IoDescriptor->u.DevicePrivate.Data[1] = 3;
00640 
00641         /* First, the VGA range at 0xA0000 */
00642         IoDescriptor[1].Type = CmResourceTypeMemory;
00643         IoDescriptor[1].Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00644         IoDescriptor[1].u.Port.Length = 0x20000;
00645         IoDescriptor[1].u.Port.Alignment = 1;
00646         IoDescriptor[1].u.Port.MinimumAddress.QuadPart = 0xA0000;
00647         IoDescriptor[1].u.Port.MaximumAddress.QuadPart = 0xBFFFF;
00648 
00649         /* Then, the VGA registers at 0x3B0 */
00650         IoDescriptor[2].Type = CmResourceTypePort;
00651         IoDescriptor[2].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
00652                                 CM_RESOURCE_PORT_10_BIT_DECODE;
00653         IoDescriptor[2].u.Port.Length = 12;
00654         IoDescriptor[2].u.Port.Alignment = 1;
00655         IoDescriptor[2].u.Port.MinimumAddress.QuadPart = 0x3B0;
00656         IoDescriptor[2].u.Port.MaximumAddress.QuadPart = 0x3BB;
00657 
00658         /* And finally the VGA registers at 0x3C0 */
00659         IoDescriptor[3].Type = CmResourceTypePort;
00660         IoDescriptor[3].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
00661                                 CM_RESOURCE_PORT_10_BIT_DECODE;
00662         IoDescriptor[3].u.Port.Length = 32;
00663         IoDescriptor[3].u.Port.Alignment = 1;
00664         IoDescriptor[3].u.Port.MinimumAddress.QuadPart = 0x3C0;
00665         IoDescriptor[3].u.Port.MaximumAddress.QuadPart = 0x3DF;
00666     }
00667 }
00668 
00669 VOID
00670 NTAPI
00671 PPBridge_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension,
00672                      IN PPCI_COMMON_HEADER PciData)
00673 {
00674     UNIMPLEMENTED;
00675     while (TRUE);
00676 }
00677 
00678 VOID
00679 NTAPI
00680 PPBridge_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension,
00681                                 IN PPCI_COMMON_HEADER PciData)
00682 {
00683     //BOOLEAN IoActive;
00684     PPCI_FDO_EXTENSION FdoExtension;
00685     PPCI_FUNCTION_RESOURCES PciResources;
00686     ULONG i;
00687 
00688     /* Check if I/O Decodes are enabled */
00689     //IoActive = (PciData->u.type1.IOBase & 0xF) == 1;
00690 
00691     /*
00692      * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
00693      * i820, i840, i845 Chipsets) that don't have subtractive decode broken.
00694      * If they do have broken subtractive support, or if they are not ICH bridges,
00695      * then check if the bridge supports substractive decode at all.
00696      */
00697     if ((((PdoExtension->VendorId == 0x8086) &&
00698          ((PdoExtension->DeviceId == 0x2418) ||
00699           (PdoExtension->DeviceId == 0x2428) ||
00700           (PdoExtension->DeviceId == 0x244E) ||
00701           (PdoExtension->DeviceId == 0x2448))) &&
00702          (!(PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE) ||
00703          (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE))) ||
00704         (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE))
00705     {
00706         /* No resources are needed on a subtractive decode bridge */
00707         PciData->u.type1.MemoryBase = 0xFFFF;
00708         PciData->u.type1.PrefetchBase = 0xFFFF;
00709         PciData->u.type1.IOBase = 0xFF;
00710         PciData->u.type1.IOLimit = 0;
00711         PciData->u.type1.MemoryLimit = 0;
00712         PciData->u.type1.PrefetchLimit = 0;
00713         PciData->u.type1.PrefetchBaseUpper32 = 0;
00714         PciData->u.type1.PrefetchLimitUpper32 = 0;
00715         PciData->u.type1.IOBaseUpper16 = 0;
00716         PciData->u.type1.IOLimitUpper16 = 0;
00717     }
00718     else
00719     {
00720         /*
00721          * Otherwise, get the FDO to read the old PCI configuration header that
00722          * had been saved by the hack in PPBridge_SaveCurrentSettings.
00723          */
00724         FdoExtension = PdoExtension->ParentFdoExtension;
00725         ASSERT(PdoExtension->Resources == NULL);
00726 
00727         /* Read the PCI header data and use that here */
00728         PciData->u.type1.IOBase = FdoExtension->PreservedConfig->u.type1.IOBase;
00729         PciData->u.type1.IOLimit = FdoExtension->PreservedConfig->u.type1.IOLimit;
00730         PciData->u.type1.MemoryBase = FdoExtension->PreservedConfig->u.type1.MemoryBase;
00731         PciData->u.type1.MemoryLimit = FdoExtension->PreservedConfig->u.type1.MemoryLimit;
00732         PciData->u.type1.PrefetchBase = FdoExtension->PreservedConfig->u.type1.PrefetchBase;
00733         PciData->u.type1.PrefetchLimit = FdoExtension->PreservedConfig->u.type1.PrefetchLimit;
00734         PciData->u.type1.PrefetchBaseUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchBaseUpper32;
00735         PciData->u.type1.PrefetchLimitUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchLimitUpper32;
00736         PciData->u.type1.IOBaseUpper16 = FdoExtension->PreservedConfig->u.type1.IOBaseUpper16;
00737         PciData->u.type1.IOLimitUpper16 = FdoExtension->PreservedConfig->u.type1.IOLimitUpper16;
00738     }
00739 
00740     /* Loop bus resources */
00741     PciResources = PdoExtension->Resources;
00742     if (PciResources)
00743     {
00744         /* Loop each resource type (the BARs, ROM BAR and Prefetch) */
00745         for (i = 0; i < 6; i++)
00746         {
00747             UNIMPLEMENTED;
00748         }
00749     }
00750 
00751     /* Copy the bus number data */
00752     PciData->u.type1.PrimaryBus = PdoExtension->Dependent.type1.PrimaryBus;
00753     PciData->u.type1.SecondaryBus = PdoExtension->Dependent.type1.SecondaryBus;
00754     PciData->u.type1.SubordinateBus = PdoExtension->Dependent.type1.SubordinateBus;
00755 
00756     /* Copy the decode flags */
00757     if (PdoExtension->Dependent.type1.IsaBitSet)
00758     {
00759         PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_ISA;
00760     }
00761 
00762     if (PdoExtension->Dependent.type1.VgaBitSet)
00763     {
00764         PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_VGA;
00765     }
00766 }
00767 
00768 /* EOF */

Generated on Thu May 24 2012 04:28:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.