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