3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "NonDiscoverablePciDeviceIo.h"
12 #include <Library/DxeServicesTableLib.h>
14 #include <IndustryStandard/Acpi.h>
16 #include <Protocol/PciRootBridgeIo.h>
19 EFI_PHYSICAL_ADDRESS AllocAddress
;
21 EFI_PCI_IO_PROTOCOL_OPERATION Operation
;
23 } NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
;
26 Get the resource associated with BAR number 'BarIndex'.
28 @param Dev Point to the NON_DISCOVERABLE_PCI_DEVICE instance.
29 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
30 base address for the memory operation to perform.
31 @param Descriptor Points to the address space descriptor
36 IN NON_DISCOVERABLE_PCI_DEVICE
*Dev
,
38 OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptor
41 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
43 if (BarIndex
< Dev
->BarOffset
) {
47 BarIndex
-= (UINT8
)Dev
->BarOffset
;
49 if (BarIndex
>= Dev
->BarCount
) {
50 return EFI_UNSUPPORTED
;
53 for (Desc
= Dev
->Device
->Resources
;
54 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
55 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3))
69 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
70 satisfied or after a defined duration.
72 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
73 @param Width Signifies the width of the memory or I/O operations.
74 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
75 base address for the memory operation to perform.
76 @param Offset The offset within the selected BAR to start the memory operation.
77 @param Mask Mask used for the polling criteria.
78 @param Value The comparison value used for the polling exit criteria.
79 @param Delay The number of 100 ns units to poll.
80 @param Result Pointer to the last value read from the memory location.
87 IN EFI_PCI_IO_PROTOCOL
*This
,
88 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
97 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
98 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
102 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
103 return EFI_INVALID_PARAMETER
;
106 if (Result
== NULL
) {
107 return EFI_INVALID_PARAMETER
;
110 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
113 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
114 if (EFI_ERROR (Status
)) {
118 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
119 return EFI_UNSUPPORTED
;
123 return EFI_UNSUPPORTED
;
127 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
128 satisfied or after a defined duration.
130 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
131 @param Width Signifies the width of the memory or I/O operations.
132 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
133 base address for the memory operation to perform.
134 @param Offset The offset within the selected BAR to start the memory operation.
135 @param Mask Mask used for the polling criteria.
136 @param Value The comparison value used for the polling exit criteria.
137 @param Delay The number of 100 ns units to poll.
138 @param Result Pointer to the last value read from the memory location.
145 IN EFI_PCI_IO_PROTOCOL
*This
,
146 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
155 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
156 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
160 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
161 return EFI_INVALID_PARAMETER
;
164 if (Result
== NULL
) {
165 return EFI_INVALID_PARAMETER
;
168 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
171 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
172 if (EFI_ERROR (Status
)) {
176 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
177 return EFI_UNSUPPORTED
;
181 return EFI_UNSUPPORTED
;
185 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
187 @param Width Signifies the width of the memory or I/O operations.
188 @param Count The number of memory or I/O operations to perform.
189 @param DstStride The stride of the destination buffer.
190 @param Dst For read operations, the destination buffer to store the results. For write
191 operations, the destination buffer to write data to.
192 @param SrcStride The stride of the source buffer.
193 @param Src For read operations, the source buffer to read data from. For write
194 operations, the source buffer to write data from.
196 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
197 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
204 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
212 volatile UINT8
*Dst8
;
213 volatile UINT16
*Dst16
;
214 volatile UINT32
*Dst32
;
215 volatile CONST UINT8
*Src8
;
216 volatile CONST UINT16
*Src16
;
217 volatile CONST UINT32
*Src32
;
220 // Loop for each iteration and move the data
222 switch (Width
& 0x3) {
223 case EfiPciWidthUint8
:
226 for ( ; Count
> 0; Count
--, Dst8
+= DstStride
, Src8
+= SrcStride
) {
231 case EfiPciWidthUint16
:
232 Dst16
= (UINT16
*)Dst
;
233 Src16
= (UINT16
*)Src
;
234 for ( ; Count
> 0; Count
--, Dst16
+= DstStride
, Src16
+= SrcStride
) {
239 case EfiPciWidthUint32
:
240 Dst32
= (UINT32
*)Dst
;
241 Src32
= (UINT32
*)Src
;
242 for ( ; Count
> 0; Count
--, Dst32
+= DstStride
, Src32
+= SrcStride
) {
248 return EFI_INVALID_PARAMETER
;
255 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
257 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
258 @param Width Signifies the width of the memory or I/O operations.
259 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
260 base address for the memory or I/O operation to perform.
261 @param Offset The offset within the selected BAR to start the memory or I/O operation.
262 @param Count The number of memory or I/O operations to perform.
263 @param Buffer For read operations, the destination buffer to store the results. For write
264 operations, the source buffer to write data from.
266 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
267 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
268 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
269 valid for the PCI BAR specified by BarIndex.
270 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
271 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
278 IN EFI_PCI_IO_PROTOCOL
*This
,
279 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
286 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
289 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
292 if (Buffer
== NULL
) {
293 return EFI_INVALID_PARAMETER
;
296 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
299 // Only allow accesses to the BARs we emulate
301 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
302 if (EFI_ERROR (Status
)) {
306 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
307 return EFI_UNSUPPORTED
;
310 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
311 AlignMask
= (1 << (Width
& 0x03)) - 1;
312 if ((UINTN
)Address
& AlignMask
) {
313 return EFI_INVALID_PARAMETER
;
317 case EfiPciIoWidthUint8
:
318 case EfiPciIoWidthUint16
:
319 case EfiPciIoWidthUint32
:
320 case EfiPciIoWidthUint64
:
321 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
323 case EfiPciIoWidthFifoUint8
:
324 case EfiPciIoWidthFifoUint16
:
325 case EfiPciIoWidthFifoUint32
:
326 case EfiPciIoWidthFifoUint64
:
327 return PciIoMemRW (Width
, Count
, 1, Buffer
, 0, Address
);
329 case EfiPciIoWidthFillUint8
:
330 case EfiPciIoWidthFillUint16
:
331 case EfiPciIoWidthFillUint32
:
332 case EfiPciIoWidthFillUint64
:
333 return PciIoMemRW (Width
, Count
, 0, Buffer
, 1, Address
);
339 return EFI_INVALID_PARAMETER
;
343 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
345 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
346 @param Width Signifies the width of the memory or I/O operations.
347 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
348 base address for the memory or I/O operation to perform.
349 @param Offset The offset within the selected BAR to start the memory or I/O operation.
350 @param Count The number of memory or I/O operations to perform.
351 @param Buffer For read operations, the destination buffer to store the results. For write
352 operations, the source buffer to write data from.
354 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
355 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
356 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
357 valid for the PCI BAR specified by BarIndex.
358 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
359 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
366 IN EFI_PCI_IO_PROTOCOL
*This
,
367 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
374 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
377 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
380 if (Buffer
== NULL
) {
381 return EFI_INVALID_PARAMETER
;
384 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
387 // Only allow accesses to the BARs we emulate
389 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
390 if (EFI_ERROR (Status
)) {
394 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
395 return EFI_UNSUPPORTED
;
398 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
399 AlignMask
= (1 << (Width
& 0x03)) - 1;
400 if ((UINTN
)Address
& AlignMask
) {
401 return EFI_INVALID_PARAMETER
;
405 case EfiPciIoWidthUint8
:
406 case EfiPciIoWidthUint16
:
407 case EfiPciIoWidthUint32
:
408 case EfiPciIoWidthUint64
:
409 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
411 case EfiPciIoWidthFifoUint8
:
412 case EfiPciIoWidthFifoUint16
:
413 case EfiPciIoWidthFifoUint32
:
414 case EfiPciIoWidthFifoUint64
:
415 return PciIoMemRW (Width
, Count
, 0, Address
, 1, Buffer
);
417 case EfiPciIoWidthFillUint8
:
418 case EfiPciIoWidthFillUint16
:
419 case EfiPciIoWidthFillUint32
:
420 case EfiPciIoWidthFillUint64
:
421 return PciIoMemRW (Width
, Count
, 1, Address
, 0, Buffer
);
427 return EFI_INVALID_PARAMETER
;
431 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
433 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
434 @param Width Signifies the width of the memory or I/O operations.
435 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
436 base address for the memory or I/O operation to perform.
437 @param Offset The offset within the selected BAR to start the memory or I/O operation.
438 @param Count The number of memory or I/O operations to perform.
439 @param Buffer For read operations, the destination buffer to store the results. For write
440 operations, the source buffer to write data from.
447 IN EFI_PCI_IO_PROTOCOL
*This
,
448 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
455 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
456 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
459 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
460 return EFI_INVALID_PARAMETER
;
463 if (Buffer
== NULL
) {
464 return EFI_INVALID_PARAMETER
;
467 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
469 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
470 if (EFI_ERROR (Status
)) {
474 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
475 return EFI_UNSUPPORTED
;
479 return EFI_UNSUPPORTED
;
483 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
485 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
486 @param Width Signifies the width of the memory or I/O operations.
487 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
488 base address for the memory or I/O operation to perform.
489 @param Offset The offset within the selected BAR to start the memory or I/O operation.
490 @param Count The number of memory or I/O operations to perform.
491 @param Buffer For read operations, the destination buffer to store the results. For write
492 operations, the source buffer to write data from.
499 IN EFI_PCI_IO_PROTOCOL
*This
,
500 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
507 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
508 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
511 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
512 return EFI_INVALID_PARAMETER
;
515 if (Buffer
== NULL
) {
516 return EFI_INVALID_PARAMETER
;
519 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
521 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
522 if (EFI_ERROR (Status
)) {
526 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
527 return EFI_UNSUPPORTED
;
531 return EFI_UNSUPPORTED
;
535 Enable a PCI driver to access PCI config space.
537 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
538 @param Width Signifies the width of the memory or I/O operations.
539 @param Offset The offset within the selected BAR to start the memory or I/O operation.
540 @param Count The number of memory or I/O operations to perform.
541 @param Buffer For read operations, the destination buffer to store the results. For write
542 operations, the source buffer to write data from.
549 IN EFI_PCI_IO_PROTOCOL
*This
,
550 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
556 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
560 if ((Width
< 0) || (Width
>= EfiPciIoWidthMaximum
) || (Buffer
== NULL
)) {
561 return EFI_INVALID_PARAMETER
;
564 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
565 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
566 Length
= Count
<< ((UINTN
)Width
& 0x3);
568 if (Offset
>= sizeof (Dev
->ConfigSpace
)) {
569 ZeroMem (Buffer
, Length
);
573 if (Offset
+ Length
> sizeof (Dev
->ConfigSpace
)) {
575 // Read all zeroes for config space accesses beyond the first
578 Length
-= sizeof (Dev
->ConfigSpace
) - Offset
;
579 ZeroMem ((UINT8
*)Buffer
+ sizeof (Dev
->ConfigSpace
) - Offset
, Length
);
581 Count
-= Length
>> ((UINTN
)Width
& 0x3);
584 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
588 Enable a PCI driver to access PCI config space.
590 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
591 @param Width Signifies the width of the memory or I/O operations.
592 @param Offset The offset within the selected BAR to start the memory or I/O operation.
593 @param Count The number of memory or I/O operations to perform.
594 @param Buffer For read operations, the destination buffer to store the results. For write
595 operations, the source buffer to write data from
597 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
598 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
599 valid for the PCI BAR specified by BarIndex.
600 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
607 IN EFI_PCI_IO_PROTOCOL
*This
,
608 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
614 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
617 if ((Width
< 0) || (Width
>= EfiPciIoWidthMaximum
) || (Buffer
== NULL
)) {
618 return EFI_INVALID_PARAMETER
;
621 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
622 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
624 if (Offset
+ (Count
<< ((UINTN
)Width
& 0x3)) > sizeof (Dev
->ConfigSpace
)) {
625 return EFI_UNSUPPORTED
;
628 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
632 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
635 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
636 @param Width Signifies the width of the memory operations.
637 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
638 base address for the memory operation to perform.
639 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
640 start the memory writes for the copy operation.
641 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
642 base address for the memory operation to perform.
643 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
644 the memory reads for the copy operation.
645 @param Count The number of memory operations to perform. Bytes moved is Width
646 size * Count, starting at DestOffset and SrcOffset.
653 IN EFI_PCI_IO_PROTOCOL
*This
,
654 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
655 IN UINT8 DestBarIndex
,
656 IN UINT64 DestOffset
,
657 IN UINT8 SrcBarIndex
,
662 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
663 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*DestDesc
;
664 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*SrcDesc
;
667 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
668 return EFI_INVALID_PARAMETER
;
671 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
673 Status
= GetBarResource (Dev
, DestBarIndex
, &DestDesc
);
674 if (EFI_ERROR (Status
)) {
678 if (DestOffset
+ (Count
<< (Width
& 0x3)) > DestDesc
->AddrLen
) {
679 return EFI_UNSUPPORTED
;
682 Status
= GetBarResource (Dev
, SrcBarIndex
, &SrcDesc
);
683 if (EFI_ERROR (Status
)) {
687 if (SrcOffset
+ (Count
<< (Width
& 0x3)) > SrcDesc
->AddrLen
) {
688 return EFI_UNSUPPORTED
;
692 return EFI_UNSUPPORTED
;
696 Provides the PCI controller-specific addresses needed to access system memory.
698 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
699 @param Operation Indicates if the bus master is going to read or write to system memory.
700 @param HostAddress The system memory address to map to the PCI controller.
701 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
703 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
704 access the hosts HostAddress.
705 @param Mapping A resulting value to pass to Unmap().
707 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
708 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
709 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
710 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
711 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
718 IN EFI_PCI_IO_PROTOCOL
*This
,
719 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
720 IN VOID
*HostAddress
,
721 IN OUT UINTN
*NumberOfBytes
,
722 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
726 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
728 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
730 if ((Operation
!= EfiPciIoOperationBusMasterRead
) &&
731 (Operation
!= EfiPciIoOperationBusMasterWrite
) &&
732 (Operation
!= EfiPciIoOperationBusMasterCommonBuffer
))
734 return EFI_INVALID_PARAMETER
;
737 if ((HostAddress
== NULL
) ||
738 (NumberOfBytes
== NULL
) ||
739 (DeviceAddress
== NULL
) ||
742 return EFI_INVALID_PARAMETER
;
746 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
747 // addressing, we need to allocate a bounce buffer and copy over the data.
749 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
750 if (((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) &&
751 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
))
754 // Bounce buffering is not possible for consistent mappings
756 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
757 return EFI_UNSUPPORTED
;
760 MapInfo
= AllocatePool (sizeof *MapInfo
);
761 if (MapInfo
== NULL
) {
762 return EFI_OUT_OF_RESOURCES
;
765 MapInfo
->AllocAddress
= MAX_UINT32
;
766 MapInfo
->HostAddress
= HostAddress
;
767 MapInfo
->Operation
= Operation
;
768 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
770 Status
= gBS
->AllocatePages (
773 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
774 &MapInfo
->AllocAddress
776 if (EFI_ERROR (Status
)) {
778 // If we fail here, it is likely because the system has no memory below
779 // 4 GB to begin with. There is not much we can do about that other than
780 // fail the map request.
783 return EFI_DEVICE_ERROR
;
786 if (Operation
== EfiPciIoOperationBusMasterRead
) {
788 (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
794 *DeviceAddress
= MapInfo
->AllocAddress
;
797 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
805 Completes the Map() operation and releases any corresponding resources.
807 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
808 @param Mapping The mapping value returned from Map().
810 @retval EFI_SUCCESS The range was unmapped.
817 IN EFI_PCI_IO_PROTOCOL
*This
,
821 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
824 if (MapInfo
!= NULL
) {
825 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
827 MapInfo
->HostAddress
,
828 (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
829 MapInfo
->NumberOfBytes
834 MapInfo
->AllocAddress
,
835 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
)
846 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
847 @param Type This parameter is not used and must be ignored.
848 @param MemoryType The type of memory to allocate, EfiBootServicesData or
849 EfiRuntimeServicesData.
850 @param Pages The number of pages to allocate.
851 @param HostAddress A pointer to store the base system memory address of the
853 @param Attributes The requested bit mask of attributes for the allocated range.
855 @retval EFI_SUCCESS The requested memory pages were allocated.
856 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
857 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
858 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
859 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
865 CoherentPciIoAllocateBuffer (
866 IN EFI_PCI_IO_PROTOCOL
*This
,
867 IN EFI_ALLOCATE_TYPE Type
,
868 IN EFI_MEMORY_TYPE MemoryType
,
870 OUT VOID
**HostAddress
,
874 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
875 EFI_PHYSICAL_ADDRESS AllocAddress
;
876 EFI_ALLOCATE_TYPE AllocType
;
879 if ((Attributes
& ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
880 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
)) != 0)
882 return EFI_UNSUPPORTED
;
885 if (HostAddress
== NULL
) {
886 return EFI_INVALID_PARAMETER
;
889 if ((MemoryType
!= EfiBootServicesData
) &&
890 (MemoryType
!= EfiRuntimeServicesData
))
892 return EFI_INVALID_PARAMETER
;
896 // Allocate below 4 GB if the dual address cycle attribute has not
897 // been set. If the system has no memory available below 4 GB, there
898 // is little we can do except propagate the error.
900 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
901 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
902 AllocAddress
= MAX_UINT32
;
903 AllocType
= AllocateMaxAddress
;
905 AllocType
= AllocateAnyPages
;
908 Status
= gBS
->AllocatePages (AllocType
, MemoryType
, Pages
, &AllocAddress
);
909 if (!EFI_ERROR (Status
)) {
910 *HostAddress
= (VOID
*)(UINTN
)AllocAddress
;
917 Frees memory that was allocated in function CoherentPciIoAllocateBuffer ().
919 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
920 @param Pages The number of pages to free.
921 @param HostAddress The base system memory address of the allocated range.
923 @retval EFI_SUCCESS The requested memory pages were freed.
929 CoherentPciIoFreeBuffer (
930 IN EFI_PCI_IO_PROTOCOL
*This
,
935 FreePages (HostAddress
, Pages
);
940 Frees memory that was allocated in function NonCoherentPciIoAllocateBuffer ().
942 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
943 @param Pages The number of pages to free.
944 @param HostAddress The base system memory address of the allocated range.
946 @retval EFI_SUCCESS The requested memory pages were freed.
947 @retval others The operation contain some errors.
953 NonCoherentPciIoFreeBuffer (
954 IN EFI_PCI_IO_PROTOCOL
*This
,
959 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
962 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
963 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*AllocHead
;
964 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*AllocTail
;
969 if (HostAddress
!= ALIGN_POINTER (HostAddress
, EFI_PAGE_SIZE
)) {
970 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
971 return EFI_INVALID_PARAMETER
;
974 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
983 // Find the uncached allocation list entry associated
984 // with this allocation
986 for (Entry
= Dev
->UncachedAllocationList
.ForwardLink
;
987 Entry
!= &Dev
->UncachedAllocationList
;
988 Entry
= Entry
->ForwardLink
)
990 Alloc
= BASE_CR (Entry
, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
, List
);
993 if (Alloc
->HostAddress
< HostAddress
) {
994 StartPages
= EFI_SIZE_TO_PAGES (
995 (UINTN
)HostAddress
- (UINTN
)Alloc
->HostAddress
999 if ((Alloc
->HostAddress
<= HostAddress
) &&
1000 (Alloc
->NumPages
>= (Pages
+ StartPages
)))
1003 // We are freeing at least part of what we were given
1004 // before by AllocateBuffer()
1012 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
1013 return EFI_NOT_FOUND
;
1016 EndPages
= Alloc
->NumPages
- (Pages
+ StartPages
);
1018 if (StartPages
!= 0) {
1019 AllocHead
= AllocatePool (sizeof *AllocHead
);
1020 if (AllocHead
== NULL
) {
1021 return EFI_OUT_OF_RESOURCES
;
1024 AllocHead
->HostAddress
= Alloc
->HostAddress
;
1026 AllocHead
->NumPages
= StartPages
;
1027 AllocHead
->Attributes
= Alloc
->Attributes
;
1030 if (EndPages
!= 0) {
1031 AllocTail
= AllocatePool (sizeof *AllocTail
);
1032 if (AllocTail
== NULL
) {
1033 return EFI_OUT_OF_RESOURCES
;
1036 AllocTail
->HostAddress
= (UINT8
*)Alloc
->HostAddress
+
1037 EFI_PAGES_TO_SIZE (Pages
+ StartPages
);
1039 AllocTail
->NumPages
= EndPages
;
1040 AllocTail
->Attributes
= Alloc
->Attributes
;
1043 RemoveEntryList (&Alloc
->List
);
1045 // Record this new sub allocations in the linked list, so we
1046 // can restore the memory space attributes later
1048 if (AllocHead
!= NULL
) {
1049 InsertHeadList (&Dev
->UncachedAllocationList
, &AllocHead
->List
);
1052 if (AllocTail
!= NULL
) {
1053 InsertHeadList (&Dev
->UncachedAllocationList
, &AllocTail
->List
);
1056 Status
= gDS
->SetMemorySpaceAttributes (
1057 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1058 EFI_PAGES_TO_SIZE (Pages
),
1061 if (EFI_ERROR (Status
)) {
1066 // If we fail to restore the original attributes, it is better to leak the
1067 // memory than to return it to the heap
1069 FreePages (HostAddress
, Pages
);
1079 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1080 @param Type This parameter is not used and must be ignored.
1081 @param MemoryType The type of memory to allocate, EfiBootServicesData or
1082 EfiRuntimeServicesData.
1083 @param Pages The number of pages to allocate.
1084 @param HostAddress A pointer to store the base system memory address of the
1086 @param Attributes The requested bit mask of attributes for the allocated range.
1088 @retval EFI_SUCCESS The requested memory pages were allocated.
1089 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
1090 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
1091 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1092 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1098 NonCoherentPciIoAllocateBuffer (
1099 IN EFI_PCI_IO_PROTOCOL
*This
,
1100 IN EFI_ALLOCATE_TYPE Type
,
1101 IN EFI_MEMORY_TYPE MemoryType
,
1103 OUT VOID
**HostAddress
,
1104 IN UINT64 Attributes
1107 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1108 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1111 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
1114 if (HostAddress
== NULL
) {
1115 return EFI_INVALID_PARAMETER
;
1118 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1120 Status
= CoherentPciIoAllocateBuffer (
1128 if (EFI_ERROR (Status
)) {
1132 Status
= gDS
->GetMemorySpaceDescriptor (
1133 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1136 if (EFI_ERROR (Status
)) {
1140 if ((GcdDescriptor
.Capabilities
& (EFI_MEMORY_WC
| EFI_MEMORY_UC
)) == 0) {
1141 Status
= EFI_UNSUPPORTED
;
1146 // Set the preferred memory attributes
1148 if (((Attributes
& EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
) != 0) ||
1149 ((GcdDescriptor
.Capabilities
& EFI_MEMORY_UC
) == 0))
1152 // Use write combining if it was requested, or if it is the only
1153 // type supported by the region.
1155 MemType
= EFI_MEMORY_WC
;
1157 MemType
= EFI_MEMORY_UC
;
1160 Alloc
= AllocatePool (sizeof *Alloc
);
1161 if (Alloc
== NULL
) {
1165 Alloc
->HostAddress
= AllocAddress
;
1166 Alloc
->NumPages
= Pages
;
1167 Alloc
->Attributes
= GcdDescriptor
.Attributes
;
1170 // Record this allocation in the linked list, so we
1171 // can restore the memory space attributes later
1173 InsertHeadList (&Dev
->UncachedAllocationList
, &Alloc
->List
);
1175 Status
= gDS
->SetMemorySpaceAttributes (
1176 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1177 EFI_PAGES_TO_SIZE (Pages
),
1180 if (EFI_ERROR (Status
)) {
1184 Status
= mCpu
->FlushDataCache (
1186 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1187 EFI_PAGES_TO_SIZE (Pages
),
1188 EfiCpuFlushTypeInvalidate
1190 if (EFI_ERROR (Status
)) {
1194 *HostAddress
= AllocAddress
;
1199 RemoveEntryList (&Alloc
->List
);
1203 CoherentPciIoFreeBuffer (This
, Pages
, AllocAddress
);
1208 Provides the PCI controller-specific addresses needed to access system memory.
1210 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1211 @param Operation Indicates if the bus master is going to read or write to system memory.
1212 @param HostAddress The system memory address to map to the PCI controller.
1213 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
1215 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
1216 access the hosts HostAddress.
1217 @param Mapping A resulting value to pass to Unmap().
1219 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1220 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
1221 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1222 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1223 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1229 NonCoherentPciIoMap (
1230 IN EFI_PCI_IO_PROTOCOL
*This
,
1231 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
1232 IN VOID
*HostAddress
,
1233 IN OUT UINTN
*NumberOfBytes
,
1234 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1238 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1240 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1243 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1246 if ((HostAddress
== NULL
) ||
1247 (NumberOfBytes
== NULL
) ||
1248 (DeviceAddress
== NULL
) ||
1251 return EFI_INVALID_PARAMETER
;
1254 if ((Operation
!= EfiPciIoOperationBusMasterRead
) &&
1255 (Operation
!= EfiPciIoOperationBusMasterWrite
) &&
1256 (Operation
!= EfiPciIoOperationBusMasterCommonBuffer
))
1258 return EFI_INVALID_PARAMETER
;
1261 MapInfo
= AllocatePool (sizeof *MapInfo
);
1262 if (MapInfo
== NULL
) {
1263 return EFI_OUT_OF_RESOURCES
;
1266 MapInfo
->HostAddress
= HostAddress
;
1267 MapInfo
->Operation
= Operation
;
1268 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1270 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1273 // If this device does not support 64-bit DMA addressing, we need to allocate
1274 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
1276 Bounce
= ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
1277 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
);
1280 switch (Operation
) {
1281 case EfiPciIoOperationBusMasterRead
:
1282 case EfiPciIoOperationBusMasterWrite
:
1284 // For streaming DMA, it is sufficient if the buffer is aligned to
1285 // the CPUs DMA buffer alignment.
1287 AlignMask
= mCpu
->DmaBufferAlignment
- 1;
1288 if ((((UINTN
)HostAddress
| *NumberOfBytes
) & AlignMask
) == 0) {
1294 case EfiPciIoOperationBusMasterCommonBuffer
:
1296 // Check whether the host address refers to an uncached mapping.
1298 Status
= gDS
->GetMemorySpaceDescriptor (
1299 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1302 if (EFI_ERROR (Status
) ||
1303 ((GcdDescriptor
.Attributes
& (EFI_MEMORY_WB
|EFI_MEMORY_WT
)) != 0))
1316 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
1317 Status
= EFI_DEVICE_ERROR
;
1321 Status
= NonCoherentPciIoAllocateBuffer (
1324 EfiBootServicesData
,
1325 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1327 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
1329 if (EFI_ERROR (Status
)) {
1333 MapInfo
->AllocAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
;
1334 if (Operation
== EfiPciIoOperationBusMasterRead
) {
1335 gBS
->CopyMem (AllocAddress
, HostAddress
, *NumberOfBytes
);
1338 *DeviceAddress
= MapInfo
->AllocAddress
;
1340 MapInfo
->AllocAddress
= 0;
1341 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
1344 // We are not using a bounce buffer: the mapping is sufficiently
1345 // aligned to allow us to simply flush the caches. Note that cleaning
1346 // the caches is necessary for both data directions:
1347 // - for bus master read, we want the latest data to be present
1349 // - for bus master write, we don't want any stale dirty cachelines that
1350 // may be written back unexpectedly, and clobber the data written to
1351 // main memory by the device.
1353 mCpu
->FlushDataCache (
1355 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1357 EfiCpuFlushTypeWriteBack
1371 Completes the Map() operation and releases any corresponding resources.
1373 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1374 @param Mapping The mapping value returned from Map().
1376 @retval EFI_SUCCESS The range was unmapped.
1382 NonCoherentPciIoUnmap (
1383 IN EFI_PCI_IO_PROTOCOL
*This
,
1387 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1389 if (Mapping
== NULL
) {
1390 return EFI_DEVICE_ERROR
;
1394 if (MapInfo
->AllocAddress
!= 0) {
1396 // We are using a bounce buffer: copy back the data if necessary,
1397 // and free the buffer.
1399 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1401 MapInfo
->HostAddress
,
1402 (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
1403 MapInfo
->NumberOfBytes
1407 NonCoherentPciIoFreeBuffer (
1409 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1410 (VOID
*)(UINTN
)MapInfo
->AllocAddress
1414 // We are *not* using a bounce buffer: if this is a bus master write,
1415 // we have to invalidate the caches so the CPU will see the uncached
1416 // data written by the device.
1418 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1419 mCpu
->FlushDataCache (
1421 (EFI_PHYSICAL_ADDRESS
)(UINTN
)MapInfo
->HostAddress
,
1422 MapInfo
->NumberOfBytes
,
1423 EfiCpuFlushTypeInvalidate
1433 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1435 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1442 IN EFI_PCI_IO_PROTOCOL
*This
1449 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1451 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1452 @param SegmentNumber The PCI controller's current PCI segment number.
1453 @param BusNumber The PCI controller's current PCI bus number.
1454 @param DeviceNumber The PCI controller's current PCI device number.
1455 @param FunctionNumber The PCI controller's current PCI function number.
1457 @retval EFI_SUCCESS The PCI controller location was returned.
1458 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1465 IN EFI_PCI_IO_PROTOCOL
*This
,
1466 OUT UINTN
*SegmentNumber
,
1467 OUT UINTN
*BusNumber
,
1468 OUT UINTN
*DeviceNumber
,
1469 OUT UINTN
*FunctionNumber
1472 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1474 if ((SegmentNumber
== NULL
) ||
1475 (BusNumber
== NULL
) ||
1476 (DeviceNumber
== NULL
) ||
1477 (FunctionNumber
== NULL
))
1479 return EFI_INVALID_PARAMETER
;
1482 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1484 *SegmentNumber
= 0xff;
1485 *BusNumber
= Dev
->UniqueId
>> 5;
1486 *DeviceNumber
= Dev
->UniqueId
& 0x1f;
1487 *FunctionNumber
= 0;
1493 Performs an operation on the attributes that this PCI controller supports. The operations include
1494 getting the set of supported attributes, retrieving the current attributes, setting the current
1495 attributes, enabling attributes, and disabling attributes.
1497 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1498 @param Operation The operation to perform on the attributes for this PCI controller.
1499 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1501 @param Result A pointer to the result mask of attributes that are returned for the Get
1502 and Supported operations.
1504 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1505 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1506 @retval EFI_UNSUPPORTED one or more of the bits set in
1507 Attributes are not supported by this PCI controller or one of
1508 its parent bridges when Operation is Set, Enable or Disable.
1515 IN EFI_PCI_IO_PROTOCOL
*This
,
1516 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1517 IN UINT64 Attributes
,
1518 OUT UINT64
*Result OPTIONAL
1521 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1524 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1526 if ((Attributes
& (~(DEV_SUPPORTED_ATTRIBUTES
))) != 0) {
1527 return EFI_UNSUPPORTED
;
1531 switch (Operation
) {
1532 case EfiPciIoAttributeOperationGet
:
1533 if (Result
== NULL
) {
1534 return EFI_INVALID_PARAMETER
;
1537 *Result
= Dev
->Attributes
;
1540 case EfiPciIoAttributeOperationSupported
:
1541 if (Result
== NULL
) {
1542 return EFI_INVALID_PARAMETER
;
1545 *Result
= DEV_SUPPORTED_ATTRIBUTES
;
1548 case EfiPciIoAttributeOperationEnable
:
1549 Attributes
|= Dev
->Attributes
;
1550 case EfiPciIoAttributeOperationSet
:
1551 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
1552 Dev
->Attributes
= Attributes
;
1555 case EfiPciIoAttributeOperationDisable
:
1556 Dev
->Attributes
&= ~Attributes
;
1560 return EFI_INVALID_PARAMETER
;
1564 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
1565 // the device specific initialization now.
1567 if (Enable
&& !Dev
->Enabled
&& (Dev
->Device
->Initialize
!= NULL
)) {
1568 Dev
->Device
->Initialize (Dev
->Device
);
1569 Dev
->Enabled
= TRUE
;
1576 Gets the attributes that this PCI controller supports setting on a BAR using
1577 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1579 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1580 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1581 base address for resource range. The legal range for this field is 0..5.
1582 @param Supports A pointer to the mask of attributes that this PCI controller supports
1583 setting for this BAR with SetBarAttributes().
1584 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1585 configuration of this BAR of the PCI controller.
1587 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1588 controller supports are returned in Supports. If Resources
1589 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1590 controller is currently using are returned in Resources.
1591 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1592 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1593 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1600 PciIoGetBarAttributes (
1601 IN EFI_PCI_IO_PROTOCOL
*This
,
1603 OUT UINT64
*Supports OPTIONAL
,
1604 OUT VOID
**Resources OPTIONAL
1607 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1608 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1609 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
1610 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1613 if ((Supports
== NULL
) && (Resources
== NULL
)) {
1614 return EFI_INVALID_PARAMETER
;
1617 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1619 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
1620 if (EFI_ERROR (Status
)) {
1625 // Don't expose any configurable attributes for our emulated BAR
1627 if (Supports
!= NULL
) {
1631 if (Resources
!= NULL
) {
1632 Descriptor
= AllocatePool (
1633 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1634 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1636 if (Descriptor
== NULL
) {
1637 return EFI_OUT_OF_RESOURCES
;
1640 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
1642 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Descriptor
+ 1);
1643 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1646 *Resources
= Descriptor
;
1653 Sets the attributes for a range of a BAR on a PCI controller.
1655 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1656 @param Attributes The mask of attributes to set for the resource range specified by
1657 BarIndex, Offset, and Length.
1658 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1659 base address for resource range. The legal range for this field is 0..5.
1660 @param Offset A pointer to the BAR relative base address of the resource range to be
1661 modified by the attributes specified by Attributes.
1662 @param Length A pointer to the length of the resource range to be modified by the
1663 attributes specified by Attributes.
1668 PciIoSetBarAttributes (
1669 IN EFI_PCI_IO_PROTOCOL
*This
,
1670 IN UINT64 Attributes
,
1672 IN OUT UINT64
*Offset
,
1673 IN OUT UINT64
*Length
1676 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1677 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1678 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
1682 if ((Attributes
& (~DEV_SUPPORTED_ATTRIBUTES
)) != 0) {
1683 return EFI_UNSUPPORTED
;
1686 if ((Offset
== NULL
) || (Length
== NULL
)) {
1687 return EFI_INVALID_PARAMETER
;
1690 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1691 Width
= EfiPciIoWidthUint8
;
1692 Count
= (UINT32
)*Length
;
1694 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
1695 if (EFI_ERROR (Status
)) {
1699 if (*Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
1700 return EFI_UNSUPPORTED
;
1704 return EFI_UNSUPPORTED
;
1707 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
1711 { PciIoMemRead
, PciIoMemWrite
},
1712 { PciIoIoRead
, PciIoIoWrite
},
1713 { PciIoPciRead
, PciIoPciWrite
},
1717 CoherentPciIoAllocateBuffer
,
1718 CoherentPciIoFreeBuffer
,
1722 PciIoGetBarAttributes
,
1723 PciIoSetBarAttributes
,
1729 Initialize PciIo Protocol.
1731 @param Dev Point to NON_DISCOVERABLE_PCI_DEVICE instance.
1735 InitializePciIoProtocol (
1736 NON_DISCOVERABLE_PCI_DEVICE
*Dev
1739 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1742 InitializeListHead (&Dev
->UncachedAllocationList
);
1744 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
1745 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
1747 // Copy protocol structure
1748 CopyMem (&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
1750 if (Dev
->Device
->DmaType
== NonDiscoverableDeviceDmaTypeNonCoherent
) {
1751 Dev
->PciIo
.AllocateBuffer
= NonCoherentPciIoAllocateBuffer
;
1752 Dev
->PciIo
.FreeBuffer
= NonCoherentPciIoFreeBuffer
;
1753 Dev
->PciIo
.Map
= NonCoherentPciIoMap
;
1754 Dev
->PciIo
.Unmap
= NonCoherentPciIoUnmap
;
1757 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
1758 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
1759 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
1760 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1762 } else if (CompareGuid (
1764 &gEdkiiNonDiscoverableEhciDeviceGuid
1767 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
1768 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1769 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1771 } else if (CompareGuid (
1773 &gEdkiiNonDiscoverableNvmeDeviceGuid
1776 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
1777 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
1778 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1780 } else if (CompareGuid (
1782 &gEdkiiNonDiscoverableOhciDeviceGuid
1785 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
1786 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1787 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1789 } else if (CompareGuid (
1791 &gEdkiiNonDiscoverableSdhciDeviceGuid
1794 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1795 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
1796 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
1798 } else if (CompareGuid (
1800 &gEdkiiNonDiscoverableXhciDeviceGuid
1803 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
1804 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1805 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1807 } else if (CompareGuid (
1809 &gEdkiiNonDiscoverableUhciDeviceGuid
1812 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
1813 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1814 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1816 } else if (CompareGuid (
1818 &gEdkiiNonDiscoverableUfsDeviceGuid
1821 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1822 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
1823 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1826 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
1830 // Iterate over the resources to populate the virtual BARs
1832 Idx
= Dev
->BarOffset
;
1833 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
1834 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
1835 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3))
1837 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1838 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
1840 if ((Idx
>= PCI_MAX_BAR
) ||
1841 ((Idx
== PCI_MAX_BAR
- 1) && (Desc
->AddrSpaceGranularity
== 64)))
1845 "%a: resource count exceeds number of emulated BARs\n",
1852 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
1855 if (Desc
->AddrSpaceGranularity
== 64) {
1856 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
1857 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (