PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/PciBusNoEnumerationDxe/PciEnumeratorSupport.c

https://github.com/SunnyKi/bareBoot
C | 1404 lines | 742 code | 223 blank | 439 comment | 116 complexity | 251955054e240ee1af619949925ee518 MD5 | raw file
  1. /*++
  2. Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
  3. This program and the accompanying materials
  4. are licensed and made available under the terms and conditions of the BSD License
  5. which accompanies this distribution. The full text of the license may be found at
  6. http://opensource.org/licenses/bsd-license.php
  7. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  9. Module Name:
  10. PciEnumeratorSupport.c
  11. Abstract:
  12. PCI Bus Driver
  13. Revision History
  14. --*/
  15. #include "PciBus.h"
  16. EFI_STATUS
  17. InitializePPB (
  18. IN PCI_IO_DEVICE *PciIoDevice
  19. );
  20. EFI_STATUS
  21. InitializeP2C (
  22. IN PCI_IO_DEVICE *PciIoDevice
  23. );
  24. PCI_IO_DEVICE*
  25. CreatePciIoDevice (
  26. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  27. IN PCI_TYPE00 *Pci,
  28. UINT8 Bus,
  29. UINT8 Device,
  30. UINT8 Func
  31. );
  32. PCI_IO_DEVICE*
  33. GatherP2CInfo (
  34. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  35. IN PCI_TYPE00 *Pci,
  36. UINT8 Bus,
  37. UINT8 Device,
  38. UINT8 Func
  39. );
  40. UINTN
  41. PciParseBar (
  42. IN PCI_IO_DEVICE *PciIoDevice,
  43. IN UINTN Offset,
  44. IN UINTN BarIndex
  45. );
  46. EFI_STATUS
  47. PciSearchDevice (
  48. IN PCI_IO_DEVICE *Bridge,
  49. PCI_TYPE00 *Pci,
  50. UINT8 Bus,
  51. UINT8 Device,
  52. UINT8 Func,
  53. PCI_IO_DEVICE **PciDevice
  54. );
  55. EFI_STATUS
  56. DetermineDeviceAttribute (
  57. IN PCI_IO_DEVICE *PciIoDevice
  58. );
  59. EFI_STATUS
  60. BarExisted (
  61. IN PCI_IO_DEVICE *PciIoDevice,
  62. IN UINTN Offset,
  63. OUT UINT32 *BarLengthValue,
  64. OUT UINT32 *OriginalBarValue
  65. );
  66. EFI_DEVICE_PATH_PROTOCOL*
  67. CreatePciDevicePath(
  68. IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  69. IN PCI_IO_DEVICE *PciIoDevice
  70. );
  71. PCI_IO_DEVICE*
  72. GatherDeviceInfo (
  73. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  74. IN PCI_TYPE00 *Pci,
  75. UINT8 Bus,
  76. UINT8 Device,
  77. UINT8 Func
  78. );
  79. PCI_IO_DEVICE*
  80. GatherPPBInfo (
  81. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  82. IN PCI_TYPE00 *Pci,
  83. UINT8 Bus,
  84. UINT8 Device,
  85. UINT8 Func
  86. );
  87. EFI_STATUS
  88. PciDevicePresent (
  89. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  90. PCI_TYPE00 *Pci,
  91. UINT8 Bus,
  92. UINT8 Device,
  93. UINT8 Func
  94. )
  95. /*++
  96. Routine Description:
  97. This routine is used to check whether the pci device is present
  98. Arguments:
  99. Returns:
  100. None
  101. --*/
  102. {
  103. UINT64 Address;
  104. EFI_STATUS Status;
  105. //
  106. // Create PCI address map in terms of Bus, Device and Func
  107. //
  108. Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
  109. //
  110. // Read the Vendor Id register
  111. //
  112. Status = PciRootBridgeIo->Pci.Read (
  113. PciRootBridgeIo,
  114. EfiPciWidthUint32,
  115. Address,
  116. 1,
  117. Pci
  118. );
  119. if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
  120. //
  121. // Read the entire config header for the device
  122. //
  123. Status = PciRootBridgeIo->Pci.Read (
  124. PciRootBridgeIo,
  125. EfiPciWidthUint32,
  126. Address,
  127. sizeof (PCI_TYPE00) / sizeof (UINT32),
  128. Pci
  129. );
  130. return EFI_SUCCESS;
  131. }
  132. return EFI_NOT_FOUND;
  133. }
  134. EFI_STATUS
  135. PciPciDeviceInfoCollector (
  136. IN PCI_IO_DEVICE *Bridge,
  137. UINT8 StartBusNumber
  138. )
  139. /*++
  140. Routine Description:
  141. Arguments:
  142. Returns:
  143. None
  144. --*/
  145. {
  146. EFI_STATUS Status;
  147. PCI_TYPE00 Pci;
  148. UINT8 Device;
  149. UINT8 Func;
  150. UINT8 SecBus;
  151. PCI_IO_DEVICE *PciIoDevice;
  152. EFI_PCI_IO_PROTOCOL *PciIo;
  153. UINT32 rcba;
  154. UINT32 *fdr;
  155. UINT32 *hptcr;
  156. PciIoDevice = NULL;
  157. Status = EFI_SUCCESS;
  158. SecBus = 0;
  159. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  160. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  161. //
  162. // Check to see whether PCI device is present
  163. //
  164. Status = PciDevicePresent (
  165. Bridge->PciRootBridgeIo,
  166. &Pci,
  167. (UINT8) StartBusNumber,
  168. (UINT8) Device,
  169. (UINT8) Func
  170. );
  171. if (!EFI_ERROR (Status)) {
  172. //
  173. // Collect all the information about the PCI device discovered
  174. //
  175. Status = PciSearchDevice (
  176. Bridge,
  177. &Pci,
  178. (UINT8) StartBusNumber,
  179. Device,
  180. Func,
  181. &PciIoDevice
  182. );
  183. if (!EFI_ERROR (Status)) {
  184. if ((StartBusNumber == 0) && (Device == 0x1F) && (Func == 0)) {
  185. //
  186. // if found LPC - write 0 in SMbus Disabled (3 bit Function Disable register 0x3418)
  187. //
  188. PciIo = &(PciIoDevice->PciIo);
  189. Status = PciIo->Pci.Read (
  190. PciIo,
  191. EfiPciIoWidthUint32,
  192. (UINT64) (0xF0 & ~3),
  193. 1,
  194. &rcba
  195. );
  196. if (rcba != 0) {
  197. rcba &= ~1;
  198. fdr = ((UINT32 *) (UINTN) (rcba + 0x3418));
  199. *fdr &= ~0x8;
  200. hptcr = ((UINT32 *) (UINTN) (rcba + 0x3404));
  201. if ((*hptcr & 0x80) == 0) {
  202. *hptcr |= 0x80;
  203. }
  204. }
  205. }
  206. //
  207. // Recursively scan PCI busses on the other side of PCI-PCI bridges
  208. //
  209. if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
  210. //
  211. // If it is PPB, we need to get the secondary bus to continue the enumeration
  212. //
  213. PciIo = &(PciIoDevice->PciIo);
  214. Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
  215. if (EFI_ERROR (Status)) {
  216. return Status;
  217. }
  218. //
  219. // Deep enumerate the next level bus
  220. //
  221. Status = PciPciDeviceInfoCollector (
  222. PciIoDevice,
  223. (UINT8) (SecBus)
  224. );
  225. }
  226. }
  227. if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
  228. //
  229. // Skip sub functions, this is not a multi function device
  230. //
  231. Func = PCI_MAX_FUNC;
  232. }
  233. }
  234. }
  235. }
  236. return EFI_SUCCESS;
  237. }
  238. EFI_STATUS
  239. PciSearchDevice (
  240. IN PCI_IO_DEVICE *Bridge,
  241. IN PCI_TYPE00 *Pci,
  242. IN UINT8 Bus,
  243. IN UINT8 Device,
  244. IN UINT8 Func,
  245. OUT PCI_IO_DEVICE **PciDevice
  246. )
  247. /*++
  248. Routine Description:
  249. Search required device.
  250. Arguments:
  251. Bridge - A pointer to the PCI_IO_DEVICE.
  252. Pci - A pointer to the PCI_TYPE00.
  253. Bus - Bus number.
  254. Device - Device number.
  255. Func - Function number.
  256. PciDevice - The Required pci device.
  257. Returns:
  258. Status code.
  259. --*/
  260. {
  261. PCI_IO_DEVICE *PciIoDevice;
  262. PciIoDevice = NULL;
  263. if (!IS_PCI_BRIDGE (Pci)) {
  264. if (IS_CARDBUS_BRIDGE (Pci)) {
  265. PciIoDevice = GatherP2CInfo (
  266. Bridge->PciRootBridgeIo,
  267. Pci,
  268. Bus,
  269. Device,
  270. Func
  271. );
  272. if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
  273. InitializeP2C (PciIoDevice);
  274. }
  275. } else {
  276. //
  277. // Create private data for Pci Device
  278. //
  279. PciIoDevice = GatherDeviceInfo (
  280. Bridge->PciRootBridgeIo,
  281. Pci,
  282. Bus,
  283. Device,
  284. Func
  285. );
  286. }
  287. } else {
  288. //
  289. // Create private data for PPB
  290. //
  291. PciIoDevice = GatherPPBInfo (
  292. Bridge->PciRootBridgeIo,
  293. Pci,
  294. Bus,
  295. Device,
  296. Func
  297. );
  298. //
  299. // Special initialization for PPB including making the PPB quiet
  300. //
  301. if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
  302. InitializePPB (PciIoDevice);
  303. }
  304. }
  305. if (!PciIoDevice) {
  306. return EFI_OUT_OF_RESOURCES;
  307. }
  308. //
  309. // Create a device path for this PCI device and store it into its private data
  310. //
  311. CreatePciDevicePath(
  312. Bridge->DevicePath,
  313. PciIoDevice
  314. );
  315. //
  316. // Detect this function has option rom
  317. //
  318. if (gFullEnumeration) {
  319. if (!IS_CARDBUS_BRIDGE (Pci)) {
  320. GetOpRomInfo (PciIoDevice);
  321. }
  322. ResetPowerManagementFeature (PciIoDevice);
  323. }
  324. else {
  325. PciRomGetRomResourceFromPciOptionRomTable (
  326. &gPciBusDriverBinding,
  327. PciIoDevice->PciRootBridgeIo,
  328. PciIoDevice
  329. );
  330. }
  331. //
  332. // Insert it into a global tree for future reference
  333. //
  334. InsertPciDevice (Bridge, PciIoDevice);
  335. //
  336. // Determine PCI device attributes
  337. //
  338. DetermineDeviceAttribute (PciIoDevice);
  339. if (PciDevice != NULL) {
  340. *PciDevice = PciIoDevice;
  341. }
  342. return EFI_SUCCESS;
  343. }
  344. PCI_IO_DEVICE *
  345. GatherDeviceInfo (
  346. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  347. IN PCI_TYPE00 *Pci,
  348. UINT8 Bus,
  349. UINT8 Device,
  350. UINT8 Func
  351. )
  352. /*++
  353. Routine Description:
  354. Arguments:
  355. Returns:
  356. None
  357. --*/
  358. {
  359. UINTN Offset;
  360. UINTN BarIndex;
  361. PCI_IO_DEVICE *PciIoDevice;
  362. PciIoDevice = CreatePciIoDevice (
  363. PciRootBridgeIo,
  364. Pci,
  365. Bus,
  366. Device,
  367. Func
  368. );
  369. if (!PciIoDevice) {
  370. return NULL;
  371. }
  372. //
  373. // If it is a full enumeration, disconnect the device in advance
  374. //
  375. if (gFullEnumeration) {
  376. PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  377. }
  378. //
  379. // Start to parse the bars
  380. //
  381. for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
  382. Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
  383. }
  384. return PciIoDevice;
  385. }
  386. PCI_IO_DEVICE *
  387. GatherPPBInfo (
  388. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  389. IN PCI_TYPE00 *Pci,
  390. UINT8 Bus,
  391. UINT8 Device,
  392. UINT8 Func
  393. )
  394. /*++
  395. Routine Description:
  396. Arguments:
  397. Returns:
  398. None
  399. --*/
  400. {
  401. PCI_IO_DEVICE *PciIoDevice;
  402. EFI_STATUS Status;
  403. UINT8 Value;
  404. EFI_PCI_IO_PROTOCOL *PciIo;
  405. UINT8 Temp;
  406. PciIoDevice = CreatePciIoDevice (
  407. PciRootBridgeIo,
  408. Pci,
  409. Bus,
  410. Device,
  411. Func
  412. );
  413. if (!PciIoDevice) {
  414. return NULL;
  415. }
  416. if (gFullEnumeration) {
  417. PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  418. //
  419. // Initalize the bridge control register
  420. //
  421. PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
  422. }
  423. PciIo = &PciIoDevice->PciIo;
  424. //
  425. // Test whether it support 32 decode or not
  426. //
  427. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  428. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  429. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  430. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  431. if (Value) {
  432. if (Value & 0x01) {
  433. PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  434. } else {
  435. PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
  436. }
  437. }
  438. Status = BarExisted (
  439. PciIoDevice,
  440. 0x24,
  441. NULL,
  442. NULL
  443. );
  444. //
  445. // test if it supports 64 memory or not
  446. //
  447. if (!EFI_ERROR (Status)) {
  448. Status = BarExisted (
  449. PciIoDevice,
  450. 0x28,
  451. NULL,
  452. NULL
  453. );
  454. if (!EFI_ERROR (Status)) {
  455. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  456. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
  457. } else {
  458. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  459. }
  460. }
  461. //
  462. // Memory 32 code is required for ppb
  463. //
  464. PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
  465. return PciIoDevice;
  466. }
  467. PCI_IO_DEVICE *
  468. GatherP2CInfo (
  469. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  470. IN PCI_TYPE00 *Pci,
  471. UINT8 Bus,
  472. UINT8 Device,
  473. UINT8 Func
  474. )
  475. /*++
  476. Routine Description:
  477. Arguments:
  478. Returns:
  479. None
  480. --*/
  481. {
  482. PCI_IO_DEVICE *PciIoDevice;
  483. PciIoDevice = CreatePciIoDevice (
  484. PciRootBridgeIo,
  485. Pci,
  486. Bus,
  487. Device,
  488. Func
  489. );
  490. if (!PciIoDevice) {
  491. return NULL;
  492. }
  493. if (gFullEnumeration) {
  494. PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  495. //
  496. // Initalize the bridge control register
  497. //
  498. PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
  499. }
  500. //
  501. // P2C only has one bar that is in 0x10
  502. //
  503. PciParseBar(PciIoDevice, 0x10, 0);
  504. PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
  505. EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
  506. EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  507. return PciIoDevice;
  508. }
  509. EFI_DEVICE_PATH_PROTOCOL *
  510. CreatePciDevicePath (
  511. IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  512. IN PCI_IO_DEVICE *PciIoDevice
  513. )
  514. /*++
  515. Routine Description:
  516. Arguments:
  517. Returns:
  518. None
  519. --*/
  520. {
  521. PCI_DEVICE_PATH PciNode;
  522. //
  523. // Create PCI device path
  524. //
  525. PciNode.Header.Type = HARDWARE_DEVICE_PATH;
  526. PciNode.Header.SubType = HW_PCI_DP;
  527. SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
  528. PciNode.Device = PciIoDevice->DeviceNumber;
  529. PciNode.Function = PciIoDevice->FunctionNumber;
  530. PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
  531. return PciIoDevice->DevicePath;
  532. }
  533. EFI_STATUS
  534. BarExisted (
  535. IN PCI_IO_DEVICE *PciIoDevice,
  536. IN UINTN Offset,
  537. OUT UINT32 *BarLengthValue,
  538. OUT UINT32 *OriginalBarValue
  539. )
  540. /*++
  541. Routine Description:
  542. Check the bar is existed or not.
  543. Arguments:
  544. PciIoDevice - A pointer to the PCI_IO_DEVICE.
  545. Offset - The offset.
  546. BarLengthValue - The bar length value.
  547. OriginalBarValue - The original bar value.
  548. Returns:
  549. EFI_NOT_FOUND - The bar don't exist.
  550. EFI_SUCCESS - The bar exist.
  551. --*/
  552. {
  553. EFI_PCI_IO_PROTOCOL *PciIo;
  554. UINT32 OriginalValue;
  555. UINT32 Value;
  556. EFI_TPL OldTpl;
  557. PciIo = &PciIoDevice->PciIo;
  558. //
  559. // Preserve the original value
  560. //
  561. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
  562. //
  563. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  564. //
  565. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  566. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
  567. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
  568. //
  569. // Write back the original value
  570. //
  571. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
  572. //
  573. // Restore TPL to its original level
  574. //
  575. gBS->RestoreTPL (OldTpl);
  576. if (BarLengthValue != NULL) {
  577. *BarLengthValue = Value;
  578. }
  579. if (OriginalBarValue != NULL) {
  580. *OriginalBarValue = OriginalValue;
  581. }
  582. if (Value == 0) {
  583. return EFI_NOT_FOUND;
  584. } else {
  585. return EFI_SUCCESS;
  586. }
  587. }
  588. EFI_STATUS
  589. DetermineDeviceAttribute (
  590. IN PCI_IO_DEVICE *PciIoDevice
  591. )
  592. /*++
  593. Routine Description:
  594. Determine the related attributes of all devices under a Root Bridge
  595. Arguments:
  596. Returns:
  597. None
  598. --*/
  599. {
  600. UINT16 Command;
  601. UINT16 BridgeControl;
  602. Command = 0;
  603. PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
  604. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
  605. if (IS_PCI_VGA (&(PciIoDevice->Pci))){
  606. //
  607. // If the device is VGA, VGA related Attributes are supported
  608. //
  609. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
  610. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ;
  611. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ;
  612. }
  613. if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
  614. //
  615. // If the devie is a ISA Bridge, set the two attributes
  616. //
  617. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
  618. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
  619. }
  620. if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
  621. //
  622. // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
  623. // attribute
  624. //
  625. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
  626. }
  627. //
  628. // If the device is IDE, IDE related attributes are supported
  629. //
  630. if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
  631. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ;
  632. PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ;
  633. }
  634. PciReadCommandRegister(PciIoDevice, &Command);
  635. if (Command & EFI_PCI_COMMAND_IO_SPACE) {
  636. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
  637. }
  638. if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
  639. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
  640. }
  641. if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
  642. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
  643. }
  644. if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
  645. IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
  646. //
  647. // If it is a PPB, read the Bridge Control Register to determine
  648. // the relevant attributes
  649. //
  650. BridgeControl = 0;
  651. PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
  652. //
  653. // Determine whether the ISA bit is set
  654. // If ISA Enable on Bridge is set, the PPB
  655. // will block forwarding 0x100-0x3ff for each 1KB in the
  656. // first 64KB I/O range.
  657. //
  658. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
  659. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
  660. }
  661. //
  662. // Determine whether the VGA bit is set
  663. // If it is set, the bridge is set to decode VGA memory range
  664. // and palette register range
  665. //
  666. if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
  667. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
  668. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  669. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  670. }
  671. //
  672. // if the palette snoop bit is set, then the brige is set to
  673. // decode palette IO write
  674. //
  675. if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
  676. PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  677. }
  678. }
  679. return EFI_SUCCESS;
  680. }
  681. UINTN
  682. PciParseBar (
  683. IN PCI_IO_DEVICE *PciIoDevice,
  684. IN UINTN Offset,
  685. IN UINTN BarIndex
  686. )
  687. /*++
  688. Routine Description:
  689. Arguments:
  690. Returns:
  691. None
  692. --*/
  693. {
  694. UINT32 Value;
  695. UINT32 OriginalValue;
  696. UINT32 Mask;
  697. EFI_STATUS Status;
  698. OriginalValue = 0;
  699. Value = 0;
  700. Status = BarExisted (
  701. PciIoDevice,
  702. Offset,
  703. &Value,
  704. &OriginalValue
  705. );
  706. if (EFI_ERROR (Status)) {
  707. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  708. PciIoDevice->PciBar[BarIndex].Length = 0;
  709. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  710. //
  711. // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
  712. //
  713. PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
  714. return Offset + 4;
  715. }
  716. PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
  717. if (Value & 0x01) {
  718. //
  719. // Device I/Os
  720. //
  721. Mask = 0xfffffffc;
  722. if (Value & 0xFFFF0000) {
  723. //
  724. // It is a IO32 bar
  725. //
  726. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
  727. PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
  728. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  729. } else {
  730. //
  731. // It is a IO16 bar
  732. //
  733. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
  734. PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
  735. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  736. }
  737. //
  738. // Workaround. Some platforms inplement IO bar with 0 length
  739. // Need to treat it as no-bar
  740. //
  741. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  742. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  743. }
  744. PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
  745. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  746. } else {
  747. Mask = 0xfffffff0;
  748. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  749. switch (Value & 0x07) {
  750. //
  751. //memory space; anywhere in 32 bit address space
  752. //
  753. case 0x00:
  754. if (Value & 0x08) {
  755. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
  756. } else {
  757. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
  758. }
  759. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  760. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  761. break;
  762. //
  763. // memory space; anywhere in 64 bit address space
  764. //
  765. case 0x04:
  766. if (Value & 0x08) {
  767. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
  768. } else {
  769. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
  770. }
  771. //
  772. // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
  773. // is regarded as an extension for the first bar. As a result
  774. // the sizing will be conducted on combined 64 bit value
  775. // Here just store the masked first 32bit value for future size
  776. // calculation
  777. //
  778. PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
  779. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  780. //
  781. // Increment the offset to point to next DWORD
  782. //
  783. Offset += 4;
  784. Status = BarExisted (
  785. PciIoDevice,
  786. Offset,
  787. &Value,
  788. &OriginalValue
  789. );
  790. if (EFI_ERROR (Status)) {
  791. return Offset + 4;
  792. }
  793. //
  794. // Fix the length to support some spefic 64 bit BAR
  795. //
  796. Value |= ((UINT32)(-1) << HighBitSet32 (Value));
  797. //
  798. // Calculate the size of 64bit bar
  799. //
  800. PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
  801. PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
  802. PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
  803. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  804. break;
  805. //
  806. // reserved
  807. //
  808. default:
  809. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  810. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  811. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  812. break;
  813. }
  814. }
  815. //
  816. // Check the length again so as to keep compatible with some special bars
  817. //
  818. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  819. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  820. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  821. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  822. }
  823. //
  824. // Increment number of bar
  825. //
  826. return Offset + 4;
  827. }
  828. EFI_STATUS
  829. InitializePPB (
  830. IN PCI_IO_DEVICE *PciIoDevice
  831. )
  832. /*++
  833. Routine Description:
  834. Arguments:
  835. Returns:
  836. None
  837. --*/
  838. {
  839. EFI_PCI_IO_PROTOCOL *PciIo;
  840. PciIo = &(PciIoDevice->PciIo);
  841. //
  842. // Put all the resource apertures including IO16
  843. // Io32, pMem32, pMem64 to quiescent state
  844. // Resource base all ones, Resource limit all zeros
  845. //
  846. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  847. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
  848. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
  849. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
  850. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
  851. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
  852. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
  853. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
  854. //
  855. // don't support use io32 as for now
  856. //
  857. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
  858. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
  859. return EFI_SUCCESS;
  860. }
  861. EFI_STATUS
  862. InitializeP2C (
  863. IN PCI_IO_DEVICE *PciIoDevice
  864. )
  865. /*++
  866. Routine Description:
  867. Arguments:
  868. Returns:
  869. None
  870. --*/
  871. {
  872. EFI_PCI_IO_PROTOCOL *PciIo;
  873. PciIo = &(PciIoDevice->PciIo);
  874. //
  875. // Put all the resource apertures including IO16
  876. // Io32, pMem32, pMem64 to quiescent state(
  877. // Resource base all ones, Resource limit all zeros
  878. //
  879. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
  880. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
  881. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
  882. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
  883. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
  884. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
  885. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
  886. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
  887. return EFI_SUCCESS;
  888. }
  889. PCI_IO_DEVICE *
  890. CreatePciIoDevice (
  891. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  892. IN PCI_TYPE00 *Pci,
  893. UINT8 Bus,
  894. UINT8 Device,
  895. UINT8 Func
  896. )
  897. /*++
  898. Routine Description:
  899. Arguments:
  900. Returns:
  901. None
  902. --*/
  903. {
  904. EFI_STATUS Status;
  905. PCI_IO_DEVICE *PciIoDevice;
  906. PciIoDevice = NULL;
  907. Status = gBS->AllocatePool (
  908. EfiBootServicesData,
  909. sizeof (PCI_IO_DEVICE),
  910. (VOID **) &PciIoDevice
  911. );
  912. if (EFI_ERROR (Status)) {
  913. return NULL;
  914. }
  915. ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
  916. PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
  917. PciIoDevice->Handle = NULL;
  918. PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
  919. PciIoDevice->DevicePath = NULL;
  920. PciIoDevice->BusNumber = Bus;
  921. PciIoDevice->DeviceNumber = Device;
  922. PciIoDevice->FunctionNumber = Func;
  923. PciIoDevice->Decodes = 0;
  924. if (gFullEnumeration) {
  925. PciIoDevice->Allocated = FALSE;
  926. } else {
  927. PciIoDevice->Allocated = TRUE;
  928. }
  929. PciIoDevice->Attributes = 0;
  930. PciIoDevice->Supports = 0;
  931. PciIoDevice->BusOverride = FALSE;
  932. PciIoDevice->IsPciExp = FALSE;
  933. CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
  934. //
  935. // Initialize the PCI I/O instance structure
  936. //
  937. Status = InitializePciIoInstance (PciIoDevice);
  938. Status = InitializePciDriverOverrideInstance (PciIoDevice);
  939. if (EFI_ERROR (Status)) {
  940. gBS->FreePool (PciIoDevice);
  941. return NULL;
  942. }
  943. //
  944. // Initialize the reserved resource list
  945. //
  946. InitializeListHead (&PciIoDevice->ReservedResourceList);
  947. //
  948. // Initialize the driver list
  949. //
  950. InitializeListHead (&PciIoDevice->OptionRomDriverList);
  951. //
  952. // Initialize the child list
  953. //
  954. InitializeListHead (&PciIoDevice->ChildList);
  955. return PciIoDevice;
  956. }
  957. EFI_STATUS
  958. PciEnumeratorLight (
  959. IN EFI_HANDLE Controller
  960. )
  961. /*++
  962. Routine Description:
  963. This routine is used to enumerate entire pci bus system
  964. in a given platform
  965. Arguments:
  966. Returns:
  967. None
  968. --*/
  969. {
  970. EFI_STATUS Status;
  971. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  972. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  973. PCI_IO_DEVICE *RootBridgeDev;
  974. UINT16 MinBus;
  975. UINT16 MaxBus;
  976. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
  977. MinBus = 0;
  978. MaxBus = PCI_MAX_BUS;
  979. Descriptors = NULL;
  980. //
  981. // If this host bridge has been already enumerated, then return successfully
  982. //
  983. if (RootBridgeExisted (Controller)) {
  984. return EFI_SUCCESS;
  985. }
  986. //
  987. // Open the IO Abstraction(s) needed to perform the supported test
  988. //
  989. Status = gBS->OpenProtocol (
  990. Controller ,
  991. &gEfiDevicePathProtocolGuid,
  992. (VOID **)&ParentDevicePath,
  993. gPciBusDriverBinding.DriverBindingHandle,
  994. Controller,
  995. EFI_OPEN_PROTOCOL_BY_DRIVER
  996. );
  997. if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
  998. return Status;
  999. }
  1000. //
  1001. // Open pci root bridge io protocol
  1002. //
  1003. Status = gBS->OpenProtocol (
  1004. Controller,
  1005. &gEfiPciRootBridgeIoProtocolGuid,
  1006. (VOID **) &PciRootBridgeIo,
  1007. gPciBusDriverBinding.DriverBindingHandle,
  1008. Controller,
  1009. EFI_OPEN_PROTOCOL_BY_DRIVER
  1010. );
  1011. if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
  1012. return Status;
  1013. }
  1014. //
  1015. // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge
  1016. //
  1017. Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);
  1018. Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
  1019. if (EFI_ERROR (Status)) {
  1020. return Status;
  1021. }
  1022. while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
  1023. //
  1024. // Create a device node for root bridge device with a NULL host bridge controller handle
  1025. //
  1026. RootBridgeDev = CreateRootBridge (Controller);
  1027. //
  1028. // Record the root bridge device path
  1029. //
  1030. RootBridgeDev->DevicePath = ParentDevicePath;
  1031. //
  1032. // Record the root bridge io protocol
  1033. //
  1034. RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
  1035. Status = PciPciDeviceInfoCollector (
  1036. RootBridgeDev,
  1037. (UINT8) MinBus
  1038. );
  1039. if (!EFI_ERROR (Status)) {
  1040. //
  1041. // If successfully, insert the node into device pool
  1042. //
  1043. InsertRootBridge (RootBridgeDev);
  1044. } else {
  1045. //
  1046. // If unsuccessly, destroy the entire node
  1047. //
  1048. DestroyRootBridge (RootBridgeDev);
  1049. }
  1050. Descriptors++;
  1051. }
  1052. return EFI_SUCCESS;
  1053. }
  1054. EFI_STATUS
  1055. PciGetBusRange (
  1056. IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
  1057. OUT UINT16 *MinBus,
  1058. OUT UINT16 *MaxBus,
  1059. OUT UINT16 *BusRange
  1060. )
  1061. /*++
  1062. Routine Description:
  1063. Get the bus range.
  1064. Arguments:
  1065. Descriptors - A pointer to the address space descriptor.
  1066. MinBus - The min bus.
  1067. MaxBus - The max bus.
  1068. BusRange - The bus range.
  1069. Returns:
  1070. Status Code.
  1071. --*/
  1072. {
  1073. while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
  1074. if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
  1075. if (MinBus != NULL) {
  1076. *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
  1077. }
  1078. if (MaxBus != NULL) {
  1079. *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
  1080. }
  1081. if (BusRange != NULL) {
  1082. *BusRange = (UINT16)(*Descriptors)->AddrLen;
  1083. }
  1084. return EFI_SUCCESS;
  1085. }
  1086. (*Descriptors)++;
  1087. }
  1088. return EFI_NOT_FOUND;
  1089. }