2 Functions in this library instance make use of MMIO functions in IoLib to
3 access memory mapped PCI configuration space.
5 All assertions for I/O operations are handled in MMIO functions in the IoLib
8 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
15 #include <Guid/EventGroup.h>
17 #include <Library/BaseLib.h>
18 #include <Library/PciExpressLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PcdLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/DxeServicesTableLib.h>
25 #include <Library/UefiRuntimeLib.h>
28 Assert the validity of a PCI address. A valid PCI address should contain 1's
29 only in the low 28 bits.
31 @param A The address to validate.
34 #define ASSERT_INVALID_PCI_ADDRESS(A) \
35 ASSERT (((A) & ~0xfffffff) == 0)
38 /// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime
41 UINTN PhysicalAddress
;
43 } PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
;
46 /// Set Virtual Address Map Event
48 EFI_EVENT mDxeRuntimePciExpressLibVirtualNotifyEvent
= NULL
;
51 /// Module global that contains the base physical address and size of the PCI Express MMIO range.
53 UINTN mDxeRuntimePciExpressLibPciExpressBaseAddress
= 0;
54 UINTN mDxeRuntimePciExpressLibPciExpressBaseSize
= 0;
57 /// The number of PCI devices that have been registered for runtime access.
59 UINTN mDxeRuntimePciExpressLibNumberOfRuntimeRanges
= 0;
62 /// The table of PCI devices that have been registered for runtime access.
64 PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
*mDxeRuntimePciExpressLibRegistrationTable
= NULL
;
67 /// The table index of the most recent virtual address lookup.
69 UINTN mDxeRuntimePciExpressLibLastRuntimeRange
= 0;
72 Convert the physical PCI Express MMIO addresses for all registered PCI devices
75 @param[in] Event The event that is being processed.
76 @param[in] Context The Event Context.
80 DxeRuntimePciExpressLibVirtualNotify (
88 // If there have been no runtime registrations, then just return
90 if (mDxeRuntimePciExpressLibRegistrationTable
== NULL
) {
95 // Convert physical addresses associated with the set of registered PCI devices to
98 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
99 EfiConvertPointer (0, (VOID
**)&(mDxeRuntimePciExpressLibRegistrationTable
[Index
].VirtualAddress
));
103 // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
105 EfiConvertPointer (0, (VOID
**)&mDxeRuntimePciExpressLibRegistrationTable
);
109 The constructor function caches the PCI Express Base Address and creates a
110 Set Virtual Address Map event to convert physical address to virtual addresses.
112 @param ImageHandle The firmware allocated handle for the EFI image.
113 @param SystemTable A pointer to the EFI System Table.
115 @retval EFI_SUCCESS The constructor completed successfully.
116 @retval Other value The constructor did not complete successfully.
121 DxeRuntimePciExpressLibConstructor (
122 IN EFI_HANDLE ImageHandle
,
123 IN EFI_SYSTEM_TABLE
*SystemTable
129 // Cache the physical address of the PCI Express MMIO range into a module global variable
131 mDxeRuntimePciExpressLibPciExpressBaseAddress
= (UINTN
)PcdGet64 (PcdPciExpressBaseAddress
);
132 mDxeRuntimePciExpressLibPciExpressBaseSize
= (UINTN
)PcdGet64 (PcdPciExpressBaseSize
);
135 // Register SetVirtualAddressMap () notify function
137 Status
= gBS
->CreateEvent (
138 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
,
140 DxeRuntimePciExpressLibVirtualNotify
,
142 &mDxeRuntimePciExpressLibVirtualNotifyEvent
144 ASSERT_EFI_ERROR (Status
);
150 The destructor function frees any allocated buffers and closes the Set Virtual
153 @param ImageHandle The firmware allocated handle for the EFI image.
154 @param SystemTable A pointer to the EFI System Table.
156 @retval EFI_SUCCESS The destructor completed successfully.
157 @retval Other value The destructor did not complete successfully.
162 DxeRuntimePciExpressLibDestructor (
163 IN EFI_HANDLE ImageHandle
,
164 IN EFI_SYSTEM_TABLE
*SystemTable
170 // If one or more PCI devices have been registered for runtime access, then
171 // free the registration table.
173 if (mDxeRuntimePciExpressLibRegistrationTable
!= NULL
) {
174 FreePool (mDxeRuntimePciExpressLibRegistrationTable
);
178 // Close the Set Virtual Address Map event
180 Status
= gBS
->CloseEvent (mDxeRuntimePciExpressLibVirtualNotifyEvent
);
181 ASSERT_EFI_ERROR (Status
);
187 Gets the base address of PCI Express.
189 This internal functions retrieves PCI Express Base Address via a PCD entry
190 PcdPciExpressBaseAddress.
192 If Address > 0x0FFFFFFF, then ASSERT().
194 @param Address The address that encodes the PCI Bus, Device, Function and Register.
196 @retval (UINTN)-1 Invalid PCI address.
197 @retval other The base address of PCI Express.
201 GetPciExpressAddress (
208 // Make sure Address is valid
210 ASSERT_INVALID_PCI_ADDRESS (Address
);
213 // Make sure the Address is in MMCONF address space
215 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
220 // Convert Address to a physical address in the MMIO PCI Express range
222 Address
+= mDxeRuntimePciExpressLibPciExpressBaseAddress
;
225 // If SetVirtualAddressMap() has not been called, then just return the physical address
227 if (!EfiGoneVirtual ()) {
232 // See if there is a physical address match at the exact same index as the last address match
234 if (mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibLastRuntimeRange
].PhysicalAddress
== (Address
& (~0x00000fff))) {
236 // Convert the physical address to a virtual address and return the virtual address
238 return (Address
& 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibLastRuntimeRange
].VirtualAddress
;
242 // Search the entire table for a physical address match
244 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
245 if (mDxeRuntimePciExpressLibRegistrationTable
[Index
].PhysicalAddress
== (Address
& (~0x00000fff))) {
247 // Cache the matching index value
249 mDxeRuntimePciExpressLibLastRuntimeRange
= Index
;
251 // Convert the physical address to a virtual address and return the virtual address
253 return (Address
& 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable
[Index
].VirtualAddress
;
258 // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
263 // Return the physical address
269 Registers a PCI device so PCI configuration registers may be accessed after
270 SetVirtualAddressMap().
272 Registers the PCI device specified by Address so all the PCI configuration
273 registers associated with that PCI device may be accessed after SetVirtualAddressMap()
276 If Address > 0x0FFFFFFF, then ASSERT().
278 @param Address The address that encodes the PCI Bus, Device, Function and
281 @retval RETURN_SUCCESS The PCI device was registered for runtime access.
282 @retval RETURN_UNSUPPORTED An attempt was made to call this function
283 after ExitBootServices().
284 @retval RETURN_UNSUPPORTED The resources required to access the PCI device
285 at runtime could not be mapped.
286 @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
287 complete the registration.
292 PciExpressRegisterForRuntimeAccess (
297 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
302 // Return an error if this function is called after ExitBootServices().
304 if (EfiAtRuntime ()) {
305 return RETURN_UNSUPPORTED
;
309 // Make sure Address is valid
311 ASSERT_INVALID_PCI_ADDRESS (Address
);
314 // Make sure the Address is in MMCONF address space
316 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
317 return RETURN_UNSUPPORTED
;
321 // Convert Address to a physical address in the MMIO PCI Express range
322 // at the beginning of the PCI Configuration header for the specified
325 Address
= GetPciExpressAddress (Address
& 0x0ffff000);
328 // See if Address has already been registered for runtime access
330 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
331 if (mDxeRuntimePciExpressLibRegistrationTable
[Index
].PhysicalAddress
== Address
) {
332 return RETURN_SUCCESS
;
337 // Get the GCD Memory Descriptor for the PCI Express Bus/Dev/Func specified by Address
339 Status
= gDS
->GetMemorySpaceDescriptor (Address
, &Descriptor
);
340 if (EFI_ERROR (Status
)) {
341 return RETURN_UNSUPPORTED
;
345 // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
346 // will allocate a virtual address range for the 4KB PCI Configuration Header.
348 Status
= gDS
->SetMemorySpaceAttributes (Address
, 0x1000, Descriptor
.Attributes
| EFI_MEMORY_RUNTIME
);
349 if (EFI_ERROR (Status
)) {
350 return RETURN_UNSUPPORTED
;
354 // Grow the size of the registration table
356 NewTable
= ReallocateRuntimePool (
357 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges
+ 0) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
),
358 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges
+ 1) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
),
359 mDxeRuntimePciExpressLibRegistrationTable
361 if (NewTable
== NULL
) {
362 return RETURN_OUT_OF_RESOURCES
;
365 mDxeRuntimePciExpressLibRegistrationTable
= NewTable
;
366 mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibNumberOfRuntimeRanges
].PhysicalAddress
= Address
;
367 mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibNumberOfRuntimeRanges
].VirtualAddress
= Address
;
368 mDxeRuntimePciExpressLibNumberOfRuntimeRanges
++;
370 return RETURN_SUCCESS
;
374 Reads an 8-bit PCI configuration register.
376 Reads and returns the 8-bit PCI configuration register specified by Address.
377 This function must guarantee that all PCI read and write operations are
380 If Address > 0x0FFFFFFF, then ASSERT().
382 @param Address The address that encodes the PCI Bus, Device, Function and
384 @retval 0xFF Invalid PCI address.
385 @retval other The read value from the PCI configuration register.
394 ASSERT_INVALID_PCI_ADDRESS (Address
);
395 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
399 return MmioRead8 (GetPciExpressAddress (Address
));
403 Writes an 8-bit PCI configuration register.
405 Writes the 8-bit PCI configuration register specified by Address with the
406 value specified by Value. Value is returned. This function must guarantee
407 that all PCI read and write operations are serialized.
409 If Address > 0x0FFFFFFF, then ASSERT().
411 @param Address The address that encodes the PCI Bus, Device, Function and
413 @param Value The value to write.
415 @retval 0xFF Invalid PCI address.
416 @retval other The value written to the PCI configuration register.
426 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
430 return MmioWrite8 (GetPciExpressAddress (Address
), Value
);
434 Performs a bitwise OR of an 8-bit PCI configuration register with
437 Reads the 8-bit PCI configuration register specified by Address, performs a
438 bitwise OR between the read result and the value specified by
439 OrData, and writes the result to the 8-bit PCI configuration register
440 specified by Address. The value written to the PCI configuration register is
441 returned. This function must guarantee that all PCI read and write operations
444 If Address > 0x0FFFFFFF, then ASSERT().
446 @param Address The address that encodes the PCI Bus, Device, Function and
448 @param OrData The value to OR with the PCI configuration register.
450 @retval 0xFF Invalid PCI address.
451 @retval other The value written back to the PCI configuration register.
461 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
465 return MmioOr8 (GetPciExpressAddress (Address
), OrData
);
469 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
472 Reads the 8-bit PCI configuration register specified by Address, performs a
473 bitwise AND between the read result and the value specified by AndData, and
474 writes the result to the 8-bit PCI configuration register specified by
475 Address. The value written to the PCI configuration register is returned.
476 This function must guarantee that all PCI read and write operations are
479 If Address > 0x0FFFFFFF, then ASSERT().
481 @param Address The address that encodes the PCI Bus, Device, Function and
483 @param AndData The value to AND with the PCI configuration register.
485 @retval 0xFF Invalid PCI address.
486 @retval other The value written back to the PCI configuration register.
496 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
500 return MmioAnd8 (GetPciExpressAddress (Address
), AndData
);
504 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
505 value, followed a bitwise OR with another 8-bit value.
507 Reads the 8-bit PCI configuration register specified by Address, performs a
508 bitwise AND between the read result and the value specified by AndData,
509 performs a bitwise OR between the result of the AND operation and
510 the value specified by OrData, and writes the result to the 8-bit PCI
511 configuration register specified by Address. The value written to the PCI
512 configuration register is returned. This function must guarantee that all PCI
513 read and write operations are serialized.
515 If Address > 0x0FFFFFFF, then ASSERT().
517 @param Address The address that encodes the PCI Bus, Device, Function and
519 @param AndData The value to AND with the PCI configuration register.
520 @param OrData The value to OR with the result of the AND operation.
522 @retval 0xFF Invalid PCI address.
523 @retval other The value written back to the PCI configuration register.
528 PciExpressAndThenOr8 (
534 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
538 return MmioAndThenOr8 (
539 GetPciExpressAddress (Address
),
546 Reads a bit field of a PCI configuration register.
548 Reads the bit field in an 8-bit PCI configuration register. The bit field is
549 specified by the StartBit and the EndBit. The value of the bit field is
552 If Address > 0x0FFFFFFF, then ASSERT().
553 If StartBit is greater than 7, then ASSERT().
554 If EndBit is greater than 7, then ASSERT().
555 If EndBit is less than StartBit, then ASSERT().
557 @param Address The PCI configuration register to read.
558 @param StartBit The ordinal of the least significant bit in the bit field.
560 @param EndBit The ordinal of the most significant bit in the bit field.
563 @retval 0xFF Invalid PCI address.
564 @retval other The value of the bit field read from the PCI configuration register.
569 PciExpressBitFieldRead8 (
575 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
579 return MmioBitFieldRead8 (
580 GetPciExpressAddress (Address
),
587 Writes a bit field to a PCI configuration register.
589 Writes Value to the bit field of the PCI configuration register. The bit
590 field is specified by the StartBit and the EndBit. All other bits in the
591 destination PCI configuration register are preserved. The new value of the
592 8-bit register is returned.
594 If Address > 0x0FFFFFFF, then ASSERT().
595 If StartBit is greater than 7, then ASSERT().
596 If EndBit is greater than 7, then ASSERT().
597 If EndBit is less than StartBit, then ASSERT().
598 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
600 @param Address The PCI configuration register to write.
601 @param StartBit The ordinal of the least significant bit in the bit field.
603 @param EndBit The ordinal of the most significant bit in the bit field.
605 @param Value The new value of the bit field.
607 @retval 0xFF Invalid PCI address.
608 @retval other The value written back to the PCI configuration register.
613 PciExpressBitFieldWrite8 (
620 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
624 return MmioBitFieldWrite8 (
625 GetPciExpressAddress (Address
),
633 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
634 writes the result back to the bit field in the 8-bit port.
636 Reads the 8-bit PCI configuration register specified by Address, performs a
637 bitwise OR between the read result and the value specified by
638 OrData, and writes the result to the 8-bit PCI configuration register
639 specified by Address. The value written to the PCI configuration register is
640 returned. This function must guarantee that all PCI read and write operations
641 are serialized. Extra left bits in OrData are stripped.
643 If Address > 0x0FFFFFFF, then ASSERT().
644 If StartBit is greater than 7, then ASSERT().
645 If EndBit is greater than 7, then ASSERT().
646 If EndBit is less than StartBit, then ASSERT().
647 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
649 @param Address The PCI configuration register to write.
650 @param StartBit The ordinal of the least significant bit in the bit field.
652 @param EndBit The ordinal of the most significant bit in the bit field.
654 @param OrData The value to OR with the PCI configuration register.
656 @retval 0xFF Invalid PCI address.
657 @retval other The value written back to the PCI configuration register.
662 PciExpressBitFieldOr8 (
669 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
673 return MmioBitFieldOr8 (
674 GetPciExpressAddress (Address
),
682 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
683 AND, and writes the result back to the bit field in the 8-bit register.
685 Reads the 8-bit PCI configuration register specified by Address, performs a
686 bitwise AND between the read result and the value specified by AndData, and
687 writes the result to the 8-bit PCI configuration register specified by
688 Address. The value written to the PCI configuration register is returned.
689 This function must guarantee that all PCI read and write operations are
690 serialized. Extra left bits in AndData are stripped.
692 If Address > 0x0FFFFFFF, then ASSERT().
693 If StartBit is greater than 7, then ASSERT().
694 If EndBit is greater than 7, then ASSERT().
695 If EndBit is less than StartBit, then ASSERT().
696 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
698 @param Address The PCI configuration register to write.
699 @param StartBit The ordinal of the least significant bit in the bit field.
701 @param EndBit The ordinal of the most significant bit in the bit field.
703 @param AndData The value to AND with the PCI configuration register.
705 @retval 0xFF Invalid PCI address.
706 @retval other The value written back to the PCI configuration register.
711 PciExpressBitFieldAnd8 (
718 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
722 return MmioBitFieldAnd8 (
723 GetPciExpressAddress (Address
),
731 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
732 bitwise OR, and writes the result back to the bit field in the
735 Reads the 8-bit PCI configuration register specified by Address, performs a
736 bitwise AND followed by a bitwise OR between the read result and
737 the value specified by AndData, and writes the result to the 8-bit PCI
738 configuration register specified by Address. The value written to the PCI
739 configuration register is returned. This function must guarantee that all PCI
740 read and write operations are serialized. Extra left bits in both AndData and
743 If Address > 0x0FFFFFFF, then ASSERT().
744 If StartBit is greater than 7, then ASSERT().
745 If EndBit is greater than 7, then ASSERT().
746 If EndBit is less than StartBit, then ASSERT().
747 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
748 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
750 @param Address The PCI configuration register to write.
751 @param StartBit The ordinal of the least significant bit in the bit field.
753 @param EndBit The ordinal of the most significant bit in the bit field.
755 @param AndData The value to AND with the PCI configuration register.
756 @param OrData The value to OR with the result of the AND operation.
758 @retval 0xFF Invalid PCI address.
759 @retval other The value written back to the PCI configuration register.
764 PciExpressBitFieldAndThenOr8 (
772 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
776 return MmioBitFieldAndThenOr8 (
777 GetPciExpressAddress (Address
),
786 Reads a 16-bit PCI configuration register.
788 Reads and returns the 16-bit PCI configuration register specified by Address.
789 This function must guarantee that all PCI read and write operations are
792 If Address > 0x0FFFFFFF, then ASSERT().
793 If Address is not aligned on a 16-bit boundary, then ASSERT().
795 @param Address The address that encodes the PCI Bus, Device, Function and
798 @retval 0xFFFF Invalid PCI address.
799 @retval other The read value from the PCI configuration register.
808 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
812 return MmioRead16 (GetPciExpressAddress (Address
));
816 Writes a 16-bit PCI configuration register.
818 Writes the 16-bit PCI configuration register specified by Address with the
819 value specified by Value. Value is returned. This function must guarantee
820 that all PCI read and write operations are serialized.
822 If Address > 0x0FFFFFFF, then ASSERT().
823 If Address is not aligned on a 16-bit boundary, then ASSERT().
825 @param Address The address that encodes the PCI Bus, Device, Function and
827 @param Value The value to write.
829 @retval 0xFFFF Invalid PCI address.
830 @retval other The value written to the PCI configuration register.
840 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
844 return MmioWrite16 (GetPciExpressAddress (Address
), Value
);
848 Performs a bitwise OR of a 16-bit PCI configuration register with
851 Reads the 16-bit PCI configuration register specified by Address, performs a
852 bitwise OR between the read result and the value specified by
853 OrData, and writes the result to the 16-bit PCI configuration register
854 specified by Address. The value written to the PCI configuration register is
855 returned. This function must guarantee that all PCI read and write operations
858 If Address > 0x0FFFFFFF, then ASSERT().
859 If Address is not aligned on a 16-bit boundary, then ASSERT().
861 @param Address The address that encodes the PCI Bus, Device, Function and
863 @param OrData The value to OR with the PCI configuration register.
865 @retval 0xFFFF Invalid PCI address.
866 @retval other The value written back to the PCI configuration register.
876 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
880 return MmioOr16 (GetPciExpressAddress (Address
), OrData
);
884 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
887 Reads the 16-bit PCI configuration register specified by Address, performs a
888 bitwise AND between the read result and the value specified by AndData, and
889 writes the result to the 16-bit PCI configuration register specified by
890 Address. The value written to the PCI configuration register is returned.
891 This function must guarantee that all PCI read and write operations are
894 If Address > 0x0FFFFFFF, then ASSERT().
895 If Address is not aligned on a 16-bit boundary, then ASSERT().
897 @param Address The address that encodes the PCI Bus, Device, Function and
899 @param AndData The value to AND with the PCI configuration register.
901 @retval 0xFFFF Invalid PCI address.
902 @retval other The value written back to the PCI configuration register.
912 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
916 return MmioAnd16 (GetPciExpressAddress (Address
), AndData
);
920 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
921 value, followed a bitwise OR with another 16-bit value.
923 Reads the 16-bit PCI configuration register specified by Address, performs a
924 bitwise AND between the read result and the value specified by AndData,
925 performs a bitwise OR between the result of the AND operation and
926 the value specified by OrData, and writes the result to the 16-bit PCI
927 configuration register specified by Address. The value written to the PCI
928 configuration register is returned. This function must guarantee that all PCI
929 read and write operations are serialized.
931 If Address > 0x0FFFFFFF, then ASSERT().
932 If Address is not aligned on a 16-bit boundary, then ASSERT().
934 @param Address The address that encodes the PCI Bus, Device, Function and
936 @param AndData The value to AND with the PCI configuration register.
937 @param OrData The value to OR with the result of the AND operation.
939 @retval 0xFFFF Invalid PCI address.
940 @retval other The value written back to the PCI configuration register.
945 PciExpressAndThenOr16 (
951 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
955 return MmioAndThenOr16 (
956 GetPciExpressAddress (Address
),
963 Reads a bit field of a PCI configuration register.
965 Reads the bit field in a 16-bit PCI configuration register. The bit field is
966 specified by the StartBit and the EndBit. The value of the bit field is
969 If Address > 0x0FFFFFFF, then ASSERT().
970 If Address is not aligned on a 16-bit boundary, then ASSERT().
971 If StartBit is greater than 15, then ASSERT().
972 If EndBit is greater than 15, then ASSERT().
973 If EndBit is less than StartBit, then ASSERT().
975 @param Address The PCI configuration register to read.
976 @param StartBit The ordinal of the least significant bit in the bit field.
978 @param EndBit The ordinal of the most significant bit in the bit field.
981 @retval 0xFFFF Invalid PCI address.
982 @retval other The value of the bit field read from the PCI configuration register.
987 PciExpressBitFieldRead16 (
993 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
997 return MmioBitFieldRead16 (
998 GetPciExpressAddress (Address
),
1005 Writes a bit field to a PCI configuration register.
1007 Writes Value to the bit field of the PCI configuration register. The bit
1008 field is specified by the StartBit and the EndBit. All other bits in the
1009 destination PCI configuration register are preserved. The new value of the
1010 16-bit register is returned.
1012 If Address > 0x0FFFFFFF, then ASSERT().
1013 If Address is not aligned on a 16-bit boundary, then ASSERT().
1014 If StartBit is greater than 15, then ASSERT().
1015 If EndBit is greater than 15, then ASSERT().
1016 If EndBit is less than StartBit, then ASSERT().
1017 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1019 @param Address The PCI configuration register to write.
1020 @param StartBit The ordinal of the least significant bit in the bit field.
1022 @param EndBit The ordinal of the most significant bit in the bit field.
1024 @param Value The new value of the bit field.
1026 @retval 0xFFFF Invalid PCI address.
1027 @retval other The value written back to the PCI configuration register.
1032 PciExpressBitFieldWrite16 (
1039 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1043 return MmioBitFieldWrite16 (
1044 GetPciExpressAddress (Address
),
1052 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
1053 writes the result back to the bit field in the 16-bit port.
1055 Reads the 16-bit PCI configuration register specified by Address, performs a
1056 bitwise OR between the read result and the value specified by
1057 OrData, and writes the result to the 16-bit PCI configuration register
1058 specified by Address. The value written to the PCI configuration register is
1059 returned. This function must guarantee that all PCI read and write operations
1060 are serialized. Extra left bits in OrData are stripped.
1062 If Address > 0x0FFFFFFF, then ASSERT().
1063 If Address is not aligned on a 16-bit boundary, then ASSERT().
1064 If StartBit is greater than 15, then ASSERT().
1065 If EndBit is greater than 15, then ASSERT().
1066 If EndBit is less than StartBit, then ASSERT().
1067 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1069 @param Address The PCI configuration register to write.
1070 @param StartBit The ordinal of the least significant bit in the bit field.
1072 @param EndBit The ordinal of the most significant bit in the bit field.
1074 @param OrData The value to OR with the PCI configuration register.
1076 @retval 0xFFFF Invalid PCI address.
1077 @retval other The value written back to the PCI configuration register.
1082 PciExpressBitFieldOr16 (
1089 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1093 return MmioBitFieldOr16 (
1094 GetPciExpressAddress (Address
),
1102 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
1103 AND, and writes the result back to the bit field in the 16-bit register.
1105 Reads the 16-bit PCI configuration register specified by Address, performs a
1106 bitwise AND between the read result and the value specified by AndData, and
1107 writes the result to the 16-bit PCI configuration register specified by
1108 Address. The value written to the PCI configuration register is returned.
1109 This function must guarantee that all PCI read and write operations are
1110 serialized. Extra left bits in AndData are stripped.
1112 If Address > 0x0FFFFFFF, then ASSERT().
1113 If Address is not aligned on a 16-bit boundary, then ASSERT().
1114 If StartBit is greater than 15, then ASSERT().
1115 If EndBit is greater than 15, then ASSERT().
1116 If EndBit is less than StartBit, then ASSERT().
1117 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1119 @param Address The PCI configuration register to write.
1120 @param StartBit The ordinal of the least significant bit in the bit field.
1122 @param EndBit The ordinal of the most significant bit in the bit field.
1124 @param AndData The value to AND with the PCI configuration register.
1126 @retval 0xFFFF Invalid PCI address.
1127 @retval other The value written back to the PCI configuration register.
1132 PciExpressBitFieldAnd16 (
1139 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1143 return MmioBitFieldAnd16 (
1144 GetPciExpressAddress (Address
),
1152 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
1153 bitwise OR, and writes the result back to the bit field in the
1156 Reads the 16-bit PCI configuration register specified by Address, performs a
1157 bitwise AND followed by a bitwise OR between the read result and
1158 the value specified by AndData, and writes the result to the 16-bit PCI
1159 configuration register specified by Address. The value written to the PCI
1160 configuration register is returned. This function must guarantee that all PCI
1161 read and write operations are serialized. Extra left bits in both AndData and
1162 OrData are stripped.
1164 If Address > 0x0FFFFFFF, then ASSERT().
1165 If Address is not aligned on a 16-bit boundary, then ASSERT().
1166 If StartBit is greater than 15, then ASSERT().
1167 If EndBit is greater than 15, then ASSERT().
1168 If EndBit is less than StartBit, then ASSERT().
1169 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1170 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1172 @param Address The PCI configuration register to write.
1173 @param StartBit The ordinal of the least significant bit in the bit field.
1175 @param EndBit The ordinal of the most significant bit in the bit field.
1177 @param AndData The value to AND with the PCI configuration register.
1178 @param OrData The value to OR with the result of the AND operation.
1180 @retval 0xFFFF Invalid PCI address.
1181 @retval other The value written back to the PCI configuration register.
1186 PciExpressBitFieldAndThenOr16 (
1194 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1198 return MmioBitFieldAndThenOr16 (
1199 GetPciExpressAddress (Address
),
1208 Reads a 32-bit PCI configuration register.
1210 Reads and returns the 32-bit PCI configuration register specified by Address.
1211 This function must guarantee that all PCI read and write operations are
1214 If Address > 0x0FFFFFFF, then ASSERT().
1215 If Address is not aligned on a 32-bit boundary, then ASSERT().
1217 @param Address The address that encodes the PCI Bus, Device, Function and
1220 @retval 0xFFFF Invalid PCI address.
1221 @retval other The read value from the PCI configuration register.
1230 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1234 return MmioRead32 (GetPciExpressAddress (Address
));
1238 Writes a 32-bit PCI configuration register.
1240 Writes the 32-bit PCI configuration register specified by Address with the
1241 value specified by Value. Value is returned. This function must guarantee
1242 that all PCI read and write operations are serialized.
1244 If Address > 0x0FFFFFFF, then ASSERT().
1245 If Address is not aligned on a 32-bit boundary, then ASSERT().
1247 @param Address The address that encodes the PCI Bus, Device, Function and
1249 @param Value The value to write.
1251 @retval 0xFFFFFFFF Invalid PCI address.
1252 @retval other The value written to the PCI configuration register.
1262 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1266 return MmioWrite32 (GetPciExpressAddress (Address
), Value
);
1270 Performs a bitwise OR of a 32-bit PCI configuration register with
1273 Reads the 32-bit PCI configuration register specified by Address, performs a
1274 bitwise OR between the read result and the value specified by
1275 OrData, and writes the result to the 32-bit PCI configuration register
1276 specified by Address. The value written to the PCI configuration register is
1277 returned. This function must guarantee that all PCI read and write operations
1280 If Address > 0x0FFFFFFF, then ASSERT().
1281 If Address is not aligned on a 32-bit boundary, then ASSERT().
1283 @param Address The address that encodes the PCI Bus, Device, Function and
1285 @param OrData The value to OR with the PCI configuration register.
1287 @retval 0xFFFFFFFF Invalid PCI address.
1288 @retval other The value written back to the PCI configuration register.
1298 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1302 return MmioOr32 (GetPciExpressAddress (Address
), OrData
);
1306 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1309 Reads the 32-bit PCI configuration register specified by Address, performs a
1310 bitwise AND between the read result and the value specified by AndData, and
1311 writes the result to the 32-bit PCI configuration register specified by
1312 Address. The value written to the PCI configuration register is returned.
1313 This function must guarantee that all PCI read and write operations are
1316 If Address > 0x0FFFFFFF, then ASSERT().
1317 If Address is not aligned on a 32-bit boundary, then ASSERT().
1319 @param Address The address that encodes the PCI Bus, Device, Function and
1321 @param AndData The value to AND with the PCI configuration register.
1323 @retval 0xFFFFFFFF Invalid PCI address.
1324 @retval other The value written back to the PCI configuration register.
1334 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1338 return MmioAnd32 (GetPciExpressAddress (Address
), AndData
);
1342 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1343 value, followed a bitwise OR with another 32-bit value.
1345 Reads the 32-bit PCI configuration register specified by Address, performs a
1346 bitwise AND between the read result and the value specified by AndData,
1347 performs a bitwise OR between the result of the AND operation and
1348 the value specified by OrData, and writes the result to the 32-bit PCI
1349 configuration register specified by Address. The value written to the PCI
1350 configuration register is returned. This function must guarantee that all PCI
1351 read and write operations are serialized.
1353 If Address > 0x0FFFFFFF, then ASSERT().
1354 If Address is not aligned on a 32-bit boundary, then ASSERT().
1356 @param Address The address that encodes the PCI Bus, Device, Function and
1358 @param AndData The value to AND with the PCI configuration register.
1359 @param OrData The value to OR with the result of the AND operation.
1361 @retval 0xFFFFFFFF Invalid PCI address.
1362 @retval other The value written back to the PCI configuration register.
1367 PciExpressAndThenOr32 (
1373 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1377 return MmioAndThenOr32 (
1378 GetPciExpressAddress (Address
),
1385 Reads a bit field of a PCI configuration register.
1387 Reads the bit field in a 32-bit PCI configuration register. The bit field is
1388 specified by the StartBit and the EndBit. The value of the bit field is
1391 If Address > 0x0FFFFFFF, then ASSERT().
1392 If Address is not aligned on a 32-bit boundary, then ASSERT().
1393 If StartBit is greater than 31, then ASSERT().
1394 If EndBit is greater than 31, then ASSERT().
1395 If EndBit is less than StartBit, then ASSERT().
1397 @param Address The PCI configuration register to read.
1398 @param StartBit The ordinal of the least significant bit in the bit field.
1400 @param EndBit The ordinal of the most significant bit in the bit field.
1403 @retval 0xFFFFFFFF Invalid PCI address.
1404 @retval other The value of the bit field read from the PCI configuration register.
1409 PciExpressBitFieldRead32 (
1415 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1419 return MmioBitFieldRead32 (
1420 GetPciExpressAddress (Address
),
1427 Writes a bit field to a PCI configuration register.
1429 Writes Value to the bit field of the PCI configuration register. The bit
1430 field is specified by the StartBit and the EndBit. All other bits in the
1431 destination PCI configuration register are preserved. The new value of the
1432 32-bit register is returned.
1434 If Address > 0x0FFFFFFF, then ASSERT().
1435 If Address is not aligned on a 32-bit boundary, then ASSERT().
1436 If StartBit is greater than 31, then ASSERT().
1437 If EndBit is greater than 31, then ASSERT().
1438 If EndBit is less than StartBit, then ASSERT().
1439 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1441 @param Address The PCI configuration register to write.
1442 @param StartBit The ordinal of the least significant bit in the bit field.
1444 @param EndBit The ordinal of the most significant bit in the bit field.
1446 @param Value The new value of the bit field.
1448 @retval 0xFFFFFFFF Invalid PCI address.
1449 @retval other The value written back to the PCI configuration register.
1454 PciExpressBitFieldWrite32 (
1461 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1465 return MmioBitFieldWrite32 (
1466 GetPciExpressAddress (Address
),
1474 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1475 writes the result back to the bit field in the 32-bit port.
1477 Reads the 32-bit PCI configuration register specified by Address, performs a
1478 bitwise OR between the read result and the value specified by
1479 OrData, and writes the result to the 32-bit PCI configuration register
1480 specified by Address. The value written to the PCI configuration register is
1481 returned. This function must guarantee that all PCI read and write operations
1482 are serialized. Extra left bits in OrData are stripped.
1484 If Address > 0x0FFFFFFF, then ASSERT().
1485 If Address is not aligned on a 32-bit boundary, then ASSERT().
1486 If StartBit is greater than 31, then ASSERT().
1487 If EndBit is greater than 31, then ASSERT().
1488 If EndBit is less than StartBit, then ASSERT().
1489 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1491 @param Address The PCI configuration register to write.
1492 @param StartBit The ordinal of the least significant bit in the bit field.
1494 @param EndBit The ordinal of the most significant bit in the bit field.
1496 @param OrData The value to OR with the PCI configuration register.
1498 @retval 0xFFFFFFFF Invalid PCI address.
1499 @retval other The value written back to the PCI configuration register.
1504 PciExpressBitFieldOr32 (
1511 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1515 return MmioBitFieldOr32 (
1516 GetPciExpressAddress (Address
),
1524 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1525 AND, and writes the result back to the bit field in the 32-bit register.
1527 Reads the 32-bit PCI configuration register specified by Address, performs a
1528 bitwise AND between the read result and the value specified by AndData, and
1529 writes the result to the 32-bit PCI configuration register specified by
1530 Address. The value written to the PCI configuration register is returned.
1531 This function must guarantee that all PCI read and write operations are
1532 serialized. Extra left bits in AndData are stripped.
1534 If Address > 0x0FFFFFFF, then ASSERT().
1535 If Address is not aligned on a 32-bit boundary, then ASSERT().
1536 If StartBit is greater than 31, then ASSERT().
1537 If EndBit is greater than 31, then ASSERT().
1538 If EndBit is less than StartBit, then ASSERT().
1539 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1541 @param Address The PCI configuration register to write.
1542 @param StartBit The ordinal of the least significant bit in the bit field.
1544 @param EndBit The ordinal of the most significant bit in the bit field.
1546 @param AndData The value to AND with the PCI configuration register.
1548 @retval 0xFFFFFFFF Invalid PCI address.
1549 @retval other The value written back to the PCI configuration register.
1554 PciExpressBitFieldAnd32 (
1561 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1565 return MmioBitFieldAnd32 (
1566 GetPciExpressAddress (Address
),
1574 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1575 bitwise OR, and writes the result back to the bit field in the
1578 Reads the 32-bit PCI configuration register specified by Address, performs a
1579 bitwise AND followed by a bitwise OR between the read result and
1580 the value specified by AndData, and writes the result to the 32-bit PCI
1581 configuration register specified by Address. The value written to the PCI
1582 configuration register is returned. This function must guarantee that all PCI
1583 read and write operations are serialized. Extra left bits in both AndData and
1584 OrData are stripped.
1586 If Address > 0x0FFFFFFF, then ASSERT().
1587 If Address is not aligned on a 32-bit boundary, then ASSERT().
1588 If StartBit is greater than 31, then ASSERT().
1589 If EndBit is greater than 31, then ASSERT().
1590 If EndBit is less than StartBit, then ASSERT().
1591 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1592 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1594 @param Address The PCI configuration register to write.
1595 @param StartBit The ordinal of the least significant bit in the bit field.
1597 @param EndBit The ordinal of the most significant bit in the bit field.
1599 @param AndData The value to AND with the PCI configuration register.
1600 @param OrData The value to OR with the result of the AND operation.
1602 @retval 0xFFFFFFFF Invalid PCI address.
1603 @retval other The value written back to the PCI configuration register.
1608 PciExpressBitFieldAndThenOr32 (
1616 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1620 return MmioBitFieldAndThenOr32 (
1621 GetPciExpressAddress (Address
),
1630 Reads a range of PCI configuration registers into a caller supplied buffer.
1632 Reads the range of PCI configuration registers specified by StartAddress and
1633 Size into the buffer specified by Buffer. This function only allows the PCI
1634 configuration registers from a single PCI function to be read. Size is
1635 returned. When possible 32-bit PCI configuration read cycles are used to read
1636 from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
1637 and 16-bit PCI configuration read cycles may be used at the beginning and the
1640 If StartAddress > 0x0FFFFFFF, then ASSERT().
1641 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1642 If Size > 0 and Buffer is NULL, then ASSERT().
1644 @param StartAddress The starting address that encodes the PCI Bus, Device,
1645 Function and Register.
1646 @param Size The size in bytes of the transfer.
1647 @param Buffer The pointer to a buffer receiving the data read.
1649 @retval 0xFFFFFFFF Invalid PCI address.
1650 @retval other Size read data from StartAddress.
1655 PciExpressReadBuffer (
1656 IN UINTN StartAddress
,
1664 // Make sure Address is valid
1666 ASSERT_INVALID_PCI_ADDRESS (StartAddress
);
1667 ASSERT (((StartAddress
& 0xFFF) + Size
) <= 0x1000);
1670 // Make sure the Address is in MMCONF address space
1672 if (StartAddress
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1680 ASSERT (Buffer
!= NULL
);
1683 // Save Size for return
1687 if ((StartAddress
& 1) != 0) {
1689 // Read a byte if StartAddress is byte aligned
1691 *(volatile UINT8
*)Buffer
= PciExpressRead8 (StartAddress
);
1692 StartAddress
+= sizeof (UINT8
);
1693 Size
-= sizeof (UINT8
);
1694 Buffer
= (UINT8
*)Buffer
+ 1;
1697 if ((Size
>= sizeof (UINT16
)) && ((StartAddress
& 2) != 0)) {
1699 // Read a word if StartAddress is word aligned
1701 WriteUnaligned16 ((UINT16
*)Buffer
, (UINT16
)PciExpressRead16 (StartAddress
));
1703 StartAddress
+= sizeof (UINT16
);
1704 Size
-= sizeof (UINT16
);
1705 Buffer
= (UINT16
*)Buffer
+ 1;
1708 while (Size
>= sizeof (UINT32
)) {
1710 // Read as many double words as possible
1712 WriteUnaligned32 ((UINT32
*)Buffer
, (UINT32
)PciExpressRead32 (StartAddress
));
1714 StartAddress
+= sizeof (UINT32
);
1715 Size
-= sizeof (UINT32
);
1716 Buffer
= (UINT32
*)Buffer
+ 1;
1719 if (Size
>= sizeof (UINT16
)) {
1721 // Read the last remaining word if exist
1723 WriteUnaligned16 ((UINT16
*)Buffer
, (UINT16
)PciExpressRead16 (StartAddress
));
1724 StartAddress
+= sizeof (UINT16
);
1725 Size
-= sizeof (UINT16
);
1726 Buffer
= (UINT16
*)Buffer
+ 1;
1729 if (Size
>= sizeof (UINT8
)) {
1731 // Read the last remaining byte if exist
1733 *(volatile UINT8
*)Buffer
= PciExpressRead8 (StartAddress
);
1740 Copies the data in a caller supplied buffer to a specified range of PCI
1741 configuration space.
1743 Writes the range of PCI configuration registers specified by StartAddress and
1744 Size from the buffer specified by Buffer. This function only allows the PCI
1745 configuration registers from a single PCI function to be written. Size is
1746 returned. When possible 32-bit PCI configuration write cycles are used to
1747 write from StartAddress to StartAddress + Size. Due to alignment restrictions,
1748 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1749 and the end of the range.
1751 If StartAddress > 0x0FFFFFFF, then ASSERT().
1752 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1753 If Size > 0 and Buffer is NULL, then ASSERT().
1755 @param StartAddress The starting address that encodes the PCI Bus, Device,
1756 Function and Register.
1757 @param Size The size in bytes of the transfer.
1758 @param Buffer The pointer to a buffer containing the data to write.
1760 @retval 0xFFFFFFFF Invalid PCI address.
1761 @retval other Size written to StartAddress.
1766 PciExpressWriteBuffer (
1767 IN UINTN StartAddress
,
1775 // Make sure Address is valid
1777 ASSERT_INVALID_PCI_ADDRESS (StartAddress
);
1778 ASSERT (((StartAddress
& 0xFFF) + Size
) <= 0x1000);
1781 // Make sure the Address is in MMCONF address space
1783 if (StartAddress
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1791 ASSERT (Buffer
!= NULL
);
1794 // Save Size for return
1798 if ((StartAddress
& 1) != 0) {
1800 // Write a byte if StartAddress is byte aligned
1802 PciExpressWrite8 (StartAddress
, *(UINT8
*)Buffer
);
1803 StartAddress
+= sizeof (UINT8
);
1804 Size
-= sizeof (UINT8
);
1805 Buffer
= (UINT8
*)Buffer
+ 1;
1808 if ((Size
>= sizeof (UINT16
)) && ((StartAddress
& 2) != 0)) {
1810 // Write a word if StartAddress is word aligned
1812 PciExpressWrite16 (StartAddress
, ReadUnaligned16 ((UINT16
*)Buffer
));
1813 StartAddress
+= sizeof (UINT16
);
1814 Size
-= sizeof (UINT16
);
1815 Buffer
= (UINT16
*)Buffer
+ 1;
1818 while (Size
>= sizeof (UINT32
)) {
1820 // Write as many double words as possible
1822 PciExpressWrite32 (StartAddress
, ReadUnaligned32 ((UINT32
*)Buffer
));
1823 StartAddress
+= sizeof (UINT32
);
1824 Size
-= sizeof (UINT32
);
1825 Buffer
= (UINT32
*)Buffer
+ 1;
1828 if (Size
>= sizeof (UINT16
)) {
1830 // Write the last remaining word if exist
1832 PciExpressWrite16 (StartAddress
, ReadUnaligned16 ((UINT16
*)Buffer
));
1833 StartAddress
+= sizeof (UINT16
);
1834 Size
-= sizeof (UINT16
);
1835 Buffer
= (UINT16
*)Buffer
+ 1;
1838 if (Size
>= sizeof (UINT8
)) {
1840 // Write the last remaining byte if exist
1842 PciExpressWrite8 (StartAddress
, *(UINT8
*)Buffer
);