3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 PCI I/O Abstraction Driver
27 // PCI I/O Support Function Prototypes
32 PciDevicesOnTheSamePath (
33 IN PCI_IO_DEVICE
*PciDevice1
,
34 IN PCI_IO_DEVICE
*PciDevice2
39 UpStreamBridgesAttributes (
40 IN PCI_IO_DEVICE
*PciIoDevice
,
41 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
48 IN PCI_IO_DEVICE
*PciIoDevice
,
56 IN PCI_IO_DEVICE
*PciIoDevice
61 IN PCI_IO_DEVICE
*PciIoDevice
66 PciIoVerifyBarAccess (
67 PCI_IO_DEVICE
*PciIoDevice
,
70 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
76 PciIoVerifyConfigAccess (
77 PCI_IO_DEVICE
*PciIoDevice
,
78 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
86 IN EFI_PCI_IO_PROTOCOL
*This
,
87 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
99 IN EFI_PCI_IO_PROTOCOL
*This
,
100 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
112 IN EFI_PCI_IO_PROTOCOL
*This
,
113 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
123 IN EFI_PCI_IO_PROTOCOL
*This
,
124 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
134 IN EFI_PCI_IO_PROTOCOL
*This
,
135 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
145 IN EFI_PCI_IO_PROTOCOL
*This
,
146 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
156 IN EFI_PCI_IO_PROTOCOL
*This
,
157 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
166 IN EFI_PCI_IO_PROTOCOL
*This
,
167 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
176 IN EFI_PCI_IO_PROTOCOL
*This
,
177 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
178 IN UINT8 DestBarIndex
,
179 IN UINT64 DestOffset
,
180 IN UINT8 SrcBarIndex
,
188 IN EFI_PCI_IO_PROTOCOL
*This
,
189 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
190 IN VOID
*HostAddress
,
191 IN OUT UINTN
*NumberOfBytes
,
192 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
199 IN EFI_PCI_IO_PROTOCOL
*This
,
205 PciIoAllocateBuffer (
206 IN EFI_PCI_IO_PROTOCOL
*This
,
207 IN EFI_ALLOCATE_TYPE Type
,
208 IN EFI_MEMORY_TYPE MemoryType
,
210 OUT VOID
**HostAddress
,
217 IN EFI_PCI_IO_PROTOCOL
*This
,
225 IN EFI_PCI_IO_PROTOCOL
*This
231 IN EFI_PCI_IO_PROTOCOL
*This
,
241 IN EFI_PCI_IO_PROTOCOL
*This
,
242 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
243 IN UINT64 Attributes
,
244 OUT UINT64
*Result OPTIONAL
249 PciIoGetBarAttributes(
250 IN EFI_PCI_IO_PROTOCOL
*This
,
252 OUT UINT64
*Supports
, OPTIONAL
253 OUT VOID
**Resources OPTIONAL
258 PciIoSetBarAttributes(
259 IN EFI_PCI_IO_PROTOCOL
*This
,
260 IN UINT64 Attributes
,
262 IN OUT UINT64
*Offset
,
263 IN OUT UINT64
*Length
268 // Pci Io Protocol Interface
270 EFI_PCI_IO_PROTOCOL PciIoInterface
= {
293 PciIoGetBarAttributes
,
294 PciIoSetBarAttributes
,
301 InitializePciIoInstance (
302 PCI_IO_DEVICE
*PciIoDevice
308 Initializes a PCI I/O Instance
319 CopyMem (&PciIoDevice
->PciIo
, &PciIoInterface
, sizeof (EFI_PCI_IO_PROTOCOL
));
324 PciIoVerifyBarAccess (
325 PCI_IO_DEVICE
*PciIoDevice
,
328 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
336 Verifies access to a PCI Base Address Register (BAR)
346 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
347 return EFI_INVALID_PARAMETER
;
350 if (BarIndex
== EFI_PCI_IO_PASS_THROUGH_BAR
) {
355 // BarIndex 0-5 is legal
357 if (BarIndex
>= PCI_MAX_BAR
) {
358 return EFI_INVALID_PARAMETER
;
361 if (!CheckBarType (PciIoDevice
, BarIndex
, Type
)) {
362 return EFI_INVALID_PARAMETER
;
366 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
367 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
369 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
373 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
375 if ((*Offset
+ Count
* ((UINTN
)1 << Width
)) - 1 >= PciIoDevice
->PciBar
[BarIndex
].Length
) {
376 return EFI_INVALID_PARAMETER
;
379 *Offset
= *Offset
+ PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
385 PciIoVerifyConfigAccess (
386 PCI_IO_DEVICE
*PciIoDevice
,
387 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
395 Verifies access to a PCI Config Header
407 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
408 return EFI_INVALID_PARAMETER
;
412 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
413 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
415 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
417 if (PciIoDevice
->IsPciExp
) {
418 if ((*Offset
+ Count
* ((UINTN
)1 << Width
)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET
) {
419 return EFI_UNSUPPORTED
;
422 ExtendOffset
= LShiftU64 (*Offset
, 32);
423 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, 0);
424 *Offset
= (*Offset
) | ExtendOffset
;
427 if ((*Offset
+ Count
* ((UINTN
)1 << Width
)) - 1 >= PCI_MAX_CONFIG_OFFSET
) {
428 return EFI_UNSUPPORTED
;
431 *Offset
= EFI_PCI_ADDRESS (PciIoDevice
->BusNumber
, PciIoDevice
->DeviceNumber
, PciIoDevice
->FunctionNumber
, *Offset
);
440 IN EFI_PCI_IO_PROTOCOL
*This
,
441 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
464 PCI_IO_DEVICE
*PciIoDevice
;
466 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
468 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
469 return EFI_INVALID_PARAMETER
;
472 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, 1, &Offset
);
473 if (EFI_ERROR (Status
)) {
474 return EFI_UNSUPPORTED
;
477 if (Width
> EfiPciIoWidthUint64
) {
478 return EFI_INVALID_PARAMETER
;
481 Status
= PciIoDevice
->PciRootBridgeIo
->PollMem (
482 PciIoDevice
->PciRootBridgeIo
,
483 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
496 IN EFI_PCI_IO_PROTOCOL
*This
,
497 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
520 PCI_IO_DEVICE
*PciIoDevice
;
522 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
524 if (Width
< 0 || Width
> EfiPciIoWidthUint64
) {
525 return EFI_INVALID_PARAMETER
;
528 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, 1, &Offset
);
529 if (EFI_ERROR (Status
)) {
530 return EFI_UNSUPPORTED
;
533 Status
= PciIoDevice
->PciRootBridgeIo
->PollIo (
534 PciIoDevice
->PciRootBridgeIo
,
535 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
549 IN EFI_PCI_IO_PROTOCOL
*This
,
550 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
560 Performs a PCI Memory Read Cycle
571 PCI_IO_DEVICE
*PciIoDevice
;
574 return EFI_INVALID_PARAMETER
;
577 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
579 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
580 return EFI_INVALID_PARAMETER
;
583 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
584 if (EFI_ERROR (Status
)) {
585 return EFI_UNSUPPORTED
;
588 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Read (
589 PciIoDevice
->PciRootBridgeIo
,
590 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
602 IN EFI_PCI_IO_PROTOCOL
*This
,
603 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
613 Performs a PCI Memory Write Cycle
624 PCI_IO_DEVICE
*PciIoDevice
;
627 return EFI_INVALID_PARAMETER
;
630 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
632 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
633 return EFI_INVALID_PARAMETER
;
636 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeMem
, Width
, Count
, &Offset
);
637 if (EFI_ERROR (Status
)) {
638 return EFI_UNSUPPORTED
;
641 Status
= PciIoDevice
->PciRootBridgeIo
->Mem
.Write (
642 PciIoDevice
->PciRootBridgeIo
,
643 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
655 IN EFI_PCI_IO_PROTOCOL
*This
,
656 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
666 Performs a PCI I/O Read Cycle
677 PCI_IO_DEVICE
*PciIoDevice
;
680 return EFI_INVALID_PARAMETER
;
683 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
685 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
686 return EFI_INVALID_PARAMETER
;
689 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
690 if (EFI_ERROR (Status
)) {
691 return EFI_UNSUPPORTED
;
694 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Read (
695 PciIoDevice
->PciRootBridgeIo
,
696 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
708 IN EFI_PCI_IO_PROTOCOL
*This
,
709 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
719 Performs a PCI I/O Write Cycle
730 PCI_IO_DEVICE
*PciIoDevice
;
733 return EFI_INVALID_PARAMETER
;
736 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
738 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
) {
739 return EFI_INVALID_PARAMETER
;
742 Status
= PciIoVerifyBarAccess (PciIoDevice
, BarIndex
, PciBarTypeIo
, Width
, Count
, &Offset
);
743 if (EFI_ERROR (Status
)) {
744 return EFI_UNSUPPORTED
;
747 Status
= PciIoDevice
->PciRootBridgeIo
->Io
.Write (
748 PciIoDevice
->PciRootBridgeIo
,
749 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
761 IN EFI_PCI_IO_PROTOCOL
*This
,
762 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
771 Performs a PCI Configuration Read Cycle
782 PCI_IO_DEVICE
*PciIoDevice
;
785 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
788 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
789 if (EFI_ERROR (Status
)) {
793 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Read (
794 PciIoDevice
->PciRootBridgeIo
,
795 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
807 IN EFI_PCI_IO_PROTOCOL
*This
,
808 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
817 Performs a PCI Configuration Write Cycle
828 PCI_IO_DEVICE
*PciIoDevice
;
831 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
834 Status
= PciIoVerifyConfigAccess (PciIoDevice
, Width
, Count
, &Address
);
835 if (EFI_ERROR (Status
)) {
839 Status
= PciIoDevice
->PciRootBridgeIo
->Pci
.Write (
840 PciIoDevice
->PciRootBridgeIo
,
841 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
853 IN EFI_PCI_IO_PROTOCOL
*This
,
854 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
855 IN UINT8 DestBarIndex
,
856 IN UINT64 DestOffset
,
857 IN UINT8 SrcBarIndex
,
876 PCI_IO_DEVICE
*PciIoDevice
;
878 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
880 if (Width
< 0 || 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
;
905 Status
= PciIoDevice
->PciRootBridgeIo
->CopyMem (
906 PciIoDevice
->PciRootBridgeIo
,
907 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
919 IN EFI_PCI_IO_PROTOCOL
*This
,
920 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
921 IN VOID
*HostAddress
,
922 IN OUT UINTN
*NumberOfBytes
,
923 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
930 Maps a memory region for DMA
941 PCI_IO_DEVICE
*PciIoDevice
;
943 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
945 if (Operation
< 0 || Operation
>= EfiPciIoOperationMaximum
) {
946 return EFI_INVALID_PARAMETER
;
949 if (HostAddress
== NULL
|| NumberOfBytes
== NULL
|| DeviceAddress
== NULL
|| Mapping
== NULL
) {
950 return EFI_INVALID_PARAMETER
;
953 if (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) {
954 Operation
= (EFI_PCI_IO_PROTOCOL_OPERATION
) (Operation
+ EfiPciOperationBusMasterRead64
);
957 Status
= PciIoDevice
->PciRootBridgeIo
->Map (
958 PciIoDevice
->PciRootBridgeIo
,
959 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
) Operation
,
972 IN EFI_PCI_IO_PROTOCOL
*This
,
979 Unmaps a memory region for DMA
990 PCI_IO_DEVICE
*PciIoDevice
;
992 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
994 Status
= PciIoDevice
->PciRootBridgeIo
->Unmap (
995 PciIoDevice
->PciRootBridgeIo
,
1004 PciIoAllocateBuffer (
1005 IN EFI_PCI_IO_PROTOCOL
*This
,
1006 IN EFI_ALLOCATE_TYPE Type
,
1007 IN EFI_MEMORY_TYPE MemoryType
,
1009 OUT VOID
**HostAddress
,
1010 IN UINT64 Attributes
1014 Routine Description:
1016 Allocates a common buffer for DMA
1027 PCI_IO_DEVICE
*PciIoDevice
;
1030 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
| EFI_PCI_ATTRIBUTE_MEMORY_CACHED
))) {
1031 return EFI_UNSUPPORTED
;
1034 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1036 if (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) {
1037 Attributes
|= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
1040 Status
= PciIoDevice
->PciRootBridgeIo
->AllocateBuffer (
1041 PciIoDevice
->PciRootBridgeIo
,
1055 IN EFI_PCI_IO_PROTOCOL
*This
,
1057 IN VOID
*HostAddress
1061 Routine Description:
1063 Frees a common buffer
1074 PCI_IO_DEVICE
*PciIoDevice
;
1076 if( HostAddress
== NULL
){
1077 return EFI_INVALID_PARAMETER
;
1080 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1082 Status
= PciIoDevice
->PciRootBridgeIo
->FreeBuffer (
1083 PciIoDevice
->PciRootBridgeIo
,
1094 IN EFI_PCI_IO_PROTOCOL
*This
1098 Routine Description:
1100 Flushes a DMA buffer
1113 PCI_IO_DEVICE
*PciIoDevice
;
1115 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1118 // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to
1119 // flush the posted write cycles through the PCI-PCI bridges
1121 if (PciIoDevice
->Parent
!= NULL
) {
1122 Status
= This
->Pci
.Read (This
, EfiPciIoWidthUint32
, 0, 1, &Register
);
1126 // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
1128 Status
= PciIoDevice
->PciRootBridgeIo
->Flush (
1129 PciIoDevice
->PciRootBridgeIo
1138 IN EFI_PCI_IO_PROTOCOL
*This
,
1146 Routine Description:
1148 Gets a PCI device's current bus number, device number, and function number.
1158 PCI_IO_DEVICE
*PciIoDevice
;
1160 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1162 if (Segment
== NULL
|| Bus
== NULL
|| Device
== NULL
|| Function
== NULL
) {
1163 return EFI_INVALID_PARAMETER
;
1166 *Segment
= PciIoDevice
->PciRootBridgeIo
->SegmentNumber
;
1167 *Bus
= PciIoDevice
->BusNumber
;
1168 *Device
= PciIoDevice
->DeviceNumber
;
1169 *Function
= PciIoDevice
->FunctionNumber
;
1176 IN PCI_IO_DEVICE
*PciIoDevice
,
1178 PCI_BAR_TYPE BarType
1182 Routine Description:
1184 Sets a PCI controllers attributes on a resource range
1198 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem32
&&
1199 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem32
&&
1200 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypePMem64
&&
1201 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeMem64
) {
1208 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo32
&&
1209 PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeIo16
){
1225 IN EFI_PCI_IO_PROTOCOL
* This
,
1226 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1227 IN UINT64 Attributes
,
1228 OUT UINT64
*Result OPTIONAL
1232 Routine Description:
1245 PCI_IO_DEVICE
*PciIoDevice
;
1246 PCI_IO_DEVICE
*Temp
;
1247 UINT64 NewAttributes
;
1248 UINT64 PciRootBridgeSupports
;
1249 UINT64 PciRootBridgeAttributes
;
1250 UINT64 NewPciRootBridgeAttributes
;
1251 UINT64 NewUpStreamBridgeAttributes
;
1252 UINT64 ModifiedPciRootBridgeAttributes
;
1253 UINT16 EnableCommand
;
1254 UINT16 DisableCommand
;
1255 UINT16 EnableBridge
;
1256 UINT16 DisableBridge
;
1259 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1260 NewUpStreamBridgeAttributes
= 0;
1267 switch (Operation
) {
1268 case EfiPciIoAttributeOperationGet
:
1269 if (Result
== NULL
) {
1270 return EFI_INVALID_PARAMETER
;
1273 *Result
= PciIoDevice
->Attributes
;
1276 case EfiPciIoAttributeOperationSupported
:
1277 if (Result
== NULL
) {
1278 return EFI_INVALID_PARAMETER
;
1281 *Result
= PciIoDevice
->Supports
;
1284 case EfiPciIoAttributeOperationEnable
:
1285 if(Attributes
& ~(PciIoDevice
->Supports
)) {
1286 return EFI_UNSUPPORTED
;
1288 NewAttributes
= PciIoDevice
->Attributes
| Attributes
;
1290 case EfiPciIoAttributeOperationDisable
:
1291 if(Attributes
& ~(PciIoDevice
->Supports
)) {
1292 return EFI_UNSUPPORTED
;
1294 NewAttributes
= PciIoDevice
->Attributes
& (~Attributes
);
1296 case EfiPciIoAttributeOperationSet
:
1297 if(Attributes
& ~(PciIoDevice
->Supports
)) {
1298 return EFI_UNSUPPORTED
;
1300 NewAttributes
= Attributes
;
1303 return EFI_INVALID_PARAMETER
;
1307 // If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately.
1309 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) {
1310 NewAttributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1314 // If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately.
1316 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
) {
1317 NewAttributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
1321 // If the attributes are already set correctly, then just return EFI_SUCCESS;
1323 if ((NewAttributes
^ PciIoDevice
->Attributes
) == 0) {
1328 // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
1329 // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so
1330 // a call to the PCI Root Bridge I/O Protocol can be made
1333 if (!IS_PCI_BRIDGE(&PciIoDevice
->Pci
)) {
1334 NewPciRootBridgeAttributes
= NewAttributes
& (~(EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
| EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
));
1337 // Get the current attributes of this PCI device's PCI Root Bridge
1339 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1340 PciIoDevice
->PciRootBridgeIo
,
1341 &PciRootBridgeSupports
,
1342 &PciRootBridgeAttributes
1346 // Check to see if any of the PCI Root Bridge attributes are being modified
1348 ModifiedPciRootBridgeAttributes
= NewPciRootBridgeAttributes
^ PciRootBridgeAttributes
;
1349 if (ModifiedPciRootBridgeAttributes
) {
1352 // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
1354 if ((ModifiedPciRootBridgeAttributes
& PciRootBridgeSupports
) != ModifiedPciRootBridgeAttributes
) {
1355 // return EFI_UNSUPPORTED;
1358 // Call the PCI Root Bridge to attempt to modify the attributes
1360 Status
= PciIoDevice
->PciRootBridgeIo
->SetAttributes (
1361 PciIoDevice
->PciRootBridgeIo
,
1362 NewPciRootBridgeAttributes
,
1366 if (EFI_ERROR (Status
)) {
1368 // The PCI Root Bridge could not modify the attributes, so return the error.
1376 if (IS_PCI_BRIDGE(&PciIoDevice
->Pci
)) {
1380 // Check to see if an VGA related attributes are being set.
1382 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
)) {
1384 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) {
1385 EnableBridge
|= EFI_PCI_BRIDGE_CONTROL_VGA
;
1387 DisableBridge
|= EFI_PCI_BRIDGE_CONTROL_VGA
;
1392 // Check to see if an VGA related attributes are being set.
1393 // If ISA Enable on the PPB is set, the PPB will block the
1394 // 0x100-0x3FF for each 1KB block in the first 64K I/O block
1396 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_ISA_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_ISA_IO
)) {
1398 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_ISA_IO
) {
1399 DisableBridge
|= EFI_PCI_BRIDGE_CONTROL_ISA
;
1401 EnableBridge
|= EFI_PCI_BRIDGE_CONTROL_ISA
;
1406 // Check to see if an VGA related attributes are being set.
1408 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
)) {
1410 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
) {
1411 EnableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1413 DisableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1419 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
)) {
1421 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_IO
) {
1424 //Check if there have been an active VGA device on the same segment
1426 Temp
= ActiveVGADeviceOnTheSameSegment (PciIoDevice
);
1428 if (Temp
&& Temp
!= PciIoDevice
) {
1429 return EFI_UNSUPPORTED
;
1434 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
)) {
1435 if (IS_PCI_GFX(&PciIoDevice
->Pci
)) {
1438 //Get the boot VGA on the same segement
1440 Temp
= ActiveVGADeviceOnTheSameSegment (PciIoDevice
);
1445 // If there is no VGA device on the segement, set
1446 // this graphics card to decode the palette range
1448 DisableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1452 // Check these two agents are on the same path
1454 if (PciDevicesOnTheSamePath(Temp
, PciIoDevice
)) {
1457 // Check if they are on the same bus
1459 if (Temp
->Parent
== PciIoDevice
->Parent
) {
1461 PciReadCommandRegister (Temp
, &Command
);
1464 // If they are on the same bus, either one can
1465 // be set to snoop, the other set to decode
1467 if (Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) {
1468 DisableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1470 EnableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1475 // If they are on the same path but on the different bus
1476 // The first agent is set to snoop, the second one set to
1479 if (Temp
->BusNumber
> PciIoDevice
->BusNumber
) {
1480 PciEnableCommandRegister(Temp
,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1481 DisableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1483 PciDisableCommandRegister(Temp
,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
);
1484 EnableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1489 EnableCommand
|= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1497 // Check to see of the I/O enable is being modified
1499 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_IO
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
)) {
1500 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_IO
) {
1501 EnableCommand
|= EFI_PCI_COMMAND_IO_SPACE
;
1503 DisableCommand
|= EFI_PCI_COMMAND_IO_SPACE
;
1508 // Check to see of the Memory enable is being modified
1510 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_MEMORY
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_MEMORY
)) {
1511 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_MEMORY
) {
1512 EnableCommand
|= EFI_PCI_COMMAND_MEMORY_SPACE
;
1514 DisableCommand
|= EFI_PCI_COMMAND_MEMORY_SPACE
;
1519 // Check to see of the Bus Master enable is being modified
1521 if ((NewAttributes
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
) ^ (PciIoDevice
->Attributes
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
)) {
1522 if (NewAttributes
& EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
) {
1523 EnableCommand
|= EFI_PCI_COMMAND_BUS_MASTER
;
1525 DisableCommand
|= EFI_PCI_COMMAND_BUS_MASTER
;
1529 Status
= EFI_SUCCESS
;
1530 if (EnableCommand
) {
1531 Status
= PciEnableCommandRegister(PciIoDevice
, EnableCommand
);
1534 if (DisableCommand
) {
1535 Status
= PciDisableCommandRegister(PciIoDevice
, DisableCommand
);
1538 if (EFI_ERROR(Status
)) {
1539 return EFI_UNSUPPORTED
;
1543 Status
= PciEnableBridgeControlRegister(PciIoDevice
, EnableBridge
);
1546 if (DisableBridge
) {
1547 Status
= PciDisableBridgeControlRegister(PciIoDevice
, DisableBridge
);
1550 if (EFI_ERROR(Status
)) {
1551 return EFI_UNSUPPORTED
;
1555 // Set the upstream bridge attributes
1557 if (Operation
!= EfiPciIoAttributeOperationGet
&& Operation
!= EfiPciIoAttributeOperationSupported
) {
1560 // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
1561 // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
1562 // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge
1564 NewUpStreamBridgeAttributes
= Attributes
& \
1565 (~(EFI_PCI_IO_ATTRIBUTE_IO
| \
1566 EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
1567 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
| \
1568 EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
| \
1569 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
| \
1570 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
));
1572 if (NewUpStreamBridgeAttributes
){
1573 UpStreamBridgesAttributes(PciIoDevice
, Operation
, NewUpStreamBridgeAttributes
);
1577 PciIoDevice
->Attributes
= NewAttributes
;
1584 PciIoGetBarAttributes (
1585 IN EFI_PCI_IO_PROTOCOL
* This
,
1587 OUT UINT64
*Supports
, OPTIONAL
1588 OUT VOID
**Resources OPTIONAL
1592 Routine Description:
1604 UINT8
*Configuration
;
1606 PCI_IO_DEVICE
*PciIoDevice
;
1607 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1608 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1612 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1614 if (Supports
== NULL
&& Resources
== NULL
) {
1615 return EFI_INVALID_PARAMETER
;
1618 if (BarIndex
>= PCI_MAX_BAR
) {
1619 return EFI_UNSUPPORTED
;
1623 // This driver does not support modifications to the WRITE_COMBINE or
1624 // CACHED attributes for BAR ranges.
1626 if (Supports
!= NULL
) {
1627 *Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
1630 if (Resources
!= NULL
) {
1632 if (PciIoDevice
->PciBar
[BarIndex
].BarType
!= PciBarTypeUnknown
) {
1636 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1637 if (Configuration
== NULL
) {
1638 return EFI_OUT_OF_RESOURCES
;
1643 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1646 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1648 if (NumConfig
== 1) {
1649 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1650 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1652 Ptr
->AddrRangeMin
= PciIoDevice
->PciBar
[BarIndex
].BaseAddress
;
1653 Ptr
->AddrLen
= PciIoDevice
->PciBar
[BarIndex
].Length
;
1654 Ptr
->AddrRangeMax
= PciIoDevice
->PciBar
[BarIndex
].Alignment
;
1656 switch (PciIoDevice
->PciBar
[BarIndex
].BarType
) {
1657 case PciBarTypeIo16
:
1658 case PciBarTypeIo32
:
1662 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1665 case PciBarTypeMem32
:
1669 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1673 Ptr
->AddrSpaceGranularity
= 32;
1676 case PciBarTypePMem32
:
1680 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1684 Ptr
->SpecificFlag
= 0x6;
1688 Ptr
->AddrSpaceGranularity
= 32;
1691 case PciBarTypeMem64
:
1695 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1699 Ptr
->AddrSpaceGranularity
= 64;
1702 case PciBarTypePMem64
:
1706 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1710 Ptr
->SpecificFlag
= 0x6;
1714 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
;
1738 PciIoSetBarAttributes (
1739 IN EFI_PCI_IO_PROTOCOL
*This
,
1740 IN UINT64 Attributes
,
1742 IN OUT UINT64
*Offset
,
1743 IN OUT UINT64
*Length
1747 Routine Description:
1759 PCI_IO_DEVICE
*PciIoDevice
;
1760 UINT64 NonRelativeOffset
;
1763 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (This
);
1766 // Make sure Offset and Length are not NULL
1768 if (Offset
== NULL
|| Length
== NULL
) {
1769 return EFI_INVALID_PARAMETER
;
1772 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeUnknown
) {
1773 return EFI_UNSUPPORTED
;
1776 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
1777 // If Attributes is not 0, then return EFI_UNSUPPORTED.
1779 Supports
= PciIoDevice
->Supports
& EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
& EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
;
1781 if (Attributes
!= (Attributes
& Supports
)) {
1782 return EFI_UNSUPPORTED
;
1785 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
1786 // Length are valid for this PCI device.
1788 NonRelativeOffset
= *Offset
;
1789 Status
= PciIoVerifyBarAccess (
1797 if (EFI_ERROR (Status
)) {
1798 return EFI_UNSUPPORTED
;
1805 UpStreamBridgesAttributes (
1806 IN PCI_IO_DEVICE
*PciIoDevice
,
1807 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1808 IN UINT64 Attributes
1812 Routine Description:
1822 PCI_IO_DEVICE
*Parent
;
1823 EFI_PCI_IO_PROTOCOL
*PciIo
;
1825 Parent
= PciIoDevice
->Parent
;
1827 while (Parent
&& IS_PCI_BRIDGE (&Parent
->Pci
)) {
1830 // Get the PciIo Protocol
1832 PciIo
= &Parent
->PciIo
;
1834 PciIo
->Attributes (PciIo
, Operation
, Attributes
, NULL
);
1836 Parent
= Parent
->Parent
;
1843 PciDevicesOnTheSamePath (
1844 IN PCI_IO_DEVICE
*PciDevice1
,
1845 IN PCI_IO_DEVICE
*PciDevice2
1849 Routine Description:
1853 PciDevice1 - The pointer to the first PCI_IO_DEVICE.
1854 PciDevice2 - The pointer to the second PCI_IO_DEVICE.
1858 TRUE - The two Pci devices are on the same path.
1859 FALSE - The two Pci devices are not on the same path.
1864 if (PciDevice1
->Parent
== PciDevice2
->Parent
) {
1868 return (BOOLEAN
) ((PciDeviceExisted (PciDevice1
->Parent
, PciDevice2
)|| PciDeviceExisted (PciDevice2
->Parent
, PciDevice1
)));