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
,
97 return EFI_UNSUPPORTED
;
101 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
102 satisfied or after a defined duration.
104 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
105 @param Width Signifies the width of the memory or I/O operations.
106 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
107 base address for the memory operation to perform.
108 @param Offset The offset within the selected BAR to start the memory operation.
109 @param Mask Mask used for the polling criteria.
110 @param Value The comparison value used for the polling exit criteria.
111 @param Delay The number of 100 ns units to poll.
112 @param Result Pointer to the last value read from the memory location.
119 IN EFI_PCI_IO_PROTOCOL
*This
,
120 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
130 return EFI_UNSUPPORTED
;
134 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
136 @param Width Signifies the width of the memory or I/O operations.
137 @param Count The number of memory or I/O operations to perform.
138 @param DstStride The stride of the destination buffer.
139 @param Dst For read operations, the destination buffer to store the results. For write
140 operations, the destination buffer to write data to.
141 @param SrcStride The stride of the source buffer.
142 @param Src For read operations, the source buffer to read data from. For write
143 operations, the source buffer to write data from.
145 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
146 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
153 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
161 volatile UINT8
*Dst8
;
162 volatile UINT16
*Dst16
;
163 volatile UINT32
*Dst32
;
164 volatile CONST UINT8
*Src8
;
165 volatile CONST UINT16
*Src16
;
166 volatile CONST UINT32
*Src32
;
169 // Loop for each iteration and move the data
171 switch (Width
& 0x3) {
172 case EfiPciWidthUint8
:
175 for (;Count
> 0; Count
--, Dst8
+= DstStride
, Src8
+= SrcStride
) {
179 case EfiPciWidthUint16
:
180 Dst16
= (UINT16
*)Dst
;
181 Src16
= (UINT16
*)Src
;
182 for (;Count
> 0; Count
--, Dst16
+= DstStride
, Src16
+= SrcStride
) {
186 case EfiPciWidthUint32
:
187 Dst32
= (UINT32
*)Dst
;
188 Src32
= (UINT32
*)Src
;
189 for (;Count
> 0; Count
--, Dst32
+= DstStride
, Src32
+= SrcStride
) {
194 return EFI_INVALID_PARAMETER
;
201 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
203 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
204 @param Width Signifies the width of the memory or I/O operations.
205 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
206 base address for the memory or I/O operation to perform.
207 @param Offset The offset within the selected BAR to start the memory or I/O operation.
208 @param Count The number of memory or I/O operations to perform.
209 @param Buffer For read operations, the destination buffer to store the results. For write
210 operations, the source buffer to write data from.
212 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
213 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
214 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
215 valid for the PCI BAR specified by BarIndex.
216 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
217 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
224 IN EFI_PCI_IO_PROTOCOL
*This
,
225 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
232 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
235 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
238 if (Buffer
== NULL
) {
239 return EFI_INVALID_PARAMETER
;
242 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
245 // Only allow accesses to the BARs we emulate
247 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
248 if (EFI_ERROR (Status
)) {
252 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
253 return EFI_UNSUPPORTED
;
256 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
257 AlignMask
= (1 << (Width
& 0x03)) - 1;
258 if ((UINTN
)Address
& AlignMask
) {
259 return EFI_INVALID_PARAMETER
;
263 case EfiPciIoWidthUint8
:
264 case EfiPciIoWidthUint16
:
265 case EfiPciIoWidthUint32
:
266 case EfiPciIoWidthUint64
:
267 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
269 case EfiPciIoWidthFifoUint8
:
270 case EfiPciIoWidthFifoUint16
:
271 case EfiPciIoWidthFifoUint32
:
272 case EfiPciIoWidthFifoUint64
:
273 return PciIoMemRW (Width
, Count
, 1, Buffer
, 0, Address
);
275 case EfiPciIoWidthFillUint8
:
276 case EfiPciIoWidthFillUint16
:
277 case EfiPciIoWidthFillUint32
:
278 case EfiPciIoWidthFillUint64
:
279 return PciIoMemRW (Width
, Count
, 0, Buffer
, 1, Address
);
284 return EFI_INVALID_PARAMETER
;
288 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
290 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
291 @param Width Signifies the width of the memory or I/O operations.
292 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
293 base address for the memory or I/O operation to perform.
294 @param Offset The offset within the selected BAR to start the memory or I/O operation.
295 @param Count The number of memory or I/O operations to perform.
296 @param Buffer For read operations, the destination buffer to store the results. For write
297 operations, the source buffer to write data from.
299 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
300 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
301 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
302 valid for the PCI BAR specified by BarIndex.
303 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
304 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
311 IN EFI_PCI_IO_PROTOCOL
*This
,
312 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
319 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
322 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
325 if (Buffer
== NULL
) {
326 return EFI_INVALID_PARAMETER
;
329 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
332 // Only allow accesses to the BARs we emulate
334 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
335 if (EFI_ERROR (Status
)) {
339 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
340 return EFI_UNSUPPORTED
;
343 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
344 AlignMask
= (1 << (Width
& 0x03)) - 1;
345 if ((UINTN
)Address
& AlignMask
) {
346 return EFI_INVALID_PARAMETER
;
350 case EfiPciIoWidthUint8
:
351 case EfiPciIoWidthUint16
:
352 case EfiPciIoWidthUint32
:
353 case EfiPciIoWidthUint64
:
354 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
356 case EfiPciIoWidthFifoUint8
:
357 case EfiPciIoWidthFifoUint16
:
358 case EfiPciIoWidthFifoUint32
:
359 case EfiPciIoWidthFifoUint64
:
360 return PciIoMemRW (Width
, Count
, 0, Address
, 1, Buffer
);
362 case EfiPciIoWidthFillUint8
:
363 case EfiPciIoWidthFillUint16
:
364 case EfiPciIoWidthFillUint32
:
365 case EfiPciIoWidthFillUint64
:
366 return PciIoMemRW (Width
, Count
, 1, Address
, 0, Buffer
);
371 return EFI_INVALID_PARAMETER
;
375 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
377 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
378 @param Width Signifies the width of the memory or I/O operations.
379 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
380 base address for the memory or I/O operation to perform.
381 @param Offset The offset within the selected BAR to start the memory or I/O operation.
382 @param Count The number of memory or I/O operations to perform.
383 @param Buffer For read operations, the destination buffer to store the results. For write
384 operations, the source buffer to write data from.
391 IN EFI_PCI_IO_PROTOCOL
*This
,
392 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
400 return EFI_UNSUPPORTED
;
404 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
406 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
407 @param Width Signifies the width of the memory or I/O operations.
408 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
409 base address for the memory or I/O operation to perform.
410 @param Offset The offset within the selected BAR to start the memory or I/O operation.
411 @param Count The number of memory or I/O operations to perform.
412 @param Buffer For read operations, the destination buffer to store the results. For write
413 operations, the source buffer to write data from.
420 IN EFI_PCI_IO_PROTOCOL
*This
,
421 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
429 return EFI_UNSUPPORTED
;
433 Enable a PCI driver to access PCI config space.
435 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
436 @param Width Signifies the width of the memory or I/O operations.
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
,
454 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
458 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
459 return EFI_INVALID_PARAMETER
;
462 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
463 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
464 Length
= Count
<< ((UINTN
)Width
& 0x3);
466 if (Offset
>= sizeof (Dev
->ConfigSpace
)) {
467 ZeroMem (Buffer
, Length
);
471 if (Offset
+ Length
> sizeof (Dev
->ConfigSpace
)) {
473 // Read all zeroes for config space accesses beyond the first
476 Length
-= sizeof (Dev
->ConfigSpace
) - Offset
;
477 ZeroMem ((UINT8
*)Buffer
+ sizeof (Dev
->ConfigSpace
) - Offset
, Length
);
479 Count
-= Length
>> ((UINTN
)Width
& 0x3);
481 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
485 Enable a PCI driver to access PCI config space.
487 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
488 @param Width Signifies the width of the memory or I/O operations.
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
494 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
495 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
496 valid for the PCI BAR specified by BarIndex.
497 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
504 IN EFI_PCI_IO_PROTOCOL
*This
,
505 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
511 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
514 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
515 return EFI_INVALID_PARAMETER
;
518 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
519 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
521 if (Offset
+ (Count
<< ((UINTN
)Width
& 0x3)) > sizeof (Dev
->ConfigSpace
)) {
522 return EFI_UNSUPPORTED
;
525 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
529 Enables a PCI driver to copy one region of PCI memory space to another region of PCI
532 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
533 @param Width Signifies the width of the memory operations.
534 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the
535 base address for the memory operation to perform.
536 @param DestOffset The destination offset within the BAR specified by DestBarIndex to
537 start the memory writes for the copy operation.
538 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the
539 base address for the memory operation to perform.
540 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start
541 the memory reads for the copy operation.
542 @param Count The number of memory operations to perform. Bytes moved is Width
543 size * Count, starting at DestOffset and SrcOffset.
550 IN EFI_PCI_IO_PROTOCOL
*This
,
551 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
552 IN UINT8 DestBarIndex
,
553 IN UINT64 DestOffset
,
554 IN UINT8 SrcBarIndex
,
560 return EFI_UNSUPPORTED
;
564 Provides the PCI controller-specific addresses needed to access system memory.
566 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
567 @param Operation Indicates if the bus master is going to read or write to system memory.
568 @param HostAddress The system memory address to map to the PCI controller.
569 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
571 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
572 access the hosts HostAddress.
573 @param Mapping A resulting value to pass to Unmap().
575 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
576 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
577 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
578 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
579 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
586 IN EFI_PCI_IO_PROTOCOL
*This
,
587 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
588 IN VOID
*HostAddress
,
589 IN OUT UINTN
*NumberOfBytes
,
590 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
594 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
596 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
598 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
599 Operation
!= EfiPciIoOperationBusMasterWrite
&&
600 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
601 return EFI_INVALID_PARAMETER
;
604 if (HostAddress
== NULL
||
605 NumberOfBytes
== NULL
||
606 DeviceAddress
== NULL
||
608 return EFI_INVALID_PARAMETER
;
612 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
613 // addressing, we need to allocate a bounce buffer and copy over the data.
615 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
616 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
617 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
) {
620 // Bounce buffering is not possible for consistent mappings
622 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
623 return EFI_UNSUPPORTED
;
626 MapInfo
= AllocatePool (sizeof *MapInfo
);
627 if (MapInfo
== NULL
) {
628 return EFI_OUT_OF_RESOURCES
;
631 MapInfo
->AllocAddress
= MAX_UINT32
;
632 MapInfo
->HostAddress
= HostAddress
;
633 MapInfo
->Operation
= Operation
;
634 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
636 Status
= gBS
->AllocatePages (AllocateMaxAddress
, EfiBootServicesData
,
637 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
638 &MapInfo
->AllocAddress
);
639 if (EFI_ERROR (Status
)) {
641 // If we fail here, it is likely because the system has no memory below
642 // 4 GB to begin with. There is not much we can do about that other than
643 // fail the map request.
646 return EFI_DEVICE_ERROR
;
648 if (Operation
== EfiPciIoOperationBusMasterRead
) {
649 gBS
->CopyMem ((VOID
*)(UINTN
)MapInfo
->AllocAddress
, HostAddress
,
652 *DeviceAddress
= MapInfo
->AllocAddress
;
655 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
662 Completes the Map() operation and releases any corresponding resources.
664 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
665 @param Mapping The mapping value returned from Map().
667 @retval EFI_SUCCESS The range was unmapped.
674 IN EFI_PCI_IO_PROTOCOL
*This
,
678 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
681 if (MapInfo
!= NULL
) {
682 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
683 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
684 MapInfo
->NumberOfBytes
);
686 gBS
->FreePages (MapInfo
->AllocAddress
,
687 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
));
696 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
697 @param Type This parameter is not used and must be ignored.
698 @param MemoryType The type of memory to allocate, EfiBootServicesData or
699 EfiRuntimeServicesData.
700 @param Pages The number of pages to allocate.
701 @param HostAddress A pointer to store the base system memory address of the
703 @param Attributes The requested bit mask of attributes for the allocated range.
705 @retval EFI_SUCCESS The requested memory pages were allocated.
706 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
707 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
708 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
709 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
715 CoherentPciIoAllocateBuffer (
716 IN EFI_PCI_IO_PROTOCOL
*This
,
717 IN EFI_ALLOCATE_TYPE Type
,
718 IN EFI_MEMORY_TYPE MemoryType
,
720 OUT VOID
**HostAddress
,
724 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
725 EFI_PHYSICAL_ADDRESS AllocAddress
;
726 EFI_ALLOCATE_TYPE AllocType
;
729 if ((Attributes
& ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
730 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
731 return EFI_UNSUPPORTED
;
734 if ((MemoryType
!= EfiBootServicesData
) &&
735 (MemoryType
!= EfiRuntimeServicesData
)) {
736 return EFI_INVALID_PARAMETER
;
740 // Allocate below 4 GB if the dual address cycle attribute has not
741 // been set. If the system has no memory available below 4 GB, there
742 // is little we can do except propagate the error.
744 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
745 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
746 AllocAddress
= MAX_UINT32
;
747 AllocType
= AllocateMaxAddress
;
749 AllocType
= AllocateAnyPages
;
752 Status
= gBS
->AllocatePages (AllocType
, MemoryType
, Pages
, &AllocAddress
);
753 if (!EFI_ERROR (Status
)) {
754 *HostAddress
= (VOID
*)(UINTN
)AllocAddress
;
760 Frees memory that was allocated in function CoherentPciIoAllocateBuffer ().
762 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
763 @param Pages The number of pages to free.
764 @param HostAddress The base system memory address of the allocated range.
766 @retval EFI_SUCCESS The requested memory pages were freed.
772 CoherentPciIoFreeBuffer (
773 IN EFI_PCI_IO_PROTOCOL
*This
,
778 FreePages (HostAddress
, Pages
);
783 Frees memory that was allocated in function NonCoherentPciIoAllocateBuffer ().
785 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
786 @param Pages The number of pages to free.
787 @param HostAddress The base system memory address of the allocated range.
789 @retval EFI_SUCCESS The requested memory pages were freed.
790 @retval others The operation contain some errors.
796 NonCoherentPciIoFreeBuffer (
797 IN EFI_PCI_IO_PROTOCOL
*This
,
802 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
805 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
808 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
814 // Find the uncached allocation list entry associated
815 // with this allocation
817 for (Entry
= Dev
->UncachedAllocationList
.ForwardLink
;
818 Entry
!= &Dev
->UncachedAllocationList
;
819 Entry
= Entry
->ForwardLink
) {
821 Alloc
= BASE_CR (Entry
, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
, List
);
822 if (Alloc
->HostAddress
== HostAddress
&& Alloc
->NumPages
== Pages
) {
824 // We are freeing the exact allocation we were given
825 // before by AllocateBuffer()
833 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
834 return EFI_NOT_FOUND
;
837 RemoveEntryList (&Alloc
->List
);
839 Status
= gDS
->SetMemorySpaceAttributes (
840 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
841 EFI_PAGES_TO_SIZE (Pages
),
843 if (EFI_ERROR (Status
)) {
848 // If we fail to restore the original attributes, it is better to leak the
849 // memory than to return it to the heap
851 FreePages (HostAddress
, Pages
);
861 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
862 @param Type This parameter is not used and must be ignored.
863 @param MemoryType The type of memory to allocate, EfiBootServicesData or
864 EfiRuntimeServicesData.
865 @param Pages The number of pages to allocate.
866 @param HostAddress A pointer to store the base system memory address of the
868 @param Attributes The requested bit mask of attributes for the allocated range.
870 @retval EFI_SUCCESS The requested memory pages were allocated.
871 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
872 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
873 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
874 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
880 NonCoherentPciIoAllocateBuffer (
881 IN EFI_PCI_IO_PROTOCOL
*This
,
882 IN EFI_ALLOCATE_TYPE Type
,
883 IN EFI_MEMORY_TYPE MemoryType
,
885 OUT VOID
**HostAddress
,
889 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
890 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
893 NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION
*Alloc
;
896 if (HostAddress
== NULL
) {
897 return EFI_INVALID_PARAMETER
;
900 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
902 Status
= CoherentPciIoAllocateBuffer (This
, Type
, MemoryType
, Pages
,
903 &AllocAddress
, Attributes
);
904 if (EFI_ERROR (Status
)) {
908 Status
= gDS
->GetMemorySpaceDescriptor (
909 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
911 if (EFI_ERROR (Status
)) {
915 if ((GcdDescriptor
.Capabilities
& (EFI_MEMORY_WC
| EFI_MEMORY_UC
)) == 0) {
916 Status
= EFI_UNSUPPORTED
;
921 // Set the preferred memory attributes
923 if ((Attributes
& EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
) != 0 ||
924 (GcdDescriptor
.Capabilities
& EFI_MEMORY_UC
) == 0) {
926 // Use write combining if it was requested, or if it is the only
927 // type supported by the region.
929 MemType
= EFI_MEMORY_WC
;
931 MemType
= EFI_MEMORY_UC
;
934 Alloc
= AllocatePool (sizeof *Alloc
);
939 Alloc
->HostAddress
= AllocAddress
;
940 Alloc
->NumPages
= Pages
;
941 Alloc
->Attributes
= GcdDescriptor
.Attributes
;
944 // Record this allocation in the linked list, so we
945 // can restore the memory space attributes later
947 InsertHeadList (&Dev
->UncachedAllocationList
, &Alloc
->List
);
949 Status
= gDS
->SetMemorySpaceAttributes (
950 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
951 EFI_PAGES_TO_SIZE (Pages
),
953 if (EFI_ERROR (Status
)) {
957 Status
= mCpu
->FlushDataCache (
959 (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
,
960 EFI_PAGES_TO_SIZE (Pages
),
961 EfiCpuFlushTypeInvalidate
);
962 if (EFI_ERROR (Status
)) {
966 *HostAddress
= AllocAddress
;
971 RemoveEntryList (&Alloc
->List
);
975 CoherentPciIoFreeBuffer (This
, Pages
, AllocAddress
);
980 Provides the PCI controller-specific addresses needed to access system memory.
982 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
983 @param Operation Indicates if the bus master is going to read or write to system memory.
984 @param HostAddress The system memory address to map to the PCI controller.
985 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
987 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
988 access the hosts HostAddress.
989 @param Mapping A resulting value to pass to Unmap().
991 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
992 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
993 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
994 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
995 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
1001 NonCoherentPciIoMap (
1002 IN EFI_PCI_IO_PROTOCOL
*This
,
1003 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
1004 IN VOID
*HostAddress
,
1005 IN OUT UINTN
*NumberOfBytes
,
1006 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
1010 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1012 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1015 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
1018 if (HostAddress
== NULL
||
1019 NumberOfBytes
== NULL
||
1020 DeviceAddress
== NULL
||
1022 return EFI_INVALID_PARAMETER
;
1025 if (Operation
!= EfiPciIoOperationBusMasterRead
&&
1026 Operation
!= EfiPciIoOperationBusMasterWrite
&&
1027 Operation
!= EfiPciIoOperationBusMasterCommonBuffer
) {
1028 return EFI_INVALID_PARAMETER
;
1031 MapInfo
= AllocatePool (sizeof *MapInfo
);
1032 if (MapInfo
== NULL
) {
1033 return EFI_OUT_OF_RESOURCES
;
1036 MapInfo
->HostAddress
= HostAddress
;
1037 MapInfo
->Operation
= Operation
;
1038 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
1040 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1043 // If this device does not support 64-bit DMA addressing, we need to allocate
1044 // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
1046 Bounce
= ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
1047 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
);
1050 switch (Operation
) {
1051 case EfiPciIoOperationBusMasterRead
:
1052 case EfiPciIoOperationBusMasterWrite
:
1054 // For streaming DMA, it is sufficient if the buffer is aligned to
1055 // the CPUs DMA buffer alignment.
1057 AlignMask
= mCpu
->DmaBufferAlignment
- 1;
1058 if ((((UINTN
) HostAddress
| *NumberOfBytes
) & AlignMask
) == 0) {
1063 case EfiPciIoOperationBusMasterCommonBuffer
:
1065 // Check whether the host address refers to an uncached mapping.
1067 Status
= gDS
->GetMemorySpaceDescriptor (
1068 (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1070 if (EFI_ERROR (Status
) ||
1071 (GcdDescriptor
.Attributes
& (EFI_MEMORY_WB
|EFI_MEMORY_WT
)) != 0) {
1082 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
1083 Status
= EFI_DEVICE_ERROR
;
1087 Status
= NonCoherentPciIoAllocateBuffer (This
, AllocateAnyPages
,
1088 EfiBootServicesData
, EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1089 &AllocAddress
, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
);
1090 if (EFI_ERROR (Status
)) {
1093 MapInfo
->AllocAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)AllocAddress
;
1094 if (Operation
== EfiPciIoOperationBusMasterRead
) {
1095 gBS
->CopyMem (AllocAddress
, HostAddress
, *NumberOfBytes
);
1097 *DeviceAddress
= MapInfo
->AllocAddress
;
1099 MapInfo
->AllocAddress
= 0;
1100 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
1103 // We are not using a bounce buffer: the mapping is sufficiently
1104 // aligned to allow us to simply flush the caches. Note that cleaning
1105 // the caches is necessary for both data directions:
1106 // - for bus master read, we want the latest data to be present
1108 // - for bus master write, we don't want any stale dirty cachelines that
1109 // may be written back unexpectedly, and clobber the data written to
1110 // main memory by the device.
1112 mCpu
->FlushDataCache (mCpu
, (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
,
1113 *NumberOfBytes
, EfiCpuFlushTypeWriteBack
);
1126 Completes the Map() operation and releases any corresponding resources.
1128 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1129 @param Mapping The mapping value returned from Map().
1131 @retval EFI_SUCCESS The range was unmapped.
1137 NonCoherentPciIoUnmap (
1138 IN EFI_PCI_IO_PROTOCOL
*This
,
1142 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
1144 if (Mapping
== NULL
) {
1145 return EFI_DEVICE_ERROR
;
1149 if (MapInfo
->AllocAddress
!= 0) {
1151 // We are using a bounce buffer: copy back the data if necessary,
1152 // and free the buffer.
1154 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1155 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
1156 MapInfo
->NumberOfBytes
);
1158 NonCoherentPciIoFreeBuffer (This
,
1159 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
1160 (VOID
*)(UINTN
)MapInfo
->AllocAddress
);
1163 // We are *not* using a bounce buffer: if this is a bus master write,
1164 // we have to invalidate the caches so the CPU will see the uncached
1165 // data written by the device.
1167 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
1168 mCpu
->FlushDataCache (mCpu
,
1169 (EFI_PHYSICAL_ADDRESS
)(UINTN
)MapInfo
->HostAddress
,
1170 MapInfo
->NumberOfBytes
, EfiCpuFlushTypeInvalidate
);
1178 Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1180 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1187 IN EFI_PCI_IO_PROTOCOL
*This
1194 Retrieves this PCI controller's current PCI bus number, device number, and function number.
1196 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1197 @param SegmentNumber The PCI controller's current PCI segment number.
1198 @param BusNumber The PCI controller's current PCI bus number.
1199 @param DeviceNumber The PCI controller's current PCI device number.
1200 @param FunctionNumber The PCI controller's current PCI function number.
1202 @retval EFI_SUCCESS The PCI controller location was returned.
1203 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1210 IN EFI_PCI_IO_PROTOCOL
*This
,
1211 OUT UINTN
*SegmentNumber
,
1212 OUT UINTN
*BusNumber
,
1213 OUT UINTN
*DeviceNumber
,
1214 OUT UINTN
*FunctionNumber
1217 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1219 if (SegmentNumber
== NULL
||
1220 BusNumber
== NULL
||
1221 DeviceNumber
== NULL
||
1222 FunctionNumber
== NULL
) {
1223 return EFI_INVALID_PARAMETER
;
1226 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1228 *SegmentNumber
= 0xff;
1229 *BusNumber
= Dev
->UniqueId
>> 5;
1230 *DeviceNumber
= Dev
->UniqueId
& 0x1f;
1231 *FunctionNumber
= 0;
1237 Performs an operation on the attributes that this PCI controller supports. The operations include
1238 getting the set of supported attributes, retrieving the current attributes, setting the current
1239 attributes, enabling attributes, and disabling attributes.
1241 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1242 @param Operation The operation to perform on the attributes for this PCI controller.
1243 @param Attributes The mask of attributes that are used for Set, Enable, and Disable
1245 @param Result A pointer to the result mask of attributes that are returned for the Get
1246 and Supported operations.
1248 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.
1249 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1250 @retval EFI_UNSUPPORTED one or more of the bits set in
1251 Attributes are not supported by this PCI controller or one of
1252 its parent bridges when Operation is Set, Enable or Disable.
1259 IN EFI_PCI_IO_PROTOCOL
*This
,
1260 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
1261 IN UINT64 Attributes
,
1262 OUT UINT64
*Result OPTIONAL
1265 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1268 #define DEV_SUPPORTED_ATTRIBUTES \
1269 (EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
1271 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1273 if ((Attributes
& (~(DEV_SUPPORTED_ATTRIBUTES
))) != 0) {
1274 return EFI_UNSUPPORTED
;
1278 switch (Operation
) {
1279 case EfiPciIoAttributeOperationGet
:
1280 if (Result
== NULL
) {
1281 return EFI_INVALID_PARAMETER
;
1283 *Result
= Dev
->Attributes
;
1286 case EfiPciIoAttributeOperationSupported
:
1287 if (Result
== NULL
) {
1288 return EFI_INVALID_PARAMETER
;
1290 *Result
= DEV_SUPPORTED_ATTRIBUTES
;
1293 case EfiPciIoAttributeOperationEnable
:
1294 Attributes
|= Dev
->Attributes
;
1295 case EfiPciIoAttributeOperationSet
:
1296 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
1297 Dev
->Attributes
= Attributes
;
1300 case EfiPciIoAttributeOperationDisable
:
1301 Dev
->Attributes
&= ~Attributes
;
1305 return EFI_INVALID_PARAMETER
;
1309 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
1310 // the device specific initialization now.
1312 if (Enable
&& !Dev
->Enabled
&& Dev
->Device
->Initialize
!= NULL
) {
1313 Dev
->Device
->Initialize (Dev
->Device
);
1314 Dev
->Enabled
= TRUE
;
1320 Gets the attributes that this PCI controller supports setting on a BAR using
1321 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
1323 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1324 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1325 base address for resource range. The legal range for this field is 0..5.
1326 @param Supports A pointer to the mask of attributes that this PCI controller supports
1327 setting for this BAR with SetBarAttributes().
1328 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current
1329 configuration of this BAR of the PCI controller.
1331 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI
1332 controller supports are returned in Supports. If Resources
1333 is not NULL, then the ACPI 2.0 resource descriptors that the PCI
1334 controller is currently using are returned in Resources.
1335 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
1336 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.
1337 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate
1344 PciIoGetBarAttributes (
1345 IN EFI_PCI_IO_PROTOCOL
*This
,
1347 OUT UINT64
*Supports OPTIONAL
,
1348 OUT VOID
**Resources OPTIONAL
1351 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
1352 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1353 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
1354 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1357 if (Supports
== NULL
&& Resources
== NULL
) {
1358 return EFI_INVALID_PARAMETER
;
1361 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
1363 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
1364 if (EFI_ERROR (Status
)) {
1369 // Don't expose any configurable attributes for our emulated BAR
1371 if (Supports
!= NULL
) {
1375 if (Resources
!= NULL
) {
1376 Descriptor
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
1377 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1378 if (Descriptor
== NULL
) {
1379 return EFI_OUT_OF_RESOURCES
;
1382 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
1384 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1385 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1388 *Resources
= Descriptor
;
1394 Sets the attributes for a range of a BAR on a PCI controller.
1396 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
1397 @param Attributes The mask of attributes to set for the resource range specified by
1398 BarIndex, Offset, and Length.
1399 @param BarIndex The BAR index of the standard PCI Configuration header to use as the
1400 base address for resource range. The legal range for this field is 0..5.
1401 @param Offset A pointer to the BAR relative base address of the resource range to be
1402 modified by the attributes specified by Attributes.
1403 @param Length A pointer to the length of the resource range to be modified by the
1404 attributes specified by Attributes.
1409 PciIoSetBarAttributes (
1410 IN EFI_PCI_IO_PROTOCOL
*This
,
1411 IN UINT64 Attributes
,
1413 IN OUT UINT64
*Offset
,
1414 IN OUT UINT64
*Length
1418 return EFI_UNSUPPORTED
;
1421 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
1425 { PciIoMemRead
, PciIoMemWrite
},
1426 { PciIoIoRead
, PciIoIoWrite
},
1427 { PciIoPciRead
, PciIoPciWrite
},
1431 CoherentPciIoAllocateBuffer
,
1432 CoherentPciIoFreeBuffer
,
1436 PciIoGetBarAttributes
,
1437 PciIoSetBarAttributes
,
1443 Initialize PciIo Protocol.
1445 @param Dev Point to NON_DISCOVERABLE_PCI_DEVICE instance.
1449 InitializePciIoProtocol (
1450 NON_DISCOVERABLE_PCI_DEVICE
*Dev
1453 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
1456 InitializeListHead (&Dev
->UncachedAllocationList
);
1458 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
1459 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
1461 // Copy protocol structure
1462 CopyMem(&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
1464 if (Dev
->Device
->DmaType
== NonDiscoverableDeviceDmaTypeNonCoherent
) {
1465 Dev
->PciIo
.AllocateBuffer
= NonCoherentPciIoAllocateBuffer
;
1466 Dev
->PciIo
.FreeBuffer
= NonCoherentPciIoFreeBuffer
;
1467 Dev
->PciIo
.Map
= NonCoherentPciIoMap
;
1468 Dev
->PciIo
.Unmap
= NonCoherentPciIoUnmap
;
1471 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
1472 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
1473 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
1474 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1476 } else if (CompareGuid (Dev
->Device
->Type
,
1477 &gEdkiiNonDiscoverableEhciDeviceGuid
)) {
1478 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
1479 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1480 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1482 } else if (CompareGuid (Dev
->Device
->Type
,
1483 &gEdkiiNonDiscoverableNvmeDeviceGuid
)) {
1484 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
1485 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
1486 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1488 } else if (CompareGuid (Dev
->Device
->Type
,
1489 &gEdkiiNonDiscoverableOhciDeviceGuid
)) {
1490 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
1491 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1492 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1494 } else if (CompareGuid (Dev
->Device
->Type
,
1495 &gEdkiiNonDiscoverableSdhciDeviceGuid
)) {
1496 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1497 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
1498 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
1500 } else if (CompareGuid (Dev
->Device
->Type
,
1501 &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
1502 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
1503 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
1504 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
1506 } else if (CompareGuid (Dev
->Device
->Type
,
1507 &gEdkiiNonDiscoverableUhciDeviceGuid
)) {
1508 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
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 &gEdkiiNonDiscoverableUfsDeviceGuid
)) {
1514 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
1515 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
1516 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
1519 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
1523 // Iterate over the resources to populate the virtual BARs
1525 Idx
= Dev
->BarOffset
;
1526 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
1527 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
1528 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
1530 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1531 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
1533 if (Idx
>= PCI_MAX_BARS
||
1534 (Idx
== PCI_MAX_BARS
- 1 && Desc
->AddrSpaceGranularity
== 64)) {
1535 DEBUG ((DEBUG_ERROR
,
1536 "%a: resource count exceeds number of emulated BARs\n",
1542 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
1545 if (Desc
->AddrSpaceGranularity
== 64) {
1546 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
1547 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (
1548 Desc
->AddrRangeMin
, 32);