Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenppbridge.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
1.7.6.1
|