PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/PciBusNoEnumerationDxe/PciIo.c

https://github.com/SunnyKi/bareBoot
C | 1852 lines | 1118 code | 241 blank | 493 comment | 174 complexity | 64ec3422833619a8121839667cd88c6f MD5 | raw file
  1. /*++
  2. Copyright (c) 2005 - 2014, 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. PciIo.c
  11. Abstract:
  12. PCI I/O Abstraction Driver
  13. Revision History
  14. --*/
  15. #include "PciBus.h"
  16. //
  17. // PCI I/O Support Function Prototypes
  18. //
  19. //
  20. BOOLEAN
  21. PciDevicesOnTheSamePath (
  22. IN PCI_IO_DEVICE *PciDevice1,
  23. IN PCI_IO_DEVICE *PciDevice2
  24. );
  25. EFI_STATUS
  26. UpStreamBridgesAttributes (
  27. IN PCI_IO_DEVICE *PciIoDevice,
  28. IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
  29. IN UINT64 Attributes
  30. );
  31. BOOLEAN
  32. CheckBarType (
  33. IN PCI_IO_DEVICE *PciIoDevice,
  34. UINT8 BarIndex,
  35. PCI_BAR_TYPE BarType
  36. );
  37. EFI_STATUS
  38. SetBootVGA (
  39. IN PCI_IO_DEVICE *PciIoDevice
  40. );
  41. EFI_STATUS
  42. DisableBootVGA (
  43. IN PCI_IO_DEVICE *PciIoDevice
  44. );
  45. EFI_STATUS
  46. PciIoVerifyBarAccess (
  47. PCI_IO_DEVICE *PciIoDevice,
  48. UINT8 BarIndex,
  49. PCI_BAR_TYPE Type,
  50. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  51. IN UINTN Count,
  52. UINT64 *Offset
  53. );
  54. EFI_STATUS
  55. PciIoVerifyConfigAccess (
  56. PCI_IO_DEVICE *PciIoDevice,
  57. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  58. IN UINTN Count,
  59. IN UINT64 *Offset
  60. );
  61. EFI_STATUS
  62. EFIAPI
  63. PciIoPollMem (
  64. IN EFI_PCI_IO_PROTOCOL *This,
  65. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  66. IN UINT8 BarIndex,
  67. IN UINT64 Offset,
  68. IN UINT64 Mask,
  69. IN UINT64 Value,
  70. IN UINT64 Delay,
  71. OUT UINT64 *Result
  72. );
  73. EFI_STATUS
  74. EFIAPI
  75. PciIoPollIo (
  76. IN EFI_PCI_IO_PROTOCOL *This,
  77. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  78. IN UINT8 BarIndex,
  79. IN UINT64 Offset,
  80. IN UINT64 Mask,
  81. IN UINT64 Value,
  82. IN UINT64 Delay,
  83. OUT UINT64 *Result
  84. );
  85. EFI_STATUS
  86. EFIAPI
  87. PciIoMemRead (
  88. IN EFI_PCI_IO_PROTOCOL *This,
  89. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  90. IN UINT8 BarIndex,
  91. IN UINT64 Offset,
  92. IN UINTN Count,
  93. IN OUT VOID *Buffer
  94. );
  95. EFI_STATUS
  96. EFIAPI
  97. PciIoMemWrite (
  98. IN EFI_PCI_IO_PROTOCOL *This,
  99. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  100. IN UINT8 BarIndex,
  101. IN UINT64 Offset,
  102. IN UINTN Count,
  103. IN OUT VOID *Buffer
  104. );
  105. EFI_STATUS
  106. EFIAPI
  107. PciIoIoRead (
  108. IN EFI_PCI_IO_PROTOCOL *This,
  109. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  110. IN UINT8 BarIndex,
  111. IN UINT64 Offset,
  112. IN UINTN Count,
  113. IN OUT VOID *Buffer
  114. );
  115. EFI_STATUS
  116. EFIAPI
  117. PciIoIoWrite (
  118. IN EFI_PCI_IO_PROTOCOL *This,
  119. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  120. IN UINT8 BarIndex,
  121. IN UINT64 Offset,
  122. IN UINTN Count,
  123. IN OUT VOID *Buffer
  124. );
  125. EFI_STATUS
  126. EFIAPI
  127. PciIoConfigRead (
  128. IN EFI_PCI_IO_PROTOCOL *This,
  129. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  130. IN UINT32 Offset,
  131. IN UINTN Count,
  132. IN OUT VOID *Buffer
  133. );
  134. EFI_STATUS
  135. EFIAPI
  136. PciIoConfigWrite (
  137. IN EFI_PCI_IO_PROTOCOL *This,
  138. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  139. IN UINT32 Offset,
  140. IN UINTN Count,
  141. IN OUT VOID *Buffer
  142. );
  143. EFI_STATUS
  144. EFIAPI
  145. PciIoCopyMem (
  146. IN EFI_PCI_IO_PROTOCOL *This,
  147. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  148. IN UINT8 DestBarIndex,
  149. IN UINT64 DestOffset,
  150. IN UINT8 SrcBarIndex,
  151. IN UINT64 SrcOffset,
  152. IN UINTN Count
  153. );
  154. EFI_STATUS
  155. EFIAPI
  156. PciIoMap (
  157. IN EFI_PCI_IO_PROTOCOL *This,
  158. IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
  159. IN VOID *HostAddress,
  160. IN OUT UINTN *NumberOfBytes,
  161. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  162. OUT VOID **Mapping
  163. );
  164. EFI_STATUS
  165. EFIAPI
  166. PciIoUnmap (
  167. IN EFI_PCI_IO_PROTOCOL *This,
  168. IN VOID *Mapping
  169. );
  170. EFI_STATUS
  171. EFIAPI
  172. PciIoAllocateBuffer (
  173. IN EFI_PCI_IO_PROTOCOL *This,
  174. IN EFI_ALLOCATE_TYPE Type,
  175. IN EFI_MEMORY_TYPE MemoryType,
  176. IN UINTN Pages,
  177. OUT VOID **HostAddress,
  178. IN UINT64 Attributes
  179. );
  180. EFI_STATUS
  181. EFIAPI
  182. PciIoFreeBuffer (
  183. IN EFI_PCI_IO_PROTOCOL *This,
  184. IN UINTN Pages,
  185. IN VOID *HostAddress
  186. );
  187. EFI_STATUS
  188. EFIAPI
  189. PciIoFlush (
  190. IN EFI_PCI_IO_PROTOCOL *This
  191. );
  192. EFI_STATUS
  193. EFIAPI
  194. PciIoGetLocation (
  195. IN EFI_PCI_IO_PROTOCOL *This,
  196. OUT UINTN *Segment,
  197. OUT UINTN *Bus,
  198. OUT UINTN *Device,
  199. OUT UINTN *Function
  200. );
  201. EFI_STATUS
  202. EFIAPI
  203. PciIoAttributes (
  204. IN EFI_PCI_IO_PROTOCOL *This,
  205. IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
  206. IN UINT64 Attributes,
  207. OUT UINT64 *Result OPTIONAL
  208. );
  209. EFI_STATUS
  210. EFIAPI
  211. PciIoGetBarAttributes(
  212. IN EFI_PCI_IO_PROTOCOL *This,
  213. IN UINT8 BarIndex,
  214. OUT UINT64 *Supports, OPTIONAL
  215. OUT VOID **Resources OPTIONAL
  216. );
  217. EFI_STATUS
  218. EFIAPI
  219. PciIoSetBarAttributes(
  220. IN EFI_PCI_IO_PROTOCOL *This,
  221. IN UINT64 Attributes,
  222. IN UINT8 BarIndex,
  223. IN OUT UINT64 *Offset,
  224. IN OUT UINT64 *Length
  225. );
  226. //
  227. // Pci Io Protocol Interface
  228. //
  229. EFI_PCI_IO_PROTOCOL PciIoInterface = {
  230. PciIoPollMem,
  231. PciIoPollIo,
  232. {
  233. PciIoMemRead,
  234. PciIoMemWrite
  235. },
  236. {
  237. PciIoIoRead,
  238. PciIoIoWrite
  239. },
  240. {
  241. PciIoConfigRead,
  242. PciIoConfigWrite
  243. },
  244. PciIoCopyMem,
  245. PciIoMap,
  246. PciIoUnmap,
  247. PciIoAllocateBuffer,
  248. PciIoFreeBuffer,
  249. PciIoFlush,
  250. PciIoGetLocation,
  251. PciIoAttributes,
  252. PciIoGetBarAttributes,
  253. PciIoSetBarAttributes,
  254. 0,
  255. NULL
  256. };
  257. EFI_STATUS
  258. InitializePciIoInstance (
  259. PCI_IO_DEVICE *PciIoDevice
  260. )
  261. /*++
  262. Routine Description:
  263. Initializes a PCI I/O Instance
  264. Arguments:
  265. Returns:
  266. None
  267. --*/
  268. {
  269. CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
  270. return EFI_SUCCESS;
  271. }
  272. EFI_STATUS
  273. PciIoVerifyBarAccess (
  274. PCI_IO_DEVICE *PciIoDevice,
  275. UINT8 BarIndex,
  276. PCI_BAR_TYPE Type,
  277. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  278. IN UINTN Count,
  279. UINT64 *Offset
  280. )
  281. /*++
  282. Routine Description:
  283. Verifies access to a PCI Base Address Register (BAR)
  284. Arguments:
  285. Returns:
  286. None
  287. --*/
  288. {
  289. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  290. return EFI_INVALID_PARAMETER;
  291. }
  292. if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
  293. return EFI_SUCCESS;
  294. }
  295. //
  296. // BarIndex 0-5 is legal
  297. //
  298. if (BarIndex >= PCI_MAX_BAR) {
  299. return EFI_INVALID_PARAMETER;
  300. }
  301. if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
  302. return EFI_INVALID_PARAMETER;
  303. }
  304. //
  305. // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
  306. // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
  307. //
  308. if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) {
  309. Count = 1;
  310. }
  311. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
  312. if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
  313. return EFI_INVALID_PARAMETER;
  314. }
  315. *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
  316. return EFI_SUCCESS;
  317. }
  318. EFI_STATUS
  319. PciIoVerifyConfigAccess (
  320. PCI_IO_DEVICE *PciIoDevice,
  321. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  322. IN UINTN Count,
  323. IN UINT64 *Offset
  324. )
  325. /*++
  326. Routine Description:
  327. Verifies access to a PCI Config Header
  328. Arguments:
  329. Returns:
  330. None
  331. --*/
  332. {
  333. UINT64 ExtendOffset;
  334. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  335. return EFI_INVALID_PARAMETER;
  336. }
  337. //
  338. // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
  339. // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
  340. //
  341. Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
  342. if (PciIoDevice->IsPciExp) {
  343. if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
  344. return EFI_UNSUPPORTED;
  345. }
  346. ExtendOffset = LShiftU64 (*Offset, 32);
  347. *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
  348. *Offset = (*Offset) | ExtendOffset;
  349. } else {
  350. if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
  351. return EFI_UNSUPPORTED;
  352. }
  353. *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
  354. }
  355. return EFI_SUCCESS;
  356. }
  357. EFI_STATUS
  358. EFIAPI
  359. PciIoPollMem (
  360. IN EFI_PCI_IO_PROTOCOL *This,
  361. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  362. IN UINT8 BarIndex,
  363. IN UINT64 Offset,
  364. IN UINT64 Mask,
  365. IN UINT64 Value,
  366. IN UINT64 Delay,
  367. OUT UINT64 *Result
  368. )
  369. /*++
  370. Routine Description:
  371. Poll PCI Memmory
  372. Arguments:
  373. Returns:
  374. None
  375. --*/
  376. {
  377. EFI_STATUS Status;
  378. PCI_IO_DEVICE *PciIoDevice;
  379. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  380. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  381. return EFI_INVALID_PARAMETER;
  382. }
  383. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
  384. if (EFI_ERROR (Status)) {
  385. return EFI_UNSUPPORTED;
  386. }
  387. if (Width > EfiPciIoWidthUint64) {
  388. return EFI_INVALID_PARAMETER;
  389. }
  390. Status = PciIoDevice->PciRootBridgeIo->PollMem (
  391. PciIoDevice->PciRootBridgeIo,
  392. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  393. Offset,
  394. Mask,
  395. Value,
  396. Delay,
  397. Result
  398. );
  399. return Status;
  400. }
  401. EFI_STATUS
  402. EFIAPI
  403. PciIoPollIo (
  404. IN EFI_PCI_IO_PROTOCOL *This,
  405. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  406. IN UINT8 BarIndex,
  407. IN UINT64 Offset,
  408. IN UINT64 Mask,
  409. IN UINT64 Value,
  410. IN UINT64 Delay,
  411. OUT UINT64 *Result
  412. )
  413. /*++
  414. Routine Description:
  415. Poll PCI IO
  416. Arguments:
  417. Returns:
  418. None
  419. --*/
  420. {
  421. EFI_STATUS Status;
  422. PCI_IO_DEVICE *PciIoDevice;
  423. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  424. if ((UINT32)Width > EfiPciIoWidthUint64) {
  425. return EFI_INVALID_PARAMETER;
  426. }
  427. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
  428. if (EFI_ERROR (Status)) {
  429. return EFI_UNSUPPORTED;
  430. }
  431. Status = PciIoDevice->PciRootBridgeIo->PollIo (
  432. PciIoDevice->PciRootBridgeIo,
  433. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  434. Offset,
  435. Mask,
  436. Value,
  437. Delay,
  438. Result
  439. );
  440. return Status;
  441. }
  442. EFI_STATUS
  443. EFIAPI
  444. PciIoMemRead (
  445. IN EFI_PCI_IO_PROTOCOL *This,
  446. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  447. IN UINT8 BarIndex,
  448. IN UINT64 Offset,
  449. IN UINTN Count,
  450. IN OUT VOID *Buffer
  451. )
  452. /*++
  453. Routine Description:
  454. Performs a PCI Memory Read Cycle
  455. Arguments:
  456. Returns:
  457. None
  458. --*/
  459. {
  460. EFI_STATUS Status;
  461. PCI_IO_DEVICE *PciIoDevice;
  462. if (Buffer == NULL){
  463. return EFI_INVALID_PARAMETER;
  464. }
  465. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  466. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  467. return EFI_INVALID_PARAMETER;
  468. }
  469. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
  470. if (EFI_ERROR (Status)) {
  471. return EFI_UNSUPPORTED;
  472. }
  473. Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
  474. PciIoDevice->PciRootBridgeIo,
  475. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  476. Offset,
  477. Count,
  478. Buffer
  479. );
  480. return Status;
  481. }
  482. EFI_STATUS
  483. EFIAPI
  484. PciIoMemWrite (
  485. IN EFI_PCI_IO_PROTOCOL *This,
  486. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  487. IN UINT8 BarIndex,
  488. IN UINT64 Offset,
  489. IN UINTN Count,
  490. IN OUT VOID *Buffer
  491. )
  492. /*++
  493. Routine Description:
  494. Performs a PCI Memory Write Cycle
  495. Arguments:
  496. Returns:
  497. None
  498. --*/
  499. {
  500. EFI_STATUS Status;
  501. PCI_IO_DEVICE *PciIoDevice;
  502. if (Buffer == NULL){
  503. return EFI_INVALID_PARAMETER;
  504. }
  505. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  506. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  507. return EFI_INVALID_PARAMETER;
  508. }
  509. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
  510. if (EFI_ERROR (Status)) {
  511. return EFI_UNSUPPORTED;
  512. }
  513. Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
  514. PciIoDevice->PciRootBridgeIo,
  515. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  516. Offset,
  517. Count,
  518. Buffer
  519. );
  520. return Status;
  521. }
  522. EFI_STATUS
  523. EFIAPI
  524. PciIoIoRead (
  525. IN EFI_PCI_IO_PROTOCOL *This,
  526. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  527. IN UINT8 BarIndex,
  528. IN UINT64 Offset,
  529. IN UINTN Count,
  530. IN OUT VOID *Buffer
  531. )
  532. /*++
  533. Routine Description:
  534. Performs a PCI I/O Read Cycle
  535. Arguments:
  536. Returns:
  537. None
  538. --*/
  539. {
  540. EFI_STATUS Status;
  541. PCI_IO_DEVICE *PciIoDevice;
  542. if (Buffer == NULL){
  543. return EFI_INVALID_PARAMETER;
  544. }
  545. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  546. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  547. return EFI_INVALID_PARAMETER;
  548. }
  549. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
  550. if (EFI_ERROR (Status)) {
  551. return EFI_UNSUPPORTED;
  552. }
  553. Status = PciIoDevice->PciRootBridgeIo->Io.Read (
  554. PciIoDevice->PciRootBridgeIo,
  555. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  556. Offset,
  557. Count,
  558. Buffer
  559. );
  560. return Status;
  561. }
  562. EFI_STATUS
  563. EFIAPI
  564. PciIoIoWrite (
  565. IN EFI_PCI_IO_PROTOCOL *This,
  566. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  567. IN UINT8 BarIndex,
  568. IN UINT64 Offset,
  569. IN UINTN Count,
  570. IN OUT VOID *Buffer
  571. )
  572. /*++
  573. Routine Description:
  574. Performs a PCI I/O Write Cycle
  575. Arguments:
  576. Returns:
  577. None
  578. --*/
  579. {
  580. EFI_STATUS Status;
  581. PCI_IO_DEVICE *PciIoDevice;
  582. if (Buffer == NULL){
  583. return EFI_INVALID_PARAMETER;
  584. }
  585. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  586. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  587. return EFI_INVALID_PARAMETER;
  588. }
  589. Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
  590. if (EFI_ERROR (Status)) {
  591. return EFI_UNSUPPORTED;
  592. }
  593. Status = PciIoDevice->PciRootBridgeIo->Io.Write (
  594. PciIoDevice->PciRootBridgeIo,
  595. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  596. Offset,
  597. Count,
  598. Buffer
  599. );
  600. return Status;
  601. }
  602. EFI_STATUS
  603. EFIAPI
  604. PciIoConfigRead (
  605. IN EFI_PCI_IO_PROTOCOL *This,
  606. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  607. IN UINT32 Offset,
  608. IN UINTN Count,
  609. IN OUT VOID *Buffer
  610. )
  611. /*++
  612. Routine Description:
  613. Performs a PCI Configuration Read Cycle
  614. Arguments:
  615. Returns:
  616. None
  617. --*/
  618. {
  619. EFI_STATUS Status;
  620. PCI_IO_DEVICE *PciIoDevice;
  621. UINT64 Address;
  622. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  623. Address = Offset;
  624. Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
  625. if (EFI_ERROR (Status)) {
  626. return Status;
  627. }
  628. Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
  629. PciIoDevice->PciRootBridgeIo,
  630. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  631. Address,
  632. Count,
  633. Buffer
  634. );
  635. return Status;
  636. }
  637. EFI_STATUS
  638. EFIAPI
  639. PciIoConfigWrite (
  640. IN EFI_PCI_IO_PROTOCOL *This,
  641. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  642. IN UINT32 Offset,
  643. IN UINTN Count,
  644. IN OUT VOID *Buffer
  645. )
  646. /*++
  647. Routine Description:
  648. Performs a PCI Configuration Write Cycle
  649. Arguments:
  650. Returns:
  651. None
  652. --*/
  653. {
  654. EFI_STATUS Status;
  655. PCI_IO_DEVICE *PciIoDevice;
  656. UINT64 Address;
  657. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  658. Address = Offset;
  659. Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
  660. if (EFI_ERROR (Status)) {
  661. return Status;
  662. }
  663. Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
  664. PciIoDevice->PciRootBridgeIo,
  665. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  666. Address,
  667. Count,
  668. Buffer
  669. );
  670. return Status;
  671. }
  672. EFI_STATUS
  673. EFIAPI
  674. PciIoCopyMem (
  675. IN EFI_PCI_IO_PROTOCOL *This,
  676. IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
  677. IN UINT8 DestBarIndex,
  678. IN UINT64 DestOffset,
  679. IN UINT8 SrcBarIndex,
  680. IN UINT64 SrcOffset,
  681. IN UINTN Count
  682. )
  683. /*++
  684. Routine Description:
  685. Copy PCI Memory
  686. Arguments:
  687. Returns:
  688. None
  689. --*/
  690. {
  691. EFI_STATUS Status;
  692. PCI_IO_DEVICE *PciIoDevice;
  693. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  694. if ((UINT32)Width >= EfiPciIoWidthMaximum) {
  695. return EFI_INVALID_PARAMETER;
  696. }
  697. if (Width == EfiPciIoWidthFifoUint8 ||
  698. Width == EfiPciIoWidthFifoUint16 ||
  699. Width == EfiPciIoWidthFifoUint32 ||
  700. Width == EfiPciIoWidthFifoUint64 ||
  701. Width == EfiPciIoWidthFillUint8 ||
  702. Width == EfiPciIoWidthFillUint16 ||
  703. Width == EfiPciIoWidthFillUint32 ||
  704. Width == EfiPciIoWidthFillUint64) {
  705. return EFI_INVALID_PARAMETER;
  706. }
  707. Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
  708. if (EFI_ERROR (Status)) {
  709. return EFI_UNSUPPORTED;
  710. }
  711. Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
  712. if (EFI_ERROR (Status)) {
  713. return EFI_UNSUPPORTED;
  714. }
  715. Status = PciIoDevice->PciRootBridgeIo->CopyMem (
  716. PciIoDevice->PciRootBridgeIo,
  717. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
  718. DestOffset,
  719. SrcOffset,
  720. Count
  721. );
  722. return Status;
  723. }
  724. EFI_STATUS
  725. EFIAPI
  726. PciIoMap (
  727. IN EFI_PCI_IO_PROTOCOL *This,
  728. IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
  729. IN VOID *HostAddress,
  730. IN OUT UINTN *NumberOfBytes,
  731. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  732. OUT VOID **Mapping
  733. )
  734. /*++
  735. Routine Description:
  736. Maps a memory region for DMA
  737. Arguments:
  738. Returns:
  739. None
  740. --*/
  741. {
  742. EFI_STATUS Status;
  743. PCI_IO_DEVICE *PciIoDevice;
  744. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  745. if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
  746. return EFI_INVALID_PARAMETER;
  747. }
  748. if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
  749. return EFI_INVALID_PARAMETER;
  750. }
  751. if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
  752. Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
  753. }
  754. Status = PciIoDevice->PciRootBridgeIo->Map (
  755. PciIoDevice->PciRootBridgeIo,
  756. (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
  757. HostAddress,
  758. NumberOfBytes,
  759. DeviceAddress,
  760. Mapping
  761. );
  762. return Status;
  763. }
  764. EFI_STATUS
  765. EFIAPI
  766. PciIoUnmap (
  767. IN EFI_PCI_IO_PROTOCOL *This,
  768. IN VOID *Mapping
  769. )
  770. /*++
  771. Routine Description:
  772. Unmaps a memory region for DMA
  773. Arguments:
  774. Returns:
  775. None
  776. --*/
  777. {
  778. EFI_STATUS Status;
  779. PCI_IO_DEVICE *PciIoDevice;
  780. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  781. Status = PciIoDevice->PciRootBridgeIo->Unmap (
  782. PciIoDevice->PciRootBridgeIo,
  783. Mapping
  784. );
  785. return Status;
  786. }
  787. EFI_STATUS
  788. EFIAPI
  789. PciIoAllocateBuffer (
  790. IN EFI_PCI_IO_PROTOCOL *This,
  791. IN EFI_ALLOCATE_TYPE Type,
  792. IN EFI_MEMORY_TYPE MemoryType,
  793. IN UINTN Pages,
  794. OUT VOID **HostAddress,
  795. IN UINT64 Attributes
  796. )
  797. /*++
  798. Routine Description:
  799. Allocates a common buffer for DMA
  800. Arguments:
  801. Returns:
  802. None
  803. --*/
  804. {
  805. EFI_STATUS Status;
  806. PCI_IO_DEVICE *PciIoDevice;
  807. if (Attributes &
  808. (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
  809. return EFI_UNSUPPORTED;
  810. }
  811. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  812. if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
  813. Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
  814. }
  815. Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
  816. PciIoDevice->PciRootBridgeIo,
  817. Type,
  818. MemoryType,
  819. Pages,
  820. HostAddress,
  821. Attributes
  822. );
  823. return Status;
  824. }
  825. EFI_STATUS
  826. EFIAPI
  827. PciIoFreeBuffer (
  828. IN EFI_PCI_IO_PROTOCOL *This,
  829. IN UINTN Pages,
  830. IN VOID *HostAddress
  831. )
  832. /*++
  833. Routine Description:
  834. Frees a common buffer
  835. Arguments:
  836. Returns:
  837. None
  838. --*/
  839. {
  840. EFI_STATUS Status;
  841. PCI_IO_DEVICE *PciIoDevice;
  842. if( HostAddress == NULL ){
  843. return EFI_INVALID_PARAMETER;
  844. }
  845. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  846. Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
  847. PciIoDevice->PciRootBridgeIo,
  848. Pages,
  849. HostAddress
  850. );
  851. return Status;
  852. }
  853. EFI_STATUS
  854. EFIAPI
  855. PciIoFlush (
  856. IN EFI_PCI_IO_PROTOCOL *This
  857. )
  858. /*++
  859. Routine Description:
  860. Flushes a DMA buffer
  861. Arguments:
  862. Returns:
  863. None
  864. --*/
  865. {
  866. EFI_STATUS Status;
  867. UINT32 Register;
  868. PCI_IO_DEVICE *PciIoDevice;
  869. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  870. //
  871. // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to
  872. // flush the posted write cycles through the PCI-PCI bridges
  873. //
  874. if (PciIoDevice->Parent != NULL) {
  875. Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);
  876. }
  877. //
  878. // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
  879. //
  880. Status = PciIoDevice->PciRootBridgeIo->Flush (
  881. PciIoDevice->PciRootBridgeIo
  882. );
  883. return Status;
  884. }
  885. EFI_STATUS
  886. EFIAPI
  887. PciIoGetLocation (
  888. IN EFI_PCI_IO_PROTOCOL *This,
  889. OUT UINTN *Segment,
  890. OUT UINTN *Bus,
  891. OUT UINTN *Device,
  892. OUT UINTN *Function
  893. )
  894. /*++
  895. Routine Description:
  896. Gets a PCI device's current bus number, device number, and function number.
  897. Arguments:
  898. Returns:
  899. None
  900. --*/
  901. {
  902. PCI_IO_DEVICE *PciIoDevice;
  903. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  904. if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
  905. return EFI_INVALID_PARAMETER;
  906. }
  907. *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
  908. *Bus = PciIoDevice->BusNumber;
  909. *Device = PciIoDevice->DeviceNumber;
  910. *Function = PciIoDevice->FunctionNumber;
  911. return EFI_SUCCESS;
  912. }
  913. BOOLEAN
  914. CheckBarType (
  915. IN PCI_IO_DEVICE *PciIoDevice,
  916. UINT8 BarIndex,
  917. PCI_BAR_TYPE BarType
  918. )
  919. /*++
  920. Routine Description:
  921. Sets a PCI controllers attributes on a resource range
  922. Arguments:
  923. Returns:
  924. None
  925. --*/
  926. {
  927. switch (BarType) {
  928. case PciBarTypeMem:
  929. if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&
  930. PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
  931. PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
  932. PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {
  933. return FALSE;
  934. }
  935. return TRUE;
  936. case PciBarTypeIo:
  937. if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
  938. PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
  939. return FALSE;
  940. }
  941. return TRUE;
  942. default:
  943. break;
  944. }
  945. return FALSE;
  946. }
  947. EFI_STATUS
  948. EFIAPI
  949. PciIoAttributes (
  950. IN EFI_PCI_IO_PROTOCOL * This,
  951. IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
  952. IN UINT64 Attributes,
  953. OUT UINT64 *Result OPTIONAL
  954. )
  955. /*++
  956. Routine Description:
  957. Arguments:
  958. Returns:
  959. None
  960. --*/
  961. {
  962. EFI_STATUS Status;
  963. PCI_IO_DEVICE *PciIoDevice;
  964. PCI_IO_DEVICE *Temp;
  965. UINT64 NewAttributes;
  966. UINT64 PciRootBridgeSupports;
  967. UINT64 PciRootBridgeAttributes;
  968. UINT64 NewPciRootBridgeAttributes;
  969. UINT64 NewUpStreamBridgeAttributes;
  970. UINT64 ModifiedPciRootBridgeAttributes;
  971. UINT16 EnableCommand;
  972. UINT16 DisableCommand;
  973. UINT16 EnableBridge;
  974. UINT16 DisableBridge;
  975. UINT16 Command;
  976. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  977. NewUpStreamBridgeAttributes = 0;
  978. EnableCommand = 0;
  979. DisableCommand = 0;
  980. EnableBridge = 0;
  981. DisableBridge = 0;
  982. switch (Operation) {
  983. case EfiPciIoAttributeOperationGet:
  984. if (Result == NULL) {
  985. return EFI_INVALID_PARAMETER;
  986. }
  987. *Result = PciIoDevice->Attributes;
  988. return EFI_SUCCESS;
  989. case EfiPciIoAttributeOperationSupported:
  990. if (Result == NULL) {
  991. return EFI_INVALID_PARAMETER;
  992. }
  993. *Result = PciIoDevice->Supports;
  994. return EFI_SUCCESS;
  995. case EfiPciIoAttributeOperationEnable:
  996. if(Attributes & ~(PciIoDevice->Supports)) {
  997. return EFI_UNSUPPORTED;
  998. }
  999. NewAttributes = PciIoDevice->Attributes | Attributes;
  1000. break;
  1001. case EfiPciIoAttributeOperationDisable:
  1002. if(Attributes & ~(PciIoDevice->Supports)) {
  1003. return EFI_UNSUPPORTED;
  1004. }
  1005. NewAttributes = PciIoDevice->Attributes & (~Attributes);
  1006. break;
  1007. case EfiPciIoAttributeOperationSet:
  1008. if(Attributes & ~(PciIoDevice->Supports)) {
  1009. return EFI_UNSUPPORTED;
  1010. }
  1011. NewAttributes = Attributes;
  1012. break;
  1013. default:
  1014. return EFI_INVALID_PARAMETER;
  1015. }
  1016. //
  1017. // If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately.
  1018. //
  1019. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
  1020. NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  1021. }
  1022. //
  1023. // If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately.
  1024. //
  1025. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {
  1026. NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
  1027. }
  1028. //
  1029. // If the attributes are already set correctly, then just return EFI_SUCCESS;
  1030. //
  1031. if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {
  1032. return EFI_SUCCESS;
  1033. }
  1034. //
  1035. // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
  1036. // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so
  1037. // a call to the PCI Root Bridge I/O Protocol can be made
  1038. //
  1039. if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
  1040. NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
  1041. //
  1042. // Get the current attributes of this PCI device's PCI Root Bridge
  1043. //
  1044. Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
  1045. PciIoDevice->PciRootBridgeIo,
  1046. &PciRootBridgeSupports,
  1047. &PciRootBridgeAttributes
  1048. );
  1049. //
  1050. // Check to see if any of the PCI Root Bridge attributes are being modified
  1051. //
  1052. ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;
  1053. if (ModifiedPciRootBridgeAttributes) {
  1054. //
  1055. // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
  1056. //
  1057. if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {
  1058. // return EFI_UNSUPPORTED;
  1059. }
  1060. //
  1061. // Call the PCI Root Bridge to attempt to modify the attributes
  1062. //
  1063. Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
  1064. PciIoDevice->PciRootBridgeIo,
  1065. NewPciRootBridgeAttributes,
  1066. NULL,
  1067. NULL
  1068. );
  1069. if (EFI_ERROR (Status)) {
  1070. //
  1071. // The PCI Root Bridge could not modify the attributes, so return the error.
  1072. //
  1073. return Status;
  1074. }
  1075. }
  1076. }
  1077. if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
  1078. //
  1079. // Check to see if an VGA related attributes are being set.
  1080. //
  1081. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
  1082. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
  1083. EnableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;
  1084. } else {
  1085. DisableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;
  1086. }
  1087. }
  1088. //
  1089. // Check to see if an VGA related attributes are being set.
  1090. // If ISA Enable on the PPB is set, the PPB will block the
  1091. // 0x100-0x3FF for each 1KB block in the first 64K I/O block
  1092. //
  1093. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {
  1094. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
  1095. DisableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;
  1096. } else {
  1097. EnableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;
  1098. }
  1099. }
  1100. //
  1101. // Check to see if an VGA related attributes are being set.
  1102. //
  1103. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
  1104. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
  1105. EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1106. } else {
  1107. DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1108. }
  1109. }
  1110. } else {
  1111. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
  1112. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
  1113. //
  1114. //Check if there have been an active VGA device on the same segment
  1115. //
  1116. Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
  1117. if (Temp && Temp != PciIoDevice) {
  1118. return EFI_UNSUPPORTED;
  1119. }
  1120. }
  1121. }
  1122. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
  1123. if (IS_PCI_GFX(&PciIoDevice->Pci)) {
  1124. //
  1125. //Get the boot VGA on the same segement
  1126. //
  1127. Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
  1128. if (!Temp) {
  1129. //
  1130. // If there is no VGA device on the segement, set
  1131. // this graphics card to decode the palette range
  1132. //
  1133. DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1134. } else {
  1135. //
  1136. // Check these two agents are on the same path
  1137. //
  1138. if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {
  1139. //
  1140. // Check if they are on the same bus
  1141. //
  1142. if (Temp->Parent == PciIoDevice->Parent) {
  1143. PciReadCommandRegister (Temp, &Command);
  1144. //
  1145. // If they are on the same bus, either one can
  1146. // be set to snoop, the other set to decode
  1147. //
  1148. if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
  1149. DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1150. } else {
  1151. EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1152. }
  1153. } else {
  1154. //
  1155. // If they are on the same path but on the different bus
  1156. // The first agent is set to snoop, the second one set to
  1157. // decode
  1158. //
  1159. if (Temp->BusNumber > PciIoDevice->BusNumber) {
  1160. PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
  1161. DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1162. } else {
  1163. PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
  1164. EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1165. }
  1166. }
  1167. } else {
  1168. EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1169. }
  1170. }
  1171. }
  1172. }
  1173. }
  1174. //
  1175. // Check to see of the I/O enable is being modified
  1176. //
  1177. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {
  1178. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {
  1179. EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;
  1180. } else {
  1181. DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;
  1182. }
  1183. }
  1184. //
  1185. // Check to see of the Memory enable is being modified
  1186. //
  1187. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {
  1188. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
  1189. EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
  1190. } else {
  1191. DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
  1192. }
  1193. }
  1194. //
  1195. // Check to see of the Bus Master enable is being modified
  1196. //
  1197. if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {
  1198. if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
  1199. EnableCommand |= EFI_PCI_COMMAND_BUS_MASTER;
  1200. } else {
  1201. DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;
  1202. }
  1203. }
  1204. Status = EFI_SUCCESS;
  1205. if (EnableCommand) {
  1206. Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);
  1207. }
  1208. if (DisableCommand) {
  1209. Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);
  1210. }
  1211. if (EFI_ERROR(Status)) {
  1212. return EFI_UNSUPPORTED;
  1213. }
  1214. if (EnableBridge) {
  1215. Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);
  1216. }
  1217. if (DisableBridge) {
  1218. Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);
  1219. }
  1220. if (EFI_ERROR(Status)) {
  1221. return EFI_UNSUPPORTED;
  1222. }
  1223. //
  1224. // Set the upstream bridge attributes
  1225. //
  1226. if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {
  1227. //
  1228. // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
  1229. // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
  1230. // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge
  1231. //
  1232. NewUpStreamBridgeAttributes = Attributes & \
  1233. (~(EFI_PCI_IO_ATTRIBUTE_IO | \
  1234. EFI_PCI_IO_ATTRIBUTE_MEMORY | \
  1235. EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \
  1236. EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \
  1237. EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \
  1238. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
  1239. if (NewUpStreamBridgeAttributes){
  1240. UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);
  1241. }
  1242. }
  1243. PciIoDevice->Attributes = NewAttributes;
  1244. return Status;
  1245. }
  1246. EFI_STATUS
  1247. EFIAPI
  1248. PciIoGetBarAttributes (
  1249. IN EFI_PCI_IO_PROTOCOL * This,
  1250. IN UINT8 BarIndex,
  1251. OUT UINT64 *Supports, OPTIONAL
  1252. OUT VOID **Resources OPTIONAL
  1253. )
  1254. /*++
  1255. Routine Description:
  1256. Arguments:
  1257. Returns:
  1258. None
  1259. --*/
  1260. {
  1261. UINT8 *Configuration;
  1262. PCI_IO_DEVICE *PciIoDevice;
  1263. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace;
  1264. EFI_ACPI_END_TAG_DESCRIPTOR *End;
  1265. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  1266. if (Supports == NULL && Resources == NULL) {
  1267. return EFI_INVALID_PARAMETER;
  1268. }
  1269. if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {
  1270. return EFI_UNSUPPORTED;
  1271. }
  1272. //
  1273. // This driver does not support modifications to the WRITE_COMBINE or
  1274. // CACHED attributes for BAR ranges.
  1275. //
  1276. if (Supports != NULL) {
  1277. *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
  1278. }
  1279. if (Resources != NULL) {
  1280. Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
  1281. if (Configuration == NULL) {
  1282. return EFI_OUT_OF_RESOURCES;
  1283. }
  1284. AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
  1285. AddressSpace->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1286. AddressSpace->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
  1287. AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
  1288. AddressSpace->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
  1289. AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
  1290. switch (PciIoDevice->PciBar[BarIndex].BarType) {
  1291. case PciBarTypeIo16:
  1292. case PciBarTypeIo32:
  1293. //
  1294. // Io
  1295. //
  1296. AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
  1297. break;
  1298. case PciBarTypeMem32:
  1299. //
  1300. // Mem
  1301. //
  1302. AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1303. //
  1304. // 32 bit
  1305. //
  1306. AddressSpace->AddrSpaceGranularity = 32;
  1307. break;
  1308. case PciBarTypePMem32:
  1309. //
  1310. // Mem
  1311. //
  1312. AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1313. //
  1314. // prefechable
  1315. //
  1316. AddressSpace->SpecificFlag = 0x6;
  1317. //
  1318. // 32 bit
  1319. //
  1320. AddressSpace->AddrSpaceGranularity = 32;
  1321. break;
  1322. case PciBarTypeMem64:
  1323. //
  1324. // Mem
  1325. //
  1326. AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1327. //
  1328. // 64 bit
  1329. //
  1330. AddressSpace->AddrSpaceGranularity = 64;
  1331. break;
  1332. case PciBarTypePMem64:
  1333. //
  1334. // Mem
  1335. //
  1336. AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1337. //
  1338. // prefechable
  1339. //
  1340. AddressSpace->SpecificFlag = 0x6;
  1341. //
  1342. // 64 bit
  1343. //
  1344. AddressSpace->AddrSpaceGranularity = 64;
  1345. break;
  1346. default:
  1347. break;
  1348. }
  1349. //
  1350. // put the checksum
  1351. //
  1352. End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1);
  1353. End->Desc = ACPI_END_TAG_DESCRIPTOR;
  1354. End->Checksum = 0;
  1355. *Resources = Configuration;
  1356. }
  1357. return EFI_SUCCESS;
  1358. }
  1359. EFI_STATUS
  1360. EFIAPI
  1361. PciIoSetBarAttributes (
  1362. IN EFI_PCI_IO_PROTOCOL *This,
  1363. IN UINT64 Attributes,
  1364. IN UINT8 BarIndex,
  1365. IN OUT UINT64 *Offset,
  1366. IN OUT UINT64 *Length
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. Arguments:
  1371. Returns:
  1372. None
  1373. --*/
  1374. {
  1375. EFI_STATUS Status;
  1376. PCI_IO_DEVICE *PciIoDevice;
  1377. UINT64 NonRelativeOffset;
  1378. UINT64 Supports;
  1379. PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
  1380. //
  1381. // Make sure Offset and Length are not NULL
  1382. //
  1383. if (Offset == NULL || Length == NULL) {
  1384. return EFI_INVALID_PARAMETER;
  1385. }
  1386. if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
  1387. return EFI_UNSUPPORTED;
  1388. }
  1389. //
  1390. // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
  1391. // If Attributes is not 0, then return EFI_UNSUPPORTED.
  1392. //
  1393. Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
  1394. if (Attributes != (Attributes & Supports)) {
  1395. return EFI_UNSUPPORTED;
  1396. }
  1397. //
  1398. // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
  1399. // Length are valid for this PCI device.
  1400. //
  1401. NonRelativeOffset = *Offset;
  1402. Status = PciIoVerifyBarAccess (
  1403. PciIoDevice,
  1404. BarIndex,
  1405. PciBarTypeMem,
  1406. EfiPciIoWidthUint8,
  1407. (UINT32) *Length,
  1408. &NonRelativeOffset
  1409. );
  1410. if (EFI_ERROR (Status)) {
  1411. return EFI_UNSUPPORTED;
  1412. }
  1413. return EFI_SUCCESS;
  1414. }
  1415. EFI_STATUS
  1416. UpStreamBridgesAttributes (
  1417. IN PCI_IO_DEVICE *PciIoDevice,
  1418. IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
  1419. IN UINT64 Attributes
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. Arguments:
  1424. Returns:
  1425. None
  1426. --*/
  1427. {
  1428. PCI_IO_DEVICE *Parent;
  1429. EFI_PCI_IO_PROTOCOL *PciIo;
  1430. Parent = PciIoDevice->Parent;
  1431. while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
  1432. //
  1433. // Get the PciIo Protocol
  1434. //
  1435. PciIo = &Parent->PciIo;
  1436. PciIo->Attributes (PciIo, Operation, Attributes, NULL);
  1437. Parent = Parent->Parent;
  1438. }
  1439. return EFI_SUCCESS;
  1440. }
  1441. BOOLEAN
  1442. PciDevicesOnTheSamePath (
  1443. IN PCI_IO_DEVICE *PciDevice1,
  1444. IN PCI_IO_DEVICE *PciDevice2
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Arguments:
  1449. PciDevice1 - The pointer to the first PCI_IO_DEVICE.
  1450. PciDevice2 - The pointer to the second PCI_IO_DEVICE.
  1451. Returns:
  1452. TRUE - The two Pci devices are on the same path.
  1453. FALSE - The two Pci devices are not on the same path.
  1454. --*/
  1455. {
  1456. if (PciDevice1->Parent == PciDevice2->Parent) {
  1457. return TRUE;
  1458. }
  1459. return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1)));
  1460. }