1 /* 2 * PROJECT: ReactOS PCI Bus Driver 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: drivers/bus/pci/pci/ppbridge.c 5 * PURPOSE: PCI-to-PCI Bridge Support 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <pci.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS ******************************************************************/ 17 18 ULONG 19 NTAPI 20 PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData) 21 { 22 BOOLEAN Is32Bit; 23 ULONG Base, IoBase; 24 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 25 26 /* Get the base */ 27 Base = PciData->u.type1.IOLimit; 28 29 /* Low bit specifies 32-bit address, top bits specify the base */ 30 Is32Bit = (Base & 0xF) == 1; 31 IoBase = (Base & 0xF0) << 8; 32 33 /* Is it 32-bit? */ 34 if (Is32Bit) 35 { 36 /* Read the upper 16-bits from the other register */ 37 IoBase |= PciData->u.type1.IOBaseUpper16 << 16; 38 ASSERT(PciData->u.type1.IOLimit & 0x1); 39 } 40 41 /* Return the base address */ 42 return IoBase; 43 } 44 45 ULONG 46 NTAPI 47 PciBridgeIoLimit(IN PPCI_COMMON_HEADER PciData) 48 { 49 BOOLEAN Is32Bit; 50 ULONG Limit, IoLimit; 51 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 52 53 /* Get the limit */ 54 Limit = PciData->u.type1.IOLimit; 55 56 /* Low bit specifies 32-bit address, top bits specify the limit */ 57 Is32Bit = (Limit & 0xF) == 1; 58 IoLimit = (Limit & 0xF0) << 8; 59 60 /* Is it 32-bit? */ 61 if (Is32Bit) 62 { 63 /* Read the upper 16-bits from the other register */ 64 IoLimit |= PciData->u.type1.IOLimitUpper16 << 16; 65 ASSERT(PciData->u.type1.IOBase & 0x1); 66 } 67 68 /* Return the I/O limit */ 69 return IoLimit | 0xFFF; 70 } 71 72 ULONG 73 NTAPI 74 PciBridgeMemoryBase(IN PPCI_COMMON_HEADER PciData) 75 { 76 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 77 78 /* Return the memory base */ 79 return (PciData->u.type1.MemoryBase << 16); 80 } 81 82 ULONG 83 NTAPI 84 PciBridgeMemoryLimit(IN PPCI_COMMON_HEADER PciData) 85 { 86 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 87 88 /* Return the memory limit */ 89 return (PciData->u.type1.MemoryLimit << 16) | 0xFFFFF; 90 } 91 92 PHYSICAL_ADDRESS 93 NTAPI 94 PciBridgePrefetchMemoryBase(IN PPCI_COMMON_HEADER PciData) 95 { 96 BOOLEAN Is64Bit; 97 LARGE_INTEGER Base; 98 USHORT PrefetchBase; 99 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 100 101 /* Get the base */ 102 PrefetchBase = PciData->u.type1.PrefetchBase; 103 104 /* Low bit specifies 64-bit address, top bits specify the base */ 105 Is64Bit = (PrefetchBase & 0xF) == 1; 106 Base.LowPart = ((PrefetchBase & 0xFFF0) << 16); 107 108 /* Is it 64-bit? */ 109 if (Is64Bit) 110 { 111 /* Read the upper 32-bits from the other register */ 112 Base.HighPart = PciData->u.type1.PrefetchBaseUpper32; 113 } 114 115 /* Return the base */ 116 return Base; 117 } 118 119 PHYSICAL_ADDRESS 120 NTAPI 121 PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData) 122 { 123 BOOLEAN Is64Bit; 124 LARGE_INTEGER Limit; 125 USHORT PrefetchLimit; 126 ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE); 127 128 /* Get the base */ 129 PrefetchLimit = PciData->u.type1.PrefetchLimit; 130 131 /* Low bit specifies 64-bit address, top bits specify the limit */ 132 Is64Bit = (PrefetchLimit & 0xF) == 1; 133 Limit.LowPart = (PrefetchLimit << 16) | 0xFFFFF; 134 135 /* Is it 64-bit? */ 136 if (Is64Bit) 137 { 138 /* Read the upper 32-bits from the other register */ 139 Limit.HighPart = PciData->u.type1.PrefetchLimitUpper32; 140 } 141 142 /* Return the limit */ 143 return Limit; 144 } 145 146 ULONG 147 NTAPI 148 PciBridgeMemoryWorstCaseAlignment(IN ULONG Length) 149 { 150 ULONG Alignment; 151 ASSERT(Length != 0); 152 153 /* Start with highest alignment (2^31) */ 154 Alignment = 0x80000000; 155 156 /* Keep dividing until we reach the correct power of two */ 157 while (!(Length & Alignment)) Alignment >>= 1; 158 159 /* Return the alignment */ 160 return Alignment; 161 } 162 163 BOOLEAN 164 NTAPI 165 PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension) 166 { 167 /* Undocumented ACPI Method PDEC to get positive decode settings */ 168 return PciIsSlotPresentInParentMethod(PdoExtension, 'CEDP'); 169 } 170 171 BOOLEAN 172 NTAPI 173 PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context) 174 { 175 PPCI_COMMON_HEADER Current, PciData; 176 PPCI_PDO_EXTENSION PdoExtension; 177 178 /* Get pointers from context */ 179 Current = Context->Current; 180 PciData = Context->PciData; 181 PdoExtension = Context->PdoExtension; 182 183 /* Only valid for PCI-to-PCI bridges */ 184 ASSERT((Current->BaseClass == PCI_CLASS_BRIDGE_DEV) && 185 (Current->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)); 186 187 /* Check for hacks first, then check the ProgIf of the bridge */ 188 if (!(PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE) && 189 (Current->ProgIf != 1) && 190 ((PciData->u.type1.IOLimit & 0xF0) == 0xF0)) 191 { 192 /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */ 193 DPRINT("Subtractive decode does not seem to be enabled\n"); 194 return FALSE; 195 } 196 197 /* 198 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810, 199 * i820, i840, i845 Chipsets) that have subtractive decode broken. 200 */ 201 if (((PdoExtension->VendorId == 0x8086) && 202 ((PdoExtension->DeviceId == 0x2418) || 203 (PdoExtension->DeviceId == 0x2428) || 204 (PdoExtension->DeviceId == 0x244E) || 205 (PdoExtension->DeviceId == 0x2448))) || 206 (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE)) 207 { 208 /* Check if the ACPI BIOS says positive decode should be enabled */ 209 if (PciBridgeIsPositiveDecode(PdoExtension)) 210 { 211 /* Obey ACPI */ 212 DPRINT1("Putting bridge in positive decode because of PDEC\n"); 213 return FALSE; 214 } 215 } 216 217 /* If we found subtractive decode, we'll need a resource update later */ 218 DPRINT1("PCI : Subtractive decode on 0x%x\n", Current->u.type1.SecondaryBus); 219 PdoExtension->UpdateHardware = TRUE; 220 return TRUE; 221 } 222 223 VOID 224 NTAPI 225 PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context) 226 { 227 NTSTATUS Status; 228 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor; 229 PIO_RESOURCE_DESCRIPTOR IoDescriptor; 230 PPCI_FUNCTION_RESOURCES Resources; 231 PCI_COMMON_HEADER BiosData; 232 PPCI_COMMON_HEADER Current; 233 PPCI_COMMON_CONFIG SavedConfig; 234 ULONG i, Bar, BarMask; 235 PULONG BarArray; 236 PHYSICAL_ADDRESS Limit, Base, Length; 237 BOOLEAN HaveIoLimit, CheckAlignment; 238 PPCI_PDO_EXTENSION PdoExtension; 239 240 /* Get the pointers from the extension */ 241 PdoExtension = Context->PdoExtension; 242 Resources = PdoExtension->Resources; 243 Current = Context->Current; 244 245 /* Check if decodes are disabled */ 246 if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) 247 { 248 /* Well, we're going to need them from somewhere, use the registry data */ 249 Status = PciGetBiosConfig(PdoExtension, &BiosData); 250 if (NT_SUCCESS(Status)) Current = &BiosData; 251 } 252 253 /* Scan all current and limit descriptors for each BAR needed */ 254 BarArray = Current->u.type1.BaseAddresses; 255 for (i = 0; i < 6; i++) 256 { 257 /* Get the current resource descriptor, and the limit requirement */ 258 CmDescriptor = &Resources->Current[i]; 259 IoDescriptor = &Resources->Limit[i]; 260 261 /* Copy descriptor data, skipping null descriptors */ 262 CmDescriptor->Type = IoDescriptor->Type; 263 if (CmDescriptor->Type == CmResourceTypeNull) continue; 264 CmDescriptor->Flags = IoDescriptor->Flags; 265 CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition; 266 267 /* Initialize the high-parts to zero, since most stuff is 32-bit only */ 268 Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0; 269 270 /* Check if we're handling PCI BARs, or the ROM BAR */ 271 if ((i < PCI_TYPE1_ADDRESSES) || (i == 5)) 272 { 273 /* Is this the ROM BAR? */ 274 if (i == 5) 275 { 276 /* Read the correct bar, with the appropriate mask */ 277 Bar = Current->u.type1.ROMBaseAddress; 278 BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK; 279 280 /* Decode the base address, and write down the length */ 281 Base.LowPart = Bar & BarMask; 282 DPRINT1("ROM BAR Base: %lx\n", Base.LowPart); 283 CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length; 284 } 285 else 286 { 287 /* Otherwise, get the BAR from the array */ 288 Bar = BarArray[i]; 289 290 /* Is this an I/O BAR? */ 291 if (Bar & PCI_ADDRESS_IO_SPACE) 292 { 293 /* Set the correct mask */ 294 ASSERT(CmDescriptor->Type == CmResourceTypePort); 295 BarMask = PCI_ADDRESS_IO_ADDRESS_MASK; 296 } 297 else 298 { 299 /* This is a memory BAR, set the correct base */ 300 ASSERT(CmDescriptor->Type == CmResourceTypeMemory); 301 BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK; 302 303 /* IS this a 64-bit BAR? */ 304 if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) 305 { 306 /* Read the next 32-bits as well, ie, the next BAR */ 307 Base.HighPart = BarArray[i + 1]; 308 } 309 } 310 311 /* Decode the base address, and write down the length */ 312 Base.LowPart = Bar & BarMask; 313 DPRINT1("BAR Base: %lx\n", Base.LowPart); 314 CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length; 315 } 316 } 317 else 318 { 319 /* Reset loop conditions */ 320 HaveIoLimit = FALSE; 321 CheckAlignment = FALSE; 322 323 /* Check which descriptor is being parsed */ 324 if (i == 2) 325 { 326 /* I/O Port Requirements */ 327 Base.LowPart = PciBridgeIoBase(Current); 328 Limit.LowPart = PciBridgeIoLimit(Current); 329 DPRINT1("Bridge I/O Base and Limit: %lx %lx\n", 330 Base.LowPart, Limit.LowPart); 331 332 /* Do we have any I/O Port data? */ 333 if (!(Base.LowPart) && (Current->u.type1.IOLimit)) 334 { 335 /* There's a limit */ 336 HaveIoLimit = TRUE; 337 } 338 } 339 else if (i == 3) 340 { 341 /* Memory requirements */ 342 Base.LowPart = PciBridgeMemoryBase(Current); 343 Limit.LowPart = PciBridgeMemoryLimit(Current); 344 345 /* These should always be there, so check their alignment */ 346 DPRINT1("Bridge MEM Base and Limit: %lx %lx\n", 347 Base.LowPart, Limit.LowPart); 348 CheckAlignment = TRUE; 349 } 350 else if (i == 4) 351 { 352 /* This should only be present for prefetch memory */ 353 ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE); 354 Base = PciBridgePrefetchMemoryBase(Current); 355 Limit = PciBridgePrefetchMemoryLimit(Current); 356 357 /* If it's there, check the alignment */ 358 DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base, Limit); 359 CheckAlignment = TRUE; 360 } 361 362 /* Check for invalid base address */ 363 if (Base.QuadPart >= Limit.QuadPart) 364 { 365 /* Assume the descriptor is bogus */ 366 CmDescriptor->Type = CmResourceTypeNull; 367 IoDescriptor->Type = CmResourceTypeNull; 368 continue; 369 } 370 371 /* Check if there's no memory, and no I/O port either */ 372 if (!(Base.LowPart) && !(HaveIoLimit)) 373 { 374 /* This seems like a bogus requirement, ignore it */ 375 CmDescriptor->Type = CmResourceTypeNull; 376 continue; 377 } 378 379 /* Set the length to be the limit - the base; should always be 32-bit */ 380 Length.QuadPart = Limit.LowPart - Base.LowPart + 1; 381 ASSERT(Length.HighPart == 0); 382 CmDescriptor->u.Generic.Length = Length.LowPart; 383 384 /* Check if alignment should be set */ 385 if (CheckAlignment) 386 { 387 /* Compute the required alignment for this length */ 388 ASSERT(CmDescriptor->u.Memory.Length > 0); 389 IoDescriptor->u.Memory.Alignment = 390 PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length); 391 } 392 } 393 394 /* Now set the base address */ 395 CmDescriptor->u.Generic.Start.LowPart = Base.LowPart; 396 } 397 398 /* Save PCI settings into the PDO extension for easy access later */ 399 PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus; 400 PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus; 401 PdoExtension->Dependent.type1.SubordinateBus = Current->u.type1.SubordinateBus; 402 403 /* Check for subtractive decode bridges */ 404 if (PdoExtension->Dependent.type1.SubtractiveDecode) 405 { 406 /* Check if legacy VGA decodes are enabled */ 407 DPRINT1("Subtractive decode bridge\n"); 408 if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) 409 { 410 /* Save this setting for later */ 411 DPRINT1("VGA Bridge\n"); 412 PdoExtension->Dependent.type1.VgaBitSet = TRUE; 413 } 414 415 /* Legacy ISA decoding is not compatible with subtractive decode */ 416 ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE); 417 } 418 else 419 { 420 /* Check if legacy VGA decodes are enabled */ 421 if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) 422 { 423 /* Save this setting for later */ 424 DPRINT1("VGA Bridge\n"); 425 PdoExtension->Dependent.type1.VgaBitSet = TRUE; 426 427 /* And on positive decode, we'll also need extra resources locked */ 428 PdoExtension->AdditionalResourceCount = 4; 429 } 430 431 /* Check if legacy ISA decoding is enabled */ 432 if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA) 433 { 434 /* Save this setting for later */ 435 DPRINT1("ISA Bridge\n"); 436 PdoExtension->Dependent.type1.IsaBitSet = TRUE; 437 } 438 } 439 440 /* 441 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810, 442 * i820, i840, i845 Chipsets) that have subtractive decode broken. 443 */ 444 if (((PdoExtension->VendorId == 0x8086) && 445 ((PdoExtension->DeviceId == 0x2418) || 446 (PdoExtension->DeviceId == 0x2428) || 447 (PdoExtension->DeviceId == 0x244E) || 448 (PdoExtension->DeviceId == 0x2448))) || 449 (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE)) 450 { 451 /* Check if subtractive decode is actually enabled */ 452 if (PdoExtension->Dependent.type1.SubtractiveDecode) 453 { 454 /* We're going to need a copy of the configuration for later use */ 455 DPRINT1("apply config save hack to ICH subtractive decode\n"); 456 SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH, 'PciP'); 457 PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig; 458 if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH); 459 } 460 } 461 } 462 463 VOID 464 NTAPI 465 PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context) 466 { 467 PIO_RESOURCE_DESCRIPTOR Limit; 468 PULONG BarArray; 469 PHYSICAL_ADDRESS MemoryLimit; 470 ULONG i; 471 PPCI_COMMON_HEADER Working; 472 PPCI_PDO_EXTENSION PdoExtension; 473 474 /* Get the pointers from the context */ 475 Working = Context->PciData; 476 PdoExtension = Context->PdoExtension; 477 478 /* Scan the BARs into the limit descriptors */ 479 BarArray = Working->u.type1.BaseAddresses; 480 Limit = PdoExtension->Resources->Limit; 481 482 /* First of all, loop all the BARs */ 483 for (i = 0; i < PCI_TYPE1_ADDRESSES; i++) 484 { 485 /* Create a descriptor for their limits */ 486 if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE)) 487 { 488 /* This was a 64-bit descriptor, make sure there's space */ 489 ASSERT((i + 1) < PCI_TYPE1_ADDRESSES); 490 491 /* Skip the next descriptor since this one is double sized */ 492 i++; 493 Limit[i].Type = CmResourceTypeNull; 494 } 495 } 496 497 /* Check if this is a subtractive decode bridge */ 498 if (PciBridgeIsSubtractiveDecode(Context)) 499 { 500 /* This bridge is subtractive */ 501 PdoExtension->Dependent.type1.SubtractiveDecode = TRUE; 502 503 /* Subtractive bridges cannot use legacy ISA or VGA functionality */ 504 PdoExtension->Dependent.type1.IsaBitSet = FALSE; 505 PdoExtension->Dependent.type1.VgaBitSet = FALSE; 506 } 507 508 /* For normal decode bridges, we'll need to find the bridge limits too */ 509 if (!PdoExtension->Dependent.type1.SubtractiveDecode) 510 { 511 /* Loop the descriptors that are left, to store the bridge limits */ 512 for (i = PCI_TYPE1_ADDRESSES; i < 5; i++) 513 { 514 /* No 64-bit memory addresses, and set the address to 0 to begin */ 515 MemoryLimit.HighPart = 0; 516 (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; 517 518 /* Are we getting the I/O limit? */ 519 if (i == 2) 520 { 521 /* There should be one, get it */ 522 ASSERT(Working->u.type1.IOLimit != 0); 523 ASSERT((Working->u.type1.IOLimit & 0x0E) == 0); 524 MemoryLimit.LowPart = PciBridgeIoLimit(Working); 525 526 /* Build a descriptor for this limit */ 527 (&Limit[i])->Type = CmResourceTypePort; 528 (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE | 529 CM_RESOURCE_PORT_POSITIVE_DECODE; 530 (&Limit[i])->u.Port.Alignment = 0x1000; 531 (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0; 532 (&Limit[i])->u.Port.MaximumAddress = MemoryLimit; 533 (&Limit[i])->u.Port.Length = 0; 534 } 535 else if (i == 3) 536 { 537 /* There should be a valid memory limit, get it */ 538 ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0); 539 MemoryLimit.LowPart = PciBridgeMemoryLimit(Working); 540 541 /* Build the descriptor for it */ 542 (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE; 543 (&Limit[i])->Type = CmResourceTypeMemory; 544 (&Limit[i])->u.Memory.Alignment = 0x100000; 545 (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; 546 (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; 547 (&Limit[i])->u.Memory.Length = 0; 548 } 549 else if (Working->u.type1.PrefetchLimit) 550 { 551 /* Get the prefetch memory limit, if there is one */ 552 MemoryLimit = PciBridgePrefetchMemoryLimit(Working); 553 554 /* Write out the descriptor for it */ 555 (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE; 556 (&Limit[i])->Type = CmResourceTypeMemory; 557 (&Limit[i])->u.Memory.Alignment = 0x100000; 558 (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0; 559 (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit; 560 (&Limit[i])->u.Memory.Length = 0; 561 } 562 else 563 { 564 /* Blank descriptor */ 565 (&Limit[i])->Type = CmResourceTypeNull; 566 } 567 } 568 } 569 570 /* Does the ROM have its own BAR? */ 571 if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) 572 { 573 /* Build a limit for it as well */ 574 PciCreateIoDescriptorFromBarLimit(&Limit[i], 575 &Working->u.type1.ROMBaseAddress, 576 TRUE); 577 } 578 } 579 580 VOID 581 NTAPI 582 PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context) 583 { 584 PPCI_COMMON_HEADER PciData, Current; 585 586 /* Get pointers from context */ 587 PciData = Context->PciData; 588 Current = Context->Current; 589 590 /* 591 * Write FFh everywhere so that the PCI bridge ignores what it can't handle. 592 * Based on the bits that were ignored (still 0), this is how we can tell 593 * what the limit is. 594 */ 595 RtlFillMemory(PciData->u.type1.BaseAddresses, 596 FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr) - 597 FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BaseAddresses), 598 0xFF); 599 600 /* Copy the saved settings from the current context into the PCI header */ 601 PciData->u.type1.PrimaryBus = Current->u.type1.PrimaryBus; 602 PciData->u.type1.SecondaryBus = Current->u.type1.SecondaryBus; 603 PciData->u.type1.SubordinateBus = Current->u.type1.SubordinateBus; 604 PciData->u.type1.SecondaryLatency = Current->u.type1.SecondaryLatency; 605 606 /* No I/O limit or base. The bottom base bit specifies that FIXME */ 607 PciData->u.type1.IOBaseUpper16 = 0xFFFE; 608 PciData->u.type1.IOLimitUpper16 = 0xFFFF; 609 610 /* Save secondary status before it gets cleared */ 611 Context->SecondaryStatus = Current->u.type1.SecondaryStatus; 612 613 /* Clear secondary status */ 614 Current->u.type1.SecondaryStatus = 0; 615 PciData->u.type1.SecondaryStatus = 0; 616 } 617 618 VOID 619 NTAPI 620 PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context) 621 { 622 /* Copy back the secondary status register */ 623 Context->Current->u.type1.SecondaryStatus = Context->SecondaryStatus; 624 } 625 626 VOID 627 NTAPI 628 PPBridge_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context, 629 IN PPCI_COMMON_HEADER PciData, 630 IN PIO_RESOURCE_DESCRIPTOR IoDescriptor) 631 { 632 633 UNREFERENCED_PARAMETER(Context); 634 635 /* Does this bridge have VGA decodes on it? */ 636 if (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) 637 { 638 /* Build a private descriptor with 3 entries */ 639 IoDescriptor->Type = CmResourceTypeDevicePrivate; 640 IoDescriptor->u.DevicePrivate.Data[0] = 3; 641 IoDescriptor->u.DevicePrivate.Data[1] = 3; 642 643 /* First, the VGA range at 0xA0000 */ 644 IoDescriptor[1].Type = CmResourceTypeMemory; 645 IoDescriptor[1].Flags = CM_RESOURCE_MEMORY_READ_WRITE; 646 IoDescriptor[1].u.Port.Length = 0x20000; 647 IoDescriptor[1].u.Port.Alignment = 1; 648 IoDescriptor[1].u.Port.MinimumAddress.QuadPart = 0xA0000; 649 IoDescriptor[1].u.Port.MaximumAddress.QuadPart = 0xBFFFF; 650 651 /* Then, the VGA registers at 0x3B0 */ 652 IoDescriptor[2].Type = CmResourceTypePort; 653 IoDescriptor[2].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | 654 CM_RESOURCE_PORT_10_BIT_DECODE; 655 IoDescriptor[2].u.Port.Length = 12; 656 IoDescriptor[2].u.Port.Alignment = 1; 657 IoDescriptor[2].u.Port.MinimumAddress.QuadPart = 0x3B0; 658 IoDescriptor[2].u.Port.MaximumAddress.QuadPart = 0x3BB; 659 660 /* And finally the VGA registers at 0x3C0 */ 661 IoDescriptor[3].Type = CmResourceTypePort; 662 IoDescriptor[3].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | 663 CM_RESOURCE_PORT_10_BIT_DECODE; 664 IoDescriptor[3].u.Port.Length = 32; 665 IoDescriptor[3].u.Port.Alignment = 1; 666 IoDescriptor[3].u.Port.MinimumAddress.QuadPart = 0x3C0; 667 IoDescriptor[3].u.Port.MaximumAddress.QuadPart = 0x3DF; 668 } 669 } 670 671 VOID 672 NTAPI 673 PPBridge_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension, 674 IN PPCI_COMMON_HEADER PciData) 675 { 676 UNREFERENCED_PARAMETER(PdoExtension); 677 UNREFERENCED_PARAMETER(PciData); 678 UNIMPLEMENTED_DBGBREAK(); 679 } 680 681 VOID 682 NTAPI 683 PPBridge_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension, 684 IN PPCI_COMMON_HEADER PciData) 685 { 686 //BOOLEAN IoActive; 687 PPCI_FDO_EXTENSION FdoExtension; 688 PPCI_FUNCTION_RESOURCES PciResources; 689 ULONG i; 690 691 /* Check if I/O Decodes are enabled */ 692 //IoActive = (PciData->u.type1.IOBase & 0xF) == 1; 693 694 /* 695 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810, 696 * i820, i840, i845 Chipsets) that don't have subtractive decode broken. 697 * If they do have broken subtractive support, or if they are not ICH bridges, 698 * then check if the bridge supports subtractive decode at all. 699 */ 700 if ((((PdoExtension->VendorId == 0x8086) && 701 ((PdoExtension->DeviceId == 0x2418) || 702 (PdoExtension->DeviceId == 0x2428) || 703 (PdoExtension->DeviceId == 0x244E) || 704 (PdoExtension->DeviceId == 0x2448))) && 705 (!(PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE) || 706 (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE))) || 707 (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE)) 708 { 709 /* No resources are needed on a subtractive decode bridge */ 710 PciData->u.type1.MemoryBase = 0xFFFF; 711 PciData->u.type1.PrefetchBase = 0xFFFF; 712 PciData->u.type1.IOBase = 0xFF; 713 PciData->u.type1.IOLimit = 0; 714 PciData->u.type1.MemoryLimit = 0; 715 PciData->u.type1.PrefetchLimit = 0; 716 PciData->u.type1.PrefetchBaseUpper32 = 0; 717 PciData->u.type1.PrefetchLimitUpper32 = 0; 718 PciData->u.type1.IOBaseUpper16 = 0; 719 PciData->u.type1.IOLimitUpper16 = 0; 720 } 721 else 722 { 723 /* 724 * Otherwise, get the FDO to read the old PCI configuration header that 725 * had been saved by the hack in PPBridge_SaveCurrentSettings. 726 */ 727 FdoExtension = PdoExtension->ParentFdoExtension; 728 ASSERT(PdoExtension->Resources == NULL); 729 730 /* Read the PCI header data and use that here */ 731 PciData->u.type1.IOBase = FdoExtension->PreservedConfig->u.type1.IOBase; 732 PciData->u.type1.IOLimit = FdoExtension->PreservedConfig->u.type1.IOLimit; 733 PciData->u.type1.MemoryBase = FdoExtension->PreservedConfig->u.type1.MemoryBase; 734 PciData->u.type1.MemoryLimit = FdoExtension->PreservedConfig->u.type1.MemoryLimit; 735 PciData->u.type1.PrefetchBase = FdoExtension->PreservedConfig->u.type1.PrefetchBase; 736 PciData->u.type1.PrefetchLimit = FdoExtension->PreservedConfig->u.type1.PrefetchLimit; 737 PciData->u.type1.PrefetchBaseUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchBaseUpper32; 738 PciData->u.type1.PrefetchLimitUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchLimitUpper32; 739 PciData->u.type1.IOBaseUpper16 = FdoExtension->PreservedConfig->u.type1.IOBaseUpper16; 740 PciData->u.type1.IOLimitUpper16 = FdoExtension->PreservedConfig->u.type1.IOLimitUpper16; 741 } 742 743 /* Loop bus resources */ 744 PciResources = PdoExtension->Resources; 745 if (PciResources) 746 { 747 /* Loop each resource type (the BARs, ROM BAR and Prefetch) */ 748 for (i = 0; i < 6; i++) 749 { 750 UNIMPLEMENTED; 751 } 752 } 753 754 /* Copy the bus number data */ 755 PciData->u.type1.PrimaryBus = PdoExtension->Dependent.type1.PrimaryBus; 756 PciData->u.type1.SecondaryBus = PdoExtension->Dependent.type1.SecondaryBus; 757 PciData->u.type1.SubordinateBus = PdoExtension->Dependent.type1.SubordinateBus; 758 759 /* Copy the decode flags */ 760 if (PdoExtension->Dependent.type1.IsaBitSet) 761 { 762 PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_ISA; 763 } 764 765 if (PdoExtension->Dependent.type1.VgaBitSet) 766 { 767 PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_VGA; 768 } 769 } 770 771 /* EOF */ 772