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
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 /* FUNCTIONS ******************************************************************/
21 PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData
)
25 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
28 Base
= PciData
->u
.type1
.IOLimit
;
30 /* Low bit specifies 32-bit address, top bits specify the base */
31 Is32Bit
= (Base
& 0xF) == 1;
32 IoBase
= (Base
& 0xF0) << 8;
37 /* Read the upper 16-bits from the other register */
38 IoBase
|= PciData
->u
.type1
.IOBaseUpper16
<< 16;
39 ASSERT(PciData
->u
.type1
.IOLimit
& 0x1);
42 /* Return the base address */
48 PciBridgeIoLimit(IN PPCI_COMMON_HEADER PciData
)
52 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
55 Limit
= PciData
->u
.type1
.IOLimit
;
57 /* Low bit specifies 32-bit address, top bits specify the limit */
58 Is32Bit
= (Limit
& 0xF) == 1;
59 IoLimit
= (Limit
& 0xF0) << 8;
64 /* Read the upper 16-bits from the other register */
65 IoLimit
|= PciData
->u
.type1
.IOLimitUpper16
<< 16;
66 ASSERT(PciData
->u
.type1
.IOBase
& 0x1);
69 /* Return the I/O limit */
70 return IoLimit
| 0xFFF;
75 PciBridgeMemoryBase(IN PPCI_COMMON_HEADER PciData
)
77 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
79 /* Return the memory base */
80 return (PciData
->u
.type1
.MemoryBase
<< 16);
85 PciBridgeMemoryLimit(IN PPCI_COMMON_HEADER PciData
)
87 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
89 /* Return the memory limit */
90 return (PciData
->u
.type1
.MemoryLimit
<< 16) | 0xFFFFF;
95 PciBridgePrefetchMemoryBase(IN PPCI_COMMON_HEADER PciData
)
100 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
103 PrefetchBase
= PciData
->u
.type1
.PrefetchBase
;
105 /* Low bit specifies 64-bit address, top bits specify the base */
106 Is64Bit
= (PrefetchBase
& 0xF) == 1;
107 Base
.LowPart
= ((PrefetchBase
& 0xFFF0) << 16);
112 /* Read the upper 32-bits from the other register */
113 Base
.HighPart
= PciData
->u
.type1
.PrefetchBaseUpper32
;
116 /* Return the base */
122 PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData
)
126 USHORT PrefetchLimit
;
127 ASSERT(PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
);
130 PrefetchLimit
= PciData
->u
.type1
.PrefetchLimit
;
132 /* Low bit specifies 64-bit address, top bits specify the limit */
133 Is64Bit
= (PrefetchLimit
& 0xF) == 1;
134 Limit
.LowPart
= (PrefetchLimit
<< 16) | 0xFFFFF;
139 /* Read the upper 32-bits from the other register */
140 Limit
.HighPart
= PciData
->u
.type1
.PrefetchLimitUpper32
;
143 /* Return the limit */
149 PciBridgeMemoryWorstCaseAlignment(IN ULONG Length
)
154 /* Start with highest alignment (2^31) */
155 Alignment
= 0x80000000;
157 /* Keep dividing until we reach the correct power of two */
158 while (!(Length
& Alignment
)) Alignment
>>= 1;
160 /* Return the alignment */
166 PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension
)
168 /* Undocumented ACPI Method PDEC to get positive decode settings */
169 return PciIsSlotPresentInParentMethod(PdoExtension
, 'CEDP');
174 PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context
)
176 PPCI_COMMON_HEADER Current
, PciData
;
177 PPCI_PDO_EXTENSION PdoExtension
;
179 /* Get pointers from context */
180 Current
= Context
->Current
;
181 PciData
= Context
->PciData
;
182 PdoExtension
= Context
->PdoExtension
;
184 /* Only valid for PCI-to-PCI bridges */
185 ASSERT((Current
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
186 (Current
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
));
188 /* Check for hacks first, then check the ProgIf of the bridge */
189 if (!(PdoExtension
->HackFlags
& PCI_HACK_SUBTRACTIVE_DECODE
) &&
190 (Current
->ProgIf
!= 1) &&
191 ((PciData
->u
.type1
.IOLimit
& 0xF0) == 0xF0))
193 /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */
194 DPRINT("Subtractive decode does not seem to be enabled\n");
199 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
200 * i820, i840, i845 Chipsets) that have subtractive decode broken.
202 if (((PdoExtension
->VendorId
== 0x8086) &&
203 ((PdoExtension
->DeviceId
== 0x2418) ||
204 (PdoExtension
->DeviceId
== 0x2428) ||
205 (PdoExtension
->DeviceId
== 0x244E) ||
206 (PdoExtension
->DeviceId
== 0x2448))) ||
207 (PdoExtension
->HackFlags
& PCI_HACK_BROKEN_SUBTRACTIVE_DECODE
))
209 /* Check if the ACPI BIOS says positive decode should be enabled */
210 if (PciBridgeIsPositiveDecode(PdoExtension
))
213 DPRINT1("Putting bridge in positive decode because of PDEC\n");
218 /* If we found subtractive decode, we'll need a resource update later */
219 DPRINT1("PCI : Subtractive decode on 0x%x\n", Current
->u
.type1
.SecondaryBus
);
220 PdoExtension
->UpdateHardware
= TRUE
;
226 PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context
)
229 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
;
230 PIO_RESOURCE_DESCRIPTOR IoDescriptor
;
231 PPCI_FUNCTION_RESOURCES Resources
;
232 PCI_COMMON_HEADER BiosData
;
233 PPCI_COMMON_HEADER Current
;
234 PPCI_COMMON_CONFIG SavedConfig
;
235 ULONG i
, Bar
, BarMask
;
237 PHYSICAL_ADDRESS Limit
, Base
, Length
;
238 BOOLEAN HaveIoLimit
, CheckAlignment
;
239 PPCI_PDO_EXTENSION PdoExtension
;
241 /* Get the pointers from the extension */
242 PdoExtension
= Context
->PdoExtension
;
243 Resources
= PdoExtension
->Resources
;
244 Current
= Context
->Current
;
246 /* Check if decodes are disabled */
247 if (!(Context
->Command
& (PCI_ENABLE_IO_SPACE
| PCI_ENABLE_MEMORY_SPACE
)))
249 /* Well, we're going to need them from somewhere, use the registry data */
250 Status
= PciGetBiosConfig(PdoExtension
, &BiosData
);
251 if (NT_SUCCESS(Status
)) Current
= &BiosData
;
254 /* Scan all current and limit descriptors for each BAR needed */
255 BarArray
= Current
->u
.type1
.BaseAddresses
;
256 for (i
= 0; i
< 6; i
++)
258 /* Get the current resource descriptor, and the limit requirement */
259 CmDescriptor
= &Resources
->Current
[i
];
260 IoDescriptor
= &Resources
->Limit
[i
];
262 /* Copy descriptor data, skipping null descriptors */
263 CmDescriptor
->Type
= IoDescriptor
->Type
;
264 if (CmDescriptor
->Type
== CmResourceTypeNull
) continue;
265 CmDescriptor
->Flags
= IoDescriptor
->Flags
;
266 CmDescriptor
->ShareDisposition
= IoDescriptor
->ShareDisposition
;
268 /* Initialize the high-parts to zero, since most stuff is 32-bit only */
269 Base
.QuadPart
= Limit
.QuadPart
= Length
.QuadPart
= 0;
271 /* Check if we're handling PCI BARs, or the ROM BAR */
272 if ((i
< PCI_TYPE1_ADDRESSES
) || (i
== 5))
274 /* Is this the ROM BAR? */
277 /* Read the correct bar, with the appropriate mask */
278 Bar
= Current
->u
.type1
.ROMBaseAddress
;
279 BarMask
= PCI_ADDRESS_ROM_ADDRESS_MASK
;
281 /* Decode the base address, and write down the length */
282 Base
.LowPart
= Bar
& BarMask
;
283 DPRINT1("ROM BAR Base: %lx\n", Base
.LowPart
);
284 CmDescriptor
->u
.Memory
.Length
= IoDescriptor
->u
.Memory
.Length
;
288 /* Otherwise, get the BAR from the array */
291 /* Is this an I/O BAR? */
292 if (Bar
& PCI_ADDRESS_IO_SPACE
)
294 /* Set the correct mask */
295 ASSERT(CmDescriptor
->Type
== CmResourceTypePort
);
296 BarMask
= PCI_ADDRESS_IO_ADDRESS_MASK
;
300 /* This is a memory BAR, set the correct base */
301 ASSERT(CmDescriptor
->Type
== CmResourceTypeMemory
);
302 BarMask
= PCI_ADDRESS_MEMORY_ADDRESS_MASK
;
304 /* IS this a 64-bit BAR? */
305 if ((Bar
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
)
307 /* Read the next 32-bits as well, ie, the next BAR */
308 Base
.HighPart
= BarArray
[i
+ 1];
312 /* Decode the base address, and write down the length */
313 Base
.LowPart
= Bar
& BarMask
;
314 DPRINT1("BAR Base: %lx\n", Base
.LowPart
);
315 CmDescriptor
->u
.Generic
.Length
= IoDescriptor
->u
.Generic
.Length
;
320 /* Reset loop conditions */
322 CheckAlignment
= FALSE
;
324 /* Check which descriptor is being parsed */
327 /* I/O Port Requirements */
328 Base
.LowPart
= PciBridgeIoBase(Current
);
329 Limit
.LowPart
= PciBridgeIoLimit(Current
);
330 DPRINT1("Bridge I/O Base and Limit: %lx %lx\n",
331 Base
.LowPart
, Limit
.LowPart
);
333 /* Do we have any I/O Port data? */
334 if (!(Base
.LowPart
) && (Current
->u
.type1
.IOLimit
))
336 /* There's a limit */
342 /* Memory requirements */
343 Base
.LowPart
= PciBridgeMemoryBase(Current
);
344 Limit
.LowPart
= PciBridgeMemoryLimit(Current
);
346 /* These should always be there, so check their alignment */
347 DPRINT1("Bridge MEM Base and Limit: %lx %lx\n",
348 Base
.LowPart
, Limit
.LowPart
);
349 CheckAlignment
= TRUE
;
353 /* This should only be present for prefetch memory */
354 ASSERT(CmDescriptor
->Flags
& CM_RESOURCE_MEMORY_PREFETCHABLE
);
355 Base
= PciBridgePrefetchMemoryBase(Current
);
356 Limit
= PciBridgePrefetchMemoryLimit(Current
);
358 /* If it's there, check the alignment */
359 DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base
, Limit
);
360 CheckAlignment
= TRUE
;
363 /* Check for invalid base address */
364 if (Base
.QuadPart
>= Limit
.QuadPart
)
366 /* Assume the descriptor is bogus */
367 CmDescriptor
->Type
= CmResourceTypeNull
;
368 IoDescriptor
->Type
= CmResourceTypeNull
;
372 /* Check if there's no memory, and no I/O port either */
373 if (!(Base
.LowPart
) && !(HaveIoLimit
))
375 /* This seems like a bogus requirement, ignore it */
376 CmDescriptor
->Type
= CmResourceTypeNull
;
380 /* Set the length to be the limit - the base; should always be 32-bit */
381 Length
.QuadPart
= Limit
.LowPart
- Base
.LowPart
+ 1;
382 ASSERT(Length
.HighPart
== 0);
383 CmDescriptor
->u
.Generic
.Length
= Length
.LowPart
;
385 /* Check if alignment should be set */
388 /* Compute the required alignment for this length */
389 ASSERT(CmDescriptor
->u
.Memory
.Length
> 0);
390 IoDescriptor
->u
.Memory
.Alignment
=
391 PciBridgeMemoryWorstCaseAlignment(CmDescriptor
->u
.Memory
.Length
);
395 /* Now set the base address */
396 CmDescriptor
->u
.Generic
.Start
.LowPart
= Base
.LowPart
;
399 /* Save PCI settings into the PDO extension for easy access later */
400 PdoExtension
->Dependent
.type1
.PrimaryBus
= Current
->u
.type1
.PrimaryBus
;
401 PdoExtension
->Dependent
.type1
.SecondaryBus
= Current
->u
.type1
.SecondaryBus
;
402 PdoExtension
->Dependent
.type1
.SubordinateBus
= Current
->u
.type1
.SubordinateBus
;
404 /* Check for subtractive decode bridges */
405 if (PdoExtension
->Dependent
.type1
.SubtractiveDecode
)
407 /* Check if legacy VGA decodes are enabled */
408 DPRINT1("Subtractive decode bridge\n");
409 if (Current
->u
.type1
.BridgeControl
& PCI_ENABLE_BRIDGE_VGA
)
411 /* Save this setting for later */
412 DPRINT1("VGA Bridge\n");
413 PdoExtension
->Dependent
.type1
.VgaBitSet
= TRUE
;
416 /* Legacy ISA decoding is not compatible with subtractive decode */
417 ASSERT(PdoExtension
->Dependent
.type1
.IsaBitSet
== FALSE
);
421 /* Check if legacy VGA decodes are enabled */
422 if (Current
->u
.type1
.BridgeControl
& PCI_ENABLE_BRIDGE_VGA
)
424 /* Save this setting for later */
425 DPRINT1("VGA Bridge\n");
426 PdoExtension
->Dependent
.type1
.VgaBitSet
= TRUE
;
428 /* And on positive decode, we'll also need extra resources locked */
429 PdoExtension
->AdditionalResourceCount
= 4;
432 /* Check if legacy ISA decoding is enabled */
433 if (Current
->u
.type1
.BridgeControl
& PCI_ENABLE_BRIDGE_ISA
)
435 /* Save this setting for later */
436 DPRINT1("ISA Bridge\n");
437 PdoExtension
->Dependent
.type1
.IsaBitSet
= TRUE
;
442 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
443 * i820, i840, i845 Chipsets) that have subtractive decode broken.
445 if (((PdoExtension
->VendorId
== 0x8086) &&
446 ((PdoExtension
->DeviceId
== 0x2418) ||
447 (PdoExtension
->DeviceId
== 0x2428) ||
448 (PdoExtension
->DeviceId
== 0x244E) ||
449 (PdoExtension
->DeviceId
== 0x2448))) ||
450 (PdoExtension
->HackFlags
& PCI_HACK_BROKEN_SUBTRACTIVE_DECODE
))
452 /* Check if subtractive decode is actually enabled */
453 if (PdoExtension
->Dependent
.type1
.SubtractiveDecode
)
455 /* We're going to need a copy of the configuration for later use */
456 DPRINT1("apply config save hack to ICH subtractive decode\n");
457 SavedConfig
= ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH
, 'PciP');
458 PdoExtension
->ParentFdoExtension
->PreservedConfig
= SavedConfig
;
459 if (SavedConfig
) RtlCopyMemory(SavedConfig
, Current
, PCI_COMMON_HDR_LENGTH
);
466 PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context
)
468 PIO_RESOURCE_DESCRIPTOR Limit
;
470 PHYSICAL_ADDRESS MemoryLimit
;
472 PPCI_COMMON_HEADER Working
;
473 PPCI_PDO_EXTENSION PdoExtension
;
475 /* Get the pointers from the context */
476 Working
= Context
->PciData
;
477 PdoExtension
= Context
->PdoExtension
;
479 /* Scan the BARs into the limit descriptors */
480 BarArray
= Working
->u
.type1
.BaseAddresses
;
481 Limit
= PdoExtension
->Resources
->Limit
;
483 /* First of all, loop all the BARs */
484 for (i
= 0; i
< PCI_TYPE1_ADDRESSES
; i
++)
486 /* Create a descriptor for their limits */
487 if (PciCreateIoDescriptorFromBarLimit(&Limit
[i
], &BarArray
[i
], FALSE
))
489 /* This was a 64-bit descriptor, make sure there's space */
490 ASSERT((i
+ 1) < PCI_TYPE1_ADDRESSES
);
492 /* Skip the next descriptor since this one is double sized */
494 (&Limit
[i
])->Type
== CmResourceTypeNull
;
498 /* Check if this is a subtractive decode bridge */
499 if (PciBridgeIsSubtractiveDecode(Context
))
501 /* This bridge is subtractive */
502 PdoExtension
->Dependent
.type1
.SubtractiveDecode
= TRUE
;
504 /* Subtractive bridges cannot use legacy ISA or VGA functionality */
505 PdoExtension
->Dependent
.type1
.IsaBitSet
= FALSE
;
506 PdoExtension
->Dependent
.type1
.VgaBitSet
= FALSE
;
509 /* For normal decode bridges, we'll need to find the bridge limits too */
510 if (!PdoExtension
->Dependent
.type1
.SubtractiveDecode
)
512 /* Loop the descriptors that are left, to store the bridge limits */
513 for (i
= PCI_TYPE1_ADDRESSES
; i
< 5; i
++)
515 /* No 64-bit memory addresses, and set the address to 0 to begin */
516 MemoryLimit
.HighPart
= 0;
517 (&Limit
[i
])->u
.Port
.MinimumAddress
.QuadPart
= 0;
519 /* Are we getting the I/O limit? */
522 /* There should be one, get it */
523 ASSERT(Working
->u
.type1
.IOLimit
!= 0);
524 ASSERT((Working
->u
.type1
.IOLimit
& 0x0E) == 0);
525 MemoryLimit
.LowPart
= PciBridgeIoLimit(Working
);
527 /* Build a descriptor for this limit */
528 (&Limit
[i
])->Type
= CmResourceTypePort
;
529 (&Limit
[i
])->Flags
= CM_RESOURCE_PORT_WINDOW_DECODE
|
530 CM_RESOURCE_PORT_POSITIVE_DECODE
;
531 (&Limit
[i
])->u
.Port
.Alignment
= 0x1000;
532 (&Limit
[i
])->u
.Port
.MinimumAddress
.QuadPart
= 0;
533 (&Limit
[i
])->u
.Port
.MaximumAddress
= MemoryLimit
;
534 (&Limit
[i
])->u
.Port
.Length
= 0;
538 /* There should be a valid memory limit, get it */
539 ASSERT((Working
->u
.type1
.MemoryLimit
& 0xF) == 0);
540 MemoryLimit
.LowPart
= PciBridgeMemoryLimit(Working
);
542 /* Build the descriptor for it */
543 (&Limit
[i
])->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
;
544 (&Limit
[i
])->Type
= CmResourceTypeMemory
;
545 (&Limit
[i
])->u
.Memory
.Alignment
= 0x100000;
546 (&Limit
[i
])->u
.Memory
.MinimumAddress
.QuadPart
= 0;
547 (&Limit
[i
])->u
.Memory
.MaximumAddress
= MemoryLimit
;
548 (&Limit
[i
])->u
.Memory
.Length
= 0;
550 else if (Working
->u
.type1
.PrefetchLimit
)
552 /* Get the prefetch memory limit, if there is one */
553 MemoryLimit
= PciBridgePrefetchMemoryLimit(Working
);
555 /* Write out the descriptor for it */
556 (&Limit
[i
])->Flags
= CM_RESOURCE_MEMORY_PREFETCHABLE
;
557 (&Limit
[i
])->Type
= CmResourceTypeMemory
;
558 (&Limit
[i
])->u
.Memory
.Alignment
= 0x100000;
559 (&Limit
[i
])->u
.Memory
.MinimumAddress
.QuadPart
= 0;
560 (&Limit
[i
])->u
.Memory
.MaximumAddress
= MemoryLimit
;
561 (&Limit
[i
])->u
.Memory
.Length
= 0;
565 /* Blank descriptor */
566 (&Limit
[i
])->Type
= CmResourceTypeNull
;
571 /* Does the ROM have its own BAR? */
572 if (Working
->u
.type1
.ROMBaseAddress
& PCI_ROMADDRESS_ENABLED
)
574 /* Build a limit for it as well */
575 PciCreateIoDescriptorFromBarLimit(&Limit
[i
],
576 &Working
->u
.type1
.ROMBaseAddress
,
583 PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context
)
585 PPCI_COMMON_HEADER PciData
, Current
;
587 /* Get pointers from context */
588 PciData
= Context
->PciData
;
589 Current
= Context
->Current
;
592 * Write FFh everywhere so that the PCI bridge ignores what it can't handle.
593 * Based on the bits that were ignored (still 0), this is how we can tell
596 RtlFillMemory(PciData
->u
.type1
.BaseAddresses
,
597 FIELD_OFFSET(PCI_COMMON_HEADER
, u
.type1
.CapabilitiesPtr
) -
598 FIELD_OFFSET(PCI_COMMON_HEADER
, u
.type1
.BaseAddresses
),
601 /* Copy the saved settings from the current context into the PCI header */
602 PciData
->u
.type1
.PrimaryBus
= Current
->u
.type1
.PrimaryBus
;
603 PciData
->u
.type1
.SecondaryBus
= Current
->u
.type1
.SecondaryBus
;
604 PciData
->u
.type1
.SubordinateBus
= Current
->u
.type1
.SubordinateBus
;
605 PciData
->u
.type1
.SecondaryLatency
= Current
->u
.type1
.SecondaryLatency
;
607 /* No I/O limit or base. The bottom base bit specifies that FIXME */
608 PciData
->u
.type1
.IOBaseUpper16
= 0xFFFE;
609 PciData
->u
.type1
.IOLimitUpper16
= 0xFFFF;
611 /* Save secondary status before it gets cleared */
612 Context
->SecondaryStatus
= Current
->u
.type1
.SecondaryStatus
;
614 /* Clear secondary status */
615 Current
->u
.type1
.SecondaryStatus
= 0;
616 PciData
->u
.type1
.SecondaryStatus
= 0;
621 PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context
)
623 /* Copy back the secondary status register */
624 Context
->Current
->u
.type1
.SecondaryStatus
= Context
->SecondaryStatus
;
629 PPBridge_GetAdditionalResourceDescriptors(IN PPCI_CONFIGURATOR_CONTEXT Context
,
630 IN PPCI_COMMON_HEADER PciData
,
631 IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
)
633 /* Does this bridge have VGA decodes on it? */
634 if (PciData
->u
.type1
.BridgeControl
& PCI_ENABLE_BRIDGE_VGA
)
636 /* Build a private descriptor with 3 entries */
637 IoDescriptor
->Type
= CmResourceTypeDevicePrivate
;
638 IoDescriptor
->u
.DevicePrivate
.Data
[0] = 3;
639 IoDescriptor
->u
.DevicePrivate
.Data
[1] = 3;
641 /* First, the VGA range at 0xA0000 */
642 IoDescriptor
[1].Type
= CmResourceTypeMemory
;
643 IoDescriptor
[1].Flags
= CM_RESOURCE_MEMORY_READ_WRITE
;
644 IoDescriptor
[1].u
.Port
.Length
= 0x20000;
645 IoDescriptor
[1].u
.Port
.Alignment
= 1;
646 IoDescriptor
[1].u
.Port
.MinimumAddress
.QuadPart
= 0xA0000;
647 IoDescriptor
[1].u
.Port
.MaximumAddress
.QuadPart
= 0xBFFFF;
649 /* Then, the VGA registers at 0x3B0 */
650 IoDescriptor
[2].Type
= CmResourceTypePort
;
651 IoDescriptor
[2].Flags
= CM_RESOURCE_PORT_POSITIVE_DECODE
|
652 CM_RESOURCE_PORT_10_BIT_DECODE
;
653 IoDescriptor
[2].u
.Port
.Length
= 12;
654 IoDescriptor
[2].u
.Port
.Alignment
= 1;
655 IoDescriptor
[2].u
.Port
.MinimumAddress
.QuadPart
= 0x3B0;
656 IoDescriptor
[2].u
.Port
.MaximumAddress
.QuadPart
= 0x3BB;
658 /* And finally the VGA registers at 0x3C0 */
659 IoDescriptor
[3].Type
= CmResourceTypePort
;
660 IoDescriptor
[3].Flags
= CM_RESOURCE_PORT_POSITIVE_DECODE
|
661 CM_RESOURCE_PORT_10_BIT_DECODE
;
662 IoDescriptor
[3].u
.Port
.Length
= 32;
663 IoDescriptor
[3].u
.Port
.Alignment
= 1;
664 IoDescriptor
[3].u
.Port
.MinimumAddress
.QuadPart
= 0x3C0;
665 IoDescriptor
[3].u
.Port
.MaximumAddress
.QuadPart
= 0x3DF;
671 PPBridge_ResetDevice(IN PPCI_PDO_EXTENSION PdoExtension
,
672 IN PPCI_COMMON_HEADER PciData
)
680 PPBridge_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension
,
681 IN PPCI_COMMON_HEADER PciData
)
684 PPCI_FDO_EXTENSION FdoExtension
;
685 PPCI_FUNCTION_RESOURCES PciResources
;
688 /* Check if I/O Decodes are enabled */
689 IoActive
= (PciData
->u
.type1
.IOBase
& 0xF) == 1;
692 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
693 * i820, i840, i845 Chipsets) that don't have subtractive decode broken.
694 * If they do have broken subtractive support, or if they are not ICH bridges,
695 * then check if the bridge supports substractive decode at all.
697 if ((((PdoExtension
->VendorId
== 0x8086) &&
698 ((PdoExtension
->DeviceId
== 0x2418) ||
699 (PdoExtension
->DeviceId
== 0x2428) ||
700 (PdoExtension
->DeviceId
== 0x244E) ||
701 (PdoExtension
->DeviceId
== 0x2448))) &&
702 (!(PdoExtension
->HackFlags
& PCI_HACK_BROKEN_SUBTRACTIVE_DECODE
) ||
703 (PdoExtension
->Dependent
.type1
.SubtractiveDecode
== FALSE
))) ||
704 (PdoExtension
->Dependent
.type1
.SubtractiveDecode
== FALSE
))
706 /* No resources are needed on a subtractive decode bridge */
707 PciData
->u
.type1
.MemoryBase
= 0xFFFF;
708 PciData
->u
.type1
.PrefetchBase
= 0xFFFF;
709 PciData
->u
.type1
.IOBase
= 0xFF;
710 PciData
->u
.type1
.IOLimit
= 0;
711 PciData
->u
.type1
.MemoryLimit
= 0;
712 PciData
->u
.type1
.PrefetchLimit
= 0;
713 PciData
->u
.type1
.PrefetchBaseUpper32
= 0;
714 PciData
->u
.type1
.PrefetchLimitUpper32
= 0;
715 PciData
->u
.type1
.IOBaseUpper16
= 0;
716 PciData
->u
.type1
.IOLimitUpper16
= 0;
721 * Otherwise, get the FDO to read the old PCI configuration header that
722 * had been saved by the hack in PPBridge_SaveCurrentSettings.
724 FdoExtension
= PdoExtension
->ParentFdoExtension
;
725 ASSERT(PdoExtension
->Resources
== NULL
);
727 /* Read the PCI header data and use that here */
728 PciData
->u
.type1
.IOBase
= FdoExtension
->PreservedConfig
->u
.type1
.IOBase
;
729 PciData
->u
.type1
.IOLimit
= FdoExtension
->PreservedConfig
->u
.type1
.IOLimit
;
730 PciData
->u
.type1
.MemoryBase
= FdoExtension
->PreservedConfig
->u
.type1
.MemoryBase
;
731 PciData
->u
.type1
.MemoryLimit
= FdoExtension
->PreservedConfig
->u
.type1
.MemoryLimit
;
732 PciData
->u
.type1
.PrefetchBase
= FdoExtension
->PreservedConfig
->u
.type1
.PrefetchBase
;
733 PciData
->u
.type1
.PrefetchLimit
= FdoExtension
->PreservedConfig
->u
.type1
.PrefetchLimit
;
734 PciData
->u
.type1
.PrefetchBaseUpper32
= FdoExtension
->PreservedConfig
->u
.type1
.PrefetchBaseUpper32
;
735 PciData
->u
.type1
.PrefetchLimitUpper32
= FdoExtension
->PreservedConfig
->u
.type1
.PrefetchLimitUpper32
;
736 PciData
->u
.type1
.IOBaseUpper16
= FdoExtension
->PreservedConfig
->u
.type1
.IOBaseUpper16
;
737 PciData
->u
.type1
.IOLimitUpper16
= FdoExtension
->PreservedConfig
->u
.type1
.IOLimitUpper16
;
740 /* Loop bus resources */
741 PciResources
= PdoExtension
->Resources
;
744 /* Loop each resource type (the BARs, ROM BAR and Prefetch) */
745 for (i
= 0; i
< 6; i
++)
751 /* Copy the bus number data */
752 PciData
->u
.type1
.PrimaryBus
= PdoExtension
->Dependent
.type1
.PrimaryBus
;
753 PciData
->u
.type1
.SecondaryBus
= PdoExtension
->Dependent
.type1
.SecondaryBus
;
754 PciData
->u
.type1
.SubordinateBus
= PdoExtension
->Dependent
.type1
.SubordinateBus
;
756 /* Copy the decode flags */
757 if (PdoExtension
->Dependent
.type1
.IsaBitSet
)
759 PciData
->u
.type1
.BridgeControl
|= PCI_ENABLE_BRIDGE_ISA
;
762 if (PdoExtension
->Dependent
.type1
.VgaBitSet
)
764 PciData
->u
.type1
.BridgeControl
|= PCI_ENABLE_BRIDGE_VGA
;