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)) {
68 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
69 satisfied or after a defined duration.
71 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
72 @param Width Signifies the width of the memory or I/O operations.
73 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
74 base address for the memory operation to perform.
75 @param Offset The offset within the selected BAR to start the memory operation.
76 @param Mask Mask used for the polling criteria.
77 @param Value The comparison value used for the polling exit criteria.
78 @param Delay The number of 100 ns units to poll.
79 @param Result Pointer to the last value read from the memory location.
86 IN EFI_PCI_IO_PROTOCOL
*This
,
87 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
96 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
97 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
101 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
102 return EFI_INVALID_PARAMETER
;
105 if (Result
== NULL
) {
106 return EFI_INVALID_PARAMETER
;
109 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
112 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
113 if (EFI_ERROR (Status
)) {
117 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
118 return EFI_UNSUPPORTED
;
122 return EFI_UNSUPPORTED
;
126 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
127 satisfied or after a defined duration.
129 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
130 @param Width Signifies the width of the memory or I/O operations.
131 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
132 base address for the memory operation to perform.
133 @param Offset The offset within the selected BAR to start the memory operation.
134 @param Mask Mask used for the polling criteria.
135 @param Value The comparison value used for the polling exit criteria.
136 @param Delay The number of 100 ns units to poll.
137 @param Result Pointer to the last value read from the memory location.
144 IN EFI_PCI_IO_PROTOCOL
*This
,
145 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
154 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
155 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
159 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
160 return EFI_INVALID_PARAMETER
;
163 if (Result
== NULL
) {
164 return EFI_INVALID_PARAMETER
;
167 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
170 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
171 if (EFI_ERROR (Status
)) {
175 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
176 return EFI_UNSUPPORTED
;
180 return EFI_UNSUPPORTED
;
184 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
186 @param Width Signifies the width of the memory or I/O operations.
187 @param Count The number of memory or I/O operations to perform.
188 @param DstStride The stride of the destination buffer.
189 @param Dst For read operations, the destination buffer to store the results. For write
190 operations, the destination buffer to write data to.
191 @param SrcStride The stride of the source buffer.
192 @param Src For read operations, the source buffer to read data from. For write
193 operations, the source buffer to write data from.
195 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
196 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
203 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
211 volatile UINT8
*Dst8
;
212 volatile UINT16
*Dst16
;
213 volatile UINT32
*Dst32
;
214 volatile CONST UINT8
*Src8
;
215 volatile CONST UINT16
*Src16
;
216 volatile CONST UINT32
*Src32
;
219 // Loop for each iteration and move the data
221 switch (Width
& 0x3) {
222 case EfiPciWidthUint8
:
225 for (;Count
> 0; Count
--, Dst8
+= DstStride
, Src8
+= SrcStride
) {
229 case EfiPciWidthUint16
:
230 Dst16
= (UINT16
*)Dst
;
231 Src16
= (UINT16
*)Src
;
232 for (;Count
> 0; Count
--, Dst16
+= DstStride
, Src16
+= SrcStride
) {
236 case EfiPciWidthUint32
:
237 Dst32
= (UINT32
*)Dst
;
238 Src32
= (UINT32
*)Src
;
239 for (;Count
> 0; Count
--, Dst32
+= DstStride
, Src32
+= SrcStride
) {
244 return EFI_INVALID_PARAMETER
;
251 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
253 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
254 @param Width Signifies the width of the memory or I/O operations.
255 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
256 base address for the memory or I/O operation to perform.
257 @param Offset The offset within the selected BAR to start the memory or I/O operation.
258 @param Count The number of memory or I/O operations to perform.
259 @param Buffer For read operations, the destination buffer to store the results. For write
260 operations, the source buffer to write data from.
262 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
263 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
264 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
265 valid for the PCI BAR specified by BarIndex.
266 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
267 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
274 IN EFI_PCI_IO_PROTOCOL
*This
,
275 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
282 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
285 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
288 if (Buffer
== NULL
) {
289 return EFI_INVALID_PARAMETER
;
292 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
295 // Only allow accesses to the BARs we emulate
297 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
298 if (EFI_ERROR (Status
)) {
302 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
303 return EFI_UNSUPPORTED
;
306 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
307 AlignMask
= (1 << (Width
& 0x03)) - 1;
308 if ((UINTN
)Address
& AlignMask
) {
309 return EFI_INVALID_PARAMETER
;
313 case EfiPciIoWidthUint8
:
314 case EfiPciIoWidthUint16
:
315 case EfiPciIoWidthUint32
:
316 case EfiPciIoWidthUint64
:
317 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
319 case EfiPciIoWidthFifoUint8
:
320 case EfiPciIoWidthFifoUint16
:
321 case EfiPciIoWidthFifoUint32
:
322 case EfiPciIoWidthFifoUint64
:
323 return PciIoMemRW (Width
, Count
, 1, Buffer
, 0, Address
);
325 case EfiPciIoWidthFillUint8
:
326 case EfiPciIoWidthFillUint16
:
327 case EfiPciIoWidthFillUint32
:
328 case EfiPciIoWidthFillUint64
:
329 return PciIoMemRW (Width
, Count
, 0, Buffer
, 1, Address
);
334 return EFI_INVALID_PARAMETER
;
338 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
340 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
341 @param Width Signifies the width of the memory or I/O operations.
342 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
343 base address for the memory or I/O operation to perform.
344 @param Offset The offset within the selected BAR to start the memory or I/O operation.
345 @param Count The number of memory or I/O operations to perform.
346 @param Buffer For read operations, the destination buffer to store the results. For write
347 operations, the source buffer to write data from.
349 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
350 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
351 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
352 valid for the PCI BAR specified by BarIndex.
353 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
354 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
361 IN EFI_PCI_IO_PROTOCOL
*This
,
362 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
369 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
372 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
375 if (Buffer
== NULL
) {
376 return EFI_INVALID_PARAMETER
;
379 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
382 // Only allow accesses to the BARs we emulate
384 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
385 if (EFI_ERROR (Status
)) {
389 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
390 return EFI_UNSUPPORTED
;
393 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
394 AlignMask
= (1 << (Width
& 0x03)) - 1;
395 if ((UINTN
)Address
& AlignMask
) {
396 return EFI_INVALID_PARAMETER
;
400 case EfiPciIoWidthUint8
:
401 case EfiPciIoWidthUint16
:
402 case EfiPciIoWidthUint32
:
403 case EfiPciIoWidthUint64
:
404 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
406 case EfiPciIoWidthFifoUint8
:
407 case EfiPciIoWidthFifoUint16
:
408 case EfiPciIoWidthFifoUint32
:
409 case EfiPciIoWidthFifoUint64
:
410 return PciIoMemRW (Width
, Count
, 0, Address
, 1, Buffer
);
412 case EfiPciIoWidthFillUint8
:
413 case EfiPciIoWidthFillUint16
:
414 case EfiPciIoWidthFillUint32
:
415 case EfiPciIoWidthFillUint64
:
416 return PciIoMemRW (Width
, Count
, 1, Address
, 0, Buffer
);
421 return EFI_INVALID_PARAMETER
;
425 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
427 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
428 @param Width Signifies the width of the memory or I/O operations.
429 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
430 base address for the memory or I/O operation to perform.
431 @param Offset The offset within the selected BAR to start the memory or I/O operation.
432 @param Count The number of memory or I/O operations to perform.
433 @param Buffer For read operations, the destination buffer to store the results. For write
434 operations, the source buffer to write data from.
441 IN EFI_PCI_IO_PROTOCOL
*This
,
442 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
449 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
450 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
453 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
454 return EFI_INVALID_PARAMETER
;
457 if (Buffer
== NULL
) {
458 return EFI_INVALID_PARAMETER
;
461 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
463 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
464 if (EFI_ERROR (Status
)) {
468 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
469 return EFI_UNSUPPORTED
;
473 return EFI_UNSUPPORTED
;
477 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
479 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
480 @param Width Signifies the width of the memory or I/O operations.
481 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
482 base address for the memory or I/O operation to perform.
483 @param Offset The offset within the selected BAR to start the memory or I/O operation.
484 @param Count The number of memory or I/O operations to perform.
485 @param Buffer For read operations, the destination buffer to store the results. For write
486 operations, the source buffer to write data from.
493 IN EFI_PCI_IO_PROTOCOL
*This
,
494 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
501 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
502 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
505 if ((UINT32
)Width
>= EfiPciIoWidthMaximum
) {
506 return EFI_INVALID_PARAMETER
;
509 if (Buffer
== NULL
) {
510 return EFI_INVALID_PARAMETER
;
513 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
515 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
516 if (EFI_ERROR (Status
)) {
520 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
521 return EFI_UNSUPPORTED
;
525 return EFI_UNSUPPORTED
;
529 Enable a PCI driver to access PCI config space.
531 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
532 @param Width Signifies the width of the memory or I/O operations.
533 @param Offset The offset within the selected BAR to start the memory or I/O operation.
534 @param Count The number of memory or I/O operations to perform.
535 @param Buffer For read operations, the destination buffer to store the results. For write
536 operations, the source buffer to write data from.
543 IN EFI_PCI_IO_PROTOCOL
*This
,
544 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
550 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
554 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
555 return EFI_INVALID_PARAMETER
;
558 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
559 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
560 Length
= Count
<< ((UINTN
)Width
& 0x3);
562 if (Offset
>= sizeof (Dev
->ConfigSpace
)) {
563 ZeroMem (Buffer
, Length
);
567 if (Offset
+ Length
> sizeof (Dev
->ConfigSpace
)) {
569 // Read all zeroes for config space accesses beyond the first
572 Length
-= sizeof (Dev
->ConfigSpace
) - Offset
;
573 ZeroMem ((UINT8
*)Buffer
+ sizeof (Dev
->ConfigSpace
) - Offset
, Length
);
575 Count
-= Length
>> ((UINTN
)Width
& 0x3);
577 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
581 Enable a PCI driver to access PCI config space.
583 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
584 @param Width Signifies the width of the memory or I/O operations.
585 @param Offset The offset within the selected BAR to start the memory or I/O operation.
586 @param Count The number of memory or I/O operations to perform.
587 @param Buffer For read operations, the destination buffer to store the results. For write
588 operations, the source buffer to write data from
590 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
591 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
592 valid for the PCI BAR specified by BarIndex.
593 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
600 IN EFI_PCI_IO_PROTOCOL
*This
,
601 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
607 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
610 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
611 return EFI_INVALID_PARAMETER
;
614 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
615 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
617 if (Offset
+ (Count
<< ((UINTN
)Width
& 0x3)) > sizeof (Dev
->ConfigSpace
)) {
618 return EFI_UNSUPPORTED
;
621 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
625 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
628 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
629 @param Width Signifies the width of the memory operations.
630 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
631 base address for the memory operation to perform.
632 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
633 start the memory writes for the copy operation.
634 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
635 base address for the memory operation to perform.
636 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
637 the memory reads for the copy operation.
638 @param Count The number of memory operations to perform. Bytes moved is Width
639 size * Count, starting at DestOffset and SrcOffset.
646 IN EFI_PCI_IO_PROTOCOL
*This
,
647 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
648 IN UINT8 DestBarIndex
,
649 IN UINT64 DestOffset
,
650 IN UINT8 SrcBarIndex
,
655 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
656 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*DestDesc
;
657 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*SrcDesc
;
660 if ((UINT32
)Width
> EfiPciIoWidthUint64
) {
661 return EFI_INVALID_PARAMETER
;
664 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
666 Status
= GetBarResource (Dev
, DestBarIndex
, &DestDesc
);
667 if (EFI_ERROR (Status
)) {
671 if (DestOffset
+ (Count
<< (Width
& 0x3)) > DestDesc
->AddrLen
) {
672 return EFI_UNSUPPORTED
;
675 Status
= GetBarResource (Dev
, SrcBarIndex
, &SrcDesc
);
676 if (EFI_ERROR (Status
)) {
680 if (SrcOffset
+ (Count
<< (Width
& 0x3)) > SrcDesc
->AddrLen
) {
681 return EFI_UNSUPPORTED
;
685 return EFI_UNSUPPORTED
;
689 Provides the PCI controller-specific addresses needed to access system memory.
691 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
692 @param Operation Indicates if the bus master is going to read or write to system memory.
693 @param HostAddress The system memory address to map to the PCI controller.
694 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
696 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
697 access the hosts HostAddress.
698 @param Mapping A resulting value to pass to Unmap().
700 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
701 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
702 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
703 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
704 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
711 IN EFI_PCI_IO_PROTOCOL
*This
,
712 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
713 IN VOID
*HostAddress
,
714 IN OUT UINTN
*NumberOfBytes
,
715 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
719 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
721 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
723 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
724 Operation
!= EfiPciIoOperationBusMasterWrite
&&
725 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
726 return EFI_INVALID_PARAMETER
;
729 if (HostAddress
== NULL
||
730 NumberOfBytes
== NULL
||
731 DeviceAddress
== NULL
||
733 return EFI_INVALID_PARAMETER
;
737 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
738 // addressing, we need to allocate a bounce buffer and copy over the data.
740 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
741 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
742 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
) {
745 // Bounce buffering is not possible for consistent mappings
747 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
748 return EFI_UNSUPPORTED
;
751 MapInfo
= AllocatePool (sizeof *MapInfo
);
752 if (MapInfo
== NULL
) {
753 return EFI_OUT_OF_RESOURCES
;
756 MapInfo
->AllocAddress
= MAX_UINT32
;
757 MapInfo
->HostAddress
= HostAddress
;
758 MapInfo
->Operation
= Operation
;
759 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
761 Status
= gBS
->AllocatePages (AllocateMaxAddress
, EfiBootServicesData
,
762 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
763 &MapInfo
->AllocAddress
);
764 if (EFI_ERROR (Status
)) {
766 // If we fail here, it is likely because the system has no memory below
767 // 4 GB to begin with. There is not much we can do about that other than
768 // fail the map request.
771 return EFI_DEVICE_ERROR
;
773 if (Operation
== EfiPciIoOperationBusMasterRead
) {
774 gBS
->CopyMem ((VOID
*)(UINTN
)MapInfo
->AllocAddress
, HostAddress
,
777 *DeviceAddress
= MapInfo
->AllocAddress
;
780 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
787 Completes the Map() operation and releases any corresponding resources.
789 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
790 @param Mapping The mapping value returned from Map().
792 @retval EFI_SUCCESS The range was unmapped.
799 IN EFI_PCI_IO_PROTOCOL
*This
,
803 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
806 if (MapInfo
!= NULL
) {
807 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
808 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
809 MapInfo
->NumberOfBytes
);
811 gBS
->FreePages (MapInfo
->AllocAddress
,
812 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
));
821 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
822 @param Type This parameter is not used and must be ignored.
823 @param MemoryType The type of memory to allocate, EfiBootServicesData or
824 EfiRuntimeServicesData.
825 @param Pages The number of pages to allocate.
826 @param HostAddress A pointer to store the base system memory address of the
828 @param Attributes The requested bit mask of attributes for the allocated range.
830 @retval EFI_SUCCESS The requested memory pages were allocated.
831 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
832 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
833 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
834 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
840 CoherentPciIoAllocateBuffer (
841 IN EFI_PCI_IO_PROTOCOL
*This
,
842 IN EFI_ALLOCATE_TYPE Type
,
843 IN EFI_MEMORY_TYPE MemoryType
,
845 OUT VOID
**HostAddress
,
849 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
850 EFI_PHYSICAL_ADDRESS AllocAddress
;
851 EFI_ALLOCATE_TYPE AllocType
;
854 if ((Attributes
& ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
855 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
856 return EFI_UNSUPPORTED
;
859 if ((MemoryType
!= EfiBootServicesData
) &&
860 (MemoryType
!= EfiRuntimeServicesData
)) {
861 return EFI_INVALID_PARAMETER
;
865 // Allocate below 4 GB if the dual address cycle attribute has not
866 // been set. If the system has no memory available below 4 GB, there
867 // is little we can do except propagate the error.
869 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
870 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
871 AllocAddress
= MAX_UINT32
;
872 AllocType
= AllocateMaxAddress
;
874 AllocType
= AllocateAnyPages
;
877 Status
= gBS
->AllocatePages (AllocType
, MemoryType
, Pages
, &AllocAddress
);
878 if (!EFI_ERROR (Status
)) {
879 *HostAddress
= (VOID
*)(UINTN
)AllocAddress
;
885 Frees memory that was allocated in function CoherentPciIoAllocateBuffer ().
887 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
888 @param Pages The number of pages to free.
889 @param HostAddress The base system memory address of the allocated range.
891 @retval EFI_SUCCESS The requested memory pages were freed.
897 CoherentPciIoFreeBuffer (
898 IN EFI_PCI_IO_PROTOCOL
*This
,
903 FreePages (HostAddress
, Pages
);
908 Frees memory that was allocated in function NonCoherentPciIoAllocateBuffer ().
910 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
911 @param Pages The number of pages to free.
912 @param HostAddress The base system memory address of the allocated range.
914 @retval EFI_SUCCESS The requested memory pages were freed.
915 @retval others The operation contain some errors.
921 NonCoherentPciIoFreeBuffer (
922 IN EFI_PCI_IO_PROTOCOL
*This
,
927 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
930 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
933 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
939 // Find the uncached allocation list entry associated
940 // with this allocation
942 for (Entry
= Dev
->UncachedAllocationList
.ForwardLink
;
943 Entry
!= &Dev
->UncachedAllocationList
;
944 Entry
= Entry
->ForwardLink
) {
946 Alloc
= BASE_CR (Entry
, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
, List
);
947 if (Alloc
->HostAddress
== HostAddress
&& Alloc
->NumPages
== Pages
) {
949 // We are freeing the exact allocation we were given
950 // before by AllocateBuffer()
958 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
959 return EFI_NOT_FOUND
;
962 RemoveEntryList (&Alloc
->List
);
964 Status
= gDS
->SetMemorySpaceAttributes (
965 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
966 EFI_PAGES_TO_SIZE (Pages
),
968 if (EFI_ERROR (Status
)) {
973 // If we fail to restore the original attributes, it is better to leak the
974 // memory than to return it to the heap
976 FreePages (HostAddress
, Pages
);
986 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
987 @param Type This parameter is not used and must be ignored.
988 @param MemoryType The type of memory to allocate, EfiBootServicesData or
989 EfiRuntimeServicesData.
990 @param Pages The number of pages to allocate.
991 @param HostAddress A pointer to store the base system memory address of the
993 @param Attributes The requested bit mask of attributes for the allocated range.
995 @retval EFI_SUCCESS The requested memory pages were allocated.
996 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
997 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
998 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
999 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
1005 NonCoherentPciIoAllocateBuffer (
1006 IN EFI_PCI_IO_PROTOCOL
*This
,
1007 IN EFI_ALLOCATE_TYPE Type
,
1008 IN EFI_MEMORY_TYPE MemoryType
,
1010 OUT VOID
**HostAddress
,
1011 IN UINT64 Attributes
1014 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1015 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1018 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
1021 if (HostAddress
== NULL
) {
1022 return EFI_INVALID_PARAMETER
;
1025 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1027 Status
= CoherentPciIoAllocateBuffer (This
, Type
, MemoryType
, Pages
,
1028 &AllocAddress
, Attributes
);
1029 if (EFI_ERROR (Status
)) {
1033 Status
= gDS
->GetMemorySpaceDescriptor (
1034 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1036 if (EFI_ERROR (Status
)) {
1040 if ((GcdDescriptor
.Capabilities
& (EFI_MEMORY_WC
| EFI_MEMORY_UC
)) == 0) {
1041 Status
= EFI_UNSUPPORTED
;
1046 // Set the preferred memory attributes
1048 if ((Attributes
& EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
) != 0 ||
1049 (GcdDescriptor
.Capabilities
& EFI_MEMORY_UC
) == 0) {
1051 // Use write combining if it was requested, or if it is the only
1052 // type supported by the region.
1054 MemType
= EFI_MEMORY_WC
;
1056 MemType
= EFI_MEMORY_UC
;
1059 Alloc
= AllocatePool (sizeof *Alloc
);
1060 if (Alloc
== NULL
) {
1064 Alloc
->HostAddress
= AllocAddress
;
1065 Alloc
->NumPages
= Pages
;
1066 Alloc
->Attributes
= GcdDescriptor
.Attributes
;
1069 // Record this allocation in the linked list, so we
1070 // can restore the memory space attributes later
1072 InsertHeadList (&Dev
->UncachedAllocationList
, &Alloc
->List
);
1074 Status
= gDS
->SetMemorySpaceAttributes (
1075 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1076 EFI_PAGES_TO_SIZE (Pages
),
1078 if (EFI_ERROR (Status
)) {
1082 Status
= mCpu
->FlushDataCache (
1084 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
1085 EFI_PAGES_TO_SIZE (Pages
),
1086 EfiCpuFlushTypeInvalidate
);
1087 if (EFI_ERROR (Status
)) {
1091 *HostAddress
= AllocAddress
;
1096 RemoveEntryList (&Alloc
->List
);
1100 CoherentPciIoFreeBuffer (This
, Pages
, AllocAddress
);
1105 Provides the PCI controller-specific addresses needed to access system memory.
1107 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1108 @param Operation Indicates if the bus master is going to read or write to system memory.
1109 @param HostAddress The system memory address to map to the PCI controller.
1110 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
1112 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
1113 access the hosts HostAddress.
1114 @param Mapping A resulting value to pass to Unmap().
1116 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
1117 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
1118 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1119 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1120 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1126 NonCoherentPciIoMap (
1127 IN EFI_PCI_IO_PROTOCOL
*This
,
1128 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
1129 IN VOID
*HostAddress
,
1130 IN OUT UINTN
*NumberOfBytes
,
1131 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1135 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1137 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1140 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1143 if (HostAddress
== NULL
||
1144 NumberOfBytes
== NULL
||
1145 DeviceAddress
== NULL
||
1147 return EFI_INVALID_PARAMETER
;
1150 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
1151 Operation
!= EfiPciIoOperationBusMasterWrite
&&
1152 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
1153 return EFI_INVALID_PARAMETER
;
1156 MapInfo
= AllocatePool (sizeof *MapInfo
);
1157 if (MapInfo
== NULL
) {
1158 return EFI_OUT_OF_RESOURCES
;
1161 MapInfo
->HostAddress
= HostAddress
;
1162 MapInfo
->Operation
= Operation
;
1163 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1165 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1168 // If this device does not support 64-bit DMA addressing, we need to allocate
1169 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
1171 Bounce
= ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
1172 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
);
1175 switch (Operation
) {
1176 case EfiPciIoOperationBusMasterRead
:
1177 case EfiPciIoOperationBusMasterWrite
:
1179 // For streaming DMA, it is sufficient if the buffer is aligned to
1180 // the CPUs DMA buffer alignment.
1182 AlignMask
= mCpu
->DmaBufferAlignment
- 1;
1183 if ((((UINTN
) HostAddress
| *NumberOfBytes
) & AlignMask
) == 0) {
1188 case EfiPciIoOperationBusMasterCommonBuffer
:
1190 // Check whether the host address refers to an uncached mapping.
1192 Status
= gDS
->GetMemorySpaceDescriptor (
1193 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1195 if (EFI_ERROR (Status
) ||
1196 (GcdDescriptor
.Attributes
& (EFI_MEMORY_WB
|EFI_MEMORY_WT
)) != 0) {
1207 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
1208 Status
= EFI_DEVICE_ERROR
;
1212 Status
= NonCoherentPciIoAllocateBuffer (This
, AllocateAnyPages
,
1213 EfiBootServicesData
, EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1214 &AllocAddress
, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
);
1215 if (EFI_ERROR (Status
)) {
1218 MapInfo
->AllocAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
;
1219 if (Operation
== EfiPciIoOperationBusMasterRead
) {
1220 gBS
->CopyMem (AllocAddress
, HostAddress
, *NumberOfBytes
);
1222 *DeviceAddress
= MapInfo
->AllocAddress
;
1224 MapInfo
->AllocAddress
= 0;
1225 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
1228 // We are not using a bounce buffer: the mapping is sufficiently
1229 // aligned to allow us to simply flush the caches. Note that cleaning
1230 // the caches is necessary for both data directions:
1231 // - for bus master read, we want the latest data to be present
1233 // - for bus master write, we don't want any stale dirty cachelines that
1234 // may be written back unexpectedly, and clobber the data written to
1235 // main memory by the device.
1237 mCpu
->FlushDataCache (mCpu
, (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1238 *NumberOfBytes
, EfiCpuFlushTypeWriteBack
);
1251 Completes the Map() operation and releases any corresponding resources.
1253 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1254 @param Mapping The mapping value returned from Map().
1256 @retval EFI_SUCCESS The range was unmapped.
1262 NonCoherentPciIoUnmap (
1263 IN EFI_PCI_IO_PROTOCOL
*This
,
1267 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1269 if (Mapping
== NULL
) {
1270 return EFI_DEVICE_ERROR
;
1274 if (MapInfo
->AllocAddress
!= 0) {
1276 // We are using a bounce buffer: copy back the data if necessary,
1277 // and free the buffer.
1279 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1280 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
1281 MapInfo
->NumberOfBytes
);
1283 NonCoherentPciIoFreeBuffer (This
,
1284 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1285 (VOID
*)(UINTN
)MapInfo
->AllocAddress
);
1288 // We are *not* using a bounce buffer: if this is a bus master write,
1289 // we have to invalidate the caches so the CPU will see the uncached
1290 // data written by the device.
1292 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1293 mCpu
->FlushDataCache (mCpu
,
1294 (EFI_PHYSICAL_ADDRESS
)(UINTN
)MapInfo
->HostAddress
,
1295 MapInfo
->NumberOfBytes
, EfiCpuFlushTypeInvalidate
);
1303 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1305 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1312 IN EFI_PCI_IO_PROTOCOL
*This
1319 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1321 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1322 @param SegmentNumber The PCI controller's current PCI segment number.
1323 @param BusNumber The PCI controller's current PCI bus number.
1324 @param DeviceNumber The PCI controller's current PCI device number.
1325 @param FunctionNumber The PCI controller's current PCI function number.
1327 @retval EFI_SUCCESS The PCI controller location was returned.
1328 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1335 IN EFI_PCI_IO_PROTOCOL
*This
,
1336 OUT UINTN
*SegmentNumber
,
1337 OUT UINTN
*BusNumber
,
1338 OUT UINTN
*DeviceNumber
,
1339 OUT UINTN
*FunctionNumber
1342 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1344 if (SegmentNumber
== NULL
||
1345 BusNumber
== NULL
||
1346 DeviceNumber
== NULL
||
1347 FunctionNumber
== NULL
) {
1348 return EFI_INVALID_PARAMETER
;
1351 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1353 *SegmentNumber
= 0xff;
1354 *BusNumber
= Dev
->UniqueId
>> 5;
1355 *DeviceNumber
= Dev
->UniqueId
& 0x1f;
1356 *FunctionNumber
= 0;
1362 Performs an operation on the attributes that this PCI controller supports. The operations include
1363 getting the set of supported attributes, retrieving the current attributes, setting the current
1364 attributes, enabling attributes, and disabling attributes.
1366 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1367 @param Operation The operation to perform on the attributes for this PCI controller.
1368 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1370 @param Result A pointer to the result mask of attributes that are returned for the Get
1371 and Supported operations.
1373 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1374 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1375 @retval EFI_UNSUPPORTED one or more of the bits set in
1376 Attributes are not supported by this PCI controller or one of
1377 its parent bridges when Operation is Set, Enable or Disable.
1384 IN EFI_PCI_IO_PROTOCOL
*This
,
1385 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1386 IN UINT64 Attributes
,
1387 OUT UINT64
*Result OPTIONAL
1390 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1393 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1395 if ((Attributes
& (~(DEV_SUPPORTED_ATTRIBUTES
))) != 0) {
1396 return EFI_UNSUPPORTED
;
1400 switch (Operation
) {
1401 case EfiPciIoAttributeOperationGet
:
1402 if (Result
== NULL
) {
1403 return EFI_INVALID_PARAMETER
;
1405 *Result
= Dev
->Attributes
;
1408 case EfiPciIoAttributeOperationSupported
:
1409 if (Result
== NULL
) {
1410 return EFI_INVALID_PARAMETER
;
1412 *Result
= DEV_SUPPORTED_ATTRIBUTES
;
1415 case EfiPciIoAttributeOperationEnable
:
1416 Attributes
|= Dev
->Attributes
;
1417 case EfiPciIoAttributeOperationSet
:
1418 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
1419 Dev
->Attributes
= Attributes
;
1422 case EfiPciIoAttributeOperationDisable
:
1423 Dev
->Attributes
&= ~Attributes
;
1427 return EFI_INVALID_PARAMETER
;
1431 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
1432 // the device specific initialization now.
1434 if (Enable
&& !Dev
->Enabled
&& Dev
->Device
->Initialize
!= NULL
) {
1435 Dev
->Device
->Initialize (Dev
->Device
);
1436 Dev
->Enabled
= TRUE
;
1442 Gets the attributes that this PCI controller supports setting on a BAR using
1443 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1445 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1446 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1447 base address for resource range. The legal range for this field is 0..5.
1448 @param Supports A pointer to the mask of attributes that this PCI controller supports
1449 setting for this BAR with SetBarAttributes().
1450 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1451 configuration of this BAR of the PCI controller.
1453 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1454 controller supports are returned in Supports. If Resources
1455 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1456 controller is currently using are returned in Resources.
1457 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1458 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1459 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1466 PciIoGetBarAttributes (
1467 IN EFI_PCI_IO_PROTOCOL
*This
,
1469 OUT UINT64
*Supports OPTIONAL
,
1470 OUT VOID
**Resources OPTIONAL
1473 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1474 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1475 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
1476 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1479 if (Supports
== NULL
&& Resources
== NULL
) {
1480 return EFI_INVALID_PARAMETER
;
1483 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1485 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
1486 if (EFI_ERROR (Status
)) {
1491 // Don't expose any configurable attributes for our emulated BAR
1493 if (Supports
!= NULL
) {
1497 if (Resources
!= NULL
) {
1498 Descriptor
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1499 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1500 if (Descriptor
== NULL
) {
1501 return EFI_OUT_OF_RESOURCES
;
1504 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
1506 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1507 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1510 *Resources
= Descriptor
;
1516 Sets the attributes for a range of a BAR on a PCI controller.
1518 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1519 @param Attributes The mask of attributes to set for the resource range specified by
1520 BarIndex, Offset, and Length.
1521 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1522 base address for resource range. The legal range for this field is 0..5.
1523 @param Offset A pointer to the BAR relative base address of the resource range to be
1524 modified by the attributes specified by Attributes.
1525 @param Length A pointer to the length of the resource range to be modified by the
1526 attributes specified by Attributes.
1531 PciIoSetBarAttributes (
1532 IN EFI_PCI_IO_PROTOCOL
*This
,
1533 IN UINT64 Attributes
,
1535 IN OUT UINT64
*Offset
,
1536 IN OUT UINT64
*Length
1539 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1540 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1541 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
1545 if ((Attributes
& (~DEV_SUPPORTED_ATTRIBUTES
)) != 0) {
1546 return EFI_UNSUPPORTED
;
1549 if (Offset
== NULL
|| Length
== NULL
) {
1550 return EFI_INVALID_PARAMETER
;
1553 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1554 Width
= EfiPciIoWidthUint8
;
1555 Count
= (UINT32
) *Length
;
1557 Status
= GetBarResource(Dev
, BarIndex
, &Desc
);
1558 if (EFI_ERROR (Status
)) {
1562 if (*Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
1563 return EFI_UNSUPPORTED
;
1567 return EFI_UNSUPPORTED
;
1570 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
1574 { PciIoMemRead
, PciIoMemWrite
},
1575 { PciIoIoRead
, PciIoIoWrite
},
1576 { PciIoPciRead
, PciIoPciWrite
},
1580 CoherentPciIoAllocateBuffer
,
1581 CoherentPciIoFreeBuffer
,
1585 PciIoGetBarAttributes
,
1586 PciIoSetBarAttributes
,
1592 Initialize PciIo Protocol.
1594 @param Dev Point to NON_DISCOVERABLE_PCI_DEVICE instance.
1598 InitializePciIoProtocol (
1599 NON_DISCOVERABLE_PCI_DEVICE
*Dev
1602 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1605 InitializeListHead (&Dev
->UncachedAllocationList
);
1607 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
1608 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
1610 // Copy protocol structure
1611 CopyMem(&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
1613 if (Dev
->Device
->DmaType
== NonDiscoverableDeviceDmaTypeNonCoherent
) {
1614 Dev
->PciIo
.AllocateBuffer
= NonCoherentPciIoAllocateBuffer
;
1615 Dev
->PciIo
.FreeBuffer
= NonCoherentPciIoFreeBuffer
;
1616 Dev
->PciIo
.Map
= NonCoherentPciIoMap
;
1617 Dev
->PciIo
.Unmap
= NonCoherentPciIoUnmap
;
1620 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
1621 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
1622 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
1623 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1625 } else if (CompareGuid (Dev
->Device
->Type
,
1626 &gEdkiiNonDiscoverableEhciDeviceGuid
)) {
1627 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
1628 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1629 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1631 } else if (CompareGuid (Dev
->Device
->Type
,
1632 &gEdkiiNonDiscoverableNvmeDeviceGuid
)) {
1633 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
1634 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
1635 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1637 } else if (CompareGuid (Dev
->Device
->Type
,
1638 &gEdkiiNonDiscoverableOhciDeviceGuid
)) {
1639 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
1640 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1641 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1643 } else if (CompareGuid (Dev
->Device
->Type
,
1644 &gEdkiiNonDiscoverableSdhciDeviceGuid
)) {
1645 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1646 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
1647 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
1649 } else if (CompareGuid (Dev
->Device
->Type
,
1650 &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
1651 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
1652 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1653 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1655 } else if (CompareGuid (Dev
->Device
->Type
,
1656 &gEdkiiNonDiscoverableUhciDeviceGuid
)) {
1657 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
1658 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1659 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1661 } else if (CompareGuid (Dev
->Device
->Type
,
1662 &gEdkiiNonDiscoverableUfsDeviceGuid
)) {
1663 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1664 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
1665 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1668 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
1672 // Iterate over the resources to populate the virtual BARs
1674 Idx
= Dev
->BarOffset
;
1675 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
1676 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
1677 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
1679 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1680 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
1682 if (Idx
>= PCI_MAX_BARS
||
1683 (Idx
== PCI_MAX_BARS
- 1 && Desc
->AddrSpaceGranularity
== 64)) {
1684 DEBUG ((DEBUG_ERROR
,
1685 "%a: resource count exceeds number of emulated BARs\n",
1691 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
1694 if (Desc
->AddrSpaceGranularity
== 64) {
1695 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
1696 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (
1697 Desc
->AddrRangeMin
, 32);