3 PCI Root Bridge Io Protocol code.
5 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "PciHostBridge.h"
11 #include "PciRootBridge.h"
12 #include "PciHostResource.h"
14 #define NO_MAPPING (VOID *) (UINTN) -1
16 #define RESOURCE_VALID(Resource) ((Resource)->Base <= (Resource)->Limit)
19 // Lookup table for increment values based on transfer widths
22 1, // EfiPciWidthUint8
23 2, // EfiPciWidthUint16
24 4, // EfiPciWidthUint32
25 8, // EfiPciWidthUint64
26 0, // EfiPciWidthFifoUint8
27 0, // EfiPciWidthFifoUint16
28 0, // EfiPciWidthFifoUint32
29 0, // EfiPciWidthFifoUint64
30 1, // EfiPciWidthFillUint8
31 2, // EfiPciWidthFillUint16
32 4, // EfiPciWidthFillUint32
33 8 // EfiPciWidthFillUint64
37 // Lookup table for increment values based on transfer widths
39 UINT8 mOutStride
[] = {
40 1, // EfiPciWidthUint8
41 2, // EfiPciWidthUint16
42 4, // EfiPciWidthUint32
43 8, // EfiPciWidthUint64
44 1, // EfiPciWidthFifoUint8
45 2, // EfiPciWidthFifoUint16
46 4, // EfiPciWidthFifoUint32
47 8, // EfiPciWidthFifoUint64
48 0, // EfiPciWidthFillUint8
49 0, // EfiPciWidthFillUint16
50 0, // EfiPciWidthFillUint32
51 0 // EfiPciWidthFillUint64
55 Construct the Pci Root Bridge instance.
57 @param Bridge The root bridge instance.
59 @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created
60 or NULL if creation fails.
62 PCI_ROOT_BRIDGE_INSTANCE
*
64 IN PCI_ROOT_BRIDGE
*Bridge
67 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
68 PCI_RESOURCE_TYPE Index
;
69 CHAR16
*DevicePathStr
;
70 PCI_ROOT_BRIDGE_APERTURE
*Aperture
;
74 DEBUG ((EFI_D_INFO
, "RootBridge: "));
75 DEBUG ((EFI_D_INFO
, "%s\n", DevicePathStr
= ConvertDevicePathToText (Bridge
->DevicePath
, FALSE
, FALSE
)));
76 DEBUG ((EFI_D_INFO
, " Support/Attr: %lx / %lx\n", Bridge
->Supports
, Bridge
->Attributes
));
77 DEBUG ((EFI_D_INFO
, " DmaAbove4G: %s\n", Bridge
->DmaAbove4G
? L
"Yes" : L
"No"));
78 DEBUG ((EFI_D_INFO
, "NoExtConfSpace: %s\n", Bridge
->NoExtendedConfigSpace
? L
"Yes" : L
"No"));
79 DEBUG ((EFI_D_INFO
, " AllocAttr: %lx (%s%s)\n", Bridge
->AllocationAttributes
,
80 (Bridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0 ? L
"CombineMemPMem " : L
"",
81 (Bridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0 ? L
"Mem64Decode" : L
""
84 EFI_D_INFO
, " Bus: %lx - %lx Translation=%lx\n",
85 Bridge
->Bus
.Base
, Bridge
->Bus
.Limit
, Bridge
->Bus
.Translation
88 // Translation for bus is not supported.
90 ASSERT (Bridge
->Bus
.Translation
== 0);
91 if (Bridge
->Bus
.Translation
!= 0) {
96 DEBUG_INFO
, " Io: %lx - %lx Translation=%lx\n",
97 Bridge
->Io
.Base
, Bridge
->Io
.Limit
, Bridge
->Io
.Translation
100 DEBUG_INFO
, " Mem: %lx - %lx Translation=%lx\n",
101 Bridge
->Mem
.Base
, Bridge
->Mem
.Limit
, Bridge
->Mem
.Translation
104 DEBUG_INFO
, " MemAbove4G: %lx - %lx Translation=%lx\n",
105 Bridge
->MemAbove4G
.Base
, Bridge
->MemAbove4G
.Limit
, Bridge
->MemAbove4G
.Translation
108 DEBUG_INFO
, " PMem: %lx - %lx Translation=%lx\n",
109 Bridge
->PMem
.Base
, Bridge
->PMem
.Limit
, Bridge
->PMem
.Translation
112 DEBUG_INFO
, " PMemAbove4G: %lx - %lx Translation=%lx\n",
113 Bridge
->PMemAbove4G
.Base
, Bridge
->PMemAbove4G
.Limit
, Bridge
->PMemAbove4G
.Translation
117 // Make sure Mem and MemAbove4G apertures are valid
119 if (RESOURCE_VALID (&Bridge
->Mem
)) {
120 ASSERT (Bridge
->Mem
.Limit
< SIZE_4GB
);
121 if (Bridge
->Mem
.Limit
>= SIZE_4GB
) {
125 if (RESOURCE_VALID (&Bridge
->MemAbove4G
)) {
126 ASSERT (Bridge
->MemAbove4G
.Base
>= SIZE_4GB
);
127 if (Bridge
->MemAbove4G
.Base
< SIZE_4GB
) {
131 if (RESOURCE_VALID (&Bridge
->PMem
)) {
132 ASSERT (Bridge
->PMem
.Limit
< SIZE_4GB
);
133 if (Bridge
->PMem
.Limit
>= SIZE_4GB
) {
137 if (RESOURCE_VALID (&Bridge
->PMemAbove4G
)) {
138 ASSERT (Bridge
->PMemAbove4G
.Base
>= SIZE_4GB
);
139 if (Bridge
->PMemAbove4G
.Base
< SIZE_4GB
) {
145 // Ignore AllocationAttributes when resources were already assigned.
147 if (!Bridge
->ResourceAssigned
) {
148 if ((Bridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
150 // If this bit is set, then the PCI Root Bridge does not
151 // support separate windows for Non-prefetchable and Prefetchable
154 ASSERT (!RESOURCE_VALID (&Bridge
->PMem
));
155 ASSERT (!RESOURCE_VALID (&Bridge
->PMemAbove4G
));
156 if (RESOURCE_VALID (&Bridge
->PMem
) || RESOURCE_VALID (&Bridge
->PMemAbove4G
)) {
161 if ((Bridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) == 0) {
163 // If this bit is not set, then the PCI Root Bridge does not support
164 // 64 bit memory windows.
166 ASSERT (!RESOURCE_VALID (&Bridge
->MemAbove4G
));
167 ASSERT (!RESOURCE_VALID (&Bridge
->PMemAbove4G
));
168 if (RESOURCE_VALID (&Bridge
->MemAbove4G
) || RESOURCE_VALID (&Bridge
->PMemAbove4G
)) {
174 RootBridge
= AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE
));
175 ASSERT (RootBridge
!= NULL
);
177 RootBridge
->Signature
= PCI_ROOT_BRIDGE_SIGNATURE
;
178 RootBridge
->Supports
= Bridge
->Supports
;
179 RootBridge
->Attributes
= Bridge
->Attributes
;
180 RootBridge
->DmaAbove4G
= Bridge
->DmaAbove4G
;
181 RootBridge
->NoExtendedConfigSpace
= Bridge
->NoExtendedConfigSpace
;
182 RootBridge
->AllocationAttributes
= Bridge
->AllocationAttributes
;
183 RootBridge
->DevicePath
= DuplicateDevicePath (Bridge
->DevicePath
);
184 RootBridge
->DevicePathStr
= DevicePathStr
;
185 RootBridge
->ConfigBuffer
= AllocatePool (
186 TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
188 ASSERT (RootBridge
->ConfigBuffer
!= NULL
);
189 InitializeListHead (&RootBridge
->Maps
);
191 CopyMem (&RootBridge
->Bus
, &Bridge
->Bus
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
192 CopyMem (&RootBridge
->Io
, &Bridge
->Io
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
193 CopyMem (&RootBridge
->Mem
, &Bridge
->Mem
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
194 CopyMem (&RootBridge
->MemAbove4G
, &Bridge
->MemAbove4G
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
195 CopyMem (&RootBridge
->PMem
, &Bridge
->PMem
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
196 CopyMem (&RootBridge
->PMemAbove4G
, &Bridge
->PMemAbove4G
, sizeof (PCI_ROOT_BRIDGE_APERTURE
));
198 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
201 Aperture
= &RootBridge
->Bus
;
204 Aperture
= &RootBridge
->Io
;
207 Aperture
= &RootBridge
->Mem
;
210 Aperture
= &RootBridge
->MemAbove4G
;
213 Aperture
= &RootBridge
->PMem
;
216 Aperture
= &RootBridge
->PMemAbove4G
;
223 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
224 if (Bridge
->ResourceAssigned
&& (Aperture
->Limit
>= Aperture
->Base
)) {
226 // Base in ResAllocNode is a host address, while Base in Aperture is a
229 RootBridge
->ResAllocNode
[Index
].Base
= TO_HOST_ADDRESS (Aperture
->Base
,
230 Aperture
->Translation
);
231 RootBridge
->ResAllocNode
[Index
].Length
= Aperture
->Limit
- Aperture
->Base
+ 1;
232 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
234 RootBridge
->ResAllocNode
[Index
].Base
= 0;
235 RootBridge
->ResAllocNode
[Index
].Length
= 0;
236 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
240 RootBridge
->RootBridgeIo
.SegmentNumber
= Bridge
->Segment
;
241 RootBridge
->RootBridgeIo
.PollMem
= RootBridgeIoPollMem
;
242 RootBridge
->RootBridgeIo
.PollIo
= RootBridgeIoPollIo
;
243 RootBridge
->RootBridgeIo
.Mem
.Read
= RootBridgeIoMemRead
;
244 RootBridge
->RootBridgeIo
.Mem
.Write
= RootBridgeIoMemWrite
;
245 RootBridge
->RootBridgeIo
.Io
.Read
= RootBridgeIoIoRead
;
246 RootBridge
->RootBridgeIo
.Io
.Write
= RootBridgeIoIoWrite
;
247 RootBridge
->RootBridgeIo
.CopyMem
= RootBridgeIoCopyMem
;
248 RootBridge
->RootBridgeIo
.Pci
.Read
= RootBridgeIoPciRead
;
249 RootBridge
->RootBridgeIo
.Pci
.Write
= RootBridgeIoPciWrite
;
250 RootBridge
->RootBridgeIo
.Map
= RootBridgeIoMap
;
251 RootBridge
->RootBridgeIo
.Unmap
= RootBridgeIoUnmap
;
252 RootBridge
->RootBridgeIo
.AllocateBuffer
= RootBridgeIoAllocateBuffer
;
253 RootBridge
->RootBridgeIo
.FreeBuffer
= RootBridgeIoFreeBuffer
;
254 RootBridge
->RootBridgeIo
.Flush
= RootBridgeIoFlush
;
255 RootBridge
->RootBridgeIo
.GetAttributes
= RootBridgeIoGetAttributes
;
256 RootBridge
->RootBridgeIo
.SetAttributes
= RootBridgeIoSetAttributes
;
257 RootBridge
->RootBridgeIo
.Configuration
= RootBridgeIoConfiguration
;
263 Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
265 The I/O operations are carried out exactly as requested. The caller is
266 responsible for satisfying any alignment and I/O width restrictions that a PI
267 System on a platform might require. For example on some platforms, width
268 requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other
269 hand, will be handled by the driver.
271 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
273 @param[in] OperationType I/O operation type: IO/MMIO/PCI.
275 @param[in] Width Signifies the width of the I/O or Memory operation.
277 @param[in] Address The base address of the I/O operation.
279 @param[in] Count The number of I/O operations to perform. The number
280 of bytes moved is Width size * Count, starting at
283 @param[in] Buffer For read operations, the destination buffer to
284 store the results. For write operations, the source
285 buffer from which to write data.
287 @retval EFI_SUCCESS The parameters for this request pass the
290 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.
292 @retval EFI_INVALID_PARAMETER Buffer is NULL.
294 @retval EFI_INVALID_PARAMETER Address or Count is invalid.
296 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.
298 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
299 and Count is not valid for this PI system.
302 RootBridgeIoCheckParameter (
303 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
304 IN OPERATION_TYPE OperationType
,
305 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
311 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
312 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*PciRbAddr
;
319 // Check to see if Buffer is NULL
321 if (Buffer
== NULL
) {
322 return EFI_INVALID_PARAMETER
;
326 // Check to see if Width is in the valid range
328 if ((UINT32
) Width
>= EfiPciWidthMaximum
) {
329 return EFI_INVALID_PARAMETER
;
333 // For FIFO type, the device address won't increase during the access,
334 // so treat Count as 1
336 if (Width
>= EfiPciWidthFifoUint8
&& Width
<= EfiPciWidthFifoUint64
) {
340 Width
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) (Width
& 0x03);
344 // Make sure (Count * Size) doesn't exceed MAX_UINT64
346 if (Count
> DivU64x32 (MAX_UINT64
, Size
)) {
347 return EFI_INVALID_PARAMETER
;
351 // Check to see if Address is aligned
353 if ((Address
& (Size
- 1)) != 0) {
354 return EFI_UNSUPPORTED
;
358 // Make sure (Address + Count * Size) doesn't exceed MAX_UINT64
360 Length
= MultU64x32 (Count
, Size
);
361 if (Address
> MAX_UINT64
- Length
) {
362 return EFI_INVALID_PARAMETER
;
365 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
368 // Check to see if any address associated with this transfer exceeds the
369 // maximum allowed address. The maximum address implied by the parameters
370 // passed in is Address + Size * Count. If the following condition is met,
371 // then the transfer is not supported.
373 // Address + Size * Count > Limit + 1
375 // Since Limit can be the maximum integer value supported by the CPU and
376 // Count can also be the maximum integer value supported by the CPU, this
377 // range check must be adjusted to avoid all oveflow conditions.
379 if (OperationType
== IoOperation
) {
381 // Allow Legacy IO access
383 if (Address
+ Length
<= 0x1000) {
384 if ((RootBridge
->Attributes
& (
385 EFI_PCI_ATTRIBUTE_ISA_IO
| EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO
| EFI_PCI_ATTRIBUTE_VGA_IO
|
386 EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO
|
387 EFI_PCI_ATTRIBUTE_ISA_IO_16
| EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
| EFI_PCI_ATTRIBUTE_VGA_IO_16
)) != 0) {
391 Base
= RootBridge
->Io
.Base
;
392 Limit
= RootBridge
->Io
.Limit
;
393 } else if (OperationType
== MemOperation
) {
395 // Allow Legacy MMIO access
397 if ((Address
>= 0xA0000) && (Address
+ Length
) <= 0xC0000) {
398 if ((RootBridge
->Attributes
& EFI_PCI_ATTRIBUTE_VGA_MEMORY
) != 0) {
403 // By comparing the Address against Limit we know which range to be used
406 if ((Address
>= RootBridge
->Mem
.Base
) && (Address
+ Length
<= RootBridge
->Mem
.Limit
+ 1)) {
407 Base
= RootBridge
->Mem
.Base
;
408 Limit
= RootBridge
->Mem
.Limit
;
409 } else if ((Address
>= RootBridge
->PMem
.Base
) && (Address
+ Length
<= RootBridge
->PMem
.Limit
+ 1)) {
410 Base
= RootBridge
->PMem
.Base
;
411 Limit
= RootBridge
->PMem
.Limit
;
412 } else if ((Address
>= RootBridge
->MemAbove4G
.Base
) && (Address
+ Length
<= RootBridge
->MemAbove4G
.Limit
+ 1)) {
413 Base
= RootBridge
->MemAbove4G
.Base
;
414 Limit
= RootBridge
->MemAbove4G
.Limit
;
416 Base
= RootBridge
->PMemAbove4G
.Base
;
417 Limit
= RootBridge
->PMemAbove4G
.Limit
;
420 PciRbAddr
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS
*) &Address
;
421 if (PciRbAddr
->Bus
< RootBridge
->Bus
.Base
||
422 PciRbAddr
->Bus
> RootBridge
->Bus
.Limit
) {
423 return EFI_INVALID_PARAMETER
;
426 if (PciRbAddr
->Device
> PCI_MAX_DEVICE
||
427 PciRbAddr
->Function
> PCI_MAX_FUNC
) {
428 return EFI_INVALID_PARAMETER
;
431 if (PciRbAddr
->ExtendedRegister
!= 0) {
432 Address
= PciRbAddr
->ExtendedRegister
;
434 Address
= PciRbAddr
->Register
;
437 Limit
= RootBridge
->NoExtendedConfigSpace
? 0xFF : 0xFFF;
440 if (Address
< Base
) {
441 return EFI_INVALID_PARAMETER
;
444 if (Address
+ Length
> Limit
+ 1) {
445 return EFI_INVALID_PARAMETER
;
452 Use address to match apertures of memory type and then get the corresponding
455 @param RootBridge The root bridge instance.
456 @param Address The address used to match aperture.
457 @param Translation Pointer containing the output translation.
459 @return EFI_SUCCESS Get translation successfully.
460 @return EFI_INVALID_PARAMETER No matched memory aperture; the input Address
464 RootBridgeIoGetMemTranslationByAddress (
465 IN PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
,
467 IN OUT UINT64
*Translation
470 if (Address
>= RootBridge
->Mem
.Base
&& Address
<= RootBridge
->Mem
.Limit
) {
471 *Translation
= RootBridge
->Mem
.Translation
;
472 } else if (Address
>= RootBridge
->PMem
.Base
&& Address
<= RootBridge
->PMem
.Limit
) {
473 *Translation
= RootBridge
->PMem
.Translation
;
474 } else if (Address
>= RootBridge
->MemAbove4G
.Base
&& Address
<= RootBridge
->MemAbove4G
.Limit
) {
475 *Translation
= RootBridge
->MemAbove4G
.Translation
;
476 } else if (Address
>= RootBridge
->PMemAbove4G
.Base
&& Address
<= RootBridge
->PMemAbove4G
.Limit
) {
477 *Translation
= RootBridge
->PMemAbove4G
.Translation
;
479 return EFI_INVALID_PARAMETER
;
486 Return the result of (Multiplicand * Multiplier / Divisor).
488 @param Multiplicand A 64-bit unsigned value.
489 @param Multiplier A 64-bit unsigned value.
490 @param Divisor A 32-bit unsigned value.
491 @param Remainder A pointer to a 32-bit unsigned value. This parameter is
492 optional and may be NULL.
494 @return Multiplicand * Multiplier / Divisor.
497 MultThenDivU64x64x32 (
498 IN UINT64 Multiplicand
,
499 IN UINT64 Multiplier
,
501 OUT UINT32
*Remainder OPTIONAL
505 UINT32 LocalRemainder
;
507 if (Multiplicand
> DivU64x64Remainder (MAX_UINT64
, Multiplier
, NULL
)) {
509 // Make sure Multiplicand is the bigger one.
511 if (Multiplicand
< Multiplier
) {
512 Uint64
= Multiplicand
;
513 Multiplicand
= Multiplier
;
517 // Because Multiplicand * Multiplier overflows,
518 // Multiplicand * Multiplier / Divisor
519 // = (2 * Multiplicand' + 1) * Multiplier / Divisor
520 // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor
522 Uint64
= MultThenDivU64x64x32 (RShiftU64 (Multiplicand
, 1), Multiplier
, Divisor
, &LocalRemainder
);
523 Uint64
= LShiftU64 (Uint64
, 1);
525 if ((Multiplicand
& 0x1) == 1) {
526 Uint64
+= DivU64x32Remainder (Multiplier
, Divisor
, &Uint32
);
528 return Uint64
+ DivU64x32Remainder (Uint32
+ LShiftU64 (LocalRemainder
, 1), Divisor
, Remainder
);
530 return DivU64x32Remainder (MultU64x64 (Multiplicand
, Multiplier
), Divisor
, Remainder
);
535 Return the elapsed tick count from CurrentTick.
537 @param CurrentTick On input, the previous tick count.
538 On output, the current tick count.
539 @param StartTick The value the performance counter starts with when it
541 @param EndTick The value that the performance counter ends with before
544 @return The elapsed tick count from CurrentTick.
555 PreviousTick
= *CurrentTick
;
556 *CurrentTick
= GetPerformanceCounter();
557 if (StartTick
< EndTick
) {
558 return *CurrentTick
- PreviousTick
;
560 return PreviousTick
- *CurrentTick
;
565 Polls an address in memory mapped I/O space until an exit condition is met,
568 This function provides a standard way to poll a PCI memory location. A PCI
569 memory read operation is performed at the PCI memory address specified by
570 Address for the width specified by Width. The result of this PCI memory read
571 operation is stored in Result. This PCI memory read operation is repeated
572 until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
575 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
576 @param[in] Width Signifies the width of the memory operations.
577 @param[in] Address The base address of the memory operations. The caller
578 is responsible for aligning Address if required.
579 @param[in] Mask Mask used for the polling criteria. Bytes above Width
580 in Mask are ignored. The bits in the bytes below Width
581 which are zero in Mask are ignored when polling the
583 @param[in] Value The comparison value used for the polling exit
585 @param[in] Delay The number of 100 ns units to poll. Note that timer
586 available may be of poorer granularity.
587 @param[out] Result Pointer to the last value read from the memory
590 @retval EFI_SUCCESS The last data returned from the access matched
591 the poll exit criteria.
592 @retval EFI_INVALID_PARAMETER Width is invalid.
593 @retval EFI_INVALID_PARAMETER Result is NULL.
594 @retval EFI_TIMEOUT Delay expired before a match occurred.
595 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
600 RootBridgeIoPollMem (
601 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
602 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
611 UINT64 NumberOfTicks
;
619 if (Result
== NULL
) {
620 return EFI_INVALID_PARAMETER
;
623 if ((UINT32
)Width
> EfiPciWidthUint64
) {
624 return EFI_INVALID_PARAMETER
;
628 // No matter what, always do a single poll.
630 Status
= This
->Mem
.Read (This
, Width
, Address
, 1, Result
);
631 if (EFI_ERROR (Status
)) {
635 if ((*Result
& Mask
) == Value
) {
644 // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
646 Frequency
= GetPerformanceCounterProperties (&StartTick
, &EndTick
);
647 NumberOfTicks
= MultThenDivU64x64x32 (Frequency
, Delay
, (UINT32
)EFI_TIMER_PERIOD_SECONDS(1), &Remainder
);
648 if (Remainder
>= (UINTN
)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
651 for ( ElapsedTick
= 0, CurrentTick
= GetPerformanceCounter()
652 ; ElapsedTick
<= NumberOfTicks
653 ; ElapsedTick
+= GetElapsedTick (&CurrentTick
, StartTick
, EndTick
)
655 Status
= This
->Mem
.Read (This
, Width
, Address
, 1, Result
);
656 if (EFI_ERROR (Status
)) {
660 if ((*Result
& Mask
) == Value
) {
669 Reads from the I/O space of a PCI Root Bridge. Returns when either the
670 polling exit criteria is satisfied or after a defined duration.
672 This function provides a standard way to poll a PCI I/O location. A PCI I/O
673 read operation is performed at the PCI I/O address specified by Address for
674 the width specified by Width.
675 The result of this PCI I/O read operation is stored in Result. This PCI I/O
676 read operation is repeated until either a timeout of Delay 100 ns units has
677 expired, or (Result & Mask) is equal to Value.
679 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
680 @param[in] Width Signifies the width of the I/O operations.
681 @param[in] Address The base address of the I/O operations. The caller is
682 responsible for aligning Address if required.
683 @param[in] Mask Mask used for the polling criteria. Bytes above Width in
684 Mask are ignored. The bits in the bytes below Width
685 which are zero in Mask are ignored when polling the I/O
687 @param[in] Value The comparison value used for the polling exit criteria.
688 @param[in] Delay The number of 100 ns units to poll. Note that timer
689 available may be of poorer granularity.
690 @param[out] Result Pointer to the last value read from the memory location.
692 @retval EFI_SUCCESS The last data returned from the access matched
693 the poll exit criteria.
694 @retval EFI_INVALID_PARAMETER Width is invalid.
695 @retval EFI_INVALID_PARAMETER Result is NULL.
696 @retval EFI_TIMEOUT Delay expired before a match occurred.
697 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
703 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
704 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
713 UINT64 NumberOfTicks
;
722 // No matter what, always do a single poll.
725 if (Result
== NULL
) {
726 return EFI_INVALID_PARAMETER
;
729 if ((UINT32
)Width
> EfiPciWidthUint64
) {
730 return EFI_INVALID_PARAMETER
;
733 Status
= This
->Io
.Read (This
, Width
, Address
, 1, Result
);
734 if (EFI_ERROR (Status
)) {
737 if ((*Result
& Mask
) == Value
) {
746 // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
748 Frequency
= GetPerformanceCounterProperties (&StartTick
, &EndTick
);
749 NumberOfTicks
= MultThenDivU64x64x32 (Frequency
, Delay
, (UINT32
)EFI_TIMER_PERIOD_SECONDS(1), &Remainder
);
750 if (Remainder
>= (UINTN
)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
753 for ( ElapsedTick
= 0, CurrentTick
= GetPerformanceCounter()
754 ; ElapsedTick
<= NumberOfTicks
755 ; ElapsedTick
+= GetElapsedTick (&CurrentTick
, StartTick
, EndTick
)
757 Status
= This
->Io
.Read (This
, Width
, Address
, 1, Result
);
758 if (EFI_ERROR (Status
)) {
762 if ((*Result
& Mask
) == Value
) {
771 Enables a PCI driver to access PCI controller registers in the PCI root
774 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
775 controller registers in the PCI root bridge memory space.
776 The memory operations are carried out exactly as requested. The caller is
777 responsible for satisfying any alignment and memory width restrictions that a
778 PCI Root Bridge on a platform might require.
780 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
781 @param[in] Width Signifies the width of the memory operation.
782 @param[in] Address The base address of the memory operation. The caller
783 is responsible for aligning the Address if required.
784 @param[in] Count The number of memory operations to perform. Bytes
785 moved is Width size * Count, starting at Address.
786 @param[out] Buffer For read operations, the destination buffer to store
787 the results. For write operations, the source buffer
790 @retval EFI_SUCCESS The data was read from or written to the PCI
792 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
793 @retval EFI_INVALID_PARAMETER Buffer is NULL.
794 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
799 RootBridgeIoMemRead (
800 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
801 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
808 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
811 Status
= RootBridgeIoCheckParameter (This
, MemOperation
, Width
, Address
,
813 if (EFI_ERROR (Status
)) {
817 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
818 Status
= RootBridgeIoGetMemTranslationByAddress (RootBridge
, Address
, &Translation
);
819 if (EFI_ERROR (Status
)) {
823 // Address passed to CpuIo->Mem.Read needs to be a host address instead of
825 return mCpuIo
->Mem
.Read (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
826 TO_HOST_ADDRESS (Address
, Translation
), Count
, Buffer
);
830 Enables a PCI driver to access PCI controller registers in the PCI root
833 The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
834 controller registers in the PCI root bridge memory space.
835 The memory operations are carried out exactly as requested. The caller is
836 responsible for satisfying any alignment and memory width restrictions that a
837 PCI Root Bridge on a platform might require.
839 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
840 @param[in] Width Signifies the width of the memory operation.
841 @param[in] Address The base address of the memory operation. The caller
842 is responsible for aligning the Address if required.
843 @param[in] Count The number of memory operations to perform. Bytes
844 moved is Width size * Count, starting at Address.
845 @param[in] Buffer For read operations, the destination buffer to store
846 the results. For write operations, the source buffer
849 @retval EFI_SUCCESS The data was read from or written to the PCI
851 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
852 @retval EFI_INVALID_PARAMETER Buffer is NULL.
853 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
858 RootBridgeIoMemWrite (
859 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
860 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
867 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
870 Status
= RootBridgeIoCheckParameter (This
, MemOperation
, Width
, Address
,
872 if (EFI_ERROR (Status
)) {
876 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
877 Status
= RootBridgeIoGetMemTranslationByAddress (RootBridge
, Address
, &Translation
);
878 if (EFI_ERROR (Status
)) {
882 // Address passed to CpuIo->Mem.Write needs to be a host address instead of
884 return mCpuIo
->Mem
.Write (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
885 TO_HOST_ADDRESS (Address
, Translation
), Count
, Buffer
);
889 Enables a PCI driver to access PCI controller registers in the PCI root
892 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
893 @param[in] Width Signifies the width of the memory operations.
894 @param[in] Address The base address of the I/O operation. The caller is
895 responsible for aligning the Address if required.
896 @param[in] Count The number of I/O operations to perform. Bytes moved
897 is Width size * Count, starting at Address.
898 @param[out] Buffer For read operations, the destination buffer to store
899 the results. For write operations, the source buffer
902 @retval EFI_SUCCESS The data was read from or written to the PCI
904 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
905 @retval EFI_INVALID_PARAMETER Buffer is NULL.
906 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
912 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
913 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
920 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
922 Status
= RootBridgeIoCheckParameter (
923 This
, IoOperation
, Width
,
924 Address
, Count
, Buffer
926 if (EFI_ERROR (Status
)) {
930 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
932 // Address passed to CpuIo->Io.Read needs to be a host address instead of
934 return mCpuIo
->Io
.Read (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
935 TO_HOST_ADDRESS (Address
, RootBridge
->Io
.Translation
), Count
, Buffer
);
939 Enables a PCI driver to access PCI controller registers in the PCI root
942 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
943 @param[in] Width Signifies the width of the memory operations.
944 @param[in] Address The base address of the I/O operation. The caller is
945 responsible for aligning the Address if required.
946 @param[in] Count The number of I/O operations to perform. Bytes moved
947 is Width size * Count, starting at Address.
948 @param[in] Buffer For read operations, the destination buffer to store
949 the results. For write operations, the source buffer
952 @retval EFI_SUCCESS The data was read from or written to the PCI
954 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
955 @retval EFI_INVALID_PARAMETER Buffer is NULL.
956 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
961 RootBridgeIoIoWrite (
962 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
963 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
970 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
972 Status
= RootBridgeIoCheckParameter (
973 This
, IoOperation
, Width
,
974 Address
, Count
, Buffer
976 if (EFI_ERROR (Status
)) {
980 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
982 // Address passed to CpuIo->Io.Write needs to be a host address instead of
984 return mCpuIo
->Io
.Write (mCpuIo
, (EFI_CPU_IO_PROTOCOL_WIDTH
) Width
,
985 TO_HOST_ADDRESS (Address
, RootBridge
->Io
.Translation
), Count
, Buffer
);
989 Enables a PCI driver to copy one region of PCI root bridge memory space to
990 another region of PCI root bridge memory space.
992 The CopyMem() function enables a PCI driver to copy one region of PCI root
993 bridge memory space to another region of PCI root bridge memory space. This
994 is especially useful for video scroll operation on a memory mapped video
996 The memory operations are carried out exactly as requested. The caller is
997 responsible for satisfying any alignment and memory width restrictions that a
998 PCI root bridge on a platform might require.
1000 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1002 @param[in] Width Signifies the width of the memory operations.
1003 @param[in] DestAddress The destination address of the memory operation. The
1004 caller is responsible for aligning the DestAddress if
1006 @param[in] SrcAddress The source address of the memory operation. The caller
1007 is responsible for aligning the SrcAddress if
1009 @param[in] Count The number of memory operations to perform. Bytes
1010 moved is Width size * Count, starting at DestAddress
1013 @retval EFI_SUCCESS The data was copied from one memory region
1014 to another memory region.
1015 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1016 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1021 RootBridgeIoCopyMem (
1022 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1023 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
1024 IN UINT64 DestAddress
,
1025 IN UINT64 SrcAddress
,
1035 if ((UINT32
) Width
> EfiPciWidthUint64
) {
1036 return EFI_INVALID_PARAMETER
;
1039 if (DestAddress
== SrcAddress
) {
1043 Stride
= (UINTN
) (1 << Width
);
1046 if ((DestAddress
> SrcAddress
) &&
1047 (DestAddress
< (SrcAddress
+ Count
* Stride
))) {
1049 SrcAddress
= SrcAddress
+ (Count
- 1) * Stride
;
1050 DestAddress
= DestAddress
+ (Count
- 1) * Stride
;
1053 for (Index
= 0; Index
< Count
; Index
++) {
1054 Status
= RootBridgeIoMemRead (
1061 if (EFI_ERROR (Status
)) {
1064 Status
= RootBridgeIoMemWrite (
1071 if (EFI_ERROR (Status
)) {
1075 SrcAddress
+= Stride
;
1076 DestAddress
+= Stride
;
1078 SrcAddress
-= Stride
;
1079 DestAddress
-= Stride
;
1087 PCI configuration space access.
1089 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1090 @param Read TRUE indicating it's a read operation.
1091 @param Width Signifies the width of the memory operation.
1092 @param Address The address within the PCI configuration space
1093 for the PCI controller.
1094 @param Count The number of PCI configuration operations
1096 @param Buffer The destination buffer to store the results.
1098 @retval EFI_SUCCESS The data was read/written from/to the PCI root bridge.
1099 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1103 RootBridgeIoPciAccess (
1104 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1106 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
1113 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1114 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
;
1120 Status
= RootBridgeIoCheckParameter (This
, PciOperation
, Width
, Address
, Count
, Buffer
);
1121 if (EFI_ERROR (Status
)) {
1126 // Read Pci configuration space
1128 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1129 CopyMem (&PciAddress
, &Address
, sizeof (PciAddress
));
1131 if (PciAddress
.ExtendedRegister
== 0) {
1132 PciAddress
.ExtendedRegister
= PciAddress
.Register
;
1135 Address
= PCI_SEGMENT_LIB_ADDRESS (
1136 RootBridge
->RootBridgeIo
.SegmentNumber
,
1139 PciAddress
.Function
,
1140 PciAddress
.ExtendedRegister
1144 // Select loop based on the width of the transfer
1146 InStride
= mInStride
[Width
];
1147 OutStride
= mOutStride
[Width
];
1148 Size
= (UINTN
) (1 << (Width
& 0x03));
1149 for (Uint8Buffer
= Buffer
; Count
> 0; Address
+= InStride
, Uint8Buffer
+= OutStride
, Count
--) {
1151 PciSegmentReadBuffer (Address
, Size
, Uint8Buffer
);
1153 PciSegmentWriteBuffer (Address
, Size
, Uint8Buffer
);
1160 Allows read from PCI configuration space.
1162 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1163 @param Width Signifies the width of the memory operation.
1164 @param Address The address within the PCI configuration space
1165 for the PCI controller.
1166 @param Count The number of PCI configuration operations
1168 @param Buffer The destination buffer to store the results.
1170 @retval EFI_SUCCESS The data was read from the PCI root bridge.
1171 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1175 RootBridgeIoPciRead (
1176 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1177 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
1183 return RootBridgeIoPciAccess (This
, TRUE
, Width
, Address
, Count
, Buffer
);
1187 Allows write to PCI configuration space.
1189 @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1190 @param Width Signifies the width of the memory operation.
1191 @param Address The address within the PCI configuration space
1192 for the PCI controller.
1193 @param Count The number of PCI configuration operations
1195 @param Buffer The source buffer to get the results.
1197 @retval EFI_SUCCESS The data was written to the PCI root bridge.
1198 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1202 RootBridgeIoPciWrite (
1203 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1204 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
1210 return RootBridgeIoPciAccess (This
, FALSE
, Width
, Address
, Count
, Buffer
);
1214 Provides the PCI controller-specific address needed to access
1215 system memory for DMA.
1217 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1218 @param Operation Indicate if the bus master is going to read or write
1220 @param HostAddress The system memory address to map on the PCI controller.
1221 @param NumberOfBytes On input the number of bytes to map.
1222 On output the number of bytes that were mapped.
1223 @param DeviceAddress The resulting map address for the bus master PCI
1224 controller to use to access the system memory's HostAddress.
1225 @param Mapping The value to pass to Unmap() when the bus master DMA
1226 operation is complete.
1228 @retval EFI_SUCCESS Success.
1229 @retval EFI_INVALID_PARAMETER Invalid parameters found.
1230 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
1231 @retval EFI_DEVICE_ERROR The System hardware could not map the requested address.
1232 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.
1237 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1238 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation
,
1239 IN VOID
*HostAddress
,
1240 IN OUT UINTN
*NumberOfBytes
,
1241 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1246 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1247 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1250 if (HostAddress
== NULL
|| NumberOfBytes
== NULL
|| DeviceAddress
== NULL
||
1252 return EFI_INVALID_PARAMETER
;
1256 // Make sure that Operation is valid
1258 if ((UINT32
) Operation
>= EfiPciOperationMaximum
) {
1259 return EFI_INVALID_PARAMETER
;
1262 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1264 if (mIoMmu
!= NULL
) {
1265 if (!RootBridge
->DmaAbove4G
) {
1267 // Clear 64bit support
1269 if (Operation
> EfiPciOperationBusMasterCommonBuffer
) {
1270 Operation
= (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
) (Operation
- EfiPciOperationBusMasterRead64
);
1273 Status
= mIoMmu
->Map (
1275 (EDKII_IOMMU_OPERATION
) Operation
,
1284 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
1285 if ((!RootBridge
->DmaAbove4G
||
1286 (Operation
!= EfiPciOperationBusMasterRead64
&&
1287 Operation
!= EfiPciOperationBusMasterWrite64
&&
1288 Operation
!= EfiPciOperationBusMasterCommonBuffer64
)) &&
1289 ((PhysicalAddress
+ *NumberOfBytes
) > SIZE_4GB
)) {
1292 // If the root bridge or the device cannot handle performing DMA above
1293 // 4GB but any part of the DMA transfer being mapped is above 4GB, then
1294 // map the DMA transfer to a buffer below 4GB.
1297 if (Operation
== EfiPciOperationBusMasterCommonBuffer
||
1298 Operation
== EfiPciOperationBusMasterCommonBuffer64
) {
1300 // Common Buffer operations can not be remapped. If the common buffer
1301 // if above 4GB, then it is not possible to generate a mapping, so return
1304 return EFI_UNSUPPORTED
;
1308 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1311 MapInfo
= AllocatePool (sizeof (MAP_INFO
));
1312 if (MapInfo
== NULL
) {
1314 return EFI_OUT_OF_RESOURCES
;
1318 // Initialize the MAP_INFO structure
1320 MapInfo
->Signature
= MAP_INFO_SIGNATURE
;
1321 MapInfo
->Operation
= Operation
;
1322 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1323 MapInfo
->NumberOfPages
= EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
);
1324 MapInfo
->HostAddress
= PhysicalAddress
;
1325 MapInfo
->MappedHostAddress
= SIZE_4GB
- 1;
1328 // Allocate a buffer below 4GB to map the transfer to.
1330 Status
= gBS
->AllocatePages (
1332 EfiBootServicesData
,
1333 MapInfo
->NumberOfPages
,
1334 &MapInfo
->MappedHostAddress
1336 if (EFI_ERROR (Status
)) {
1343 // If this is a read operation from the Bus Master's point of view,
1344 // then copy the contents of the real buffer into the mapped buffer
1345 // so the Bus Master can read the contents of the real buffer.
1347 if (Operation
== EfiPciOperationBusMasterRead
||
1348 Operation
== EfiPciOperationBusMasterRead64
) {
1350 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1351 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1352 MapInfo
->NumberOfBytes
1356 InsertTailList (&RootBridge
->Maps
, &MapInfo
->Link
);
1359 // The DeviceAddress is the address of the maped buffer below 4GB
1361 *DeviceAddress
= MapInfo
->MappedHostAddress
;
1363 // Return a pointer to the MAP_INFO structure in Mapping
1368 // If the root bridge CAN handle performing DMA above 4GB or
1369 // the transfer is below 4GB, so the DeviceAddress is simply the
1372 *DeviceAddress
= PhysicalAddress
;
1373 *Mapping
= NO_MAPPING
;
1380 Completes the Map() operation and releases any corresponding resources.
1382 The Unmap() function completes the Map() operation and releases any
1383 corresponding resources.
1384 If the operation was an EfiPciOperationBusMasterWrite or
1385 EfiPciOperationBusMasterWrite64, the data is committed to the target system
1387 Any resources used for the mapping are freed.
1389 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1390 @param[in] Mapping The mapping value returned from Map().
1392 @retval EFI_SUCCESS The range was unmapped.
1393 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
1394 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
1399 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1405 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1408 if (mIoMmu
!= NULL
) {
1409 Status
= mIoMmu
->Unmap (
1416 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1419 // See if the Map() operation associated with this Unmap() required a mapping
1420 // buffer. If a mapping buffer was not required, then this function simply
1421 // returns EFI_SUCCESS.
1423 if (Mapping
== NO_MAPPING
) {
1427 MapInfo
= NO_MAPPING
;
1428 for (Link
= GetFirstNode (&RootBridge
->Maps
)
1429 ; !IsNull (&RootBridge
->Maps
, Link
)
1430 ; Link
= GetNextNode (&RootBridge
->Maps
, Link
)
1432 MapInfo
= MAP_INFO_FROM_LINK (Link
);
1433 if (MapInfo
== Mapping
) {
1438 // Mapping is not a valid value returned by Map()
1440 if (MapInfo
!= Mapping
) {
1441 return EFI_INVALID_PARAMETER
;
1443 RemoveEntryList (&MapInfo
->Link
);
1446 // If this is a write operation from the Bus Master's point of view,
1447 // then copy the contents of the mapped buffer into the real buffer
1448 // so the processor can read the contents of the real buffer.
1450 if (MapInfo
->Operation
== EfiPciOperationBusMasterWrite
||
1451 MapInfo
->Operation
== EfiPciOperationBusMasterWrite64
) {
1453 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
1454 (VOID
*) (UINTN
) MapInfo
->MappedHostAddress
,
1455 MapInfo
->NumberOfBytes
1460 // Free the mapped buffer and the MAP_INFO structure.
1462 gBS
->FreePages (MapInfo
->MappedHostAddress
, MapInfo
->NumberOfPages
);
1468 Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
1469 or EfiPciOperationBusMasterCommonBuffer64 mapping.
1471 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1472 @param Type This parameter is not used and must be ignored.
1473 @param MemoryType The type of memory to allocate, EfiBootServicesData or
1474 EfiRuntimeServicesData.
1475 @param Pages The number of pages to allocate.
1476 @param HostAddress A pointer to store the base system memory address of the
1478 @param Attributes The requested bit mask of attributes for the allocated
1479 range. Only the attributes
1480 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
1481 EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
1482 EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
1485 @retval EFI_SUCCESS The requested memory pages were allocated.
1486 @retval EFI_INVALID_PARAMETER MemoryType is invalid.
1487 @retval EFI_INVALID_PARAMETER HostAddress is NULL.
1488 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
1489 attribute bits are MEMORY_WRITE_COMBINE,
1490 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
1491 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1495 RootBridgeIoAllocateBuffer (
1496 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1497 IN EFI_ALLOCATE_TYPE Type
,
1498 IN EFI_MEMORY_TYPE MemoryType
,
1500 OUT VOID
**HostAddress
,
1501 IN UINT64 Attributes
1505 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1506 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1507 EFI_ALLOCATE_TYPE AllocateType
;
1510 // Validate Attributes
1512 if ((Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) != 0) {
1513 return EFI_UNSUPPORTED
;
1517 // Check for invalid inputs
1519 if (HostAddress
== NULL
) {
1520 return EFI_INVALID_PARAMETER
;
1524 // The only valid memory types are EfiBootServicesData and
1525 // EfiRuntimeServicesData
1527 if (MemoryType
!= EfiBootServicesData
&&
1528 MemoryType
!= EfiRuntimeServicesData
) {
1529 return EFI_INVALID_PARAMETER
;
1532 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1534 if (mIoMmu
!= NULL
) {
1535 if (!RootBridge
->DmaAbove4G
) {
1537 // Clear DUAL_ADDRESS_CYCLE
1539 Attributes
&= ~((UINT64
) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1541 Status
= mIoMmu
->AllocateBuffer (
1552 AllocateType
= AllocateAnyPages
;
1553 if (!RootBridge
->DmaAbove4G
||
1554 (Attributes
& EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
1556 // Limit allocations to memory below 4GB
1558 AllocateType
= AllocateMaxAddress
;
1559 PhysicalAddress
= (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1);
1561 Status
= gBS
->AllocatePages (
1567 if (!EFI_ERROR (Status
)) {
1568 *HostAddress
= (VOID
*) (UINTN
) PhysicalAddress
;
1575 Frees memory that was allocated with AllocateBuffer().
1577 The FreeBuffer() function frees memory that was allocated with
1580 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1581 @param Pages The number of pages to free.
1582 @param HostAddress The base system memory address of the allocated range.
1584 @retval EFI_SUCCESS The requested memory pages were freed.
1585 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
1586 Pages was not allocated with AllocateBuffer().
1590 RootBridgeIoFreeBuffer (
1591 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1593 OUT VOID
*HostAddress
1598 if (mIoMmu
!= NULL
) {
1599 Status
= mIoMmu
->FreeBuffer (
1607 return gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
, Pages
);
1611 Flushes all PCI posted write transactions from a PCI host bridge to system
1614 The Flush() function flushes any PCI posted write transactions from a PCI
1615 host bridge to system memory. Posted write transactions are generated by PCI
1616 bus masters when they perform write transactions to target addresses in
1618 This function does not flush posted write transactions from any PCI bridges.
1619 A PCI controller specific action must be taken to guarantee that the posted
1620 write transactions have been flushed from the PCI controller and from all the
1621 PCI bridges into the PCI host bridge. This is typically done with a PCI read
1622 transaction from the PCI controller prior to calling Flush().
1624 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1626 @retval EFI_SUCCESS The PCI posted write transactions were flushed
1627 from the PCI host bridge to system memory.
1628 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed
1629 from the PCI host bridge due to a hardware error.
1634 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
1641 Gets the attributes that a PCI root bridge supports setting with
1642 SetAttributes(), and the attributes that a PCI root bridge is currently
1645 The GetAttributes() function returns the mask of attributes that this PCI
1646 root bridge supports and the mask of attributes that the PCI root bridge is
1649 @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1650 @param Supported A pointer to the mask of attributes that this PCI root
1651 bridge supports setting with SetAttributes().
1652 @param Attributes A pointer to the mask of attributes that this PCI root
1653 bridge is currently using.
1655 @retval EFI_SUCCESS If Supports is not NULL, then the attributes
1656 that the PCI root bridge supports is returned
1657 in Supports. If Attributes is not NULL, then
1658 the attributes that the PCI root bridge is
1659 currently using is returned in Attributes.
1660 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1664 RootBridgeIoGetAttributes (
1665 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1666 OUT UINT64
*Supported
,
1667 OUT UINT64
*Attributes
1670 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1672 if (Attributes
== NULL
&& Supported
== NULL
) {
1673 return EFI_INVALID_PARAMETER
;
1676 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1678 // Set the return value for Supported and Attributes
1680 if (Supported
!= NULL
) {
1681 *Supported
= RootBridge
->Supports
;
1684 if (Attributes
!= NULL
) {
1685 *Attributes
= RootBridge
->Attributes
;
1692 Sets attributes for a resource range on a PCI root bridge.
1694 The SetAttributes() function sets the attributes specified in Attributes for
1695 the PCI root bridge on the resource range specified by ResourceBase and
1696 ResourceLength. Since the granularity of setting these attributes may vary
1697 from resource type to resource type, and from platform to platform, the
1698 actual resource range and the one passed in by the caller may differ. As a
1699 result, this function may set the attributes specified by Attributes on a
1700 larger resource range than the caller requested. The actual range is returned
1701 in ResourceBase and ResourceLength. The caller is responsible for verifying
1702 that the actual range for which the attributes were set is acceptable.
1704 @param This A pointer to the
1705 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1706 @param Attributes The mask of attributes to set. If the
1707 attribute bit MEMORY_WRITE_COMBINE,
1708 MEMORY_CACHED, or MEMORY_DISABLE is set,
1709 then the resource range is specified by
1710 ResourceBase and ResourceLength. If
1711 MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
1712 MEMORY_DISABLE are not set, then
1713 ResourceBase and ResourceLength are ignored,
1715 @param ResourceBase A pointer to the base address of the
1716 resource range to be modified by the
1717 attributes specified by Attributes.
1718 @param ResourceLength A pointer to the length of the resource
1719 range to be modified by the attributes
1720 specified by Attributes.
1722 @retval EFI_SUCCESS The current configuration of this PCI root bridge
1723 was returned in Resources.
1724 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
1725 could not be retrieved.
1729 RootBridgeIoSetAttributes (
1730 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1731 IN UINT64 Attributes
,
1732 IN OUT UINT64
*ResourceBase
,
1733 IN OUT UINT64
*ResourceLength
1736 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1738 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1740 if ((Attributes
& (~RootBridge
->Supports
)) != 0) {
1741 return EFI_UNSUPPORTED
;
1744 RootBridge
->Attributes
= Attributes
;
1749 Retrieves the current resource settings of this PCI root bridge in the form
1750 of a set of ACPI resource descriptors.
1752 There are only two resource descriptor types from the ACPI Specification that
1753 may be used to describe the current resources allocated to a PCI root bridge.
1754 These are the QWORD Address Space Descriptor, and the End Tag. The QWORD
1755 Address Space Descriptor can describe memory, I/O, and bus number ranges for
1756 dynamic or fixed resources. The configuration of a PCI root bridge is described
1757 with one or more QWORD Address Space Descriptors followed by an End Tag.
1759 @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1760 @param[out] Resources A pointer to the resource descriptors that
1761 describe the current configuration of this PCI root
1762 bridge. The storage for the resource
1763 descriptors is allocated by this function. The
1764 caller must treat the return buffer as read-only
1765 data, and the buffer must not be freed by the
1768 @retval EFI_SUCCESS The current configuration of this PCI root bridge
1769 was returned in Resources.
1770 @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
1771 could not be retrieved.
1775 RootBridgeIoConfiguration (
1776 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*This
,
1777 OUT VOID
**Resources
1780 PCI_RESOURCE_TYPE Index
;
1781 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1782 PCI_RES_NODE
*ResAllocNode
;
1783 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1784 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1787 // Get this instance of the Root Bridge.
1789 RootBridge
= ROOT_BRIDGE_FROM_THIS (This
);
1791 RootBridge
->ConfigBuffer
,
1792 TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1794 Descriptor
= RootBridge
->ConfigBuffer
;
1795 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
1797 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
1799 if (ResAllocNode
->Status
!= ResAllocated
) {
1803 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1804 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1805 // According to UEFI 2.7, RootBridgeIo->Configuration should return address
1806 // range in CPU view (host address), and ResAllocNode->Base is already a CPU
1807 // view address (host address).
1808 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
1809 Descriptor
->AddrRangeMax
= ResAllocNode
->Base
+ ResAllocNode
->Length
- 1;
1810 Descriptor
->AddrLen
= ResAllocNode
->Length
;
1811 Descriptor
->AddrTranslationOffset
= GetTranslationByResourceType (
1816 switch (ResAllocNode
->Type
) {
1819 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1823 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1825 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1826 Descriptor
->AddrSpaceGranularity
= 32;
1830 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1832 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1833 Descriptor
->AddrSpaceGranularity
= 64;
1837 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1847 // Terminate the entries.
1849 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1850 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1851 End
->Checksum
= 0x0;
1853 *Resources
= RootBridge
->ConfigBuffer
;