Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1511 lines
42 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. ppbridge.c
  5. Abstract:
  6. This module contains functions associated with enumerating
  7. PCI to PCI bridges.
  8. Author:
  9. Peter Johnston (peterj) 12-Feb-1997
  10. Revision History:
  11. --*/
  12. #include "pcip.h"
  13. BOOLEAN
  14. PciBridgeIsPositiveDecode(
  15. IN PPCI_PDO_EXTENSION Pdo
  16. );
  17. BOOLEAN
  18. PciBridgeIsSubtractiveDecode(
  19. IN PPCI_CONFIGURABLE_OBJECT This
  20. );
  21. ULONG
  22. PciBridgeIoBase(
  23. IN PPCI_COMMON_CONFIG Config
  24. );
  25. ULONG
  26. PciBridgeIoLimit(
  27. IN PPCI_COMMON_CONFIG Config
  28. );
  29. ULONG
  30. PciBridgeMemoryBase(
  31. IN PPCI_COMMON_CONFIG Config
  32. );
  33. ULONG
  34. PciBridgeMemoryLimit(
  35. IN PPCI_COMMON_CONFIG Config
  36. );
  37. PHYSICAL_ADDRESS
  38. PciBridgePrefetchMemoryBase(
  39. IN PPCI_COMMON_CONFIG Config
  40. );
  41. PHYSICAL_ADDRESS
  42. PciBridgePrefetchMemoryLimit(
  43. IN PPCI_COMMON_CONFIG Config
  44. );
  45. #ifdef ALLOC_PRAGMA
  46. #pragma alloc_text(PAGE, PciBridgeIoBase)
  47. #pragma alloc_text(PAGE, PciBridgeIoLimit)
  48. #pragma alloc_text(PAGE, PciBridgeMemoryBase)
  49. #pragma alloc_text(PAGE, PciBridgeMemoryLimit)
  50. #pragma alloc_text(PAGE, PciBridgePrefetchMemoryBase)
  51. #pragma alloc_text(PAGE, PciBridgePrefetchMemoryLimit)
  52. #pragma alloc_text(PAGE, PPBridge_MassageHeaderForLimitsDetermination)
  53. #pragma alloc_text(PAGE, PPBridge_RestoreCurrent)
  54. #pragma alloc_text(PAGE, PPBridge_SaveLimits)
  55. #pragma alloc_text(PAGE, PPBridge_SaveCurrentSettings)
  56. #pragma alloc_text(PAGE, PPBridge_GetAdditionalResourceDescriptors)
  57. #pragma alloc_text(PAGE, PciBridgeIsPositiveDecode)
  58. #endif
  59. ULONG
  60. PciBridgeIoBase(
  61. IN PPCI_COMMON_CONFIG Config
  62. )
  63. /*++
  64. Routine Description:
  65. Compute the 32 bit base IO address being passed by the bridge
  66. whose config space is at Config.
  67. The IO base address is always 4KB aligned. If only 64KB IO
  68. address space is supported, this is represented in the upper
  69. nibble of Config->u.type1.IOBase giving the range 0 to 0xf000
  70. for the base address. The low nibble of Config->u.type1.IOBase
  71. contains flags. If the least significant bit is set, then the
  72. bridge supports IO addressing to 4GB and Config->u.type1.IOBaseUpper16
  73. contains the upper 16 bits of the base address.
  74. Arguments:
  75. Config - Pointer to a buffer containing the device's common (type1)
  76. configuration header.
  77. Return Value:
  78. ULONG containing the IO Base address.
  79. --*/
  80. {
  81. BOOLEAN io32Bit = (Config->u.type1.IOBase & 0x0f) == 1;
  82. ULONG base = (Config->u.type1.IOBase & 0xf0) << 8;
  83. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  84. if (io32Bit) {
  85. base |= Config->u.type1.IOBaseUpper16 << 16;
  86. //
  87. // Check h/w (base and limit must be the same bit width).
  88. //
  89. ASSERT(Config->u.type1.IOLimit & 0x1);
  90. }
  91. return base;
  92. }
  93. ULONG
  94. PciBridgeIoLimit(
  95. IN PPCI_COMMON_CONFIG Config
  96. )
  97. /*++
  98. Routine Description:
  99. Compute the 32 bit IO address limit being passed by the bridge
  100. whose config space is at Config.
  101. The range of IO addresses being passed is always a multiple of 4KB
  102. therefore the least significant 12 bits of the address limit are
  103. always 0xfff. The upper nibble of Config->u.type1.IOLimit provides
  104. the next significant 4 bits. The lower nibble of this byte contains
  105. flags. If the least significant bit is set, the bridge is capable of
  106. passing 32 bit IO addresses and the next 16 significant bits are
  107. obtained from Config->u.type1.IOLimitUpper16.
  108. Arguments:
  109. Config - Pointer to a buffer containing the device's common (type1)
  110. configuration header.
  111. Return Value:
  112. ULONG containing the IO address limit.
  113. --*/
  114. {
  115. BOOLEAN io32Bit = (Config->u.type1.IOLimit & 0x0f) == 1;
  116. ULONG limit = (Config->u.type1.IOLimit & 0xf0) << 8;
  117. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  118. if (io32Bit) {
  119. limit |= Config->u.type1.IOLimitUpper16 << 16;
  120. //
  121. // Check h/w (base and limit must be the same bit width).
  122. //
  123. ASSERT(Config->u.type1.IOBase & 0x1);
  124. }
  125. return limit | 0xfff;
  126. }
  127. ULONG
  128. PciBridgeMemoryBase(
  129. IN PPCI_COMMON_CONFIG Config
  130. )
  131. /*++
  132. Routine Description:
  133. Compute the 32 bit base Memory address being passed by the bridge
  134. whose config space is at Config.
  135. The Memory base address is always 1MB aligned.
  136. Arguments:
  137. Config - Pointer to a buffer containing the device's common (type1)
  138. configuration header.
  139. Return Value:
  140. ULONG containing the Memory Base address.
  141. --*/
  142. {
  143. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  144. //
  145. // The upper 12 bits of the memory base address are contained in
  146. // the upper 12 bits of the USHORT Config->u.type1.MemoryBase.
  147. //
  148. return Config->u.type1.MemoryBase << 16;
  149. }
  150. ULONG
  151. PciBridgeMemoryLimit(
  152. IN PPCI_COMMON_CONFIG Config
  153. )
  154. /*++
  155. Routine Description:
  156. Compute the 32 bit Memory address limit being passed by the bridge
  157. whose config space is at Config.
  158. The memory limit is always at the byte preceeding a 1MB boundary.
  159. The upper 12 bits of the limit address are contained in the upper
  160. 12 bits of Config->u.type1.MemoryLimit, the lower 20 bits are all
  161. ones.
  162. Arguments:
  163. Config - Pointer to a buffer containing the device's common (type1)
  164. configuration header.
  165. Return Value:
  166. ULONG containing the Memory limit.
  167. --*/
  168. {
  169. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  170. return (Config->u.type1.MemoryLimit << 16) | 0xfffff;
  171. }
  172. PHYSICAL_ADDRESS
  173. PciBridgePrefetchMemoryBase(
  174. IN PPCI_COMMON_CONFIG Config
  175. )
  176. /*++
  177. Routine Description:
  178. Compute the 64 bit base Prefetchable Memory address being passed
  179. by the bridge whose config space is at Config.
  180. The Prefetchable Memory base address is always 1MB aligned.
  181. Arguments:
  182. Config - Pointer to a buffer containing the device's common (type1)
  183. configuration header.
  184. Return Value:
  185. PHYSICAL_ADDRESS containing the Prefetchable Memory Base address.
  186. --*/
  187. {
  188. BOOLEAN prefetch64Bit;
  189. PHYSICAL_ADDRESS base;
  190. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  191. prefetch64Bit = (Config->u.type1.PrefetchBase & 0x000f) == 1;
  192. base.QuadPart = 0;
  193. base.LowPart = (Config->u.type1.PrefetchBase & 0xfff0) << 16;
  194. if (prefetch64Bit) {
  195. base.HighPart = Config->u.type1.PrefetchBaseUpper32;
  196. }
  197. return base;
  198. }
  199. PHYSICAL_ADDRESS
  200. PciBridgePrefetchMemoryLimit(
  201. IN PPCI_COMMON_CONFIG Config
  202. )
  203. /*++
  204. Routine Description:
  205. Compute the 64 bit Prefetchable Memory address limit being passed
  206. by the bridge whose config space is at Config.
  207. The prefetchable memory limit is always at the byte preceeding a
  208. 1MB boundary, that is, the least significant 20 bits are all ones.
  209. The next 12 bits are obtained from the upper 12 bits of
  210. Config->u.type1.PrefetchLimit. The botton 4 bits of that field
  211. provide a flag indicating whether the upper 32 bits should be obtained
  212. from Config->u.type1.PrefetchLimitUpper32 or should be 0.
  213. Arguments:
  214. Config - Pointer to a buffer containing the device's common (type1)
  215. configuration header.
  216. Return Value:
  217. PHYSICAL_ADDRESS containing the prefetchable memory limit.
  218. --*/
  219. {
  220. BOOLEAN prefetch64Bit;
  221. PHYSICAL_ADDRESS limit;
  222. ASSERT(PciGetConfigurationType(Config) == PCI_BRIDGE_TYPE);
  223. prefetch64Bit = (Config->u.type1.PrefetchLimit & 0x000f) == 1;
  224. limit.LowPart = (Config->u.type1.PrefetchLimit & 0xfff0) << 16;
  225. limit.LowPart |= 0xfffff;
  226. if (prefetch64Bit) {
  227. limit.HighPart = Config->u.type1.PrefetchLimitUpper32;
  228. } else {
  229. limit.HighPart = 0;
  230. }
  231. return limit;
  232. }
  233. ULONG
  234. PciBridgeMemoryWorstCaseAlignment(
  235. IN ULONG Length
  236. )
  237. /*
  238. Description:
  239. This function calculates the maximum alignment a device can have if it is
  240. behind a bridge with a memory window of Length. This turns out to be finding
  241. the top bit set in the length.
  242. Arguments:
  243. Length - the size of the memory window
  244. Return Value:
  245. The alignment
  246. */
  247. {
  248. ULONG alignment = 0x80000000;
  249. if (Length == 0) {
  250. ASSERT(Length != 0);
  251. return 0;
  252. }
  253. while (!(Length & alignment)) {
  254. alignment >>= 1;
  255. }
  256. return alignment;
  257. }
  258. VOID
  259. PPBridge_MassageHeaderForLimitsDetermination(
  260. IN IN PPCI_CONFIGURABLE_OBJECT This
  261. )
  262. /*++
  263. Description:
  264. The configuration header for a PCI to PCI bridge has two BARs
  265. and three range descriptors (IO, Memory and Prefetchable Memory).
  266. Arguments:
  267. This - Pointer to a PCI driver "configurable" object. This
  268. object contains configuration data for the function
  269. currently being configured.
  270. Return Value:
  271. Returns status indicating the success or failure of this routine.
  272. The Working configuration has been modified so that all range
  273. fields have been set to their maximum possible values.
  274. The Current configuration has been modified such that writing it
  275. to the hardware will restore the hardware to it's current (disabled)
  276. state.
  277. --*/
  278. {
  279. PUCHAR fStart;
  280. ULONG fLength;
  281. //
  282. // Set BARs and ranges to all ones in the working copy. Note
  283. // that the method used will overwrite some other values that
  284. // need to be restored before going any further.
  285. //
  286. fStart = (PUCHAR)&This->Working->u.type1.BaseAddresses;
  287. fLength = FIELD_OFFSET(PCI_COMMON_CONFIG,u.type1.CapabilitiesPtr) -
  288. FIELD_OFFSET(PCI_COMMON_CONFIG,u.type1.BaseAddresses[0]);
  289. RtlFillMemory(fStart, fLength, 0xff);
  290. //
  291. // Restore Primary/Secondary/Subordinate bus numbers and
  292. // Secondary Latency from the "Current" copy. (All four
  293. // are byte fields in the same ULONG so cheat).
  294. //
  295. *(PULONG)&This->Working->u.type1.PrimaryBus =
  296. *(PULONG)&This->Current->u.type1.PrimaryBus;
  297. //
  298. // Set the ROM to its maximum as well,... and disable it.
  299. //
  300. This->Working->u.type0.ROMBaseAddress =
  301. 0xffffffff & ~PCI_ROMADDRESS_ENABLED;
  302. This->PrivateData = This->Current->u.type1.SecondaryStatus;
  303. This->Current->u.type1.SecondaryStatus = 0;
  304. This->Working->u.type1.SecondaryStatus = 0;
  305. return;
  306. }
  307. VOID
  308. PPBridge_RestoreCurrent(
  309. IN PPCI_CONFIGURABLE_OBJECT This
  310. )
  311. /*++
  312. Description:
  313. Restore any type specific fields in the original copy of config
  314. space. In the case of PCI-PCI bridges, the secondary status field.
  315. Arguments:
  316. This - Pointer to a PCI driver "configurable" object. This
  317. object contains configuration data for the function
  318. currently being configured.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. This->Current->u.type1.SecondaryStatus = (USHORT)(This->PrivateData);
  324. }
  325. VOID
  326. PPBridge_SaveLimits(
  327. IN PPCI_CONFIGURABLE_OBJECT This
  328. )
  329. /*++
  330. Description:
  331. Fill in the Limit structure with a IO_RESOURCE_REQUIREMENT
  332. for each implemented BAR.
  333. Arguments:
  334. This - Pointer to a PCI driver "configurable" object. This
  335. object contains configuration data for the function
  336. currently being configured.
  337. Return Value:
  338. None.
  339. --*/
  340. {
  341. ULONG index;
  342. PIO_RESOURCE_DESCRIPTOR descriptor;
  343. PPCI_COMMON_CONFIG working = This->Working;
  344. PULONG bar = working->u.type1.BaseAddresses;
  345. PHYSICAL_ADDRESS limit;
  346. descriptor = This->PdoExtension->Resources->Limit;
  347. //
  348. // Create an IO_RESOURCE_DESCRIPTOR for each implemented
  349. // resource supported by this function.
  350. //
  351. for (index = 0; index < PCI_TYPE1_ADDRESSES; index++) {
  352. if (PciCreateIoDescriptorFromBarLimit(descriptor, bar, FALSE)) {
  353. //
  354. // This base address register is 64 bit, skip one.
  355. //
  356. ASSERT((index+1) < PCI_TYPE1_ADDRESSES);
  357. index++;
  358. bar++;
  359. //
  360. // Null descriptor in place holder.
  361. //
  362. descriptor++;
  363. descriptor->Type = CmResourceTypeNull;
  364. }
  365. descriptor++;
  366. bar++;
  367. }
  368. //
  369. // Check if we support subtractive decode (if we do then clear the VGA and
  370. // ISA bits as they don't mean anything for subtractive bridges)
  371. //
  372. if (PciBridgeIsSubtractiveDecode(This)) {
  373. This->PdoExtension->Dependent.type1.SubtractiveDecode = TRUE;
  374. This->PdoExtension->Dependent.type1.VgaBitSet = FALSE;
  375. This->PdoExtension->Dependent.type1.IsaBitSet = FALSE;
  376. }
  377. //
  378. // Skip the bridge windows for a subtractive bridge
  379. //
  380. if (!This->PdoExtension->Dependent.type1.SubtractiveDecode) {
  381. for (index = PciBridgeIo;
  382. index < PciBridgeMaxPassThru;
  383. index++, descriptor++) {
  384. limit.HighPart = 0;
  385. descriptor->u.Generic.MinimumAddress.QuadPart = 0;
  386. switch (index) {
  387. case PciBridgeIo:
  388. //
  389. // Get I/O Limit.
  390. //
  391. //
  392. ASSERT(working->u.type1.IOLimit != 0);
  393. //
  394. // IO Space is implemented by the bridge, calculate
  395. // the real limit.
  396. //
  397. // The IOLimit field is one byte, the upper nibble of
  398. // which represents the 4096 byte block number of the
  399. // highest 4096 byte block that can be addressed by
  400. // this bridge. The highest addressable byte is 4095
  401. // bytes higher.
  402. //
  403. limit.LowPart = PciBridgeIoLimit(working);
  404. //
  405. // The lower nibble is a flag. The least significant bit
  406. // indicates that this bridge supports I/O ranges up to
  407. // 4GB and the other bits are currently reserved.
  408. //
  409. ASSERT((working->u.type1.IOLimit & 0x0e) == 0);
  410. descriptor->Type = CmResourceTypePort;
  411. descriptor->Flags = CM_RESOURCE_PORT_IO
  412. | CM_RESOURCE_PORT_POSITIVE_DECODE
  413. | CM_RESOURCE_PORT_WINDOW_DECODE;
  414. descriptor->u.Generic.Alignment = 0x1000;
  415. break;
  416. case PciBridgeMem:
  417. //
  418. // Get Memory Limit. Memory limit is not optional on a bridge.
  419. // It is a 16 bit field in which only the upper 12 bits are
  420. // implemented, the lower 4 bits MUST be zero.
  421. //
  422. limit.LowPart = PciBridgeMemoryLimit(working);
  423. ASSERT((working->u.type1.MemoryLimit & 0xf) == 0);
  424. descriptor->Type = CmResourceTypeMemory;
  425. descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  426. descriptor->u.Generic.Alignment = 0x100000;
  427. break;
  428. case PciBridgePrefetch:
  429. //
  430. // Get Prefetchable memory limit.
  431. //
  432. if (working->u.type1.PrefetchLimit != 0) {
  433. //
  434. // Prefetchable memory is implemented by this bridge.
  435. //
  436. limit = PciBridgePrefetchMemoryLimit(working);
  437. } else {
  438. //
  439. // prefetchable memory not implemented on this bridge.
  440. //
  441. descriptor->Type = CmResourceTypeNull;
  442. continue;
  443. }
  444. descriptor->Type = CmResourceTypeMemory;
  445. descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
  446. CM_RESOURCE_MEMORY_PREFETCHABLE;;
  447. descriptor->u.Generic.Alignment = 0x100000;
  448. break;
  449. }
  450. descriptor->u.Generic.MinimumAddress.QuadPart = 0;
  451. descriptor->u.Generic.MaximumAddress = limit;
  452. //
  453. // Length is meaningless here.
  454. //
  455. descriptor->u.Generic.Length = 0;
  456. }
  457. }
  458. //
  459. // Do the BAR thing for the ROM if its active
  460. //
  461. if (!(This->Current->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)) {
  462. return;
  463. }
  464. PciCreateIoDescriptorFromBarLimit(descriptor,
  465. &working->u.type1.ROMBaseAddress,
  466. TRUE);
  467. }
  468. VOID
  469. PPBridge_SaveCurrentSettings(
  470. IN PPCI_CONFIGURABLE_OBJECT This
  471. )
  472. /*++
  473. Description:
  474. Fill in the Resource array in the PDO extension with the current
  475. settings for each implemented BAR.
  476. Also, fill in the PDO Extension's Dependent structure.
  477. Arguments:
  478. This - Pointer to a PCI driver "configurable" object. This
  479. object contains configuration data for the function
  480. currently being configured.
  481. Return Value:
  482. None.
  483. --*/
  484. {
  485. NTSTATUS status;
  486. ULONG index;
  487. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
  488. PIO_RESOURCE_DESCRIPTOR ioResourceDescriptor;
  489. PPCI_COMMON_CONFIG current;
  490. ULONG bar;
  491. PHYSICAL_ADDRESS base;
  492. PHYSICAL_ADDRESS limit;
  493. PHYSICAL_ADDRESS length;
  494. BOOLEAN zeroBaseOk;
  495. BOOLEAN updateAlignment;
  496. PCI_COMMON_HEADER biosConfigBuffer;
  497. PPCI_COMMON_CONFIG biosConfig = (PPCI_COMMON_CONFIG) &biosConfigBuffer;
  498. partial = This->PdoExtension->Resources->Current;
  499. ioResourceDescriptor = This->PdoExtension->Resources->Limit;
  500. //
  501. // Check if the device has either IO or Memory enabled
  502. //
  503. if (This->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)) {
  504. //
  505. // It does so use the real current settings
  506. //
  507. current = This->Current;
  508. } else {
  509. //
  510. // Check if we have a bios config
  511. //
  512. status = PciGetBiosConfig(This->PdoExtension, biosConfig);
  513. if (NT_SUCCESS(status)) {
  514. //
  515. // Ok - this is a bit gross but until multi level/multi arbiter
  516. // rebalance working this will have to do. We use the initial bios
  517. // configuration config space to record the current settings. The
  518. // current settings is used for responding to the QUERY_RESOURCES
  519. // and the QUERY_RESOURCE_REQUIREMENTS. We want to have the original
  520. // requirements be reported as the preferred location for this
  521. // bridge and, more importantly, for the original window sizes to
  522. // be used. We do not however want to report this as the resources
  523. // currently being decoded as they arn't but we have already checked
  524. // that the decodes of the device are off so PciQueryResources will
  525. // not report these.
  526. //
  527. current = biosConfig;
  528. } else {
  529. //
  530. // This is a bridge disabled by the BIOS (or one it didn't see) so
  531. // minimal requirements are likely...
  532. //
  533. current = This->Current;
  534. }
  535. }
  536. //
  537. // Create an IO_RESOURCE_DESCRIPTOR for each implemented
  538. // resource supported by this function.
  539. //
  540. for (index = 0;
  541. index < PCI_TYPE1_RANGE_COUNT;
  542. index++, partial++, ioResourceDescriptor++) {
  543. partial->Type = ioResourceDescriptor->Type;
  544. //
  545. // If this entry is not implemented, no further processing for
  546. // this partial descriptor.
  547. //
  548. if (partial->Type == CmResourceTypeNull) {
  549. continue;
  550. }
  551. partial->Flags = ioResourceDescriptor->Flags;
  552. partial->ShareDisposition = ioResourceDescriptor->ShareDisposition;
  553. base.HighPart = 0;
  554. //
  555. // Depending on where we are in the 'set' we have to look
  556. // at the data differently.
  557. //
  558. // In a header type 1, there are two BARs, I/O limit and
  559. // base, Memory limit and base, prefetchable limit and base
  560. // and a ROM BAR.
  561. //
  562. if ((index < PCI_TYPE1_ADDRESSES) ||
  563. (index == (PCI_TYPE1_RANGE_COUNT-1))) {
  564. ULONG addressMask;
  565. //
  566. // Handle BARs
  567. //
  568. if (index < PCI_TYPE1_ADDRESSES) {
  569. bar = current->u.type1.BaseAddresses[index];
  570. if ((bar & PCI_ADDRESS_IO_SPACE) != 0) {
  571. addressMask = PCI_ADDRESS_IO_ADDRESS_MASK;
  572. } else {
  573. addressMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  574. if ((bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) {
  575. //
  576. // 64 bit address, consume next BAR.
  577. //
  578. base.HighPart = current->u.type1.BaseAddresses[index+1];
  579. }
  580. }
  581. } else {
  582. bar = current->u.type1.ROMBaseAddress;
  583. addressMask = PCI_ADDRESS_ROM_ADDRESS_MASK;
  584. }
  585. base.LowPart = bar & addressMask;
  586. //
  587. // Copy the length from the limits descriptor.
  588. //
  589. partial->u.Generic.Length = ioResourceDescriptor->u.Generic.Length;
  590. } else {
  591. //
  592. // It's one of the base/limit pairs (each a different format).
  593. //
  594. limit.HighPart = 0;
  595. zeroBaseOk = FALSE;
  596. updateAlignment = FALSE;
  597. switch (index - PCI_TYPE1_ADDRESSES + PciBridgeIo) {
  598. case PciBridgeIo:
  599. //
  600. // Get I/O range.
  601. //
  602. //
  603. base.LowPart = PciBridgeIoBase(current);
  604. limit.LowPart = PciBridgeIoLimit(current);
  605. if (base.LowPart == 0) {
  606. if (This->Working->u.type1.IOLimit != 0) {
  607. //
  608. // The bridge's IO IObase and IOlimit are both
  609. // zero but the maximum setting of IOlimit is
  610. // non-zero. This means the bridge is decoding
  611. // IO addresses 0 thru 0xfff.
  612. //
  613. zeroBaseOk = TRUE;
  614. }
  615. }
  616. break;
  617. case PciBridgeMem:
  618. //
  619. // Get Memory range.
  620. //
  621. base.LowPart = PciBridgeMemoryBase(current);
  622. limit.LowPart = PciBridgeMemoryLimit(current);
  623. updateAlignment = TRUE;
  624. break;
  625. case PciBridgePrefetch:
  626. ASSERT(partial->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE);
  627. //
  628. // Get Prefetchable memory range.
  629. //
  630. base = PciBridgePrefetchMemoryBase(current);
  631. limit = PciBridgePrefetchMemoryLimit(current);
  632. updateAlignment = TRUE;
  633. break;
  634. }
  635. if ((ULONGLONG)base.QuadPart > (ULONGLONG)limit.QuadPart) {
  636. //
  637. // This resource is disabled - remove the current setting AND
  638. // the requirement
  639. //
  640. partial->Type = CmResourceTypeNull;
  641. ioResourceDescriptor->Type = CmResourceTypeNull;
  642. continue;
  643. } else if (((base.QuadPart == 0) && (!zeroBaseOk))) {
  644. //
  645. // This resource is not currently being bridged.
  646. //
  647. partial->Type = CmResourceTypeNull;
  648. continue;
  649. }
  650. length.QuadPart = limit.QuadPart - base.QuadPart + 1;
  651. ASSERT(length.HighPart == 0);
  652. partial->u.Generic.Length = length.LowPart;
  653. if (updateAlignment) {
  654. //
  655. // We don't know what the alignment requirements for the bridge
  656. // are because that is dependent on the requirements of the
  657. // childen of the bridge which we haven't enumerated yet, so
  658. // we use the maximal alignment that a child could have based
  659. // on the size of the bridge window. We don't need to do this
  660. // for IO requirements because the alignment requirements of
  661. // the bridge are greater than or equal to any child.
  662. //
  663. ASSERT(partial->u.Generic.Length > 0);
  664. ioResourceDescriptor->u.Generic.Alignment =
  665. PciBridgeMemoryWorstCaseAlignment(partial->u.Generic.Length);
  666. }
  667. }
  668. partial->u.Generic.Start = base;
  669. }
  670. //
  671. // Up until this point we might have been using the bios config but we need
  672. // to know the real current settings for thr bus number registers and the
  673. // bridge control register so undo the falsification here
  674. //
  675. current = This->Current;
  676. //
  677. // Save the header specific data in the PDO.
  678. //
  679. This->PdoExtension->Dependent.type1.PrimaryBus =
  680. current->u.type1.PrimaryBus;
  681. This->PdoExtension->Dependent.type1.SecondaryBus =
  682. current->u.type1.SecondaryBus;
  683. This->PdoExtension->Dependent.type1.SubordinateBus =
  684. current->u.type1.SubordinateBus;
  685. if (!This->PdoExtension->Dependent.type1.SubtractiveDecode) {
  686. //
  687. // If the VGA bit is set in the bridge control register, we
  688. // will be passing an additional memory range and a bunch of
  689. // IO ranges, possibly in conflict with the normal ranges.
  690. //
  691. // If this is going to be the case, BuildRequirementsList needs
  692. // to know to allocate a bunch of additional resources.
  693. //
  694. // How many? One Memory range 0xa0000 thru 0xbffff plus IO
  695. // ranges 3b0 thru 3bb and 3c0 thru 3df AND every 10 bit alias
  696. // to these in the possible 16 bit IO space.
  697. //
  698. // However, it turns out there's this neat flag so we can
  699. // tell IO that this resource uses 10 bit decode so we only
  700. // need to build the two IO port resources.
  701. //
  702. if (current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) {
  703. This->PdoExtension->AdditionalResourceCount =
  704. 1 + // Device Private
  705. 1 + // Memory
  706. 2; // Io
  707. This->PdoExtension->Dependent.type1.VgaBitSet = TRUE;
  708. }
  709. This->PdoExtension->Dependent.type1.IsaBitSet =
  710. (current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA) != 0;
  711. } else {
  712. ASSERT(!This->PdoExtension->Dependent.type1.VgaBitSet);
  713. ASSERT(!This->PdoExtension->Dependent.type1.IsaBitSet);
  714. }
  715. #if INTEL_ICH_HACKS
  716. if (PCI_IS_INTEL_ICH(This->PdoExtension)) {
  717. PPCI_FDO_EXTENSION fdo;
  718. fdo = PCI_PARENT_FDOX(This->PdoExtension);
  719. fdo->IchHackConfig = ExAllocatePool(NonPagedPool, PCI_COMMON_HDR_LENGTH);
  720. if (!fdo->IchHackConfig) {
  721. //
  722. // Um - we're screwed
  723. //
  724. return;
  725. }
  726. RtlCopyMemory(fdo->IchHackConfig, This->Current, PCI_COMMON_HDR_LENGTH);
  727. }
  728. #endif
  729. }
  730. VOID
  731. PPBridge_ChangeResourceSettings(
  732. IN PPCI_PDO_EXTENSION PdoExtension,
  733. IN PPCI_COMMON_CONFIG CommonConfig
  734. )
  735. {
  736. ULONG index;
  737. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
  738. ULONG bar;
  739. ULONG lowPart;
  740. ULONG limit;
  741. PHYSICAL_ADDRESS bigLimit;
  742. #if DBG
  743. BOOLEAN has32BitIo = ((CommonConfig->u.type1.IOBase & 0xf) == 1);
  744. #endif
  745. if (PCI_IS_INTEL_ICH(PdoExtension)) {
  746. //
  747. // If this is an ICH then copy back how it was configured before.
  748. // Yes this is a vile hack.
  749. //
  750. PPCI_FDO_EXTENSION fdo = PCI_PARENT_FDOX(PdoExtension);
  751. ASSERT(!PdoExtension->Resources);
  752. CommonConfig->u.type1.IOBase = fdo->IchHackConfig->u.type1.IOBase;
  753. CommonConfig->u.type1.IOLimit = fdo->IchHackConfig->u.type1.IOLimit;
  754. CommonConfig->u.type1.MemoryBase = fdo->IchHackConfig->u.type1.MemoryBase;
  755. CommonConfig->u.type1.MemoryLimit = fdo->IchHackConfig->u.type1.MemoryLimit;
  756. CommonConfig->u.type1.PrefetchBase = fdo->IchHackConfig->u.type1.PrefetchBase;
  757. CommonConfig->u.type1.PrefetchLimit = fdo->IchHackConfig->u.type1.PrefetchLimit;
  758. CommonConfig->u.type1.PrefetchBaseUpper32 = fdo->IchHackConfig->u.type1.PrefetchBaseUpper32;
  759. CommonConfig->u.type1.PrefetchLimitUpper32 = fdo->IchHackConfig->u.type1.PrefetchLimitUpper32;
  760. CommonConfig->u.type1.IOBaseUpper16 = fdo->IchHackConfig->u.type1.IOBaseUpper16;
  761. CommonConfig->u.type1.IOLimitUpper16 = fdo->IchHackConfig->u.type1.IOLimitUpper16;
  762. } else {
  763. //
  764. // Close the bridge windows and only open them is appropriate resources
  765. // have been assigned
  766. //
  767. CommonConfig->u.type1.IOBase = 0xff;
  768. CommonConfig->u.type1.IOLimit = 0x0;
  769. CommonConfig->u.type1.MemoryBase = 0xffff;
  770. CommonConfig->u.type1.MemoryLimit = 0x0;
  771. CommonConfig->u.type1.PrefetchBase = 0xffff;
  772. CommonConfig->u.type1.PrefetchLimit = 0x0;
  773. CommonConfig->u.type1.PrefetchBaseUpper32 = 0;
  774. CommonConfig->u.type1.PrefetchLimitUpper32 = 0;
  775. CommonConfig->u.type1.IOBaseUpper16 = 0;
  776. CommonConfig->u.type1.IOLimitUpper16 = 0;
  777. }
  778. if (PdoExtension->Resources) {
  779. partial = PdoExtension->Resources->Current;
  780. for (index = 0;
  781. index < PCI_TYPE1_RANGE_COUNT;
  782. index++, partial++) {
  783. //
  784. // If this entry is not implemented, no further processing for
  785. // this partial descriptor.
  786. //
  787. if (partial->Type == CmResourceTypeNull) {
  788. continue;
  789. }
  790. lowPart = partial->u.Generic.Start.LowPart;
  791. //
  792. // Depending on where we are in the 'set' we have to look
  793. // at the data differently.
  794. //
  795. // In a header type 1, there are two BARs, I/O limit and
  796. // base, Memory limit and base, prefetchable limit and base
  797. // and a ROM BAR.
  798. //
  799. if ((index < PCI_TYPE1_ADDRESSES) ||
  800. (index == (PCI_TYPE1_RANGE_COUNT-1))) {
  801. //
  802. // Handle BARs
  803. //
  804. if (index < PCI_TYPE1_ADDRESSES) {
  805. bar = CommonConfig->u.type1.BaseAddresses[index];
  806. if (partial->Type == CmResourceTypeMemory){
  807. if ((bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) {
  808. //
  809. // 64 bit address, set upper 32 bits in next bar.
  810. //
  811. ASSERT(index == 0);
  812. ASSERT((partial+1)->Type == CmResourceTypeNull);
  813. CommonConfig->u.type1.BaseAddresses[1] =
  814. partial->u.Generic.Start.HighPart;
  815. #if DBG
  816. } else if ((bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT) {
  817. //
  818. // This device must locate below 1MB, make sure we're
  819. // configuring it that way.
  820. //
  821. ASSERT((lowPart & 0xfff00000) == 0);
  822. #endif
  823. }
  824. }
  825. CommonConfig->u.type1.BaseAddresses[index] = lowPart;
  826. } else {
  827. ASSERT(partial->Type == CmResourceTypeMemory);
  828. bar = CommonConfig->u.type1.ROMBaseAddress;
  829. bar &= ~PCI_ADDRESS_ROM_ADDRESS_MASK;
  830. bar |= (lowPart & PCI_ADDRESS_ROM_ADDRESS_MASK);
  831. CommonConfig->u.type0.ROMBaseAddress = bar;
  832. }
  833. } else {
  834. //
  835. // It's one of the base/limit pairs (each a different format).
  836. //
  837. limit = lowPart - 1 + partial->u.Generic.Length;
  838. switch (index - PCI_TYPE1_ADDRESSES + PciBridgeIo) {
  839. case PciBridgeIo:
  840. //
  841. // Set I/O range.
  842. //
  843. //
  844. #if DBG
  845. ASSERT(((lowPart & 0xfff) == 0) && ((limit & 0xfff) == 0xfff));
  846. if (!has32BitIo) {
  847. ASSERT(((lowPart | limit) & 0xffff0000) == 0);
  848. }
  849. #endif
  850. CommonConfig->u.type1.IOBaseUpper16 = (USHORT)(lowPart >> 16);
  851. CommonConfig->u.type1.IOLimitUpper16 = (USHORT)(limit >> 16);
  852. CommonConfig->u.type1.IOBase = (UCHAR)((lowPart >> 8) & 0xf0);
  853. CommonConfig->u.type1.IOLimit = (UCHAR)((limit >> 8) & 0xf0);
  854. break;
  855. case PciBridgeMem:
  856. //
  857. // Set Memory range.
  858. //
  859. ASSERT(((lowPart & 0xfffff) == 0) &&
  860. ((limit & 0xfffff) == 0xfffff));
  861. CommonConfig->u.type1.MemoryBase = (USHORT)(lowPart >> 16);
  862. CommonConfig->u.type1.MemoryLimit =
  863. (USHORT)((limit >> 16) & 0xfff0);
  864. break;
  865. case PciBridgePrefetch:
  866. //
  867. // Set Prefetchable memory range.
  868. //
  869. bigLimit.QuadPart = partial->u.Generic.Start.QuadPart - 1 +
  870. partial->u.Generic.Length;
  871. ASSERT(((lowPart & 0xfffff) == 0) &&
  872. (bigLimit.LowPart & 0xfffff) == 0xfffff);
  873. CommonConfig->u.type1.PrefetchBase = (USHORT)(lowPart >> 16);
  874. CommonConfig->u.type1.PrefetchLimit =
  875. (USHORT)((bigLimit.LowPart >> 16) & 0xfff0);
  876. CommonConfig->u.type1.PrefetchBaseUpper32 =
  877. partial->u.Generic.Start.HighPart;
  878. CommonConfig->u.type1.PrefetchLimitUpper32 = bigLimit.HighPart;
  879. break;
  880. }
  881. }
  882. }
  883. }
  884. //
  885. // Restore the bridge's PCI bus #'s
  886. //
  887. CommonConfig->u.type1.PrimaryBus =
  888. PdoExtension->Dependent.type1.PrimaryBus;
  889. CommonConfig->u.type1.SecondaryBus =
  890. PdoExtension->Dependent.type1.SecondaryBus;
  891. CommonConfig->u.type1.SubordinateBus =
  892. PdoExtension->Dependent.type1.SubordinateBus;
  893. //
  894. // Set the bridge control register bits we might have changes
  895. //
  896. if (PdoExtension->Dependent.type1.IsaBitSet) {
  897. CommonConfig->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_ISA;
  898. }
  899. if (PdoExtension->Dependent.type1.VgaBitSet) {
  900. CommonConfig->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_VGA;
  901. }
  902. }
  903. VOID
  904. PPBridge_GetAdditionalResourceDescriptors(
  905. IN PPCI_PDO_EXTENSION PdoExtension,
  906. IN PPCI_COMMON_CONFIG CommonConfig,
  907. IN PIO_RESOURCE_DESCRIPTOR Resource
  908. )
  909. {
  910. //
  911. // If this bridge is has the ISA or VGA bits set in its Bridge
  912. // Control Register, or is doing subtractive decoding, now would
  913. // be a good time to add the descriptors.
  914. //
  915. #define SET_RESOURCE(type, minimum, maximum, flags) \
  916. \
  917. Resource->Type = type; \
  918. Resource->Flags = flags; \
  919. Resource->u.Generic.Length = (maximum) - (minimum) + 1; \
  920. Resource->u.Generic.Alignment = 1; \
  921. Resource->u.Generic.MinimumAddress.QuadPart = minimum; \
  922. Resource->u.Generic.MaximumAddress.QuadPart = maximum; \
  923. Resource++;
  924. if (CommonConfig->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) {
  925. //
  926. // Add VGA ranges.
  927. //
  928. // These are memory from 0xA0000 thru 0xBFFFF, and IO ranges
  929. // 3b0 thru 3bb and 3c0 thru 3df. These will be passed
  930. // regardless of the memory and IO range settings but IS
  931. // controlled by the Memory and IO command register bits.
  932. //
  933. // Note: It's also going to do any 10 bit alias to the two
  934. // IO ranges.
  935. //
  936. // First, indicate that the rest of the list is not for
  937. // generic processing.
  938. //
  939. Resource->Type = CmResourceTypeDevicePrivate;
  940. Resource->u.DevicePrivate.Data[0] = PciPrivateSkipList;
  941. Resource->u.DevicePrivate.Data[1] = 3; // count to skip
  942. Resource++;
  943. //
  944. // Set the memory descriptor.
  945. //
  946. SET_RESOURCE(CmResourceTypeMemory, 0xa0000, 0xbffff, 0);
  947. //
  948. // Do the two IO ranges AND their aliases positive decode.
  949. //
  950. SET_RESOURCE(CmResourceTypePort,
  951. 0x3b0,
  952. 0x3bb,
  953. CM_RESOURCE_PORT_10_BIT_DECODE | CM_RESOURCE_PORT_POSITIVE_DECODE);
  954. SET_RESOURCE(CmResourceTypePort,
  955. 0x3c0,
  956. 0x3df,
  957. CM_RESOURCE_PORT_10_BIT_DECODE | CM_RESOURCE_PORT_POSITIVE_DECODE);
  958. }
  959. return;
  960. #undef SET_RESOURCE
  961. }
  962. NTSTATUS
  963. PPBridge_ResetDevice(
  964. IN PPCI_PDO_EXTENSION PdoExtension,
  965. IN PPCI_COMMON_CONFIG CommonConfig
  966. )
  967. {
  968. USHORT bridgeControl;
  969. //
  970. // Only reset if device is not enabled and a reset is necessary
  971. //
  972. if (CommonConfig->Command == 0 && (PdoExtension->HackFlags & PCI_HACK_RESET_BRIDGE_ON_POWERUP)) {
  973. //
  974. // We should never have powered down a device on the debug path so we should
  975. // never have to reset it on the way back up... but you never know!
  976. //
  977. ASSERT(!PdoExtension->OnDebugPath);
  978. PciReadDeviceConfig(
  979. PdoExtension,
  980. &bridgeControl,
  981. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type1.BridgeControl),
  982. sizeof(bridgeControl)
  983. );
  984. bridgeControl |= PCI_ASSERT_BRIDGE_RESET;
  985. PciWriteDeviceConfig(
  986. PdoExtension,
  987. &bridgeControl,
  988. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type1.BridgeControl),
  989. sizeof(bridgeControl)
  990. );
  991. //
  992. // Per PCI 2.1, reset must remain asserted for a minimum
  993. // of 100 us.
  994. //
  995. KeStallExecutionProcessor(100);
  996. bridgeControl &= ~PCI_ASSERT_BRIDGE_RESET;
  997. PciWriteDeviceConfig(
  998. PdoExtension,
  999. &bridgeControl,
  1000. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type1.BridgeControl),
  1001. sizeof(bridgeControl)
  1002. );
  1003. }
  1004. return STATUS_SUCCESS;
  1005. }
  1006. BOOLEAN
  1007. PciBridgeIsSubtractiveDecode(
  1008. IN PPCI_CONFIGURABLE_OBJECT This
  1009. )
  1010. {
  1011. ASSERT(This->Current->BaseClass == 0x6 && This->Current->SubClass == 0x4);
  1012. //
  1013. // Bridges are subtractive if their programming interface of 0x1 or we
  1014. // have the appropriate hack flag set.
  1015. //
  1016. // They are also subtractive if the IO Limit register isn't sticky (we tried
  1017. // to write 0xFF to it (see MassageHeader) but the top nibble which is meant
  1018. // to be sticky did't stick).
  1019. //
  1020. // By tradition (NT4/Win9x) this means that the bridge performs subtractive
  1021. // decode of both memory and IO.Unfortunatly the PCI spec says that IO in
  1022. // bridges is optional and so if anyone builds a bridge that doesn't do IO
  1023. // then we will think they have subtractive IO. One might think that the
  1024. // non-optional memory limit register would have been a better choice but
  1025. // seeing as this is how it works so lets be consistent.
  1026. //
  1027. if (!((This->PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE)
  1028. || (This->Current->ProgIf == 0x1)
  1029. || ((This->Working->u.type1.IOLimit & 0xf0) != 0xf0))) {
  1030. //
  1031. // This is a positive decode bridge
  1032. //
  1033. return FALSE;
  1034. }
  1035. //
  1036. // Intel built a device that claims to be a PCI-PCI bridge - it is actually
  1037. // a hublink-PCI bridge. It operates like a PCI-PCI bridge only that it
  1038. // subtractively decodes all unclaimed cycles not in the bridge window.
  1039. // Yes so it is positive and subtractive at the same time - we can support
  1040. // this in a later release using partial arbitration but its too late for
  1041. // that now. It would be nice is we could detect such bridges - perhaps
  1042. // with a Programming Interface of 2.
  1043. //
  1044. // We are giving the OEM a choice - they can have a positive window and
  1045. // operate just like a normal PCI-PCI bridge (and thus can use peer-peer
  1046. // trafic) OR they cah operate like a subtractive PCI-PCI bridge (so ISA
  1047. // like devices (eg PCMCIA, PCI Sound Cards) work but peer-peer doesn't)).
  1048. //
  1049. // Given that most machines will want the subtractive mode, we default to
  1050. // that using the hack table (and this code relies on the correct entries
  1051. // being in said table). If the OEM wants to enfore positive decode
  1052. // they add an ACPI control method under the parent of the bridge. This
  1053. // method is a package that enumerates to a list of _ADR style slot numbers
  1054. // for each the bridge we should treat as a vanila PCI-PCI bridge.
  1055. //
  1056. // Note this is only tried for the hublink bridges we know about.
  1057. //
  1058. if (This->PdoExtension->VendorId == 0x8086
  1059. && (This->PdoExtension->DeviceId == 0x2418
  1060. || This->PdoExtension->DeviceId == 0x2428
  1061. || This->PdoExtension->DeviceId == 0x244E
  1062. || This->PdoExtension->DeviceId == 0x2448)
  1063. ) {
  1064. //
  1065. // Run the PDEC method if its present
  1066. //
  1067. if (PciBridgeIsPositiveDecode(This->PdoExtension)) {
  1068. PciDebugPrint(
  1069. PciDbgInformative,
  1070. "Putting bridge in positive decode because of PDEC\n"
  1071. );
  1072. return FALSE;
  1073. }
  1074. }
  1075. PciDebugPrint(
  1076. PciDbgInformative,
  1077. "PCI : Subtractive decode on Bus 0x%x\n",
  1078. This->Current->u.type1.SecondaryBus
  1079. );
  1080. //
  1081. // Force us to update the hardware and thus close the windows if necessary.
  1082. //
  1083. This->PdoExtension->UpdateHardware = TRUE;
  1084. return TRUE;
  1085. }
  1086. BOOLEAN
  1087. PciBridgeIsPositiveDecode(
  1088. IN PPCI_PDO_EXTENSION Pdo
  1089. )
  1090. /*++
  1091. Description:
  1092. Determines if a PCI-PCI bridge device performs positive decode even though
  1093. it says subtractive (either ProfIf=1 or from a hack flag). This is currently
  1094. only the Intel ICH.
  1095. Arguments:
  1096. Pdo - The PDO extension for the bridge
  1097. Return Value:
  1098. TRUE - the bridge performs positive decode, FASLE it does not
  1099. --*/
  1100. {
  1101. return PciIsSlotPresentInParentMethod(Pdo, (ULONG)'CEDP');
  1102. }