2 EFI PCI IO protocol functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 extern EDKII_IOMMU_PROTOCOL
*mIoMmuProtocol
;
14 // Pci Io Protocol Interface
16 EFI_PCI_IO_PROTOCOL mPciIoInterface
= {
39 PciIoGetBarAttributes
,
40 PciIoSetBarAttributes
,
46 Initializes a PCI I/O Instance.
48 @param PciIoDevice Pci device instance.
52 InitializePciIoInstance (
53 IN PCI_IO_DEVICE
*PciIoDevice
56 CopyMem (&PciIoDevice
->PciIo
, &mPciIoInterface
, sizeof (EFI_PCI_IO_PROTOCOL
));
60 Verifies access to a PCI Base Address Register (BAR).
62 @param PciIoDevice Pci device instance.
63 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
64 base address for the memory or I/O operation to perform.
65 @param Type Operation type could be memory or I/O.
66 @param Width Signifies the width of the memory or I/O operations.
67 @param Count The number of memory or I/O operations to perform.
68 @param Offset The offset within the PCI configuration space for the PCI controller.
70 @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.
71 @retval EFI_SUCCESS Successfully verified.
75 PciIoVerifyBarAccess (
76 IN PCI_IO_DEVICE
*PciIoDevice
,
79 IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
84 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
85 return EFI_INVALID_PARAMETER
;
88 if (BarIndex
== EFI_PCI_IO_PASS_THROUGH_BAR
) {
93 // BarIndex 0-5 is legal
95 if (BarIndex
>= PCI_MAX_BAR
) {
96 return EFI_INVALID_PARAMETER
;
99 if (!CheckBarType (PciIoDevice
, BarIndex
, Type
)) {
100 return EFI_INVALID_PARAMETER
;
104 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
105 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
107 if (Width
>= EfiPciIoWidthFifoUint8
&& Width
<= EfiPciIoWidthFifoUint64
) {
111 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
113 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PciIoDevice
->PciBar
[BarIndex
].Length
) {
114 return EFI_INVALID_PARAMETER
;
117 *Offset
= *Offset
+ PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
123 Verifies access to a PCI Configuration Header.
125 @param PciIoDevice Pci device instance.
126 @param Width Signifies the width of the memory or I/O operations.
127 @param Count The number of memory or I/O operations to perform.
128 @param Offset The offset within the PCI configuration space for the PCI controller.
130 @retval EFI_INVALID_PARAMETER Invalid Width
131 @retval EFI_UNSUPPORTED Offset overflowed.
132 @retval EFI_SUCCESS Successfully verified.
136 PciIoVerifyConfigAccess (
137 IN PCI_IO_DEVICE
*PciIoDevice
,
138 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
145 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
146 return EFI_INVALID_PARAMETER
;
150 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
152 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
154 if (PciIoDevice
->IsPciExp
) {
155 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET
) {
156 return EFI_UNSUPPORTED
;
159 ExtendOffset
= LShiftU64 (*Offset
, 32);
160 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, 0);
161 *Offset
= (*Offset
) | ExtendOffset
;
164 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PCI_MAX_CONFIG_OFFSET
) {
165 return EFI_UNSUPPORTED
;
168 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, *Offset
);
175 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
176 satisfied or after a defined duration.
178 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
179 @param Width Signifies the width of the memory or I/O operations.
180 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
181 base address for the memory operation to perform.
182 @param Offset The offset within the selected BAR to start the memory operation.
183 @param Mask Mask used for the polling criteria.
184 @param Value The comparison value used for the polling exit criteria.
185 @param Delay The number of 100 ns units to poll.
186 @param Result Pointer to the last value read from the memory location.
188 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
189 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
190 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.
191 @retval EFI_TIMEOUT Delay expired before a match occurred.
192 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
193 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
199 IN EFI_PCI_IO_PROTOCOL
*This
,
200 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
210 PCI_IO_DEVICE
*PciIoDevice
;
212 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
214 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
215 return EFI_INVALID_PARAMETER
;
218 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, 1, &Offset
);
219 if (EFI_ERROR (Status
)) {
220 return EFI_UNSUPPORTED
;
223 if (Width
> EfiPciIoWidthUint64
) {
224 return EFI_INVALID_PARAMETER
;
228 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
230 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
231 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
232 Status
= PciIoMemRead (This
, Width
, BarIndex
, Offset
, 1, Result
);
233 if (EFI_ERROR (Status
)) {
236 if ((*Result
& Mask
) == Value
|| Delay
== 0) {
241 // Stall 10 us = 100 * 100ns
245 Status
= PciIoMemRead (This
, Width
, BarIndex
, Offset
, 1, Result
);
246 if (EFI_ERROR (Status
)) {
249 if ((*Result
& Mask
) == Value
) {
260 Status
= PciIoDevice
->PciRootBridgeIo
->PollMem (
261 PciIoDevice
->PciRootBridgeIo
,
262 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
270 if (EFI_ERROR (Status
)) {
271 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
272 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
273 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
274 PciIoDevice
->DevicePath
282 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
283 satisfied or after a defined duration.
285 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
286 @param Width Signifies the width of the memory or I/O operations.
287 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
288 base address for the memory operation to perform.
289 @param Offset The offset within the selected BAR to start the memory operation.
290 @param Mask Mask used for the polling criteria.
291 @param Value The comparison value used for the polling exit criteria.
292 @param Delay The number of 100 ns units to poll.
293 @param Result Pointer to the last value read from the memory location.
295 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
296 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
297 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.
298 @retval EFI_TIMEOUT Delay expired before a match occurred.
299 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
300 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
306 IN EFI_PCI_IO_PROTOCOL
*This
,
307 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
317 PCI_IO_DEVICE
*PciIoDevice
;
319 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
321 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
322 return EFI_INVALID_PARAMETER
;
325 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, 1, &Offset
);
326 if (EFI_ERROR (Status
)) {
327 return EFI_UNSUPPORTED
;
331 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
333 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
334 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
335 Status
= PciIoIoRead (This
, Width
, BarIndex
, Offset
, 1, Result
);
336 if (EFI_ERROR (Status
)) {
339 if ((*Result
& Mask
) == Value
|| Delay
== 0) {
344 // Stall 10 us = 100 * 100ns
348 Status
= PciIoIoRead (This
, Width
, BarIndex
, Offset
, 1, Result
);
349 if (EFI_ERROR (Status
)) {
352 if ((*Result
& Mask
) == Value
) {
363 Status
= PciIoDevice
->PciRootBridgeIo
->PollIo (
364 PciIoDevice
->PciRootBridgeIo
,
365 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
373 if (EFI_ERROR (Status
)) {
374 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
375 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
376 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
377 PciIoDevice
->DevicePath
385 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
387 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
388 @param Width Signifies the width of the memory or I/O operations.
389 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
390 base address for the memory or I/O operation to perform.
391 @param Offset The offset within the selected BAR to start the memory or I/O operation.
392 @param Count The number of memory or I/O operations to perform.
393 @param Buffer For read operations, the destination buffer to store the results. For write
394 operations, the source buffer to write data from.
396 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
397 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
398 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
399 valid for the PCI BAR specified by BarIndex.
400 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
401 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
407 IN EFI_PCI_IO_PROTOCOL
*This
,
408 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
416 PCI_IO_DEVICE
*PciIoDevice
;
418 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
420 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
421 return EFI_INVALID_PARAMETER
;
424 if (Buffer
== NULL
) {
425 return EFI_INVALID_PARAMETER
;
428 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
429 if (EFI_ERROR (Status
)) {
430 return EFI_UNSUPPORTED
;
434 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
436 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
437 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
438 Count
*= (UINTN
)(1 << (Width
& 0x03));
439 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
444 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Read (
445 PciIoDevice
->PciRootBridgeIo
,
446 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
452 if (EFI_ERROR (Status
)) {
453 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
454 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
455 EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
,
456 PciIoDevice
->DevicePath
464 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
466 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
467 @param Width Signifies the width of the memory or I/O operations.
468 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
469 base address for the memory or I/O operation to perform.
470 @param Offset The offset within the selected BAR to start the memory or I/O operation.
471 @param Count The number of memory or I/O operations to perform.
472 @param Buffer For read operations, the destination buffer to store the results. For write
473 operations, the source buffer to write data from.
475 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
476 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
477 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
478 valid for the PCI BAR specified by BarIndex.
479 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
480 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
486 IN EFI_PCI_IO_PROTOCOL
*This
,
487 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
495 PCI_IO_DEVICE
*PciIoDevice
;
497 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
499 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
500 return EFI_INVALID_PARAMETER
;
503 if (Buffer
== NULL
) {
504 return EFI_INVALID_PARAMETER
;
507 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
508 if (EFI_ERROR (Status
)) {
509 return EFI_UNSUPPORTED
;
513 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
515 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
516 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
517 Count
*= (UINTN
)(1 << (Width
& 0x03));
518 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
522 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Write (
523 PciIoDevice
->PciRootBridgeIo
,
524 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
530 if (EFI_ERROR (Status
)) {
531 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
532 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
533 EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
,
534 PciIoDevice
->DevicePath
542 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
544 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
545 @param Width Signifies the width of the memory or I/O operations.
546 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
547 base address for the memory or I/O operation to perform.
548 @param Offset The offset within the selected BAR to start the memory or I/O operation.
549 @param Count The number of memory or I/O operations to perform.
550 @param Buffer For read operations, the destination buffer to store the results. For write
551 operations, the source buffer to write data from.
553 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
554 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
555 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
556 valid for the PCI BAR specified by BarIndex.
557 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
558 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
564 IN EFI_PCI_IO_PROTOCOL
*This
,
565 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
573 PCI_IO_DEVICE
*PciIoDevice
;
575 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
577 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
578 return EFI_INVALID_PARAMETER
;
581 if (Buffer
== NULL
) {
582 return EFI_INVALID_PARAMETER
;
585 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
586 if (EFI_ERROR (Status
)) {
587 return EFI_UNSUPPORTED
;
591 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
593 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
594 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
595 Count
*= (UINTN
)(1 << (Width
& 0x03));
596 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
600 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Read (
601 PciIoDevice
->PciRootBridgeIo
,
602 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
608 if (EFI_ERROR (Status
)) {
609 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
610 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
611 EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
,
612 PciIoDevice
->DevicePath
620 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
622 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
623 @param Width Signifies the width of the memory or I/O operations.
624 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
625 base address for the memory or I/O operation to perform.
626 @param Offset The offset within the selected BAR to start the memory or I/O operation.
627 @param Count The number of memory or I/O operations to perform.
628 @param Buffer For read operations, the destination buffer to store the results. For write
629 operations, the source buffer to write data from.
631 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
632 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
633 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
634 valid for the PCI BAR specified by BarIndex.
635 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
636 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
642 IN EFI_PCI_IO_PROTOCOL
*This
,
643 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
651 PCI_IO_DEVICE
*PciIoDevice
;
653 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
655 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
656 return EFI_INVALID_PARAMETER
;
659 if (Buffer
== NULL
) {
660 return EFI_INVALID_PARAMETER
;
663 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
664 if (EFI_ERROR (Status
)) {
665 return EFI_UNSUPPORTED
;
669 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
671 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
672 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
673 Count
*= (UINTN
)(1 << (Width
& 0x03));
674 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
678 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Write (
679 PciIoDevice
->PciRootBridgeIo
,
680 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
686 if (EFI_ERROR (Status
)) {
687 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
688 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
689 EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
,
690 PciIoDevice
->DevicePath
698 Enable a PCI driver to access PCI controller registers in PCI configuration space.
700 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
701 @param Width Signifies the width of the memory operations.
702 @param Offset The offset within the PCI configuration space for the PCI controller.
703 @param Count The number of PCI configuration operations to perform.
704 @param Buffer For read operations, the destination buffer to store the results. For write
705 operations, the source buffer to write data from.
708 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
709 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
710 valid for the PCI configuration header of the PCI controller.
711 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
712 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
718 IN EFI_PCI_IO_PROTOCOL
*This
,
719 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
726 PCI_IO_DEVICE
*PciIoDevice
;
729 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
732 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
733 if (EFI_ERROR (Status
)) {
738 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
740 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
741 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
742 Count
*= (UINTN
)(1 << (Width
& 0x03));
743 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
747 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Read (
748 PciIoDevice
->PciRootBridgeIo
,
749 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
755 if (EFI_ERROR (Status
)) {
756 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
757 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
758 EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
,
759 PciIoDevice
->DevicePath
767 Enable a PCI driver to access PCI controller registers in PCI configuration space.
769 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
770 @param Width Signifies the width of the memory operations.
771 @param Offset The offset within the PCI configuration space for the PCI controller.
772 @param Count The number of PCI configuration operations to perform.
773 @param Buffer For read operations, the destination buffer to store the results. For write
774 operations, the source buffer to write data from.
777 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
778 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
779 valid for the PCI configuration header of the PCI controller.
780 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
781 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
787 IN EFI_PCI_IO_PROTOCOL
*This
,
788 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
795 PCI_IO_DEVICE
*PciIoDevice
;
798 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
801 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
802 if (EFI_ERROR (Status
)) {
807 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
809 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
810 if ((Offset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
811 Count
*= (UINTN
)(1 << (Width
& 0x03));
812 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
816 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Write (
817 PciIoDevice
->PciRootBridgeIo
,
818 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
824 if (EFI_ERROR (Status
)) {
825 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
826 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
827 EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
,
828 PciIoDevice
->DevicePath
836 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
839 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
840 @param Width Signifies the width of the memory operations.
841 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
842 base address for the memory operation to perform.
843 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
844 start the memory writes for the copy operation.
845 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
846 base address for the memory operation to perform.
847 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
848 the memory reads for the copy operation.
849 @param Count The number of memory operations to perform. Bytes moved is Width
850 size * Count, starting at DestOffset and SrcOffset.
852 @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
853 @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.
854 @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.
855 @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count
856 is not valid for the PCI BAR specified by DestBarIndex.
857 @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is
858 not valid for the PCI BAR specified by SrcBarIndex.
859 @retval EFI_INVALID_PARAMETER Width is invalid.
860 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
866 IN EFI_PCI_IO_PROTOCOL
*This
,
867 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
868 IN UINT8 DestBarIndex
,
869 IN UINT64 DestOffset
,
870 IN UINT8 SrcBarIndex
,
876 PCI_IO_DEVICE
*PciIoDevice
;
878 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
880 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
881 return EFI_INVALID_PARAMETER
;
884 if (Width
== EfiPciIoWidthFifoUint8
||
885 Width
== EfiPciIoWidthFifoUint16
||
886 Width
== EfiPciIoWidthFifoUint32
||
887 Width
== EfiPciIoWidthFifoUint64
||
888 Width
== EfiPciIoWidthFillUint8
||
889 Width
== EfiPciIoWidthFillUint16
||
890 Width
== EfiPciIoWidthFillUint32
||
891 Width
== EfiPciIoWidthFillUint64
) {
892 return EFI_INVALID_PARAMETER
;
895 Status
= PciIoVerifyBarAccess (PciIoDevice
, DestBarIndex
, PciBarTypeMem
, Width
, Count
, &DestOffset
);
896 if (EFI_ERROR (Status
)) {
897 return EFI_UNSUPPORTED
;
900 Status
= PciIoVerifyBarAccess (PciIoDevice
, SrcBarIndex
, PciBarTypeMem
, Width
, Count
, &SrcOffset
);
901 if (EFI_ERROR (Status
)) {
902 return EFI_UNSUPPORTED
;
906 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
908 if (FeaturePcdGet (PcdUnalignedPciIoEnable
)) {
909 if ((SrcOffset
& ((1 << (Width
& 0x03)) - 1)) != 0 || (DestOffset
& ((1 << (Width
& 0x03)) - 1)) != 0) {
910 Count
*= (UINTN
)(1 << (Width
& 0x03));
911 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& (~0x03));
915 Status
= PciIoDevice
->PciRootBridgeIo
->CopyMem (
916 PciIoDevice
->PciRootBridgeIo
,
917 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
923 if (EFI_ERROR (Status
)) {
924 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
925 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
926 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
927 PciIoDevice
->DevicePath
935 Provides the PCI controller-specific addresses needed to access system memory.
937 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
938 @param Operation Indicates if the bus master is going to read or write to system memory.
939 @param HostAddress The system memory address to map to the PCI controller.
940 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
942 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
943 access the hosts HostAddress.
944 @param Mapping A resulting value to pass to Unmap().
946 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
947 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
948 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
949 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
950 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
956 IN EFI_PCI_IO_PROTOCOL
*This
,
957 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
958 IN VOID
*HostAddress
,
959 IN OUT UINTN
*NumberOfBytes
,
960 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
965 PCI_IO_DEVICE
*PciIoDevice
;
966 UINT64 IoMmuAttribute
;
967 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation
;
969 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
971 if ((UINT32
)Operation
>= EfiPciIoOperationMaximum
) {
972 return EFI_INVALID_PARAMETER
;
975 if (HostAddress
== NULL
|| NumberOfBytes
== NULL
|| DeviceAddress
== NULL
|| Mapping
== NULL
) {
976 return EFI_INVALID_PARAMETER
;
979 RootBridgeIoOperation
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
)Operation
;
980 if ((PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) != 0) {
981 RootBridgeIoOperation
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
)(Operation
+ EfiPciOperationBusMasterRead64
);
984 Status
= PciIoDevice
->PciRootBridgeIo
->Map (
985 PciIoDevice
->PciRootBridgeIo
,
986 RootBridgeIoOperation
,
993 if (EFI_ERROR (Status
)) {
994 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
995 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
996 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
997 PciIoDevice
->DevicePath
1001 if (mIoMmuProtocol
!= NULL
) {
1002 if (!EFI_ERROR (Status
)) {
1003 switch (Operation
) {
1004 case EfiPciIoOperationBusMasterRead
:
1005 IoMmuAttribute
= EDKII_IOMMU_ACCESS_READ
;
1007 case EfiPciIoOperationBusMasterWrite
:
1008 IoMmuAttribute
= EDKII_IOMMU_ACCESS_WRITE
;
1010 case EfiPciIoOperationBusMasterCommonBuffer
:
1011 IoMmuAttribute
= EDKII_IOMMU_ACCESS_READ
| EDKII_IOMMU_ACCESS_WRITE
;
1015 return EFI_INVALID_PARAMETER
;
1017 mIoMmuProtocol
->SetAttribute (
1019 PciIoDevice
->Handle
,
1030 Completes the Map() operation and releases any corresponding resources.
1032 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1033 @param Mapping The mapping value returned from Map().
1035 @retval EFI_SUCCESS The range was unmapped.
1036 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
1042 IN EFI_PCI_IO_PROTOCOL
*This
,
1047 PCI_IO_DEVICE
*PciIoDevice
;
1049 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1051 if (mIoMmuProtocol
!= NULL
) {
1052 mIoMmuProtocol
->SetAttribute (
1054 PciIoDevice
->Handle
,
1060 Status
= PciIoDevice
->PciRootBridgeIo
->Unmap (
1061 PciIoDevice
->PciRootBridgeIo
,
1065 if (EFI_ERROR (Status
)) {
1066 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1067 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1068 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
1069 PciIoDevice
->DevicePath
1077 Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
1078 or EfiPciOperationBusMasterCommonBuffer64 mapping.
1080 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1081 @param Type This parameter is not used and must be ignored.
1082 @param MemoryType The type of memory to allocate, EfiBootServicesData or
1083 EfiRuntimeServicesData.
1084 @param Pages The number of pages to allocate.
1085 @param HostAddress A pointer to store the base system memory address of the
1087 @param Attributes The requested bit mask of attributes for the allocated range.
1089 @retval EFI_SUCCESS The requested memory pages were allocated.
1090 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
1091 MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
1092 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1093 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1098 PciIoAllocateBuffer (
1099 IN EFI_PCI_IO_PROTOCOL
*This
,
1100 IN EFI_ALLOCATE_TYPE Type
,
1101 IN EFI_MEMORY_TYPE MemoryType
,
1103 OUT VOID
**HostAddress
,
1104 IN UINT64 Attributes
1108 PCI_IO_DEVICE
*PciIoDevice
;
1111 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_PCI_ATTRIBUTE_MEMORY_CACHED
))) != 0){
1112 return EFI_UNSUPPORTED
;
1115 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1117 if ((PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) != 0) {
1118 Attributes
|= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
1121 Status
= PciIoDevice
->PciRootBridgeIo
->AllocateBuffer (
1122 PciIoDevice
->PciRootBridgeIo
,
1130 if (EFI_ERROR (Status
)) {
1131 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1132 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1133 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
1134 PciIoDevice
->DevicePath
1142 Frees memory that was allocated with AllocateBuffer().
1144 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1145 @param Pages The number of pages to free.
1146 @param HostAddress The base system memory address of the allocated range.
1148 @retval EFI_SUCCESS The requested memory pages were freed.
1149 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
1150 was not allocated with AllocateBuffer().
1156 IN EFI_PCI_IO_PROTOCOL
*This
,
1158 IN VOID
*HostAddress
1162 PCI_IO_DEVICE
*PciIoDevice
;
1164 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1166 Status
= PciIoDevice
->PciRootBridgeIo
->FreeBuffer (
1167 PciIoDevice
->PciRootBridgeIo
,
1172 if (EFI_ERROR (Status
)) {
1173 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1174 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1175 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
1176 PciIoDevice
->DevicePath
1184 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1186 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1188 @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
1189 bridge to system memory.
1190 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
1191 host bridge due to a hardware error.
1197 IN EFI_PCI_IO_PROTOCOL
*This
1201 PCI_IO_DEVICE
*PciIoDevice
;
1203 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1205 Status
= PciIoDevice
->PciRootBridgeIo
->Flush (
1206 PciIoDevice
->PciRootBridgeIo
1208 if (EFI_ERROR (Status
)) {
1209 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1210 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1211 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
1212 PciIoDevice
->DevicePath
1220 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1222 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1223 @param SegmentNumber The PCI controller's current PCI segment number.
1224 @param BusNumber The PCI controller's current PCI bus number.
1225 @param DeviceNumber The PCI controller's current PCI device number.
1226 @param FunctionNumber The PCI controller's current PCI function number.
1228 @retval EFI_SUCCESS The PCI controller location was returned.
1229 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1235 IN EFI_PCI_IO_PROTOCOL
*This
,
1242 PCI_IO_DEVICE
*PciIoDevice
;
1244 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1246 if (Segment
== NULL
|| Bus
== NULL
|| Device
== NULL
|| Function
== NULL
) {
1247 return EFI_INVALID_PARAMETER
;
1250 *Segment
= PciIoDevice
->PciRootBridgeIo
->SegmentNumber
;
1251 *Bus
= PciIoDevice
->BusNumber
;
1252 *Device
= PciIoDevice
->DeviceNumber
;
1253 *Function
= PciIoDevice
->FunctionNumber
;
1259 Check BAR type for PCI resource.
1261 @param PciIoDevice PCI device instance.
1262 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1263 base address for the memory or I/O operation to perform.
1264 @param BarType Memory or I/O.
1266 @retval TRUE Pci device's bar type is same with input BarType.
1267 @retval TRUE Pci device's bar type is not same with input BarType.
1272 IN PCI_IO_DEVICE
*PciIoDevice
,
1274 IN PCI_BAR_TYPE BarType
1281 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem32
&&
1282 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem32
&&
1283 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem64
&&
1284 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem64
) {
1291 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo32
&&
1292 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo16
){
1306 Set/Disable new attributes to a Root Bridge.
1308 @param PciIoDevice Pci device instance.
1309 @param Attributes New attribute want to be set.
1310 @param Operation Set or Disable.
1312 @retval EFI_UNSUPPORTED If root bridge does not support change attribute.
1313 @retval EFI_SUCCESS Successfully set new attributes.
1317 ModifyRootBridgeAttributes (
1318 IN PCI_IO_DEVICE
*PciIoDevice
,
1319 IN UINT64 Attributes
,
1320 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1323 UINT64 PciRootBridgeSupports
;
1324 UINT64 PciRootBridgeAttributes
;
1325 UINT64 NewPciRootBridgeAttributes
;
1329 // Get the current attributes of this PCI device's PCI Root Bridge
1331 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1332 PciIoDevice
->PciRootBridgeIo
,
1333 &PciRootBridgeSupports
,
1334 &PciRootBridgeAttributes
1336 if (EFI_ERROR (Status
)) {
1337 return EFI_UNSUPPORTED
;
1341 // Mask off attributes not supported by PCI root bridge.
1343 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1344 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1345 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1348 // Record the new attribute of the Root Bridge
1350 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1351 NewPciRootBridgeAttributes
= PciRootBridgeAttributes
| Attributes
;
1353 NewPciRootBridgeAttributes
= PciRootBridgeAttributes
& (~Attributes
);
1357 // Call the PCI Root Bridge to attempt to modify the attributes
1359 if ((NewPciRootBridgeAttributes
^ PciRootBridgeAttributes
) != 0) {
1361 Status
= PciIoDevice
->PciRootBridgeIo
->SetAttributes (
1362 PciIoDevice
->PciRootBridgeIo
,
1363 NewPciRootBridgeAttributes
,
1367 if (EFI_ERROR (Status
)) {
1369 // The PCI Root Bridge could not modify the attributes, so return the error.
1371 return EFI_UNSUPPORTED
;
1376 // Also update the attributes for this Root Bridge structure
1378 PciIoDevice
->Attributes
= NewPciRootBridgeAttributes
;
1384 Check whether this device can be enable/disable to snoop.
1386 @param PciIoDevice Pci device instance.
1387 @param Operation Enable/Disable.
1389 @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop.
1390 @retval EFI_SUCCESS Snoop can be supported.
1394 SupportPaletteSnoopAttributes (
1395 IN PCI_IO_DEVICE
*PciIoDevice
,
1396 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1399 PCI_IO_DEVICE
*Temp
;
1403 // Snoop attribute can be only modified by GFX
1405 if (!IS_PCI_GFX (&PciIoDevice
->Pci
)) {
1406 return EFI_UNSUPPORTED
;
1410 // Get the boot VGA on the same Host Bridge
1412 Temp
= LocateVgaDeviceOnHostBridge (PciIoDevice
->PciRootBridgeIo
->ParentHandle
);
1416 // If there is no VGA device on the segment, set
1417 // this graphics card to decode the palette range
1423 // Check these two agents are on the same path
1425 if (!PciDevicesOnTheSamePath (Temp
, PciIoDevice
)) {
1427 // they are not on the same path, so snoop can be enabled or disabled
1432 // Check if they are on the same bus
1434 if (Temp
->Parent
== PciIoDevice
->Parent
) {
1436 PCI_READ_COMMAND_REGISTER (Temp
, &VGACommand
);
1439 // If they are on the same bus, either one can
1440 // be set to snoop, the other set to decode
1442 if ((VGACommand
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
1444 // VGA has set to snoop, so GFX can be only set to disable snoop
1446 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1447 return EFI_UNSUPPORTED
;
1451 // VGA has disabled to snoop, so GFX can be only enabled
1453 if (Operation
== EfiPciIoAttributeOperationDisable
) {
1454 return EFI_UNSUPPORTED
;
1462 // If they are on the same path but on the different bus
1463 // The first agent is set to snoop, the second one set to
1467 if (Temp
->BusNumber
< PciIoDevice
->BusNumber
) {
1469 // GFX should be set to decode
1471 if (Operation
== EfiPciIoAttributeOperationDisable
) {
1472 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1473 Temp
->Attributes
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1475 return EFI_UNSUPPORTED
;
1480 // GFX should be set to snoop
1482 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1483 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1484 Temp
->Attributes
&= (~(UINT64
)EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1486 return EFI_UNSUPPORTED
;
1495 Performs an operation on the attributes that this PCI controller supports. The operations include
1496 getting the set of supported attributes, retrieving the current attributes, setting the current
1497 attributes, enabling attributes, and disabling attributes.
1499 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1500 @param Operation The operation to perform on the attributes for this PCI controller.
1501 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1503 @param Result A pointer to the result mask of attributes that are returned for the Get
1504 and Supported operations.
1506 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1507 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1508 @retval EFI_UNSUPPORTED one or more of the bits set in
1509 Attributes are not supported by this PCI controller or one of
1510 its parent bridges when Operation is Set, Enable or Disable.
1516 IN EFI_PCI_IO_PROTOCOL
* This
,
1517 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1518 IN UINT64 Attributes
,
1519 OUT UINT64
*Result OPTIONAL
1524 PCI_IO_DEVICE
*PciIoDevice
;
1525 PCI_IO_DEVICE
*UpStreamBridge
;
1526 PCI_IO_DEVICE
*Temp
;
1529 UINT64 UpStreamAttributes
;
1530 UINT16 BridgeControl
;
1533 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1535 switch (Operation
) {
1536 case EfiPciIoAttributeOperationGet
:
1537 if (Result
== NULL
) {
1538 return EFI_INVALID_PARAMETER
;
1541 *Result
= PciIoDevice
->Attributes
;
1544 case EfiPciIoAttributeOperationSupported
:
1545 if (Result
== NULL
) {
1546 return EFI_INVALID_PARAMETER
;
1549 *Result
= PciIoDevice
->Supports
;
1552 case EfiPciIoAttributeOperationSet
:
1553 Status
= PciIoDevice
->PciIo
.Attributes (
1554 &(PciIoDevice
->PciIo
),
1555 EfiPciIoAttributeOperationEnable
,
1559 if (EFI_ERROR (Status
)) {
1560 return EFI_UNSUPPORTED
;
1563 Status
= PciIoDevice
->PciIo
.Attributes (
1564 &(PciIoDevice
->PciIo
),
1565 EfiPciIoAttributeOperationDisable
,
1566 (~Attributes
) & (PciIoDevice
->Supports
),
1569 if (EFI_ERROR (Status
)) {
1570 return EFI_UNSUPPORTED
;
1575 case EfiPciIoAttributeOperationEnable
:
1576 case EfiPciIoAttributeOperationDisable
:
1580 return EFI_INVALID_PARAMETER
;
1583 // Just a trick for ENABLE attribute
1584 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.
1585 // So, this logic doesn't conform to UEFI spec, which should be removed.
1586 // But this trick logic is still kept for some binary drivers that depend on it.
1588 if ((Attributes
& EFI_PCI_DEVICE_ENABLE
) == EFI_PCI_DEVICE_ENABLE
) {
1589 Attributes
&= (PciIoDevice
->Supports
);
1592 // Raise the EFI_P_PC_ENABLE Status code
1594 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1596 EFI_IO_BUS_PCI
| EFI_P_PC_ENABLE
,
1597 PciIoDevice
->DevicePath
1602 // Check VGA and VGA16, they can not be set at the same time
1604 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
)) != 0) {
1605 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) != 0) {
1606 return EFI_UNSUPPORTED
;
1611 // If no attributes can be supported, then return.
1612 // Otherwise, set the attributes that it can support.
1614 Supports
= (PciIoDevice
->Supports
) & Attributes
;
1615 if (Supports
!= Attributes
) {
1616 return EFI_UNSUPPORTED
;
1620 // For Root Bridge, just call RootBridgeIo to set attributes;
1622 if (PciIoDevice
->Parent
== NULL
) {
1623 Status
= ModifyRootBridgeAttributes (PciIoDevice
, Attributes
, Operation
);
1631 // For PPB & P2C, set relevant attribute bits
1633 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1635 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1636 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_VGA
;
1639 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_ISA_IO
) != 0) {
1640 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_ISA
;
1643 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) != 0) {
1644 Command
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1647 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) != 0) {
1648 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1653 // Do with the attributes on VGA
1654 // Only for VGA's legacy resource, we just can enable once.
1657 (EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1658 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
|
1659 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
)) != 0) {
1661 // Check if a VGA has been enabled before enabling a new one
1663 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1665 // Check if there have been an active VGA device on the same Host Bridge
1667 Temp
= LocateVgaDeviceOnHostBridge (PciIoDevice
->PciRootBridgeIo
->ParentHandle
);
1668 if (Temp
!= NULL
&& Temp
!= PciIoDevice
) {
1670 // An active VGA has been detected, so can not enable another
1672 return EFI_UNSUPPORTED
;
1678 // Do with the attributes on GFX
1680 if ((Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) != 0) {
1682 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1684 // Check if snoop can be enabled in current configuration
1686 Status
= SupportPaletteSnoopAttributes (PciIoDevice
, Operation
);
1688 if (EFI_ERROR (Status
)) {
1691 // Enable operation is forbidden, so mask the bit in attributes
1692 // so as to keep consistent with the actual Status
1694 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1698 return EFI_UNSUPPORTED
;
1704 // It can be supported, so get ready to set the bit
1706 Command
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1710 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) != 0) {
1711 Command
|= EFI_PCI_COMMAND_IO_SPACE
;
1714 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_MEMORY
) != 0) {
1715 Command
|= EFI_PCI_COMMAND_MEMORY_SPACE
;
1718 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
) != 0) {
1719 Command
|= EFI_PCI_COMMAND_BUS_MASTER
;
1722 // The upstream bridge should be also set to relevant attribute
1723 // expect for IO, Mem and BusMaster
1725 UpStreamAttributes
= Attributes
&
1726 (~(EFI_PCI_IO_ATTRIBUTE_IO
|
1727 EFI_PCI_IO_ATTRIBUTE_MEMORY
|
1728 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
1731 UpStreamBridge
= PciIoDevice
->Parent
;
1733 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1735 // Enable relevant attributes to command register and bridge control register
1737 Status
= PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, Command
);
1738 if (BridgeControl
!= 0) {
1739 Status
= PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
1742 PciIoDevice
->Attributes
|= Attributes
;
1745 // Enable attributes of the upstream bridge
1747 Status
= UpStreamBridge
->PciIo
.Attributes (
1748 &(UpStreamBridge
->PciIo
),
1749 EfiPciIoAttributeOperationEnable
,
1756 // Disable relevant attributes to command register and bridge control register
1758 Status
= PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, Command
);
1759 if (BridgeControl
!= 0) {
1760 Status
= PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
1763 PciIoDevice
->Attributes
&= (~Attributes
);
1764 Status
= EFI_SUCCESS
;
1768 if (EFI_ERROR (Status
)) {
1769 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1770 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1771 EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
,
1772 PciIoDevice
->DevicePath
1780 Retrieve the AddrTranslationOffset from RootBridgeIo for the
1783 @param RootBridgeIo Root Bridge IO instance.
1784 @param AddrRangeMin The base address of the MMIO.
1785 @param AddrLen The length of the MMIO.
1787 @retval The AddrTranslationOffset from RootBridgeIo for the
1788 specified range, or (UINT64) -1 if the range is not
1789 found in RootBridgeIo.
1792 GetMmioAddressTranslationOffset (
1793 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*RootBridgeIo
,
1794 UINT64 AddrRangeMin
,
1799 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1801 Status
= RootBridgeIo
->Configuration (
1803 (VOID
**) &Configuration
1805 if (EFI_ERROR (Status
)) {
1809 // According to UEFI 2.7, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration()
1810 // returns host address instead of device address, while AddrTranslationOffset
1811 // is not zero, and device address = host address + AddrTranslationOffset, so
1812 // we convert host address to device address for range compare.
1813 while (Configuration
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1814 if ((Configuration
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) &&
1815 (Configuration
->AddrRangeMin
+ Configuration
->AddrTranslationOffset
<= AddrRangeMin
) &&
1816 (Configuration
->AddrRangeMin
+ Configuration
->AddrLen
+ Configuration
->AddrTranslationOffset
>= AddrRangeMin
+ AddrLen
)
1818 return Configuration
->AddrTranslationOffset
;
1824 // The resource occupied by BAR should be in the range reported by RootBridge.
1831 Gets the attributes that this PCI controller supports setting on a BAR using
1832 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1834 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1835 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1836 base address for resource range. The legal range for this field is 0..5.
1837 @param Supports A pointer to the mask of attributes that this PCI controller supports
1838 setting for this BAR with SetBarAttributes().
1839 @param Resources A pointer to the resource descriptors that describe the current
1840 configuration of this BAR of the PCI controller.
1842 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1843 controller supports are returned in Supports. If Resources
1844 is not NULL, then the resource descriptors that the PCI
1845 controller is currently using are returned in Resources.
1846 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1847 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1848 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1854 PciIoGetBarAttributes (
1855 IN EFI_PCI_IO_PROTOCOL
* This
,
1857 OUT UINT64
*Supports
, OPTIONAL
1858 OUT VOID
**Resources OPTIONAL
1861 PCI_IO_DEVICE
*PciIoDevice
;
1862 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1863 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1865 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1867 if (Supports
== NULL
&& Resources
== NULL
) {
1868 return EFI_INVALID_PARAMETER
;
1871 if ((BarIndex
>= PCI_MAX_BAR
) || (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeUnknown
)) {
1872 return EFI_UNSUPPORTED
;
1876 // This driver does not support modifications to the WRITE_COMBINE or
1877 // CACHED attributes for BAR ranges.
1879 if (Supports
!= NULL
) {
1880 *Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
1883 if (Resources
!= NULL
) {
1884 Descriptor
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1885 if (Descriptor
== NULL
) {
1886 return EFI_OUT_OF_RESOURCES
;
1889 *Resources
= Descriptor
;
1891 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1892 Descriptor
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1893 Descriptor
->AddrRangeMin
= PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
1894 Descriptor
->AddrLen
= PciIoDevice
->PciBar
[BarIndex
].Length
;
1895 Descriptor
->AddrRangeMax
= PciIoDevice
->PciBar
[BarIndex
].Alignment
;
1897 switch (PciIoDevice
->PciBar
[BarIndex
].BarType
) {
1898 case PciBarTypeIo16
:
1899 case PciBarTypeIo32
:
1903 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1906 case PciBarTypePMem32
:
1910 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1914 case PciBarTypeMem32
:
1918 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1922 Descriptor
->AddrSpaceGranularity
= 32;
1925 case PciBarTypePMem64
:
1929 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1933 case PciBarTypeMem64
:
1937 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1941 Descriptor
->AddrSpaceGranularity
= 64;
1951 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1952 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1956 // Get the Address Translation Offset
1958 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1959 Descriptor
->AddrTranslationOffset
= GetMmioAddressTranslationOffset (
1960 PciIoDevice
->PciRootBridgeIo
,
1961 Descriptor
->AddrRangeMin
,
1964 if (Descriptor
->AddrTranslationOffset
== (UINT64
) -1) {
1965 FreePool (Descriptor
);
1966 return EFI_UNSUPPORTED
;
1970 // According to UEFI spec 2.7, we need return host address for
1971 // PciIo->GetBarAttributes, and host address = device address - translation.
1972 Descriptor
->AddrRangeMin
-= Descriptor
->AddrTranslationOffset
;
1979 Sets the attributes for a range of a BAR on a PCI controller.
1981 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1982 @param Attributes The mask of attributes to set for the resource range specified by
1983 BarIndex, Offset, and Length.
1984 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1985 base address for resource range. The legal range for this field is 0..5.
1986 @param Offset A pointer to the BAR relative base address of the resource range to be
1987 modified by the attributes specified by Attributes.
1988 @param Length A pointer to the length of the resource range to be modified by the
1989 attributes specified by Attributes.
1991 @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource
1992 range specified by BarIndex, Offset, and Length were
1993 set on the PCI controller, and the actual resource range is returned
1994 in Offset and Length.
1995 @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
1996 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1997 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the
1998 resource range specified by BarIndex, Offset, and
2004 PciIoSetBarAttributes (
2005 IN EFI_PCI_IO_PROTOCOL
*This
,
2006 IN UINT64 Attributes
,
2008 IN OUT UINT64
*Offset
,
2009 IN OUT UINT64
*Length
2013 PCI_IO_DEVICE
*PciIoDevice
;
2014 UINT64 NonRelativeOffset
;
2017 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
2020 // Make sure Offset and Length are not NULL
2022 if (Offset
== NULL
|| Length
== NULL
) {
2023 return EFI_INVALID_PARAMETER
;
2026 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeUnknown
) {
2027 return EFI_UNSUPPORTED
;
2030 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
2031 // If Attributes is not 0, then return EFI_UNSUPPORTED.
2033 Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
2035 if (Attributes
!= (Attributes
& Supports
)) {
2036 return EFI_UNSUPPORTED
;
2039 // Attributes must be supported. Make sure the BAR range described by BarIndex, Offset, and
2040 // Length are valid for this PCI device.
2042 NonRelativeOffset
= *Offset
;
2043 Status
= PciIoVerifyBarAccess (
2051 if (EFI_ERROR (Status
)) {
2052 return EFI_UNSUPPORTED
;
2060 Test whether two Pci devices has same parent bridge.
2062 @param PciDevice1 The first pci device for testing.
2063 @param PciDevice2 The second pci device for testing.
2065 @retval TRUE Two Pci device has the same parent bridge.
2066 @retval FALSE Two Pci device has not the same parent bridge.
2070 PciDevicesOnTheSamePath (
2071 IN PCI_IO_DEVICE
*PciDevice1
,
2072 IN PCI_IO_DEVICE
*PciDevice2
2078 if (PciDevice1
->Parent
== PciDevice2
->Parent
) {
2082 Existed1
= PciDeviceExisted (PciDevice1
->Parent
, PciDevice2
);
2083 Existed2
= PciDeviceExisted (PciDevice2
->Parent
, PciDevice1
);
2085 return (BOOLEAN
) (Existed1
|| Existed2
);