2 Implement all interfaces for EFI_PCI_IO_PROTOCOL.
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 ReportErrorStatusCode (
24 IN PCI_IO_DEVICE
*PciIoDevice
,
25 IN EFI_STATUS_CODE_VALUE Code
29 // PCI I/O Support Function Prototypes
33 // Pci Io Protocol Interface
35 static EFI_PCI_IO_PROTOCOL PciIoInterface
= {
58 PciIoGetBarAttributes
,
59 PciIoSetBarAttributes
,
65 report a error Status code of PCI bus driver controller
67 @param PciIoDevice Pci device instance
68 @param Code status code
72 ReportErrorStatusCode (
73 IN PCI_IO_DEVICE
*PciIoDevice
,
74 IN EFI_STATUS_CODE_VALUE Code
77 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
78 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
80 PciIoDevice
->DevicePath
85 Initializes a PCI I/O Instance
87 @param PciIoDevice Pci device instance
89 @retval EFI_SUCCESS Success operation
92 InitializePciIoInstance (
93 PCI_IO_DEVICE
*PciIoDevice
96 CopyMem (&PciIoDevice
->PciIo
, &PciIoInterface
, sizeof (EFI_PCI_IO_PROTOCOL
));
101 Verifies access to a PCI Base Address Register (BAR)
103 @param PciIoDevice Pci device instance
104 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
105 base address for the memory or I/O operation to perform.
106 @param Type Operation type could be memory or I/O
107 @param Width Signifies the width of the memory or I/O operations.
108 @param Count The number of memory or I/O operations to perform.
109 @param Offset The offset within the PCI configuration space for the PCI controller.
111 @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.
112 @retval EFI_SUCCESS Success Operation.
115 PciIoVerifyBarAccess (
116 PCI_IO_DEVICE
*PciIoDevice
,
119 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
124 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
125 return EFI_INVALID_PARAMETER
;
128 if (BarIndex
== EFI_PCI_IO_PASS_THROUGH_BAR
) {
133 // BarIndex 0-5 is legal
135 if (BarIndex
>= PCI_MAX_BAR
) {
136 return EFI_INVALID_PARAMETER
;
139 if (!CheckBarType (PciIoDevice
, BarIndex
, Type
)) {
140 return EFI_INVALID_PARAMETER
;
144 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
145 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
147 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
151 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
153 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PciIoDevice
->PciBar
[BarIndex
].Length
) {
154 return EFI_INVALID_PARAMETER
;
157 *Offset
= *Offset
+ PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
163 Verifies access to a PCI Config Header
165 @param PciIoDevice Pci device instance
166 @param Width Signifies the width of the memory or I/O operations.
167 @param Count The number of memory or I/O operations to perform.
168 @param Offset The offset within the PCI configuration space for the PCI controller.
170 @retval EFI_INVALID_PARAMETER Invalid Width
171 @retval EFI_UNSUPPORTED Offset overflow
172 @retval EFI_SUCCESS Success operation
175 PciIoVerifyConfigAccess (
176 PCI_IO_DEVICE
*PciIoDevice
,
177 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
184 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
185 return EFI_INVALID_PARAMETER
;
189 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
191 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
193 if (PciIoDevice
->IsPciExp
) {
194 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET
) {
195 return EFI_UNSUPPORTED
;
198 ExtendOffset
= LShiftU64 (*Offset
, 32);
199 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, 0);
200 *Offset
= (*Offset
) | ExtendOffset
;
203 if ((*Offset
+ Count
* (UINTN
)(1 << Width
)) - 1 >= PCI_MAX_CONFIG_OFFSET
) {
204 return EFI_UNSUPPORTED
;
207 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, *Offset
);
214 Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
215 satisfied or after a defined duration.
217 @param This Pointer to protocol instance of EFI_PCI_IO_PROTOCOL
218 @param Width Signifies the width of the memory or I/O operations.
219 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
220 base address for the memory or I/O operation to perform.
221 @param Offset The offset within the PCI configuration space for the PCI controller.
222 @param Mask Mask used for the polling criteria.
223 @param Value The comparison value used for the polling exit criteria.
224 @param Delay The number of 100 ns units to poll.
225 @param Result Pointer to the last value read from the memory location.
227 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
228 @retval EFI_TIMEOUT Delay expired before a match occurred.
229 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
230 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
235 IN EFI_PCI_IO_PROTOCOL
*This
,
236 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
246 PCI_IO_DEVICE
*PciIoDevice
;
248 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
250 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
251 return EFI_INVALID_PARAMETER
;
254 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, 1, &Offset
);
255 if (EFI_ERROR (Status
)) {
256 return EFI_UNSUPPORTED
;
259 if (Width
> EfiPciIoWidthUint64
) {
260 return EFI_INVALID_PARAMETER
;
263 Status
= PciIoDevice
->PciRootBridgeIo
->PollMem (
264 PciIoDevice
->PciRootBridgeIo
,
265 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
273 if (EFI_ERROR (Status
)) {
274 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
281 Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
282 satisfied or after a defined duration.
284 @param This A pointer to the EFI_PCI_IO_PROTOCOL.
285 @param Width Signifies the width of the memory or I/O operations.
286 @param Address The base address of the memory or I/O operations.
287 @param Mask Mask used for the polling criteria.
288 @param Value The comparison value used for the polling exit criteria.
289 @param Delay The number of 100 ns units to poll.
290 @param Result Pointer to the last value read from the memory location.
292 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
293 @retval EFI_TIMEOUT Delay expired before a match occurred.
294 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
295 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
301 IN EFI_PCI_IO_PROTOCOL
*This
,
302 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
312 PCI_IO_DEVICE
*PciIoDevice
;
314 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
316 if (Width
< 0 || Width
> EfiPciIoWidthUint64
) {
317 return EFI_INVALID_PARAMETER
;
320 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, 1, &Offset
);
321 if (EFI_ERROR (Status
)) {
322 return EFI_UNSUPPORTED
;
325 Status
= PciIoDevice
->PciRootBridgeIo
->PollIo (
326 PciIoDevice
->PciRootBridgeIo
,
327 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
335 if (EFI_ERROR (Status
)) {
336 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
343 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
345 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
346 @param Width Signifies the width of the memory or I/O operations.
347 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
348 base address for the memory or I/O operation to perform.
349 @param Offset The offset within the selected BAR to start the memory or I/O operation.
350 @param Count The number of memory or I/O operations to perform.
351 @param Buffer For read operations, the destination buffer to store the results. For write
352 operations, the source buffer to write data from.
354 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
355 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
356 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
357 valid for the PCI BAR specified by BarIndex.
358 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
359 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
365 IN EFI_PCI_IO_PROTOCOL
*This
,
366 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
374 PCI_IO_DEVICE
*PciIoDevice
;
376 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
378 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
379 return EFI_INVALID_PARAMETER
;
382 if (Buffer
== NULL
) {
383 return EFI_INVALID_PARAMETER
;
386 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
387 if (EFI_ERROR (Status
)) {
388 return EFI_UNSUPPORTED
;
391 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Read (
392 PciIoDevice
->PciRootBridgeIo
,
393 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
399 if (EFI_ERROR (Status
)) {
400 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
);
407 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
409 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
410 @param Width Signifies the width of the memory or I/O operations.
411 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
412 base address for the memory or I/O operation to perform.
413 @param Offset The offset within the selected BAR to start the memory or I/O operation.
414 @param Count The number of memory or I/O operations to perform.
415 @param Buffer For read operations, the destination buffer to store the results. For write
416 operations, the source buffer to write data from.
418 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
419 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
420 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
421 valid for the PCI BAR specified by BarIndex.
422 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
423 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
429 IN EFI_PCI_IO_PROTOCOL
*This
,
430 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
438 PCI_IO_DEVICE
*PciIoDevice
;
440 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
442 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
443 return EFI_INVALID_PARAMETER
;
446 if (Buffer
== NULL
) {
447 return EFI_INVALID_PARAMETER
;
450 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
451 if (EFI_ERROR (Status
)) {
452 return EFI_UNSUPPORTED
;
455 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Write (
456 PciIoDevice
->PciRootBridgeIo
,
457 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
463 if (EFI_ERROR (Status
)) {
464 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
);
471 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
473 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
474 @param Width Signifies the width of the memory or I/O operations.
475 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
476 base address for the memory or I/O operation to perform.
477 @param Offset The offset within the selected BAR to start the memory or I/O operation.
478 @param Count The number of memory or I/O operations to perform.
479 @param Buffer For read operations, the destination buffer to store the results. For write
480 operations, the source buffer to write data from.
482 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
483 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
484 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
485 valid for the PCI BAR specified by BarIndex.
486 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
487 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
493 IN EFI_PCI_IO_PROTOCOL
*This
,
494 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
502 PCI_IO_DEVICE
*PciIoDevice
;
504 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
506 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
507 return EFI_INVALID_PARAMETER
;
510 if (Buffer
== NULL
) {
511 return EFI_INVALID_PARAMETER
;
514 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
515 if (EFI_ERROR (Status
)) {
516 return EFI_UNSUPPORTED
;
519 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Read (
520 PciIoDevice
->PciRootBridgeIo
,
521 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
527 if (EFI_ERROR (Status
)) {
528 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
);
535 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
537 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
538 @param Width Signifies the width of the memory or I/O operations.
539 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
540 base address for the memory or I/O operation to perform.
541 @param Offset The offset within the selected BAR to start the memory or I/O operation.
542 @param Count The number of memory or I/O operations to perform.
543 @param Buffer For read operations, the destination buffer to store the results. For write
544 operations, the source buffer to write data from.
546 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
547 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
548 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
549 valid for the PCI BAR specified by BarIndex.
550 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
551 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
557 IN EFI_PCI_IO_PROTOCOL
*This
,
558 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
566 PCI_IO_DEVICE
*PciIoDevice
;
568 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
570 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
571 return EFI_INVALID_PARAMETER
;
574 if (Buffer
== NULL
) {
575 return EFI_INVALID_PARAMETER
;
578 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
579 if (EFI_ERROR (Status
)) {
580 return EFI_UNSUPPORTED
;
583 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Write (
584 PciIoDevice
->PciRootBridgeIo
,
585 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
591 if (EFI_ERROR (Status
)) {
592 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
);
599 Enable a PCI driver to access PCI controller registers in PCI configuration space.
601 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
602 @param Width Signifies the width of the memory operations.
603 @param Offset The offset within the PCI configuration space for the PCI controller.
604 @param Count The number of PCI configuration operations to perform.
605 @param Buffer For read operations, the destination buffer to store the results. For write
606 operations, the source buffer to write data from.
609 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
610 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
611 valid for the PCI configuration header of the PCI controller.
612 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
613 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
619 IN EFI_PCI_IO_PROTOCOL
*This
,
620 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
627 PCI_IO_DEVICE
*PciIoDevice
;
630 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
633 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
634 if (EFI_ERROR (Status
)) {
638 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Read (
639 PciIoDevice
->PciRootBridgeIo
,
640 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
646 if (EFI_ERROR (Status
)) {
647 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_READ_ERROR
);
654 Enable a PCI driver to access PCI controller registers in PCI configuration space.
656 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
657 @param Width Signifies the width of the memory operations.
658 @param Offset The offset within the PCI configuration space for the PCI controller.
659 @param Count The number of PCI configuration operations to perform.
660 @param Buffer For read operations, the destination buffer to store the results. For write
661 operations, the source buffer to write data from.
664 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
665 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
666 valid for the PCI configuration header of the PCI controller.
667 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
668 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
674 IN EFI_PCI_IO_PROTOCOL
*This
,
675 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
682 PCI_IO_DEVICE
*PciIoDevice
;
685 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
688 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
689 if (EFI_ERROR (Status
)) {
693 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Write (
694 PciIoDevice
->PciRootBridgeIo
,
695 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
701 if (EFI_ERROR (Status
)) {
702 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_WRITE_ERROR
);
709 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
712 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
713 @param Width Signifies the width of the memory operations.
714 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
715 base address for the memory operation to perform.
716 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
717 start the memory writes for the copy operation.
718 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
719 base address for the memory operation to perform.
720 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
721 the memory reads for the copy operation.
722 @param Count The number of memory operations to perform. Bytes moved is Width
723 size * Count, starting at DestOffset and SrcOffset.
725 @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
726 @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.
727 @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.
728 @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count
729 is not valid for the PCI BAR specified by DestBarIndex.
730 @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is
731 not valid for the PCI BAR specified by SrcBarIndex.
732 @retval EFI_INVALID_PARAMETER Width is invalid.
733 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
739 IN EFI_PCI_IO_PROTOCOL
*This
,
740 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
741 IN UINT8 DestBarIndex
,
742 IN UINT64 DestOffset
,
743 IN UINT8 SrcBarIndex
,
749 PCI_IO_DEVICE
*PciIoDevice
;
751 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
753 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
754 return EFI_INVALID_PARAMETER
;
757 if (Width
== EfiPciIoWidthFifoUint8
||
758 Width
== EfiPciIoWidthFifoUint16
||
759 Width
== EfiPciIoWidthFifoUint32
||
760 Width
== EfiPciIoWidthFifoUint64
||
761 Width
== EfiPciIoWidthFillUint8
||
762 Width
== EfiPciIoWidthFillUint16
||
763 Width
== EfiPciIoWidthFillUint32
||
764 Width
== EfiPciIoWidthFillUint64
) {
765 return EFI_INVALID_PARAMETER
;
768 Status
= PciIoVerifyBarAccess (PciIoDevice
, DestBarIndex
, PciBarTypeMem
, Width
, Count
, &DestOffset
);
769 if (EFI_ERROR (Status
)) {
770 return EFI_UNSUPPORTED
;
773 Status
= PciIoVerifyBarAccess (PciIoDevice
, SrcBarIndex
, PciBarTypeMem
, Width
, Count
, &SrcOffset
);
774 if (EFI_ERROR (Status
)) {
775 return EFI_UNSUPPORTED
;
778 Status
= PciIoDevice
->PciRootBridgeIo
->CopyMem (
779 PciIoDevice
->PciRootBridgeIo
,
780 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
786 if (EFI_ERROR (Status
)) {
787 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
794 Provides the PCI controller-Cspecific addresses needed to access system memory.
796 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
797 @param Operation Indicates if the bus master is going to read or write to system memory.
798 @param HostAddress The system memory address to map to the PCI controller.
799 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
801 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
802 access the hosts HostAddress.
803 @param Mapping A resulting value to pass to Unmap().
805 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
806 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
807 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
808 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
809 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
815 IN EFI_PCI_IO_PROTOCOL
*This
,
816 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
817 IN VOID
*HostAddress
,
818 IN OUT UINTN
*NumberOfBytes
,
819 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
824 PCI_IO_DEVICE
*PciIoDevice
;
826 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
828 if (Operation
< 0 || Operation
>= EfiPciIoOperationMaximum
) {
829 return EFI_INVALID_PARAMETER
;
832 if (HostAddress
== NULL
|| NumberOfBytes
== NULL
|| DeviceAddress
== NULL
|| Mapping
== NULL
) {
833 return EFI_INVALID_PARAMETER
;
836 if (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) {
837 Operation
= (EFI_PCI_IO_PROTOCOL_OPERATION
) (Operation
+ EfiPciOperationBusMasterRead64
);
840 Status
= PciIoDevice
->PciRootBridgeIo
->Map (
841 PciIoDevice
->PciRootBridgeIo
,
842 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
) Operation
,
849 if (EFI_ERROR (Status
)) {
850 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
857 Completes the Map() operation and releases any corresponding resources.
859 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
860 @param Mapping The mapping value returned from Map().
862 @retval EFI_SUCCESS The range was unmapped.
863 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
869 IN EFI_PCI_IO_PROTOCOL
*This
,
874 PCI_IO_DEVICE
*PciIoDevice
;
876 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
878 Status
= PciIoDevice
->PciRootBridgeIo
->Unmap (
879 PciIoDevice
->PciRootBridgeIo
,
883 if (EFI_ERROR (Status
)) {
884 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
891 Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
894 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
895 @param Type This parameter is not used and must be ignored.
896 @param MemoryType The type of memory to allocate, EfiBootServicesData or
897 EfiRuntimeServicesData.
898 @param Pages The number of pages to allocate.
899 @param HostAddress A pointer to store the base system memory address of the
901 @param Attributes The requested bit mask of attributes for the allocated range.
903 @retval EFI_SUCCESS The requested memory pages were allocated.
904 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
905 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
906 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
907 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
912 PciIoAllocateBuffer (
913 IN EFI_PCI_IO_PROTOCOL
*This
,
914 IN EFI_ALLOCATE_TYPE Type
,
915 IN EFI_MEMORY_TYPE MemoryType
,
917 OUT VOID
**HostAddress
,
922 PCI_IO_DEVICE
*PciIoDevice
;
925 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_PCI_ATTRIBUTE_MEMORY_CACHED
))) {
926 return EFI_UNSUPPORTED
;
929 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
931 if (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) {
932 Attributes
|= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
935 Status
= PciIoDevice
->PciRootBridgeIo
->AllocateBuffer (
936 PciIoDevice
->PciRootBridgeIo
,
944 if (EFI_ERROR (Status
)) {
945 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
952 Frees memory that was allocated with AllocateBuffer().
954 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
955 @param Pages The number of pages to free.
956 @param HostAddress The base system memory address of the allocated range.
958 @retval EFI_SUCCESS The requested memory pages were freed.
959 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
960 was not allocated with AllocateBuffer().
966 IN EFI_PCI_IO_PROTOCOL
*This
,
972 PCI_IO_DEVICE
*PciIoDevice
;
974 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
976 Status
= PciIoDevice
->PciRootBridgeIo
->FreeBuffer (
977 PciIoDevice
->PciRootBridgeIo
,
982 if (EFI_ERROR (Status
)) {
983 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
990 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
992 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
994 @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
995 bridge to system memory.
996 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
997 host bridge due to a hardware error.
1003 IN EFI_PCI_IO_PROTOCOL
*This
1007 PCI_IO_DEVICE
*PciIoDevice
;
1009 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1011 Status
= PciIoDevice
->PciRootBridgeIo
->Flush (
1012 PciIoDevice
->PciRootBridgeIo
1014 if (EFI_ERROR (Status
)) {
1015 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
1022 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1024 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1025 @param SegmentNumber The PCI controller's current PCI segment number.
1026 @param BusNumber The PCI controller's current PCI bus number.
1027 @param DeviceNumber The PCI controller's current PCI device number.
1028 @param FunctionNumber The PCI controller's current PCI function number.
1030 @retval EFI_SUCCESS The PCI controller location was returned.
1031 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1037 IN EFI_PCI_IO_PROTOCOL
*This
,
1044 PCI_IO_DEVICE
*PciIoDevice
;
1046 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1048 if (Segment
== NULL
|| Bus
== NULL
|| Device
== NULL
|| Function
== NULL
) {
1049 return EFI_INVALID_PARAMETER
;
1052 *Segment
= PciIoDevice
->PciRootBridgeIo
->SegmentNumber
;
1053 *Bus
= PciIoDevice
->BusNumber
;
1054 *Device
= PciIoDevice
->DeviceNumber
;
1055 *Function
= PciIoDevice
->FunctionNumber
;
1061 Check BAR type for PCI resource.
1063 @param PciIoDevice PCI device instance
1064 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1065 base address for the memory or I/O operation to perform.
1066 @param BarType Memory or I/O
1068 @return whether Pci device's bar type is same with input BarType.
1072 IN PCI_IO_DEVICE
*PciIoDevice
,
1074 PCI_BAR_TYPE BarType
1081 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem32
&&
1082 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem32
&&
1083 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem64
&&
1084 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem64
) {
1091 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo32
&&
1092 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo16
){
1106 Set/Disable new attributes to a Root Bridge
1108 @param PciIoDevice Pci device instance
1109 @param Attributes New attribute want to be set
1110 @param Operation Set or Disable
1112 @retval EFI_UNSUPPORTED If root bridge does not support change attribute
1113 @retval EFI_SUCCESS Success operation.
1116 ModifyRootBridgeAttributes (
1117 IN PCI_IO_DEVICE
*PciIoDevice
,
1118 IN UINT64 Attributes
,
1119 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1122 UINT64 PciRootBridgeSupports
;
1123 UINT64 PciRootBridgeAttributes
;
1124 UINT64 NewPciRootBridgeAttributes
;
1128 // Get the current attributes of this PCI device's PCI Root Bridge
1130 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1131 PciIoDevice
->PciRootBridgeIo
,
1132 &PciRootBridgeSupports
,
1133 &PciRootBridgeAttributes
1135 if (EFI_ERROR (Status
)) {
1136 return EFI_UNSUPPORTED
;
1140 // Record the new attribute of the Root Bridge
1142 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1143 NewPciRootBridgeAttributes
= PciRootBridgeAttributes
| Attributes
;
1145 NewPciRootBridgeAttributes
= PciRootBridgeAttributes
& (~Attributes
);
1149 // Call the PCI Root Bridge to attempt to modify the attributes
1151 if (NewPciRootBridgeAttributes
^ PciRootBridgeAttributes
) {
1153 Status
= PciIoDevice
->PciRootBridgeIo
->SetAttributes (
1154 PciIoDevice
->PciRootBridgeIo
,
1155 NewPciRootBridgeAttributes
,
1159 if (EFI_ERROR (Status
)) {
1161 // The PCI Root Bridge could not modify the attributes, so return the error.
1163 return EFI_UNSUPPORTED
;
1168 // Also update the attributes for this Root Bridge structure
1170 PciIoDevice
->Attributes
= NewPciRootBridgeAttributes
;
1176 Check whether this device can be enable/disable to snoop
1178 @param PciIoDevice Pci device instance
1179 @param Operation Enable/Disable
1181 @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop
1182 @retval EFI_SUCCESS Snoop can be supported.
1185 SupportPaletteSnoopAttributes (
1186 IN PCI_IO_DEVICE
*PciIoDevice
,
1187 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
1190 PCI_IO_DEVICE
*Temp
;
1194 // Snoop attribute can be only modified by GFX
1196 if (!IS_PCI_GFX (&PciIoDevice
->Pci
)) {
1197 return EFI_UNSUPPORTED
;
1201 // Get the boot VGA on the same segement
1203 Temp
= ActiveVGADeviceOnTheSameSegment (PciIoDevice
);
1207 // If there is no VGA device on the segement, set
1208 // this graphics card to decode the palette range
1214 // Check these two agents are on the same path
1216 if (!PciDevicesOnTheSamePath (Temp
, PciIoDevice
)) {
1218 // they are not on the same path, so snoop can be enabled or disabled
1223 // Check if they are on the same bus
1225 if (Temp
->Parent
== PciIoDevice
->Parent
) {
1227 PciReadCommandRegister (Temp
, &VGACommand
);
1230 // If they are on the same bus, either one can
1231 // be set to snoop, the other set to decode
1233 if (VGACommand
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) {
1235 // VGA has set to snoop, so GFX can be only set to disable snoop
1237 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1238 return EFI_UNSUPPORTED
;
1242 // VGA has disabled to snoop, so GFX can be only enabled
1244 if (Operation
== EfiPciIoAttributeOperationDisable
) {
1245 return EFI_UNSUPPORTED
;
1253 // If they are on the same path but on the different bus
1254 // The first agent is set to snoop, the second one set to
1258 if (Temp
->BusNumber
< PciIoDevice
->BusNumber
) {
1260 // GFX should be set to decode
1262 if (Operation
== EfiPciIoAttributeOperationDisable
) {
1263 PciEnableCommandRegister (Temp
, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1264 Temp
->Attributes
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1266 return EFI_UNSUPPORTED
;
1271 // GFX should be set to snoop
1273 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1274 PciDisableCommandRegister (Temp
, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1275 Temp
->Attributes
&= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1277 return EFI_UNSUPPORTED
;
1286 Performs an operation on the attributes that this PCI controller supports. The operations include
1287 getting the set of supported attributes, retrieving the current attributes, setting the current
1288 attributes, enabling attributes, and disabling attributes.
1290 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1291 @param Operation The operation to perform on the attributes for this PCI controller.
1292 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1294 @param Result A pointer to the result mask of attributes that are returned for the Get
1295 and Supported operations.
1297 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1298 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1299 @retval EFI_UNSUPPORTED one or more of the bits set in
1300 Attributes are not supported by this PCI controller or one of
1301 its parent bridges when Operation is Set, Enable or Disable.
1307 IN EFI_PCI_IO_PROTOCOL
* This
,
1308 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1309 IN UINT64 Attributes
,
1310 OUT UINT64
*Result OPTIONAL
1315 PCI_IO_DEVICE
*PciIoDevice
;
1316 PCI_IO_DEVICE
*UpStreamBridge
;
1317 PCI_IO_DEVICE
*Temp
;
1320 UINT64 UpStreamAttributes
;
1321 UINT16 BridgeControl
;
1324 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1326 switch (Operation
) {
1327 case EfiPciIoAttributeOperationGet
:
1328 if (Result
== NULL
) {
1329 return EFI_INVALID_PARAMETER
;
1332 *Result
= PciIoDevice
->Attributes
;
1335 case EfiPciIoAttributeOperationSupported
:
1336 if (Result
== NULL
) {
1337 return EFI_INVALID_PARAMETER
;
1340 *Result
= PciIoDevice
->Supports
;
1343 case EfiPciIoAttributeOperationSet
:
1344 Status
= PciIoDevice
->PciIo
.Attributes (
1345 &(PciIoDevice
->PciIo
),
1346 EfiPciIoAttributeOperationEnable
,
1350 if (EFI_ERROR (Status
)) {
1351 return EFI_UNSUPPORTED
;
1354 Status
= PciIoDevice
->PciIo
.Attributes (
1355 &(PciIoDevice
->PciIo
),
1356 EfiPciIoAttributeOperationDisable
,
1357 (~Attributes
) & (PciIoDevice
->Supports
),
1360 if (EFI_ERROR (Status
)) {
1361 return EFI_UNSUPPORTED
;
1366 case EfiPciIoAttributeOperationEnable
:
1367 case EfiPciIoAttributeOperationDisable
:
1371 return EFI_INVALID_PARAMETER
;
1374 // Just a trick for ENABLE attribute
1375 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.
1376 // So, this logic doesn't confrom to UEFI spec, which should be removed.
1377 // But this trick logic is still kept for some binary drivers that depend on it.
1379 if ((Attributes
& EFI_PCI_DEVICE_ENABLE
) == EFI_PCI_DEVICE_ENABLE
) {
1380 Attributes
&= (PciIoDevice
->Supports
);
1383 // Raise the EFI_P_PC_ENABLE Status code
1385 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1387 EFI_IO_BUS_PCI
| EFI_P_PC_ENABLE
,
1388 PciIoDevice
->DevicePath
1393 // If no attributes can be supported, then return.
1394 // Otherwise, set the attributes that it can support.
1396 Supports
= (PciIoDevice
->Supports
) & Attributes
;
1397 if (Supports
!= Attributes
) {
1398 return EFI_UNSUPPORTED
;
1402 // For Root Bridge, just call RootBridgeIo to set attributes;
1404 if (!PciIoDevice
->Parent
) {
1405 Status
= ModifyRootBridgeAttributes (PciIoDevice
, Attributes
, Operation
);
1413 // Check VGA and VGA16, they can not be set at the same time
1415 if (((Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) &&
1416 (Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) ||
1417 ((Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) &&
1418 (Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) ||
1419 ((Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
) &&
1420 (Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) ||
1421 ((Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
) &&
1422 (Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) ) {
1423 return EFI_UNSUPPORTED
;
1427 // For PPB & P2C, set relevant attribute bits
1429 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1431 if (Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
1432 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_VGA
;
1435 if (Attributes
& EFI_PCI_IO_ATTRIBUTE_ISA_IO
) {
1436 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_ISA
;
1439 if (Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) {
1440 Command
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1443 if (Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
1444 BridgeControl
|= EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1449 // Do with the attributes on VGA
1450 // Only for VGA's legacy resource, we just can enable once.
1453 (EFI_PCI_IO_ATTRIBUTE_VGA_IO
|
1454 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
|
1455 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
)) {
1457 // Check if a VGA has been enabled before enabling a new one
1459 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1461 // Check if there have been an active VGA device on the same segment
1463 Temp
= ActiveVGADeviceOnTheSameSegment (PciIoDevice
);
1464 if (Temp
&& Temp
!= PciIoDevice
) {
1466 // An active VGA has been detected, so can not enable another
1468 return EFI_UNSUPPORTED
;
1474 // Do with the attributes on GFX
1476 if (Attributes
& (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
)) {
1478 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1480 // Check if snoop can be enabled in current configuration
1482 Status
= SupportPaletteSnoopAttributes (PciIoDevice
, Operation
);
1484 if (EFI_ERROR (Status
)) {
1487 // Enable operation is forbidden, so mask the bit in attributes
1488 // so as to keep consistent with the actual Status
1490 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1494 return EFI_UNSUPPORTED
;
1500 // It can be supported, so get ready to set the bit
1502 Command
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1506 if (Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) {
1507 Command
|= EFI_PCI_COMMAND_IO_SPACE
;
1510 if (Attributes
& EFI_PCI_IO_ATTRIBUTE_MEMORY
) {
1511 Command
|= EFI_PCI_COMMAND_MEMORY_SPACE
;
1514 if (Attributes
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
) {
1515 Command
|= EFI_PCI_COMMAND_BUS_MASTER
;
1518 // The upstream bridge should be also set to revelant attribute
1519 // expect for IO, Mem and BusMaster
1521 UpStreamAttributes
= Attributes
&
1522 (~(EFI_PCI_IO_ATTRIBUTE_IO
|
1523 EFI_PCI_IO_ATTRIBUTE_MEMORY
|
1524 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
1527 UpStreamBridge
= PciIoDevice
->Parent
;
1529 if (Operation
== EfiPciIoAttributeOperationEnable
) {
1531 // Enable relevant attributes to command register and bridge control register
1533 Status
= PciEnableCommandRegister (PciIoDevice
, Command
);
1534 if (BridgeControl
) {
1535 Status
= PciEnableBridgeControlRegister (PciIoDevice
, BridgeControl
);
1538 PciIoDevice
->Attributes
|= Attributes
;
1541 // Enable attributes of the upstream bridge
1543 Status
= UpStreamBridge
->PciIo
.Attributes (
1544 &(UpStreamBridge
->PciIo
),
1545 EfiPciIoAttributeOperationEnable
,
1552 // Disable relevant attributes to command register and bridge control register
1554 Status
= PciDisableCommandRegister (PciIoDevice
, Command
);
1555 if (BridgeControl
) {
1556 Status
= PciDisableBridgeControlRegister (PciIoDevice
, BridgeControl
);
1559 PciIoDevice
->Attributes
&= (~Attributes
);
1560 Status
= EFI_SUCCESS
;
1564 if (EFI_ERROR (Status
)) {
1565 ReportErrorStatusCode (PciIoDevice
, EFI_IO_BUS_PCI
| EFI_IOB_EC_CONTROLLER_ERROR
);
1572 Gets the attributes that this PCI controller supports setting on a BAR using
1573 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1575 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1576 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1577 base address for resource range. The legal range for this field is 0..5.
1578 @param Supports A pointer to the mask of attributes that this PCI controller supports
1579 setting for this BAR with SetBarAttributes().
1580 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1581 configuration of this BAR of the PCI controller.
1583 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1584 controller supports are returned in Supports. If Resources
1585 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1586 controller is currently using are returned in Resources.
1587 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1588 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1589 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1595 PciIoGetBarAttributes (
1596 IN EFI_PCI_IO_PROTOCOL
* This
,
1598 OUT UINT64
*Supports
, OPTIONAL
1599 OUT VOID
**Resources OPTIONAL
1603 UINT8
*Configuration
;
1605 PCI_IO_DEVICE
*PciIoDevice
;
1606 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1607 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1611 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1613 if (Supports
== NULL
&& Resources
== NULL
) {
1614 return EFI_INVALID_PARAMETER
;
1617 if (BarIndex
>= PCI_MAX_BAR
) {
1618 return EFI_UNSUPPORTED
;
1622 // This driver does not support modifications to the WRITE_COMBINE or
1623 // CACHED attributes for BAR ranges.
1625 if (Supports
!= NULL
) {
1626 *Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
1629 if (Resources
!= NULL
) {
1631 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeUnknown
) {
1635 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1636 if (Configuration
== NULL
) {
1637 return EFI_OUT_OF_RESOURCES
;
1642 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1645 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1647 if (NumConfig
== 1) {
1648 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1649 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1651 Ptr
->AddrRangeMin
= PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
1652 Ptr
->AddrLen
= PciIoDevice
->PciBar
[BarIndex
].Length
;
1653 Ptr
->AddrRangeMax
= PciIoDevice
->PciBar
[BarIndex
].Alignment
;
1655 switch (PciIoDevice
->PciBar
[BarIndex
].BarType
) {
1656 case PciBarTypeIo16
:
1657 case PciBarTypeIo32
:
1661 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1664 case PciBarTypeMem32
:
1668 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1672 Ptr
->AddrSpaceGranularity
= 32;
1675 case PciBarTypePMem32
:
1679 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1683 Ptr
->SpecificFlag
= 0x6;
1687 Ptr
->AddrSpaceGranularity
= 32;
1690 case PciBarTypeMem64
:
1694 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1698 Ptr
->AddrSpaceGranularity
= 64;
1701 case PciBarTypePMem64
:
1705 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1709 Ptr
->SpecificFlag
= 0x6;
1713 Ptr
->AddrSpaceGranularity
= 64;
1720 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1726 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) ((UINT8
*) Ptr
);
1727 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1728 PtrEnd
->Checksum
= 0;
1730 *Resources
= Configuration
;
1737 Sets the attributes for a range of a BAR on a PCI controller.
1739 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1740 @param Attributes The mask of attributes to set for the resource range specified by
1741 BarIndex, Offset, and Length.
1742 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1743 base address for resource range. The legal range for this field is 0..5.
1744 @param Offset A pointer to the BAR relative base address of the resource range to be
1745 modified by the attributes specified by Attributes.
1746 @param Length A pointer to the length of the resource range to be modified by the
1747 attributes specified by Attributes.
1749 @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource
1750 range specified by BarIndex, Offset, and Length were
1751 set on the PCI controller, and the actual resource range is returned
1752 in Offset and Length.
1753 @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
1754 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1755 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the
1756 resource range specified by BarIndex, Offset, and
1762 PciIoSetBarAttributes (
1763 IN EFI_PCI_IO_PROTOCOL
*This
,
1764 IN UINT64 Attributes
,
1766 IN OUT UINT64
*Offset
,
1767 IN OUT UINT64
*Length
1771 PCI_IO_DEVICE
*PciIoDevice
;
1772 UINT64 NonRelativeOffset
;
1775 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1778 // Make sure Offset and Length are not NULL
1780 if (Offset
== NULL
|| Length
== NULL
) {
1781 return EFI_INVALID_PARAMETER
;
1784 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeUnknown
) {
1785 return EFI_UNSUPPORTED
;
1788 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
1789 // If Attributes is not 0, then return EFI_UNSUPPORTED.
1791 Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
1793 if (Attributes
!= (Attributes
& Supports
)) {
1794 return EFI_UNSUPPORTED
;
1797 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
1798 // Length are valid for this PCI device.
1800 NonRelativeOffset
= *Offset
;
1801 Status
= PciIoVerifyBarAccess (
1809 if (EFI_ERROR (Status
)) {
1810 return EFI_UNSUPPORTED
;
1817 Program parent bridge's attribute recurrently.
1819 @param PciIoDevice Child Pci device instance
1820 @param Operation The operation to perform on the attributes for this PCI controller.
1821 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1824 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1825 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1826 @retval EFI_UNSUPPORTED one or more of the bits set in
1827 Attributes are not supported by this PCI controller or one of
1828 its parent bridges when Operation is Set, Enable or Disable.
1832 UpStreamBridgesAttributes (
1833 IN PCI_IO_DEVICE
*PciIoDevice
,
1834 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1835 IN UINT64 Attributes
1838 PCI_IO_DEVICE
*Parent
;
1839 EFI_PCI_IO_PROTOCOL
*PciIo
;
1841 Parent
= PciIoDevice
->Parent
;
1843 while (Parent
&& IS_PCI_BRIDGE (&Parent
->Pci
)) {
1846 // Get the PciIo Protocol
1848 PciIo
= &Parent
->PciIo
;
1850 PciIo
->Attributes (PciIo
, Operation
, Attributes
, NULL
);
1852 Parent
= Parent
->Parent
;
1859 Test whether two Pci device has same parent bridge.
1861 @param PciDevice1 the frist pci device for testing
1862 @param PciDevice2 the second pci device for testing
1864 @return whether two Pci device has same parent bridge.
1867 PciDevicesOnTheSamePath (
1868 IN PCI_IO_DEVICE
*PciDevice1
,
1869 IN PCI_IO_DEVICE
*PciDevice2
1875 if (PciDevice1
->Parent
== PciDevice2
->Parent
) {
1879 Existed1
= PciDeviceExisted (PciDevice1
->Parent
, PciDevice2
);
1880 Existed2
= PciDeviceExisted (PciDevice2
->Parent
, PciDevice1
);
1882 return (BOOLEAN
) (Existed1
|| Existed2
);