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
;
965 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
971 // Find the uncached allocation list entry associated
972 // with this allocation
974 for (Entry
= Dev
->UncachedAllocationList
.ForwardLink
;
975 Entry
!= &Dev
->UncachedAllocationList
;
976 Entry
= Entry
->ForwardLink
)
978 Alloc
= BASE_CR (Entry
, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
, List
);
979 if ((Alloc
->HostAddress
== HostAddress
) && (Alloc
->NumPages
== Pages
)) {
981 // We are freeing the exact allocation we were given
982 // before by AllocateBuffer()
990 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
991 return EFI_NOT_FOUND
;
994 RemoveEntryList (&Alloc
->List
);
996 Status
= gDS
->SetMemorySpaceAttributes (
997 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
998 EFI_PAGES_TO_SIZE (Pages
),
1001 if (EFI_ERROR (Status
)) {
1006 // If we fail to restore the original attributes, it is better to leak the
1007 // memory than to return it to the heap
1009 FreePages (HostAddress
, Pages
);
1019 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1020 @param Type This parameter is not used and must be ignored.
1021 @param MemoryType The type of memory to allocate, EfiBootServicesData or
1022 EfiRuntimeServicesData.
1023 @param Pages The number of pages to allocate.
1024 @param HostAddress A pointer to store the base system memory address of the
1026 @param Attributes The requested bit mask of attributes for the allocated range.
1028 @retval EFI_SUCCESS The requested memory pages were allocated.
1029 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
1030 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
1031 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1032 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1038 NonCoherentPciIoAllocateBuffer (
1039 IN EFI_PCI_IO_PROTOCOL
*This
,
1040 IN EFI_ALLOCATE_TYPE Type
,
1041 IN EFI_MEMORY_TYPE MemoryType
,
1043 OUT VOID
**HostAddress
,
1044 IN UINT64 Attributes
1047 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1048 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1051 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
1054 if (HostAddress
== NULL
) {
1055 return EFI_INVALID_PARAMETER
;
1058 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1060 Status
= CoherentPciIoAllocateBuffer (
1068 if (EFI_ERROR (Status
)) {
1072 Status
= gDS
->GetMemorySpaceDescriptor (
1073 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1076 if (EFI_ERROR (Status
)) {
1080 if ((GcdDescriptor
.Capabilities
& (EFI_MEMORY_WC
| EFI_MEMORY_UC
)) == 0) {
1081 Status
= EFI_UNSUPPORTED
;
1086 // Set the preferred memory attributes
1088 if (((Attributes
& EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
) != 0) ||
1089 ((GcdDescriptor
.Capabilities
& EFI_MEMORY_UC
) == 0))
1092 // Use write combining if it was requested, or if it is the only
1093 // type supported by the region.
1095 MemType
= EFI_MEMORY_WC
;
1097 MemType
= EFI_MEMORY_UC
;
1100 Alloc
= AllocatePool (sizeof *Alloc
);
1101 if (Alloc
== NULL
) {
1105 Alloc
->HostAddress
= AllocAddress
;
1106 Alloc
->NumPages
= Pages
;
1107 Alloc
->Attributes
= GcdDescriptor
.Attributes
;
1110 // Record this allocation in the linked list, so we
1111 // can restore the memory space attributes later
1113 InsertHeadList (&Dev
->UncachedAllocationList
, &Alloc
->List
);
1115 Status
= gDS
->SetMemorySpaceAttributes (
1116 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1117 EFI_PAGES_TO_SIZE (Pages
),
1120 if (EFI_ERROR (Status
)) {
1124 Status
= mCpu
->FlushDataCache (
1126 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1127 EFI_PAGES_TO_SIZE (Pages
),
1128 EfiCpuFlushTypeInvalidate
1130 if (EFI_ERROR (Status
)) {
1134 *HostAddress
= AllocAddress
;
1139 RemoveEntryList (&Alloc
->List
);
1143 CoherentPciIoFreeBuffer (This
, Pages
, AllocAddress
);
1148 Provides the PCI controller-specific addresses needed to access system memory.
1150 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1151 @param Operation Indicates if the bus master is going to read or write to system memory.
1152 @param HostAddress The system memory address to map to the PCI controller.
1153 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
1155 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
1156 access the hosts HostAddress.
1157 @param Mapping A resulting value to pass to Unmap().
1159 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1160 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
1161 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1162 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1163 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1169 NonCoherentPciIoMap (
1170 IN EFI_PCI_IO_PROTOCOL
*This
,
1171 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
1172 IN VOID
*HostAddress
,
1173 IN OUT UINTN
*NumberOfBytes
,
1174 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1178 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1180 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1183 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1186 if ((HostAddress
== NULL
) ||
1187 (NumberOfBytes
== NULL
) ||
1188 (DeviceAddress
== NULL
) ||
1191 return EFI_INVALID_PARAMETER
;
1194 if ((Operation
!= EfiPciIoOperationBusMasterRead
) &&
1195 (Operation
!= EfiPciIoOperationBusMasterWrite
) &&
1196 (Operation
!= EfiPciIoOperationBusMasterCommonBuffer
))
1198 return EFI_INVALID_PARAMETER
;
1201 MapInfo
= AllocatePool (sizeof *MapInfo
);
1202 if (MapInfo
== NULL
) {
1203 return EFI_OUT_OF_RESOURCES
;
1206 MapInfo
->HostAddress
= HostAddress
;
1207 MapInfo
->Operation
= Operation
;
1208 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1210 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1213 // If this device does not support 64-bit DMA addressing, we need to allocate
1214 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
1216 Bounce
= ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
1217 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
);
1220 switch (Operation
) {
1221 case EfiPciIoOperationBusMasterRead
:
1222 case EfiPciIoOperationBusMasterWrite
:
1224 // For streaming DMA, it is sufficient if the buffer is aligned to
1225 // the CPUs DMA buffer alignment.
1227 AlignMask
= mCpu
->DmaBufferAlignment
- 1;
1228 if ((((UINTN
)HostAddress
| *NumberOfBytes
) & AlignMask
) == 0) {
1234 case EfiPciIoOperationBusMasterCommonBuffer
:
1236 // Check whether the host address refers to an uncached mapping.
1238 Status
= gDS
->GetMemorySpaceDescriptor (
1239 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1242 if (EFI_ERROR (Status
) ||
1243 ((GcdDescriptor
.Attributes
& (EFI_MEMORY_WB
|EFI_MEMORY_WT
)) != 0))
1256 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
1257 Status
= EFI_DEVICE_ERROR
;
1261 Status
= NonCoherentPciIoAllocateBuffer (
1264 EfiBootServicesData
,
1265 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1267 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
1269 if (EFI_ERROR (Status
)) {
1273 MapInfo
->AllocAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
;
1274 if (Operation
== EfiPciIoOperationBusMasterRead
) {
1275 gBS
->CopyMem (AllocAddress
, HostAddress
, *NumberOfBytes
);
1278 *DeviceAddress
= MapInfo
->AllocAddress
;
1280 MapInfo
->AllocAddress
= 0;
1281 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
1284 // We are not using a bounce buffer: the mapping is sufficiently
1285 // aligned to allow us to simply flush the caches. Note that cleaning
1286 // the caches is necessary for both data directions:
1287 // - for bus master read, we want the latest data to be present
1289 // - for bus master write, we don't want any stale dirty cachelines that
1290 // may be written back unexpectedly, and clobber the data written to
1291 // main memory by the device.
1293 mCpu
->FlushDataCache (
1295 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1297 EfiCpuFlushTypeWriteBack
1311 Completes the Map() operation and releases any corresponding resources.
1313 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1314 @param Mapping The mapping value returned from Map().
1316 @retval EFI_SUCCESS The range was unmapped.
1322 NonCoherentPciIoUnmap (
1323 IN EFI_PCI_IO_PROTOCOL
*This
,
1327 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1329 if (Mapping
== NULL
) {
1330 return EFI_DEVICE_ERROR
;
1334 if (MapInfo
->AllocAddress
!= 0) {
1336 // We are using a bounce buffer: copy back the data if necessary,
1337 // and free the buffer.
1339 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1341 MapInfo
->HostAddress
,
1342 (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
1343 MapInfo
->NumberOfBytes
1347 NonCoherentPciIoFreeBuffer (
1349 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1350 (VOID
*)(UINTN
)MapInfo
->AllocAddress
1354 // We are *not* using a bounce buffer: if this is a bus master write,
1355 // we have to invalidate the caches so the CPU will see the uncached
1356 // data written by the device.
1358 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1359 mCpu
->FlushDataCache (
1361 (EFI_PHYSICAL_ADDRESS
)(UINTN
)MapInfo
->HostAddress
,
1362 MapInfo
->NumberOfBytes
,
1363 EfiCpuFlushTypeInvalidate
1373 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1375 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1382 IN EFI_PCI_IO_PROTOCOL
*This
1389 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1391 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1392 @param SegmentNumber The PCI controller's current PCI segment number.
1393 @param BusNumber The PCI controller's current PCI bus number.
1394 @param DeviceNumber The PCI controller's current PCI device number.
1395 @param FunctionNumber The PCI controller's current PCI function number.
1397 @retval EFI_SUCCESS The PCI controller location was returned.
1398 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1405 IN EFI_PCI_IO_PROTOCOL
*This
,
1406 OUT UINTN
*SegmentNumber
,
1407 OUT UINTN
*BusNumber
,
1408 OUT UINTN
*DeviceNumber
,
1409 OUT UINTN
*FunctionNumber
1412 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1414 if ((SegmentNumber
== NULL
) ||
1415 (BusNumber
== NULL
) ||
1416 (DeviceNumber
== NULL
) ||
1417 (FunctionNumber
== NULL
))
1419 return EFI_INVALID_PARAMETER
;
1422 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1424 *SegmentNumber
= 0xff;
1425 *BusNumber
= Dev
->UniqueId
>> 5;
1426 *DeviceNumber
= Dev
->UniqueId
& 0x1f;
1427 *FunctionNumber
= 0;
1433 Performs an operation on the attributes that this PCI controller supports. The operations include
1434 getting the set of supported attributes, retrieving the current attributes, setting the current
1435 attributes, enabling attributes, and disabling attributes.
1437 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1438 @param Operation The operation to perform on the attributes for this PCI controller.
1439 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1441 @param Result A pointer to the result mask of attributes that are returned for the Get
1442 and Supported operations.
1444 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1445 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1446 @retval EFI_UNSUPPORTED one or more of the bits set in
1447 Attributes are not supported by this PCI controller or one of
1448 its parent bridges when Operation is Set, Enable or Disable.
1455 IN EFI_PCI_IO_PROTOCOL
*This
,
1456 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1457 IN UINT64 Attributes
,
1458 OUT UINT64
*Result OPTIONAL
1461 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1464 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1466 if ((Attributes
& (~(DEV_SUPPORTED_ATTRIBUTES
))) != 0) {
1467 return EFI_UNSUPPORTED
;
1471 switch (Operation
) {
1472 case EfiPciIoAttributeOperationGet
:
1473 if (Result
== NULL
) {
1474 return EFI_INVALID_PARAMETER
;
1477 *Result
= Dev
->Attributes
;
1480 case EfiPciIoAttributeOperationSupported
:
1481 if (Result
== NULL
) {
1482 return EFI_INVALID_PARAMETER
;
1485 *Result
= DEV_SUPPORTED_ATTRIBUTES
;
1488 case EfiPciIoAttributeOperationEnable
:
1489 Attributes
|= Dev
->Attributes
;
1490 case EfiPciIoAttributeOperationSet
:
1491 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
1492 Dev
->Attributes
= Attributes
;
1495 case EfiPciIoAttributeOperationDisable
:
1496 Dev
->Attributes
&= ~Attributes
;
1500 return EFI_INVALID_PARAMETER
;
1504 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
1505 // the device specific initialization now.
1507 if (Enable
&& !Dev
->Enabled
&& (Dev
->Device
->Initialize
!= NULL
)) {
1508 Dev
->Device
->Initialize (Dev
->Device
);
1509 Dev
->Enabled
= TRUE
;
1516 Gets the attributes that this PCI controller supports setting on a BAR using
1517 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1519 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1520 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1521 base address for resource range. The legal range for this field is 0..5.
1522 @param Supports A pointer to the mask of attributes that this PCI controller supports
1523 setting for this BAR with SetBarAttributes().
1524 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1525 configuration of this BAR of the PCI controller.
1527 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1528 controller supports are returned in Supports. If Resources
1529 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1530 controller is currently using are returned in Resources.
1531 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1532 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1533 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1540 PciIoGetBarAttributes (
1541 IN EFI_PCI_IO_PROTOCOL
*This
,
1543 OUT UINT64
*Supports OPTIONAL
,
1544 OUT VOID
**Resources OPTIONAL
1547 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1548 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1549 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
1550 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1553 if ((Supports
== NULL
) && (Resources
== NULL
)) {
1554 return EFI_INVALID_PARAMETER
;
1557 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1559 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
1560 if (EFI_ERROR (Status
)) {
1565 // Don't expose any configurable attributes for our emulated BAR
1567 if (Supports
!= NULL
) {
1571 if (Resources
!= NULL
) {
1572 Descriptor
= AllocatePool (
1573 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1574 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1576 if (Descriptor
== NULL
) {
1577 return EFI_OUT_OF_RESOURCES
;
1580 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
1582 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Descriptor
+ 1);
1583 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1586 *Resources
= Descriptor
;
1593 Sets the attributes for a range of a BAR on a PCI controller.
1595 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1596 @param Attributes The mask of attributes to set for the resource range specified by
1597 BarIndex, Offset, and Length.
1598 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1599 base address for resource range. The legal range for this field is 0..5.
1600 @param Offset A pointer to the BAR relative base address of the resource range to be
1601 modified by the attributes specified by Attributes.
1602 @param Length A pointer to the length of the resource range to be modified by the
1603 attributes specified by Attributes.
1608 PciIoSetBarAttributes (
1609 IN EFI_PCI_IO_PROTOCOL
*This
,
1610 IN UINT64 Attributes
,
1612 IN OUT UINT64
*Offset
,
1613 IN OUT UINT64
*Length
1616 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1617 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1618 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
1622 if ((Attributes
& (~DEV_SUPPORTED_ATTRIBUTES
)) != 0) {
1623 return EFI_UNSUPPORTED
;
1626 if ((Offset
== NULL
) || (Length
== NULL
)) {
1627 return EFI_INVALID_PARAMETER
;
1630 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This
);
1631 Width
= EfiPciIoWidthUint8
;
1632 Count
= (UINT32
)*Length
;
1634 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
1635 if (EFI_ERROR (Status
)) {
1639 if (*Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
1640 return EFI_UNSUPPORTED
;
1644 return EFI_UNSUPPORTED
;
1647 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
1651 { PciIoMemRead
, PciIoMemWrite
},
1652 { PciIoIoRead
, PciIoIoWrite
},
1653 { PciIoPciRead
, PciIoPciWrite
},
1657 CoherentPciIoAllocateBuffer
,
1658 CoherentPciIoFreeBuffer
,
1662 PciIoGetBarAttributes
,
1663 PciIoSetBarAttributes
,
1669 Initialize PciIo Protocol.
1671 @param Dev Point to NON_DISCOVERABLE_PCI_DEVICE instance.
1675 InitializePciIoProtocol (
1676 NON_DISCOVERABLE_PCI_DEVICE
*Dev
1679 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1682 InitializeListHead (&Dev
->UncachedAllocationList
);
1684 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
1685 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
1687 // Copy protocol structure
1688 CopyMem (&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
1690 if (Dev
->Device
->DmaType
== NonDiscoverableDeviceDmaTypeNonCoherent
) {
1691 Dev
->PciIo
.AllocateBuffer
= NonCoherentPciIoAllocateBuffer
;
1692 Dev
->PciIo
.FreeBuffer
= NonCoherentPciIoFreeBuffer
;
1693 Dev
->PciIo
.Map
= NonCoherentPciIoMap
;
1694 Dev
->PciIo
.Unmap
= NonCoherentPciIoUnmap
;
1697 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
1698 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
1699 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
1700 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1702 } else if (CompareGuid (
1704 &gEdkiiNonDiscoverableEhciDeviceGuid
1707 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
1708 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1709 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1711 } else if (CompareGuid (
1713 &gEdkiiNonDiscoverableNvmeDeviceGuid
1716 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
1717 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
1718 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1720 } else if (CompareGuid (
1722 &gEdkiiNonDiscoverableOhciDeviceGuid
1725 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
1726 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1727 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1729 } else if (CompareGuid (
1731 &gEdkiiNonDiscoverableSdhciDeviceGuid
1734 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1735 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
1736 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
1738 } else if (CompareGuid (
1740 &gEdkiiNonDiscoverableXhciDeviceGuid
1743 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
1744 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1745 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1747 } else if (CompareGuid (
1749 &gEdkiiNonDiscoverableUhciDeviceGuid
1752 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
1753 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1754 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1756 } else if (CompareGuid (
1758 &gEdkiiNonDiscoverableUfsDeviceGuid
1761 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1762 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
1763 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1766 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
1770 // Iterate over the resources to populate the virtual BARs
1772 Idx
= Dev
->BarOffset
;
1773 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
1774 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
1775 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3))
1777 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1778 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
1780 if ((Idx
>= PCI_MAX_BAR
) ||
1781 ((Idx
== PCI_MAX_BAR
- 1) && (Desc
->AddrSpaceGranularity
== 64)))
1785 "%a: resource count exceeds number of emulated BARs\n",
1792 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
1795 if (Desc
->AddrSpaceGranularity
== 64) {
1796 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
1797 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (