3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "NonDiscoverablePciDeviceIo.h"
18 #include <Library/DxeServicesTableLib.h>
20 #include <IndustryStandard/Acpi.h>
22 #include <Protocol/PciRootBridgeIo.h>
25 EFI_PHYSICAL_ADDRESS AllocAddress
;
27 EFI_PCI_IO_PROTOCOL_OPERATION Operation
;
29 } NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
;
32 Get the resource associated with BAR number 'BarIndex'.
34 @param Dev Point to the NON_DISCOVERABLE_PCI_DEVICE instance.
35 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
36 base address for the memory operation to perform.
37 @param Descriptor Points to the address space descriptor
42 IN NON_DISCOVERABLE_PCI_DEVICE
*Dev
,
44 OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptor
47 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
49 if (BarIndex
< Dev
->BarOffset
) {
53 BarIndex
-= (UINT8
)Dev
->BarOffset
;
55 if (BarIndex
>= Dev
->BarCount
) {
56 return EFI_UNSUPPORTED
;
59 for (Desc
= Dev
->Device
->Resources
;
60 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
61 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
74 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
75 satisfied or after a defined duration.
77 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
78 @param Width Signifies the width of the memory or I/O operations.
79 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
80 base address for the memory operation to perform.
81 @param Offset The offset within the selected BAR to start the memory operation.
82 @param Mask Mask used for the polling criteria.
83 @param Value The comparison value used for the polling exit criteria.
84 @param Delay The number of 100 ns units to poll.
85 @param Result Pointer to the last value read from the memory location.
92 IN EFI_PCI_IO_PROTOCOL
*This
,
93 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
103 return EFI_UNSUPPORTED
;
107 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
108 satisfied or after a defined duration.
110 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
111 @param Width Signifies the width of the memory or I/O operations.
112 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
113 base address for the memory operation to perform.
114 @param Offset The offset within the selected BAR to start the memory operation.
115 @param Mask Mask used for the polling criteria.
116 @param Value The comparison value used for the polling exit criteria.
117 @param Delay The number of 100 ns units to poll.
118 @param Result Pointer to the last value read from the memory location.
125 IN EFI_PCI_IO_PROTOCOL
*This
,
126 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
136 return EFI_UNSUPPORTED
;
140 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
142 @param Width Signifies the width of the memory or I/O operations.
143 @param Count The number of memory or I/O operations to perform.
144 @param DstStride The stride of the destination buffer.
145 @param Dst For read operations, the destination buffer to store the results. For write
146 operations, the destination buffer to write data to.
147 @param SrcStride The stride of the source buffer.
148 @param Src For read operations, the source buffer to read data from. For write
149 operations, the source buffer to write data from.
151 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
152 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
159 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
167 volatile UINT8
*Dst8
;
168 volatile UINT16
*Dst16
;
169 volatile UINT32
*Dst32
;
170 volatile CONST UINT8
*Src8
;
171 volatile CONST UINT16
*Src16
;
172 volatile CONST UINT32
*Src32
;
175 // Loop for each iteration and move the data
177 switch (Width
& 0x3) {
178 case EfiPciWidthUint8
:
181 for (;Count
> 0; Count
--, Dst8
+= DstStride
, Src8
+= SrcStride
) {
185 case EfiPciWidthUint16
:
186 Dst16
= (UINT16
*)Dst
;
187 Src16
= (UINT16
*)Src
;
188 for (;Count
> 0; Count
--, Dst16
+= DstStride
, Src16
+= SrcStride
) {
192 case EfiPciWidthUint32
:
193 Dst32
= (UINT32
*)Dst
;
194 Src32
= (UINT32
*)Src
;
195 for (;Count
> 0; Count
--, Dst32
+= DstStride
, Src32
+= SrcStride
) {
200 return EFI_INVALID_PARAMETER
;
207 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
209 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
210 @param Width Signifies the width of the memory or I/O operations.
211 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
212 base address for the memory or I/O operation to perform.
213 @param Offset The offset within the selected BAR to start the memory or I/O operation.
214 @param Count The number of memory or I/O operations to perform.
215 @param Buffer For read operations, the destination buffer to store the results. For write
216 operations, the source buffer to write data from.
218 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
219 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
220 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
221 valid for the PCI BAR specified by BarIndex.
222 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
223 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
230 IN EFI_PCI_IO_PROTOCOL
*This
,
231 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
238 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
241 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
244 if (Buffer
== NULL
) {
245 return EFI_INVALID_PARAMETER
;
248 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
251 // Only allow accesses to the BARs we emulate
253 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
254 if (EFI_ERROR (Status
)) {
258 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
259 return EFI_UNSUPPORTED
;
262 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
263 AlignMask
= (1 << (Width
& 0x03)) - 1;
264 if ((UINTN
)Address
& AlignMask
) {
265 return EFI_INVALID_PARAMETER
;
269 case EfiPciIoWidthUint8
:
270 case EfiPciIoWidthUint16
:
271 case EfiPciIoWidthUint32
:
272 case EfiPciIoWidthUint64
:
273 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
275 case EfiPciIoWidthFifoUint8
:
276 case EfiPciIoWidthFifoUint16
:
277 case EfiPciIoWidthFifoUint32
:
278 case EfiPciIoWidthFifoUint64
:
279 return PciIoMemRW (Width
, Count
, 1, Buffer
, 0, Address
);
281 case EfiPciIoWidthFillUint8
:
282 case EfiPciIoWidthFillUint16
:
283 case EfiPciIoWidthFillUint32
:
284 case EfiPciIoWidthFillUint64
:
285 return PciIoMemRW (Width
, Count
, 0, Buffer
, 1, Address
);
290 return EFI_INVALID_PARAMETER
;
294 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
296 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
297 @param Width Signifies the width of the memory or I/O operations.
298 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
299 base address for the memory or I/O operation to perform.
300 @param Offset The offset within the selected BAR to start the memory or I/O operation.
301 @param Count The number of memory or I/O operations to perform.
302 @param Buffer For read operations, the destination buffer to store the results. For write
303 operations, the source buffer to write data from.
305 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
306 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
307 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
308 valid for the PCI BAR specified by BarIndex.
309 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
310 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
317 IN EFI_PCI_IO_PROTOCOL
*This
,
318 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
325 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
328 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
331 if (Buffer
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
335 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
338 // Only allow accesses to the BARs we emulate
340 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
341 if (EFI_ERROR (Status
)) {
345 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
346 return EFI_UNSUPPORTED
;
349 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
350 AlignMask
= (1 << (Width
& 0x03)) - 1;
351 if ((UINTN
)Address
& AlignMask
) {
352 return EFI_INVALID_PARAMETER
;
356 case EfiPciIoWidthUint8
:
357 case EfiPciIoWidthUint16
:
358 case EfiPciIoWidthUint32
:
359 case EfiPciIoWidthUint64
:
360 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
362 case EfiPciIoWidthFifoUint8
:
363 case EfiPciIoWidthFifoUint16
:
364 case EfiPciIoWidthFifoUint32
:
365 case EfiPciIoWidthFifoUint64
:
366 return PciIoMemRW (Width
, Count
, 0, Address
, 1, Buffer
);
368 case EfiPciIoWidthFillUint8
:
369 case EfiPciIoWidthFillUint16
:
370 case EfiPciIoWidthFillUint32
:
371 case EfiPciIoWidthFillUint64
:
372 return PciIoMemRW (Width
, Count
, 1, Address
, 0, Buffer
);
377 return EFI_INVALID_PARAMETER
;
381 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
383 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
384 @param Width Signifies the width of the memory or I/O operations.
385 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
386 base address for the memory or I/O operation to perform.
387 @param Offset The offset within the selected BAR to start the memory or I/O operation.
388 @param Count The number of memory or I/O operations to perform.
389 @param Buffer For read operations, the destination buffer to store the results. For write
390 operations, the source buffer to write data from.
397 IN EFI_PCI_IO_PROTOCOL
*This
,
398 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
406 return EFI_UNSUPPORTED
;
410 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
412 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
413 @param Width Signifies the width of the memory or I/O operations.
414 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
415 base address for the memory or I/O operation to perform.
416 @param Offset The offset within the selected BAR to start the memory or I/O operation.
417 @param Count The number of memory or I/O operations to perform.
418 @param Buffer For read operations, the destination buffer to store the results. For write
419 operations, the source buffer to write data from.
426 IN EFI_PCI_IO_PROTOCOL
*This
,
427 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
435 return EFI_UNSUPPORTED
;
439 Enable a PCI driver to access PCI config space.
441 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
442 @param Width Signifies the width of the memory or I/O operations.
443 @param Offset The offset within the selected BAR to start the memory or I/O operation.
444 @param Count The number of memory or I/O operations to perform.
445 @param Buffer For read operations, the destination buffer to store the results. For write
446 operations, the source buffer to write data from.
453 IN EFI_PCI_IO_PROTOCOL
*This
,
454 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
460 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
464 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
465 return EFI_INVALID_PARAMETER
;
468 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
469 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
470 Length
= Count
<< ((UINTN
)Width
& 0x3);
472 if (Offset
>= sizeof (Dev
->ConfigSpace
)) {
473 ZeroMem (Buffer
, Length
);
477 if (Offset
+ Length
> sizeof (Dev
->ConfigSpace
)) {
479 // Read all zeroes for config space accesses beyond the first
482 Length
-= sizeof (Dev
->ConfigSpace
) - Offset
;
483 ZeroMem ((UINT8
*)Buffer
+ sizeof (Dev
->ConfigSpace
) - Offset
, Length
);
485 Count
-= Length
>> ((UINTN
)Width
& 0x3);
487 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
491 Enable a PCI driver to access PCI config space.
493 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
494 @param Width Signifies the width of the memory or I/O operations.
495 @param Offset The offset within the selected BAR to start the memory or I/O operation.
496 @param Count The number of memory or I/O operations to perform.
497 @param Buffer For read operations, the destination buffer to store the results. For write
498 operations, the source buffer to write data from
500 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
501 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
502 valid for the PCI BAR specified by BarIndex.
503 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
510 IN EFI_PCI_IO_PROTOCOL
*This
,
511 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
517 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
520 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
521 return EFI_INVALID_PARAMETER
;
524 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
525 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
527 if (Offset
+ (Count
<< ((UINTN
)Width
& 0x3)) > sizeof (Dev
->ConfigSpace
)) {
528 return EFI_UNSUPPORTED
;
531 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
535 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
538 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
539 @param Width Signifies the width of the memory operations.
540 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
541 base address for the memory operation to perform.
542 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
543 start the memory writes for the copy operation.
544 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
545 base address for the memory operation to perform.
546 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
547 the memory reads for the copy operation.
548 @param Count The number of memory operations to perform. Bytes moved is Width
549 size * Count, starting at DestOffset and SrcOffset.
556 IN EFI_PCI_IO_PROTOCOL
*This
,
557 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
558 IN UINT8 DestBarIndex
,
559 IN UINT64 DestOffset
,
560 IN UINT8 SrcBarIndex
,
566 return EFI_UNSUPPORTED
;
570 Provides the PCI controller-specific addresses needed to access system memory.
572 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
573 @param Operation Indicates if the bus master is going to read or write to system memory.
574 @param HostAddress The system memory address to map to the PCI controller.
575 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
577 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
578 access the hosts HostAddress.
579 @param Mapping A resulting value to pass to Unmap().
581 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
582 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
583 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
584 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
585 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
592 IN EFI_PCI_IO_PROTOCOL
*This
,
593 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
594 IN VOID
*HostAddress
,
595 IN OUT UINTN
*NumberOfBytes
,
596 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
600 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
602 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
604 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
605 Operation
!= EfiPciIoOperationBusMasterWrite
&&
606 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
607 return EFI_INVALID_PARAMETER
;
610 if (HostAddress
== NULL
||
611 NumberOfBytes
== NULL
||
612 DeviceAddress
== NULL
||
614 return EFI_INVALID_PARAMETER
;
618 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
619 // addressing, we need to allocate a bounce buffer and copy over the data.
621 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
622 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
623 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
) {
626 // Bounce buffering is not possible for consistent mappings
628 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
629 return EFI_UNSUPPORTED
;
632 MapInfo
= AllocatePool (sizeof *MapInfo
);
633 if (MapInfo
== NULL
) {
634 return EFI_OUT_OF_RESOURCES
;
637 MapInfo
->AllocAddress
= MAX_UINT32
;
638 MapInfo
->HostAddress
= HostAddress
;
639 MapInfo
->Operation
= Operation
;
640 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
642 Status
= gBS
->AllocatePages (AllocateMaxAddress
, EfiBootServicesData
,
643 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
644 &MapInfo
->AllocAddress
);
645 if (EFI_ERROR (Status
)) {
647 // If we fail here, it is likely because the system has no memory below
648 // 4 GB to begin with. There is not much we can do about that other than
649 // fail the map request.
652 return EFI_DEVICE_ERROR
;
654 if (Operation
== EfiPciIoOperationBusMasterRead
) {
655 gBS
->CopyMem ((VOID
*)(UINTN
)MapInfo
->AllocAddress
, HostAddress
,
658 *DeviceAddress
= MapInfo
->AllocAddress
;
661 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
668 Completes the Map() operation and releases any corresponding resources.
670 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
671 @param Mapping The mapping value returned from Map().
673 @retval EFI_SUCCESS The range was unmapped.
680 IN EFI_PCI_IO_PROTOCOL
*This
,
684 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
687 if (MapInfo
!= NULL
) {
688 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
689 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
690 MapInfo
->NumberOfBytes
);
692 gBS
->FreePages (MapInfo
->AllocAddress
,
693 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
));
702 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
703 @param Type This parameter is not used and must be ignored.
704 @param MemoryType The type of memory to allocate, EfiBootServicesData or
705 EfiRuntimeServicesData.
706 @param Pages The number of pages to allocate.
707 @param HostAddress A pointer to store the base system memory address of the
709 @param Attributes The requested bit mask of attributes for the allocated range.
711 @retval EFI_SUCCESS The requested memory pages were allocated.
712 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
713 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
714 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
715 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
721 CoherentPciIoAllocateBuffer (
722 IN EFI_PCI_IO_PROTOCOL
*This
,
723 IN EFI_ALLOCATE_TYPE Type
,
724 IN EFI_MEMORY_TYPE MemoryType
,
726 OUT VOID
**HostAddress
,
730 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
731 EFI_PHYSICAL_ADDRESS AllocAddress
;
732 EFI_ALLOCATE_TYPE AllocType
;
735 if ((Attributes
& ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
736 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
737 return EFI_UNSUPPORTED
;
740 if ((MemoryType
!= EfiBootServicesData
) &&
741 (MemoryType
!= EfiRuntimeServicesData
)) {
742 return EFI_INVALID_PARAMETER
;
746 // Allocate below 4 GB if the dual address cycle attribute has not
747 // been set. If the system has no memory available below 4 GB, there
748 // is little we can do except propagate the error.
750 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
751 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
752 AllocAddress
= MAX_UINT32
;
753 AllocType
= AllocateMaxAddress
;
755 AllocType
= AllocateAnyPages
;
758 Status
= gBS
->AllocatePages (AllocType
, MemoryType
, Pages
, &AllocAddress
);
759 if (!EFI_ERROR (Status
)) {
760 *HostAddress
= (VOID
*)(UINTN
)AllocAddress
;
766 Frees memory that was allocated in function CoherentPciIoAllocateBuffer ().
768 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
769 @param Pages The number of pages to free.
770 @param HostAddress The base system memory address of the allocated range.
772 @retval EFI_SUCCESS The requested memory pages were freed.
778 CoherentPciIoFreeBuffer (
779 IN EFI_PCI_IO_PROTOCOL
*This
,
784 FreePages (HostAddress
, Pages
);
789 Frees memory that was allocated in function NonCoherentPciIoAllocateBuffer ().
791 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
792 @param Pages The number of pages to free.
793 @param HostAddress The base system memory address of the allocated range.
795 @retval EFI_SUCCESS The requested memory pages were freed.
796 @retval others The operation contain some errors.
802 NonCoherentPciIoFreeBuffer (
803 IN EFI_PCI_IO_PROTOCOL
*This
,
808 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
811 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
814 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
820 // Find the uncached allocation list entry associated
821 // with this allocation
823 for (Entry
= Dev
->UncachedAllocationList
.ForwardLink
;
824 Entry
!= &Dev
->UncachedAllocationList
;
825 Entry
= Entry
->ForwardLink
) {
827 Alloc
= BASE_CR (Entry
, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
, List
);
828 if (Alloc
->HostAddress
== HostAddress
&& Alloc
->NumPages
== Pages
) {
830 // We are freeing the exact allocation we were given
831 // before by AllocateBuffer()
839 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
840 return EFI_NOT_FOUND
;
843 RemoveEntryList (&Alloc
->List
);
845 Status
= gDS
->SetMemorySpaceAttributes (
846 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
847 EFI_PAGES_TO_SIZE (Pages
),
849 if (EFI_ERROR (Status
)) {
854 // If we fail to restore the original attributes, it is better to leak the
855 // memory than to return it to the heap
857 FreePages (HostAddress
, Pages
);
867 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
868 @param Type This parameter is not used and must be ignored.
869 @param MemoryType The type of memory to allocate, EfiBootServicesData or
870 EfiRuntimeServicesData.
871 @param Pages The number of pages to allocate.
872 @param HostAddress A pointer to store the base system memory address of the
874 @param Attributes The requested bit mask of attributes for the allocated range.
876 @retval EFI_SUCCESS The requested memory pages were allocated.
877 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
878 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
879 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
880 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
886 NonCoherentPciIoAllocateBuffer (
887 IN EFI_PCI_IO_PROTOCOL
*This
,
888 IN EFI_ALLOCATE_TYPE Type
,
889 IN EFI_MEMORY_TYPE MemoryType
,
891 OUT VOID
**HostAddress
,
895 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
896 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
899 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
902 if (HostAddress
== NULL
) {
903 return EFI_INVALID_PARAMETER
;
906 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
908 Status
= CoherentPciIoAllocateBuffer (This
, Type
, MemoryType
, Pages
,
909 &AllocAddress
, Attributes
);
910 if (EFI_ERROR (Status
)) {
914 Status
= gDS
->GetMemorySpaceDescriptor (
915 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
917 if (EFI_ERROR (Status
)) {
921 if ((GcdDescriptor
.Capabilities
& (EFI_MEMORY_WC
| EFI_MEMORY_UC
)) == 0) {
922 Status
= EFI_UNSUPPORTED
;
927 // Set the preferred memory attributes
929 if ((Attributes
& EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
) != 0 ||
930 (GcdDescriptor
.Capabilities
& EFI_MEMORY_UC
) == 0) {
932 // Use write combining if it was requested, or if it is the only
933 // type supported by the region.
935 MemType
= EFI_MEMORY_WC
;
937 MemType
= EFI_MEMORY_UC
;
940 Alloc
= AllocatePool (sizeof *Alloc
);
945 Alloc
->HostAddress
= AllocAddress
;
946 Alloc
->NumPages
= Pages
;
947 Alloc
->Attributes
= GcdDescriptor
.Attributes
;
950 // Record this allocation in the linked list, so we
951 // can restore the memory space attributes later
953 InsertHeadList (&Dev
->UncachedAllocationList
, &Alloc
->List
);
955 Status
= gDS
->SetMemorySpaceAttributes (
956 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
957 EFI_PAGES_TO_SIZE (Pages
),
959 if (EFI_ERROR (Status
)) {
963 Status
= mCpu
->FlushDataCache (
965 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
966 EFI_PAGES_TO_SIZE (Pages
),
967 EfiCpuFlushTypeInvalidate
);
968 if (EFI_ERROR (Status
)) {
972 *HostAddress
= AllocAddress
;
977 RemoveEntryList (&Alloc
->List
);
981 CoherentPciIoFreeBuffer (This
, Pages
, AllocAddress
);
986 Provides the PCI controller-specific addresses needed to access system memory.
988 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
989 @param Operation Indicates if the bus master is going to read or write to system memory.
990 @param HostAddress The system memory address to map to the PCI controller.
991 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
993 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
994 access the hosts HostAddress.
995 @param Mapping A resulting value to pass to Unmap().
997 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
998 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
999 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1000 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1001 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1007 NonCoherentPciIoMap (
1008 IN EFI_PCI_IO_PROTOCOL
*This
,
1009 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
1010 IN VOID
*HostAddress
,
1011 IN OUT UINTN
*NumberOfBytes
,
1012 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1016 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1018 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1021 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1024 if (HostAddress
== NULL
||
1025 NumberOfBytes
== NULL
||
1026 DeviceAddress
== NULL
||
1028 return EFI_INVALID_PARAMETER
;
1031 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
1032 Operation
!= EfiPciIoOperationBusMasterWrite
&&
1033 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
1034 return EFI_INVALID_PARAMETER
;
1037 MapInfo
= AllocatePool (sizeof *MapInfo
);
1038 if (MapInfo
== NULL
) {
1039 return EFI_OUT_OF_RESOURCES
;
1042 MapInfo
->HostAddress
= HostAddress
;
1043 MapInfo
->Operation
= Operation
;
1044 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1046 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1049 // If this device does not support 64-bit DMA addressing, we need to allocate
1050 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
1052 Bounce
= ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
1053 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
);
1056 switch (Operation
) {
1057 case EfiPciIoOperationBusMasterRead
:
1058 case EfiPciIoOperationBusMasterWrite
:
1060 // For streaming DMA, it is sufficient if the buffer is aligned to
1061 // the CPUs DMA buffer alignment.
1063 AlignMask
= mCpu
->DmaBufferAlignment
- 1;
1064 if ((((UINTN
) HostAddress
| *NumberOfBytes
) & AlignMask
) == 0) {
1069 case EfiPciIoOperationBusMasterCommonBuffer
:
1071 // Check whether the host address refers to an uncached mapping.
1073 Status
= gDS
->GetMemorySpaceDescriptor (
1074 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1076 if (EFI_ERROR (Status
) ||
1077 (GcdDescriptor
.Attributes
& (EFI_MEMORY_WB
|EFI_MEMORY_WT
)) != 0) {
1088 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
1089 Status
= EFI_DEVICE_ERROR
;
1093 Status
= NonCoherentPciIoAllocateBuffer (This
, AllocateAnyPages
,
1094 EfiBootServicesData
, EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1095 &AllocAddress
, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
);
1096 if (EFI_ERROR (Status
)) {
1099 MapInfo
->AllocAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
;
1100 if (Operation
== EfiPciIoOperationBusMasterRead
) {
1101 gBS
->CopyMem (AllocAddress
, HostAddress
, *NumberOfBytes
);
1103 *DeviceAddress
= MapInfo
->AllocAddress
;
1105 MapInfo
->AllocAddress
= 0;
1106 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
1109 // We are not using a bounce buffer: the mapping is sufficiently
1110 // aligned to allow us to simply flush the caches. Note that cleaning
1111 // the caches is necessary for both data directions:
1112 // - for bus master read, we want the latest data to be present
1114 // - for bus master write, we don't want any stale dirty cachelines that
1115 // may be written back unexpectedly, and clobber the data written to
1116 // main memory by the device.
1118 mCpu
->FlushDataCache (mCpu
, (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1119 *NumberOfBytes
, EfiCpuFlushTypeWriteBack
);
1132 Completes the Map() operation and releases any corresponding resources.
1134 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1135 @param Mapping The mapping value returned from Map().
1137 @retval EFI_SUCCESS The range was unmapped.
1143 NonCoherentPciIoUnmap (
1144 IN EFI_PCI_IO_PROTOCOL
*This
,
1148 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1150 if (Mapping
== NULL
) {
1151 return EFI_DEVICE_ERROR
;
1155 if (MapInfo
->AllocAddress
!= 0) {
1157 // We are using a bounce buffer: copy back the data if necessary,
1158 // and free the buffer.
1160 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1161 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
1162 MapInfo
->NumberOfBytes
);
1164 NonCoherentPciIoFreeBuffer (This
,
1165 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1166 (VOID
*)(UINTN
)MapInfo
->AllocAddress
);
1169 // We are *not* using a bounce buffer: if this is a bus master write,
1170 // we have to invalidate the caches so the CPU will see the uncached
1171 // data written by the device.
1173 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1174 mCpu
->FlushDataCache (mCpu
,
1175 (EFI_PHYSICAL_ADDRESS
)(UINTN
)MapInfo
->HostAddress
,
1176 MapInfo
->NumberOfBytes
, EfiCpuFlushTypeInvalidate
);
1184 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1186 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1193 IN EFI_PCI_IO_PROTOCOL
*This
1200 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1202 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1203 @param SegmentNumber The PCI controller's current PCI segment number.
1204 @param BusNumber The PCI controller's current PCI bus number.
1205 @param DeviceNumber The PCI controller's current PCI device number.
1206 @param FunctionNumber The PCI controller's current PCI function number.
1208 @retval EFI_SUCCESS The PCI controller location was returned.
1209 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1216 IN EFI_PCI_IO_PROTOCOL
*This
,
1217 OUT UINTN
*SegmentNumber
,
1218 OUT UINTN
*BusNumber
,
1219 OUT UINTN
*DeviceNumber
,
1220 OUT UINTN
*FunctionNumber
1223 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1225 if (SegmentNumber
== NULL
||
1226 BusNumber
== NULL
||
1227 DeviceNumber
== NULL
||
1228 FunctionNumber
== NULL
) {
1229 return EFI_INVALID_PARAMETER
;
1232 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1234 *SegmentNumber
= 0xff;
1235 *BusNumber
= Dev
->UniqueId
>> 5;
1236 *DeviceNumber
= Dev
->UniqueId
& 0x1f;
1237 *FunctionNumber
= 0;
1243 Performs an operation on the attributes that this PCI controller supports. The operations include
1244 getting the set of supported attributes, retrieving the current attributes, setting the current
1245 attributes, enabling attributes, and disabling attributes.
1247 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1248 @param Operation The operation to perform on the attributes for this PCI controller.
1249 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1251 @param Result A pointer to the result mask of attributes that are returned for the Get
1252 and Supported operations.
1254 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1255 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1256 @retval EFI_UNSUPPORTED one or more of the bits set in
1257 Attributes are not supported by this PCI controller or one of
1258 its parent bridges when Operation is Set, Enable or Disable.
1265 IN EFI_PCI_IO_PROTOCOL
*This
,
1266 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1267 IN UINT64 Attributes
,
1268 OUT UINT64
*Result OPTIONAL
1271 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1274 #define DEV_SUPPORTED_ATTRIBUTES \
1275 (EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
1277 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1279 if ((Attributes
& (~(DEV_SUPPORTED_ATTRIBUTES
))) != 0) {
1280 return EFI_UNSUPPORTED
;
1284 switch (Operation
) {
1285 case EfiPciIoAttributeOperationGet
:
1286 if (Result
== NULL
) {
1287 return EFI_INVALID_PARAMETER
;
1289 *Result
= Dev
->Attributes
;
1292 case EfiPciIoAttributeOperationSupported
:
1293 if (Result
== NULL
) {
1294 return EFI_INVALID_PARAMETER
;
1296 *Result
= DEV_SUPPORTED_ATTRIBUTES
;
1299 case EfiPciIoAttributeOperationEnable
:
1300 Attributes
|= Dev
->Attributes
;
1301 case EfiPciIoAttributeOperationSet
:
1302 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
1303 Dev
->Attributes
= Attributes
;
1306 case EfiPciIoAttributeOperationDisable
:
1307 Dev
->Attributes
&= ~Attributes
;
1311 return EFI_INVALID_PARAMETER
;
1315 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
1316 // the device specific initialization now.
1318 if (Enable
&& !Dev
->Enabled
&& Dev
->Device
->Initialize
!= NULL
) {
1319 Dev
->Device
->Initialize (Dev
->Device
);
1320 Dev
->Enabled
= TRUE
;
1326 Gets the attributes that this PCI controller supports setting on a BAR using
1327 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1329 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1330 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1331 base address for resource range. The legal range for this field is 0..5.
1332 @param Supports A pointer to the mask of attributes that this PCI controller supports
1333 setting for this BAR with SetBarAttributes().
1334 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1335 configuration of this BAR of the PCI controller.
1337 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1338 controller supports are returned in Supports. If Resources
1339 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1340 controller is currently using are returned in Resources.
1341 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1342 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1343 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1350 PciIoGetBarAttributes (
1351 IN EFI_PCI_IO_PROTOCOL
*This
,
1353 OUT UINT64
*Supports OPTIONAL
,
1354 OUT VOID
**Resources OPTIONAL
1357 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1358 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1359 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
1360 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1363 if (Supports
== NULL
&& Resources
== NULL
) {
1364 return EFI_INVALID_PARAMETER
;
1367 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1369 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
1370 if (EFI_ERROR (Status
)) {
1375 // Don't expose any configurable attributes for our emulated BAR
1377 if (Supports
!= NULL
) {
1381 if (Resources
!= NULL
) {
1382 Descriptor
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1383 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1384 if (Descriptor
== NULL
) {
1385 return EFI_OUT_OF_RESOURCES
;
1388 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
1390 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1391 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1394 *Resources
= Descriptor
;
1400 Sets the attributes for a range of a BAR on a PCI controller.
1402 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1403 @param Attributes The mask of attributes to set for the resource range specified by
1404 BarIndex, Offset, and Length.
1405 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1406 base address for resource range. The legal range for this field is 0..5.
1407 @param Offset A pointer to the BAR relative base address of the resource range to be
1408 modified by the attributes specified by Attributes.
1409 @param Length A pointer to the length of the resource range to be modified by the
1410 attributes specified by Attributes.
1415 PciIoSetBarAttributes (
1416 IN EFI_PCI_IO_PROTOCOL
*This
,
1417 IN UINT64 Attributes
,
1419 IN OUT UINT64
*Offset
,
1420 IN OUT UINT64
*Length
1424 return EFI_UNSUPPORTED
;
1427 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
1431 { PciIoMemRead
, PciIoMemWrite
},
1432 { PciIoIoRead
, PciIoIoWrite
},
1433 { PciIoPciRead
, PciIoPciWrite
},
1437 CoherentPciIoAllocateBuffer
,
1438 CoherentPciIoFreeBuffer
,
1442 PciIoGetBarAttributes
,
1443 PciIoSetBarAttributes
,
1449 Initialize PciIo Protocol.
1451 @param Dev Point to NON_DISCOVERABLE_PCI_DEVICE instance.
1455 InitializePciIoProtocol (
1456 NON_DISCOVERABLE_PCI_DEVICE
*Dev
1459 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1462 InitializeListHead (&Dev
->UncachedAllocationList
);
1464 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
1465 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
1467 // Copy protocol structure
1468 CopyMem(&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
1470 if (Dev
->Device
->DmaType
== NonDiscoverableDeviceDmaTypeNonCoherent
) {
1471 Dev
->PciIo
.AllocateBuffer
= NonCoherentPciIoAllocateBuffer
;
1472 Dev
->PciIo
.FreeBuffer
= NonCoherentPciIoFreeBuffer
;
1473 Dev
->PciIo
.Map
= NonCoherentPciIoMap
;
1474 Dev
->PciIo
.Unmap
= NonCoherentPciIoUnmap
;
1477 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
1478 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
1479 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
1480 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1482 } else if (CompareGuid (Dev
->Device
->Type
,
1483 &gEdkiiNonDiscoverableEhciDeviceGuid
)) {
1484 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
1485 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1486 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1488 } else if (CompareGuid (Dev
->Device
->Type
,
1489 &gEdkiiNonDiscoverableNvmeDeviceGuid
)) {
1490 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
1491 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
1492 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1494 } else if (CompareGuid (Dev
->Device
->Type
,
1495 &gEdkiiNonDiscoverableOhciDeviceGuid
)) {
1496 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
1497 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1498 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1500 } else if (CompareGuid (Dev
->Device
->Type
,
1501 &gEdkiiNonDiscoverableSdhciDeviceGuid
)) {
1502 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1503 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
1504 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
1506 } else if (CompareGuid (Dev
->Device
->Type
,
1507 &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
1508 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
1509 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1510 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1512 } else if (CompareGuid (Dev
->Device
->Type
,
1513 &gEdkiiNonDiscoverableUhciDeviceGuid
)) {
1514 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
1515 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1516 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1518 } else if (CompareGuid (Dev
->Device
->Type
,
1519 &gEdkiiNonDiscoverableUfsDeviceGuid
)) {
1520 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1521 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
1522 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1525 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
1529 // Iterate over the resources to populate the virtual BARs
1531 Idx
= Dev
->BarOffset
;
1532 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
1533 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
1534 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
1536 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1537 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
1539 if (Idx
>= PCI_MAX_BARS
||
1540 (Idx
== PCI_MAX_BARS
- 1 && Desc
->AddrSpaceGranularity
== 64)) {
1541 DEBUG ((DEBUG_ERROR
,
1542 "%a: resource count exceeds number of emulated BARs\n",
1548 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
1551 if (Desc
->AddrSpaceGranularity
== 64) {
1552 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
1553 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (
1554 Desc
->AddrRangeMin
, 32);