2 PCI Root Bridge Io Protocol implementation
4 Copyright (c) 2008 - 2009, Intel Corporation<BR> All rights
5 reserved. This program and the accompanying materials are
6 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.
15 #include "PciHostBridge.h"
18 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp
[TypeMax
];
19 EFI_ACPI_END_TAG_DESCRIPTOR EndDesp
;
20 } RESOURCE_CONFIGURATION
;
22 RESOURCE_CONFIGURATION Configuration
= {
23 {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
24 {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
25 {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
26 {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
27 {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
28 {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
33 // Protocol Member Function Prototypes
39 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
40 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
51 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
52 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
63 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
64 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
72 RootBridgeIoMemWrite (
73 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
74 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
83 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
84 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
85 IN UINT64 UserAddress
,
87 IN OUT VOID
*UserBuffer
93 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
94 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
95 IN UINT64 UserAddress
,
97 IN OUT VOID
*UserBuffer
102 RootBridgeIoCopyMem (
103 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
105 IN UINT64 DestAddress
,
106 IN UINT64 SrcAddress
,
112 RootBridgeIoPciRead (
113 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
114 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
122 RootBridgeIoPciWrite (
123 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
124 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
133 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
134 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
,
135 IN VOID
*HostAddress
,
136 IN OUT UINTN
*NumberOfBytes
,
137 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
144 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
150 RootBridgeIoAllocateBuffer (
151 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
152 IN EFI_ALLOCATE_TYPE Type
,
153 IN EFI_MEMORY_TYPE MemoryType
,
155 OUT VOID
**HostAddress
,
161 RootBridgeIoFreeBuffer (
162 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
164 OUT VOID
*HostAddress
170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
175 RootBridgeIoGetAttributes (
176 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
177 OUT UINT64
*Supported
,
178 OUT UINT64
*Attributes
183 RootBridgeIoSetAttributes (
184 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
185 IN UINT64 Attributes
,
186 IN OUT UINT64
*ResourceBase
,
187 IN OUT UINT64
*ResourceLength
192 RootBridgeIoConfiguration (
193 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
198 // Sub Function Prototypes
202 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
204 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
205 IN UINT64 UserAddress
,
207 IN OUT VOID
*UserBuffer
211 // Memory Controller Pci Root Bridge Io Module Variables
213 EFI_METRONOME_ARCH_PROTOCOL
*mMetronome
;
214 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
217 RootBridgeConstructor (
218 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*Protocol
,
219 IN EFI_HANDLE HostBridgeHandle
,
221 IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE
*ResAppeture
227 Construct the Pci Root Bridge Io protocol
231 Protocol - protocol to initialize
240 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
241 PCI_RESOURCE_TYPE Index
;
243 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol
);
246 // The host to pci bridge, the host memory and io addresses are
247 // direct mapped to pci addresses, so no need translate, set bases to 0.
249 PrivateData
->MemBase
= ResAppeture
->MemBase
;
250 PrivateData
->IoBase
= ResAppeture
->IoBase
;
253 // The host bridge only supports 32bit addressing for memory
254 // and standard IA32 16bit io
256 PrivateData
->MemLimit
= ResAppeture
->MemLimit
;
257 PrivateData
->IoLimit
= ResAppeture
->IoLimit
;
260 // Bus Appeture for this Root Bridge (Possible Range)
262 PrivateData
->BusBase
= ResAppeture
->BusBase
;
263 PrivateData
->BusLimit
= ResAppeture
->BusLimit
;
266 // Specific for this chipset
268 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
269 PrivateData
->ResAllocNode
[Index
].Type
= Index
;
270 PrivateData
->ResAllocNode
[Index
].Base
= 0;
271 PrivateData
->ResAllocNode
[Index
].Length
= 0;
272 PrivateData
->ResAllocNode
[Index
].Status
= ResNone
;
276 EfiInitializeLock (&PrivateData
->PciLock
, TPL_HIGH_LEVEL
);
277 PrivateData
->PciAddress
= 0xCF8;
278 PrivateData
->PciData
= 0xCFC;
280 PrivateData
->RootBridgeAttrib
= Attri
;
282 PrivateData
->Attributes
= 0;
283 PrivateData
->Supports
= 0;
285 Protocol
->ParentHandle
= HostBridgeHandle
;
287 Protocol
->PollMem
= RootBridgeIoPollMem
;
288 Protocol
->PollIo
= RootBridgeIoPollIo
;
290 Protocol
->Mem
.Read
= RootBridgeIoMemRead
;
291 Protocol
->Mem
.Write
= RootBridgeIoMemWrite
;
293 Protocol
->Io
.Read
= RootBridgeIoIoRead
;
294 Protocol
->Io
.Write
= RootBridgeIoIoWrite
;
296 Protocol
->CopyMem
= RootBridgeIoCopyMem
;
298 Protocol
->Pci
.Read
= RootBridgeIoPciRead
;
299 Protocol
->Pci
.Write
= RootBridgeIoPciWrite
;
301 Protocol
->Map
= RootBridgeIoMap
;
302 Protocol
->Unmap
= RootBridgeIoUnmap
;
304 Protocol
->AllocateBuffer
= RootBridgeIoAllocateBuffer
;
305 Protocol
->FreeBuffer
= RootBridgeIoFreeBuffer
;
307 Protocol
->Flush
= RootBridgeIoFlush
;
309 Protocol
->GetAttributes
= RootBridgeIoGetAttributes
;
310 Protocol
->SetAttributes
= RootBridgeIoSetAttributes
;
312 Protocol
->Configuration
= RootBridgeIoConfiguration
;
314 Protocol
->SegmentNumber
= 0;
316 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**)&mCpuIo
);
317 ASSERT_EFI_ERROR (Status
);
319 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**)&mMetronome
);
320 ASSERT_EFI_ERROR (Status
);
327 RootBridgeIoPollMem (
328 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
329 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
348 UINT64 NumberOfTicks
;
351 if (Result
== NULL
) {
352 return EFI_INVALID_PARAMETER
;
355 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
356 return EFI_INVALID_PARAMETER
;
360 // No matter what, always do a single poll.
362 Status
= This
->Mem
.Read (This
, Width
, Address
, 1, Result
);
363 if (EFI_ERROR (Status
)) {
366 if ((*Result
& Mask
) == Value
) {
376 // Determine the proper # of metronome ticks to wait for polling the
377 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
378 // The "+1" to account for the possibility of the first tick being short
379 // because we started in the middle of a tick.
381 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
382 // protocol definition is updated.
384 NumberOfTicks
= DivU64x32Remainder (Delay
, (UINT32
) mMetronome
->TickPeriod
, &Remainder
);
385 if (Remainder
!= 0) {
390 while (NumberOfTicks
) {
392 mMetronome
->WaitForTick (mMetronome
, 1);
394 Status
= This
->Mem
.Read (This
, Width
, Address
, 1, Result
);
395 if (EFI_ERROR (Status
)) {
399 if ((*Result
& Mask
) == Value
) {
412 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
413 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
432 UINT64 NumberOfTicks
;
436 // No matter what, always do a single poll.
439 if (Result
== NULL
) {
440 return EFI_INVALID_PARAMETER
;
443 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
444 return EFI_INVALID_PARAMETER
;
447 Status
= This
->Io
.Read (This
, Width
, Address
, 1, Result
);
448 if (EFI_ERROR (Status
)) {
451 if ((*Result
& Mask
) == Value
) {
461 // Determine the proper # of metronome ticks to wait for polling the
462 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
463 // The "+1" to account for the possibility of the first tick being short
464 // because we started in the middle of a tick.
466 NumberOfTicks
= DivU64x32Remainder (Delay
, (UINT32
)mMetronome
->TickPeriod
, &Remainder
);
467 if (Remainder
!= 0) {
472 while (NumberOfTicks
) {
474 mMetronome
->WaitForTick (mMetronome
, 1);
476 Status
= This
->Io
.Read (This
, Width
, Address
, 1, Result
);
477 if (EFI_ERROR (Status
)) {
481 if ((*Result
& Mask
) == Value
) {
493 RootBridgeIoMemRead (
494 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
495 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
511 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
512 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth
;
515 if (Buffer
== NULL
) {
516 return EFI_INVALID_PARAMETER
;
519 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
520 return EFI_INVALID_PARAMETER
;
523 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
526 // Check memory access limit
528 if (Address
< PrivateData
->MemBase
) {
529 return EFI_INVALID_PARAMETER
;
535 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
539 Width
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)(Width
& 0x03);
541 if (Address
+ (((UINTN
)1 << Width
) * Count
) - 1 > PrivateData
->MemLimit
) {
542 return EFI_INVALID_PARAMETER
;
545 return mCpuIo
->Mem
.Read (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) OldWidth
,
546 Address
, OldCount
, Buffer
);
551 RootBridgeIoMemWrite (
552 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
553 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
569 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
570 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth
;
573 if (Buffer
== NULL
) {
574 return EFI_INVALID_PARAMETER
;
577 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
578 return EFI_INVALID_PARAMETER
;
581 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
584 // Check memory access limit
586 if (Address
< PrivateData
->MemBase
) {
587 return EFI_INVALID_PARAMETER
;
592 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
596 Width
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)(Width
& 0x03);
598 if (Address
+ (((UINTN
)1 << Width
) * Count
) - 1 > PrivateData
->MemLimit
) {
599 return EFI_INVALID_PARAMETER
;
602 return mCpuIo
->Mem
.Write (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) OldWidth
,
603 Address
, OldCount
, Buffer
);
609 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
610 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
629 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
630 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth
;
633 if (Buffer
== NULL
) {
634 return EFI_INVALID_PARAMETER
;
637 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
638 return EFI_INVALID_PARAMETER
;
641 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
643 //AlignMask = (1 << Width) - 1;
644 AlignMask
= (1 << (Width
& 0x03)) - 1;
647 // check Io access limit
649 if (Address
< PrivateData
->IoBase
) {
650 return EFI_INVALID_PARAMETER
;
655 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
659 Width
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)(Width
& 0x03);
661 if (Address
+ (((UINTN
)1 << Width
) * Count
) - 1 >= PrivateData
->IoLimit
) {
662 return EFI_INVALID_PARAMETER
;
665 if (Address
& AlignMask
) {
666 return EFI_INVALID_PARAMETER
;
669 return mCpuIo
->Io
.Read (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) OldWidth
,
670 Address
, OldCount
, Buffer
);
676 RootBridgeIoIoWrite (
677 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
678 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
695 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
696 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth
;
699 if (Buffer
== NULL
) {
700 return EFI_INVALID_PARAMETER
;
703 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
704 return EFI_INVALID_PARAMETER
;
707 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
709 //AlignMask = (1 << Width) - 1;
710 AlignMask
= (1 << (Width
& 0x03)) - 1;
713 // Check Io access limit
715 if (Address
< PrivateData
->IoBase
) {
716 return EFI_INVALID_PARAMETER
;
721 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
725 Width
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)(Width
& 0x03);
727 if (Address
+ (((UINTN
)1 << Width
) * Count
) - 1 >= PrivateData
->IoLimit
) {
728 return EFI_INVALID_PARAMETER
;
731 if (Address
& AlignMask
) {
732 return EFI_INVALID_PARAMETER
;
735 return mCpuIo
->Io
.Write (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) OldWidth
,
736 Address
, OldCount
, Buffer
);
742 RootBridgeIoCopyMem (
743 IN
struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
744 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
745 IN UINT64 DestAddress
,
746 IN UINT64 SrcAddress
,
766 if (Width
< 0 || Width
> EfiPciWidthUint64
) {
767 return EFI_INVALID_PARAMETER
;
770 if (DestAddress
== SrcAddress
) {
774 Stride
= (UINTN
)(1 << Width
);
777 if ((DestAddress
> SrcAddress
) && (DestAddress
< (SrcAddress
+ Count
* Stride
))) {
779 SrcAddress
= SrcAddress
+ (Count
-1) * Stride
;
780 DestAddress
= DestAddress
+ (Count
-1) * Stride
;
783 for (Index
= 0;Index
< Count
;Index
++) {
784 Status
= RootBridgeIoMemRead (
791 if (EFI_ERROR (Status
)) {
794 Status
= RootBridgeIoMemWrite (
801 if (EFI_ERROR (Status
)) {
805 SrcAddress
+= Stride
;
806 DestAddress
+= Stride
;
808 SrcAddress
-= Stride
;
809 DestAddress
-= Stride
;
817 RootBridgeIoPciRead (
818 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
819 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
836 if (Buffer
== NULL
) {
837 return EFI_INVALID_PARAMETER
;
840 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
841 return EFI_INVALID_PARAMETER
;
844 // Read Pci configuration space
846 return RootBridgeIoPciRW (This
, FALSE
, Width
, Address
, Count
, Buffer
);
851 RootBridgeIoPciWrite (
852 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
853 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
870 if (Buffer
== NULL
) {
871 return EFI_INVALID_PARAMETER
;
874 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
875 return EFI_INVALID_PARAMETER
;
878 // Write Pci configuration space
880 return RootBridgeIoPciRW (This
, TRUE
, Width
, Address
, Count
, Buffer
);
886 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
887 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
,
888 IN VOID
*HostAddress
,
889 IN OUT UINTN
*NumberOfBytes
,
890 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
896 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
899 if (HostAddress
== NULL
|| NumberOfBytes
== NULL
|| DeviceAddress
== NULL
|| Mapping
== NULL
) {
900 return EFI_INVALID_PARAMETER
;
904 // Initialize the return values to their defaults
909 // Make sure that Operation is valid
911 if (Operation
< 0 || Operation
>= EfiPciOperationMaximum
) {
912 return EFI_INVALID_PARAMETER
;
916 // Most PCAT like chipsets can not handle performing DMA above 4GB.
917 // If any part of the DMA transfer being mapped is above 4GB, then
918 // map the DMA transfer to a buffer below 4GB.
920 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
921 if ((PhysicalAddress
+ *NumberOfBytes
) > 0x100000000ULL
) {
924 // Common Buffer operations can not be remapped. If the common buffer
925 // if above 4GB, then it is not possible to generate a mapping, so return
928 if (Operation
== EfiPciOperationBusMasterCommonBuffer
|| Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
929 return EFI_UNSUPPORTED
;
933 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
936 Status
= gBS
->AllocatePool (
941 if (EFI_ERROR (Status
)) {
947 // Return a pointer to the MAP_INFO structure in Mapping
952 // Initialize the MAP_INFO structure
954 MapInfo
->Operation
= Operation
;
955 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
956 MapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES(*NumberOfBytes
);
957 MapInfo
->HostAddress
= PhysicalAddress
;
958 MapInfo
->MappedHostAddress
= 0x00000000ffffffff;
961 // Allocate a buffer below 4GB to map the transfer to.
963 Status
= gBS
->AllocatePages (
966 MapInfo
->NumberOfPages
,
967 &MapInfo
->MappedHostAddress
969 if (EFI_ERROR (Status
)) {
970 gBS
->FreePool (MapInfo
);
976 // If this is a read operation from the Bus Master's point of view,
977 // then copy the contents of the real buffer into the mapped buffer
978 // so the Bus Master can read the contents of the real buffer.
980 if (Operation
== EfiPciOperationBusMasterRead
|| Operation
== EfiPciOperationBusMasterRead64
) {
982 (VOID
*)(UINTN
)MapInfo
->MappedHostAddress
,
983 (VOID
*)(UINTN
)MapInfo
->HostAddress
,
984 MapInfo
->NumberOfBytes
989 // The DeviceAddress is the address of the maped buffer below 4GB
991 *DeviceAddress
= MapInfo
->MappedHostAddress
;
994 // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
996 *DeviceAddress
= PhysicalAddress
;
1005 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1013 // See if the Map() operation associated with this Unmap() required a mapping buffer.
1014 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1016 if (Mapping
!= NULL
) {
1018 // Get the MAP_INFO structure from Mapping
1020 MapInfo
= (MAP_INFO
*)Mapping
;
1023 // If this is a write operation from the Bus Master's point of view,
1024 // then copy the contents of the mapped buffer into the real buffer
1025 // so the processor can read the contents of the real buffer.
1027 if (MapInfo
->Operation
== EfiPciOperationBusMasterWrite
|| MapInfo
->Operation
== EfiPciOperationBusMasterWrite64
) {
1029 (VOID
*)(UINTN
)MapInfo
->HostAddress
,
1030 (VOID
*)(UINTN
)MapInfo
->MappedHostAddress
,
1031 MapInfo
->NumberOfBytes
1036 // Free the mapped buffer and the MAP_INFO structure.
1038 gBS
->FreePages (MapInfo
->MappedHostAddress
, MapInfo
->NumberOfPages
);
1039 gBS
->FreePool (Mapping
);
1046 RootBridgeIoAllocateBuffer (
1047 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1048 IN EFI_ALLOCATE_TYPE Type
,
1049 IN EFI_MEMORY_TYPE MemoryType
,
1051 OUT VOID
**HostAddress
,
1052 IN UINT64 Attributes
1057 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1060 // Validate Attributes
1062 if (Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) {
1063 return EFI_UNSUPPORTED
;
1067 // Check for invalid inputs
1069 if (HostAddress
== NULL
) {
1070 return EFI_INVALID_PARAMETER
;
1074 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1076 if (MemoryType
!= EfiBootServicesData
&& MemoryType
!= EfiRuntimeServicesData
) {
1077 return EFI_INVALID_PARAMETER
;
1081 // Limit allocations to memory below 4GB
1083 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
)(0xffffffff);
1085 Status
= gBS
->AllocatePages (AllocateMaxAddress
, MemoryType
, Pages
, &PhysicalAddress
);
1086 if (EFI_ERROR (Status
)) {
1090 *HostAddress
= (VOID
*)(UINTN
)PhysicalAddress
;
1097 RootBridgeIoFreeBuffer (
1098 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1100 OUT VOID
*HostAddress
1104 return gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
, Pages
);
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
1114 Routine Description:
1123 // not supported yet
1130 RootBridgeIoGetAttributes (
1131 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1132 OUT UINT64
*Supported
,
1133 OUT UINT64
*Attributes
1137 Routine Description:
1145 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1147 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
1149 if (Attributes
== NULL
&& Supported
== NULL
) {
1150 return EFI_INVALID_PARAMETER
;
1154 // Set the return value for Supported and Attributes
1157 *Supported
= PrivateData
->Supports
;
1161 *Attributes
= PrivateData
->Attributes
;
1169 RootBridgeIoSetAttributes (
1170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1171 IN UINT64 Attributes
,
1172 IN OUT UINT64
*ResourceBase
,
1173 IN OUT UINT64
*ResourceLength
1177 Routine Description:
1185 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1187 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
1190 if ((Attributes
& (~(PrivateData
->Supports
))) != 0) {
1191 return EFI_UNSUPPORTED
;
1196 // This is a generic driver for a PC-AT class system. It does not have any
1197 // chipset specific knowlegde, so none of the attributes can be set or
1198 // cleared. Any attempt to set attribute that are already set will succeed,
1199 // and any attempt to set an attribute that is not supported will fail.
1201 if (Attributes
& (~PrivateData
->Attributes
)) {
1202 return EFI_UNSUPPORTED
;
1210 RootBridgeIoConfiguration (
1211 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1212 OUT VOID
**Resources
1216 Routine Description:
1224 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1227 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This
);
1229 for (Index
= 0; Index
< TypeMax
; Index
++) {
1230 if (PrivateData
->ResAllocNode
[Index
].Status
== ResAllocated
) {
1231 Configuration
.SpaceDesp
[Index
].AddrRangeMin
= PrivateData
->ResAllocNode
[Index
].Base
;
1232 Configuration
.SpaceDesp
[Index
].AddrRangeMax
= PrivateData
->ResAllocNode
[Index
].Base
+ PrivateData
->ResAllocNode
[Index
].Length
- 1;
1233 Configuration
.SpaceDesp
[Index
].AddrLen
= PrivateData
->ResAllocNode
[Index
].Length
;
1237 *Resources
= &Configuration
;
1242 // Internal function
1246 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
1249 IN UINT64 UserAddress
,
1251 IN OUT VOID
*UserBuffer
1254 PCI_CONFIG_ACCESS_CF8 Pci
;
1255 PCI_CONFIG_ACCESS_CF8 PciAligned
;
1259 UINTN PciDataStride
;
1260 PCI_ROOT_BRIDGE_INSTANCE
*PrivateData
;
1261 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
;
1263 if (Width
< 0 || Width
>= EfiPciWidthMaximum
) {
1264 return EFI_INVALID_PARAMETER
;
1267 if ((Width
& 0x03) >= EfiPciWidthUint64
) {
1268 return EFI_INVALID_PARAMETER
;
1271 PrivateData
= DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This
);
1273 InStride
= 1 << (Width
& 0x03);
1274 OutStride
= InStride
;
1275 if (Width
>= EfiCpuIoWidthFifoUint8
&& Width
<= EfiCpuIoWidthFifoUint64
) {
1279 if (Width
>= EfiCpuIoWidthFillUint8
&& Width
<= EfiCpuIoWidthFillUint64
) {
1283 CopyMem (&PciAddress
, &UserAddress
, sizeof(UINT64
));
1285 if (PciAddress
.ExtendedRegister
> 0xFF) {
1286 return EFI_UNSUPPORTED
;
1289 if (PciAddress
.ExtendedRegister
!= 0) {
1290 Pci
.Bits
.Reg
= PciAddress
.ExtendedRegister
& 0xFF;
1292 Pci
.Bits
.Reg
= PciAddress
.Register
;
1295 Pci
.Bits
.Func
= PciAddress
.Function
;
1296 Pci
.Bits
.Dev
= PciAddress
.Device
;
1297 Pci
.Bits
.Bus
= PciAddress
.Bus
;
1298 Pci
.Bits
.Reserved
= 0;
1299 Pci
.Bits
.Enable
= 1;
1302 // PCI Config access are all 32-bit alligned, but by accessing the
1303 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
1304 // are possible on PCI.
1306 // To read a byte of PCI config space you load 0xcf8 and
1307 // read 0xcfc, 0xcfd, 0xcfe, 0xcff
1309 PciDataStride
= Pci
.Bits
.Reg
& 0x03;
1312 CopyMem (&PciAligned
, &Pci
, sizeof (PciAligned
));
1313 PciAligned
.Bits
.Reg
&= 0xfc;
1314 PciData
= (UINTN
)PrivateData
->PciData
+ PciDataStride
;
1315 EfiAcquireLock(&PrivateData
->PciLock
);
1316 This
->Io
.Write (This
, EfiPciWidthUint32
, PrivateData
->PciAddress
, 1, &PciAligned
);
1318 This
->Io
.Write (This
, Width
, PciData
, 1, UserBuffer
);
1320 This
->Io
.Read (This
, Width
, PciData
, 1, UserBuffer
);
1322 EfiReleaseLock(&PrivateData
->PciLock
);
1323 UserBuffer
= ((UINT8
*)UserBuffer
) + OutStride
;
1324 PciDataStride
= (PciDataStride
+ InStride
) % 4;
1325 Pci
.Bits
.Reg
+= InStride
;