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
16 #include <Guid/EventGroup.h>
18 #include <Library/BaseLib.h>
19 #include <Library/PciExpressLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/DxeServicesTableLib.h>
26 #include <Library/UefiRuntimeLib.h>
29 Assert the validity of a PCI address. A valid PCI address should contain 1's
30 only in the low 28 bits.
32 @param A The address to validate.
35 #define ASSERT_INVALID_PCI_ADDRESS(A) \
36 ASSERT (((A) & ~0xfffffff) == 0)
39 /// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime
42 UINTN PhysicalAddress
;
44 } PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
;
47 /// Set Virtual Address Map Event
49 EFI_EVENT mDxeRuntimePciExpressLibVirtualNotifyEvent
= NULL
;
52 /// Module global that contains the base physical address and size of the PCI Express MMIO range.
54 UINTN mDxeRuntimePciExpressLibPciExpressBaseAddress
= 0;
55 UINTN mDxeRuntimePciExpressLibPciExpressBaseSize
= 0;
58 /// The number of PCI devices that have been registered for runtime access.
60 UINTN mDxeRuntimePciExpressLibNumberOfRuntimeRanges
= 0;
63 /// The table of PCI devices that have been registered for runtime access.
65 PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
*mDxeRuntimePciExpressLibRegistrationTable
= NULL
;
68 /// The table index of the most recent virtual address lookup.
70 UINTN mDxeRuntimePciExpressLibLastRuntimeRange
= 0;
74 Convert the physical PCI Express MMIO addresses for all registered PCI devices
77 @param[in] Event The event that is being processed.
78 @param[in] Context The Event Context.
82 DxeRuntimePciExpressLibVirtualNotify (
90 // If there have been no runtime registrations, then just return
92 if (mDxeRuntimePciExpressLibRegistrationTable
== NULL
) {
97 // Convert physical addresses associated with the set of registered PCI devices to
100 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
101 EfiConvertPointer (0, (VOID
**) &(mDxeRuntimePciExpressLibRegistrationTable
[Index
].VirtualAddress
));
105 // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
107 EfiConvertPointer (0, (VOID
**) &mDxeRuntimePciExpressLibRegistrationTable
);
111 The constructor function caches the PCI Express Base Address and creates a
112 Set Virtual Address Map event to convert physical address to virtual addresses.
114 @param ImageHandle The firmware allocated handle for the EFI image.
115 @param SystemTable A pointer to the EFI System Table.
117 @retval EFI_SUCCESS The constructor completed successfully.
118 @retval Other value The constructor did not complete successfully.
123 DxeRuntimePciExpressLibConstructor (
124 IN EFI_HANDLE ImageHandle
,
125 IN EFI_SYSTEM_TABLE
*SystemTable
131 // Cache the physical address of the PCI Express MMIO range into a module global variable
133 mDxeRuntimePciExpressLibPciExpressBaseAddress
= (UINTN
) PcdGet64 (PcdPciExpressBaseAddress
);
134 mDxeRuntimePciExpressLibPciExpressBaseSize
= (UINTN
) PcdGet64 (PcdPciExpressBaseSize
);
137 // Register SetVirtualAddressMap () notify function
139 Status
= gBS
->CreateEvent (
140 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
,
142 DxeRuntimePciExpressLibVirtualNotify
,
144 &mDxeRuntimePciExpressLibVirtualNotifyEvent
146 ASSERT_EFI_ERROR (Status
);
152 The destructor function frees any allocated buffers and closes the Set Virtual
155 @param ImageHandle The firmware allocated handle for the EFI image.
156 @param SystemTable A pointer to the EFI System Table.
158 @retval EFI_SUCCESS The destructor completed successfully.
159 @retval Other value The destructor did not complete successfully.
164 DxeRuntimePciExpressLibDestructor (
165 IN EFI_HANDLE ImageHandle
,
166 IN EFI_SYSTEM_TABLE
*SystemTable
172 // If one or more PCI devices have been registered for runtime access, then
173 // free the registration table.
175 if (mDxeRuntimePciExpressLibRegistrationTable
!= NULL
) {
176 FreePool (mDxeRuntimePciExpressLibRegistrationTable
);
180 // Close the Set Virtual Address Map event
182 Status
= gBS
->CloseEvent (mDxeRuntimePciExpressLibVirtualNotifyEvent
);
183 ASSERT_EFI_ERROR (Status
);
189 Gets the base address of PCI Express.
191 This internal functions retrieves PCI Express Base Address via a PCD entry
192 PcdPciExpressBaseAddress.
194 If Address > 0x0FFFFFFF, then ASSERT().
196 @param Address The address that encodes the PCI Bus, Device, Function and Register.
198 @retval (UINTN)-1 Invalid PCI address.
199 @retval other The base address of PCI Express.
203 GetPciExpressAddress (
210 // Make sure Address is valid
212 ASSERT_INVALID_PCI_ADDRESS (Address
);
215 // Make sure the Address is in MMCONF address space
217 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
222 // Convert Address to a physical address in the MMIO PCI Express range
224 Address
+= mDxeRuntimePciExpressLibPciExpressBaseAddress
;
227 // If SetVirtualAddressMap() has not been called, then just return the physical address
229 if (!EfiGoneVirtual ()) {
234 // See if there is a physical address match at the exact same index as the last address match
236 if (mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibLastRuntimeRange
].PhysicalAddress
== (Address
& (~0x00000fff))) {
238 // Convert the physical address to a virtual address and return the virtual address
240 return (Address
& 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibLastRuntimeRange
].VirtualAddress
;
244 // Search the entire table for a physical address match
246 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
247 if (mDxeRuntimePciExpressLibRegistrationTable
[Index
].PhysicalAddress
== (Address
& (~0x00000fff))) {
249 // Cache the matching index value
251 mDxeRuntimePciExpressLibLastRuntimeRange
= Index
;
253 // Convert the physical address to a virtual address and return the virtual address
255 return (Address
& 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable
[Index
].VirtualAddress
;
260 // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
265 // Return the physical address
271 Registers a PCI device so PCI configuration registers may be accessed after
272 SetVirtualAddressMap().
274 Registers the PCI device specified by Address so all the PCI configuration
275 registers associated with that PCI device may be accessed after SetVirtualAddressMap()
278 If Address > 0x0FFFFFFF, then ASSERT().
280 @param Address The address that encodes the PCI Bus, Device, Function and
283 @retval RETURN_SUCCESS The PCI device was registered for runtime access.
284 @retval RETURN_UNSUPPORTED An attempt was made to call this function
285 after ExitBootServices().
286 @retval RETURN_UNSUPPORTED The resources required to access the PCI device
287 at runtime could not be mapped.
288 @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
289 complete the registration.
294 PciExpressRegisterForRuntimeAccess (
299 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
304 // Return an error if this function is called after ExitBootServices().
306 if (EfiAtRuntime ()) {
307 return RETURN_UNSUPPORTED
;
311 // Make sure Address is valid
313 ASSERT_INVALID_PCI_ADDRESS (Address
);
316 // Make sure the Address is in MMCONF address space
318 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
319 return RETURN_UNSUPPORTED
;
323 // Convert Address to a physical address in the MMIO PCI Express range
324 // at the beginning of the PCI Configuration header for the specified
327 Address
= GetPciExpressAddress (Address
& 0x0ffff000);
330 // See if Address has already been registered for runtime access
332 for (Index
= 0; Index
< mDxeRuntimePciExpressLibNumberOfRuntimeRanges
; Index
++) {
333 if (mDxeRuntimePciExpressLibRegistrationTable
[Index
].PhysicalAddress
== Address
) {
334 return RETURN_SUCCESS
;
339 // Get the GCD Memory Descriptor for the PCI Express Bus/Dev/Func specified by Address
341 Status
= gDS
->GetMemorySpaceDescriptor (Address
, &Descriptor
);
342 if (EFI_ERROR (Status
)) {
343 return RETURN_UNSUPPORTED
;
347 // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
348 // will allocate a virtual address range for the 4KB PCI Configuration Header.
350 Status
= gDS
->SetMemorySpaceAttributes (Address
, 0x1000, Descriptor
.Attributes
| EFI_MEMORY_RUNTIME
);
351 if (EFI_ERROR (Status
)) {
352 return RETURN_UNSUPPORTED
;
356 // Grow the size of the registration table
358 NewTable
= ReallocateRuntimePool (
359 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges
+ 0) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
),
360 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges
+ 1) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE
),
361 mDxeRuntimePciExpressLibRegistrationTable
363 if (NewTable
== NULL
) {
364 return RETURN_OUT_OF_RESOURCES
;
366 mDxeRuntimePciExpressLibRegistrationTable
= NewTable
;
367 mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibNumberOfRuntimeRanges
].PhysicalAddress
= Address
;
368 mDxeRuntimePciExpressLibRegistrationTable
[mDxeRuntimePciExpressLibNumberOfRuntimeRanges
].VirtualAddress
= Address
;
369 mDxeRuntimePciExpressLibNumberOfRuntimeRanges
++;
371 return RETURN_SUCCESS
;
376 Reads an 8-bit PCI configuration register.
378 Reads and returns the 8-bit PCI configuration register specified by Address.
379 This function must guarantee that all PCI read and write operations are
382 If Address > 0x0FFFFFFF, then ASSERT().
384 @param Address The address that encodes the PCI Bus, Device, Function and
386 @retval 0xFF Invalid PCI address.
387 @retval other The read value from the PCI configuration register.
396 ASSERT_INVALID_PCI_ADDRESS (Address
);
397 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
400 return MmioRead8 (GetPciExpressAddress (Address
));
404 Writes an 8-bit PCI configuration register.
406 Writes the 8-bit PCI configuration register specified by Address with the
407 value specified by Value. Value is returned. This function must guarantee
408 that all PCI read and write operations are serialized.
410 If Address > 0x0FFFFFFF, then ASSERT().
412 @param Address The address that encodes the PCI Bus, Device, Function and
414 @param Value The value to write.
416 @retval 0xFF Invalid PCI address.
417 @retval other The value written to the PCI configuration register.
427 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
) {
464 return MmioOr8 (GetPciExpressAddress (Address
), OrData
);
468 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
471 Reads the 8-bit PCI configuration register specified by Address, performs a
472 bitwise AND between the read result and the value specified by AndData, and
473 writes the result to the 8-bit PCI configuration register specified by
474 Address. The value written to the PCI configuration register is returned.
475 This function must guarantee that all PCI read and write operations are
478 If Address > 0x0FFFFFFF, then ASSERT().
480 @param Address The address that encodes the PCI Bus, Device, Function and
482 @param AndData The value to AND with the PCI configuration register.
484 @retval 0xFF Invalid PCI address.
485 @retval other The value written back to the PCI configuration register.
495 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
498 return MmioAnd8 (GetPciExpressAddress (Address
), AndData
);
502 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
503 value, followed a bitwise OR with another 8-bit value.
505 Reads the 8-bit PCI configuration register specified by Address, performs a
506 bitwise AND between the read result and the value specified by AndData,
507 performs a bitwise OR between the result of the AND operation and
508 the value specified by OrData, and writes the result to the 8-bit PCI
509 configuration register specified by Address. The value written to the PCI
510 configuration register is returned. This function must guarantee that all PCI
511 read and write operations are serialized.
513 If Address > 0x0FFFFFFF, then ASSERT().
515 @param Address The address that encodes the PCI Bus, Device, Function and
517 @param AndData The value to AND with the PCI configuration register.
518 @param OrData The value to OR with the result of the AND operation.
520 @retval 0xFF Invalid PCI address.
521 @retval other The value written back to the PCI configuration register.
526 PciExpressAndThenOr8 (
532 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
535 return MmioAndThenOr8 (
536 GetPciExpressAddress (Address
),
543 Reads a bit field of a PCI configuration register.
545 Reads the bit field in an 8-bit PCI configuration register. The bit field is
546 specified by the StartBit and the EndBit. The value of the bit field is
549 If Address > 0x0FFFFFFF, then ASSERT().
550 If StartBit is greater than 7, then ASSERT().
551 If EndBit is greater than 7, then ASSERT().
552 If EndBit is less than StartBit, then ASSERT().
554 @param Address The PCI configuration register to read.
555 @param StartBit The ordinal of the least significant bit in the bit field.
557 @param EndBit The ordinal of the most significant bit in the bit field.
560 @retval 0xFF Invalid PCI address.
561 @retval other The value of the bit field read from the PCI configuration register.
566 PciExpressBitFieldRead8 (
572 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
575 return MmioBitFieldRead8 (
576 GetPciExpressAddress (Address
),
583 Writes a bit field to a PCI configuration register.
585 Writes Value to the bit field of the PCI configuration register. The bit
586 field is specified by the StartBit and the EndBit. All other bits in the
587 destination PCI configuration register are preserved. The new value of the
588 8-bit register is returned.
590 If Address > 0x0FFFFFFF, then ASSERT().
591 If StartBit is greater than 7, then ASSERT().
592 If EndBit is greater than 7, then ASSERT().
593 If EndBit is less than StartBit, then ASSERT().
594 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
596 @param Address The PCI configuration register to write.
597 @param StartBit The ordinal of the least significant bit in the bit field.
599 @param EndBit The ordinal of the most significant bit in the bit field.
601 @param Value The new value of the bit field.
603 @retval 0xFF Invalid PCI address.
604 @retval other The value written back to the PCI configuration register.
609 PciExpressBitFieldWrite8 (
616 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
619 return MmioBitFieldWrite8 (
620 GetPciExpressAddress (Address
),
628 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
629 writes the result back to the bit field in the 8-bit port.
631 Reads the 8-bit PCI configuration register specified by Address, performs a
632 bitwise OR between the read result and the value specified by
633 OrData, and writes the result to the 8-bit PCI configuration register
634 specified by Address. The value written to the PCI configuration register is
635 returned. This function must guarantee that all PCI read and write operations
636 are serialized. Extra left bits in OrData are stripped.
638 If Address > 0x0FFFFFFF, then ASSERT().
639 If StartBit is greater than 7, then ASSERT().
640 If EndBit is greater than 7, then ASSERT().
641 If EndBit is less than StartBit, then ASSERT().
642 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
644 @param Address The PCI configuration register to write.
645 @param StartBit The ordinal of the least significant bit in the bit field.
647 @param EndBit The ordinal of the most significant bit in the bit field.
649 @param OrData The value to OR with the PCI configuration register.
651 @retval 0xFF Invalid PCI address.
652 @retval other The value written back to the PCI configuration register.
657 PciExpressBitFieldOr8 (
664 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
667 return MmioBitFieldOr8 (
668 GetPciExpressAddress (Address
),
676 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
677 AND, and writes the result back to the bit field in the 8-bit register.
679 Reads the 8-bit PCI configuration register specified by Address, performs a
680 bitwise AND between the read result and the value specified by AndData, and
681 writes the result to the 8-bit PCI configuration register specified by
682 Address. The value written to the PCI configuration register is returned.
683 This function must guarantee that all PCI read and write operations are
684 serialized. Extra left bits in AndData are stripped.
686 If Address > 0x0FFFFFFF, then ASSERT().
687 If StartBit is greater than 7, then ASSERT().
688 If EndBit is greater than 7, then ASSERT().
689 If EndBit is less than StartBit, then ASSERT().
690 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
692 @param Address The PCI configuration register to write.
693 @param StartBit The ordinal of the least significant bit in the bit field.
695 @param EndBit The ordinal of the most significant bit in the bit field.
697 @param AndData The value to AND with the PCI configuration register.
699 @retval 0xFF Invalid PCI address.
700 @retval other The value written back to the PCI configuration register.
705 PciExpressBitFieldAnd8 (
712 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
715 return MmioBitFieldAnd8 (
716 GetPciExpressAddress (Address
),
724 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
725 bitwise OR, and writes the result back to the bit field in the
728 Reads the 8-bit PCI configuration register specified by Address, performs a
729 bitwise AND followed by a bitwise OR between the read result and
730 the value specified by AndData, and writes the result to the 8-bit PCI
731 configuration register specified by Address. The value written to the PCI
732 configuration register is returned. This function must guarantee that all PCI
733 read and write operations are serialized. Extra left bits in both AndData and
736 If Address > 0x0FFFFFFF, then ASSERT().
737 If StartBit is greater than 7, then ASSERT().
738 If EndBit is greater than 7, then ASSERT().
739 If EndBit is less than StartBit, then ASSERT().
740 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
741 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
743 @param Address The PCI configuration register to write.
744 @param StartBit The ordinal of the least significant bit in the bit field.
746 @param EndBit The ordinal of the most significant bit in the bit field.
748 @param AndData The value to AND with the PCI configuration register.
749 @param OrData The value to OR with the result of the AND operation.
751 @retval 0xFF Invalid PCI address.
752 @retval other The value written back to the PCI configuration register.
757 PciExpressBitFieldAndThenOr8 (
765 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
768 return MmioBitFieldAndThenOr8 (
769 GetPciExpressAddress (Address
),
778 Reads a 16-bit PCI configuration register.
780 Reads and returns the 16-bit PCI configuration register specified by Address.
781 This function must guarantee that all PCI read and write operations are
784 If Address > 0x0FFFFFFF, then ASSERT().
785 If Address is not aligned on a 16-bit boundary, then ASSERT().
787 @param Address The address that encodes the PCI Bus, Device, Function and
790 @retval 0xFFFF Invalid PCI address.
791 @retval other The read value from the PCI configuration register.
800 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
803 return MmioRead16 (GetPciExpressAddress (Address
));
807 Writes a 16-bit PCI configuration register.
809 Writes the 16-bit PCI configuration register specified by Address with the
810 value specified by Value. Value is returned. This function must guarantee
811 that all PCI read and write operations are serialized.
813 If Address > 0x0FFFFFFF, then ASSERT().
814 If Address is not aligned on a 16-bit boundary, then ASSERT().
816 @param Address The address that encodes the PCI Bus, Device, Function and
818 @param Value The value to write.
820 @retval 0xFFFF Invalid PCI address.
821 @retval other The value written to the PCI configuration register.
831 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
834 return MmioWrite16 (GetPciExpressAddress (Address
), Value
);
838 Performs a bitwise OR of a 16-bit PCI configuration register with
841 Reads the 16-bit PCI configuration register specified by Address, performs a
842 bitwise OR between the read result and the value specified by
843 OrData, and writes the result to the 16-bit PCI configuration register
844 specified by Address. The value written to the PCI configuration register is
845 returned. This function must guarantee that all PCI read and write operations
848 If Address > 0x0FFFFFFF, then ASSERT().
849 If Address is not aligned on a 16-bit boundary, then ASSERT().
851 @param Address The address that encodes the PCI Bus, Device, Function and
853 @param OrData The value to OR with the PCI configuration register.
855 @retval 0xFFFF Invalid PCI address.
856 @retval other The value written back to the PCI configuration register.
866 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
869 return MmioOr16 (GetPciExpressAddress (Address
), OrData
);
873 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
876 Reads the 16-bit PCI configuration register specified by Address, performs a
877 bitwise AND between the read result and the value specified by AndData, and
878 writes the result to the 16-bit PCI configuration register specified by
879 Address. The value written to the PCI configuration register is returned.
880 This function must guarantee that all PCI read and write operations are
883 If Address > 0x0FFFFFFF, then ASSERT().
884 If Address is not aligned on a 16-bit boundary, then ASSERT().
886 @param Address The address that encodes the PCI Bus, Device, Function and
888 @param AndData The value to AND with the PCI configuration register.
890 @retval 0xFFFF Invalid PCI address.
891 @retval other The value written back to the PCI configuration register.
901 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
904 return MmioAnd16 (GetPciExpressAddress (Address
), AndData
);
908 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
909 value, followed a bitwise OR with another 16-bit value.
911 Reads the 16-bit PCI configuration register specified by Address, performs a
912 bitwise AND between the read result and the value specified by AndData,
913 performs a bitwise OR between the result of the AND operation and
914 the value specified by OrData, and writes the result to the 16-bit PCI
915 configuration register specified by Address. The value written to the PCI
916 configuration register is returned. This function must guarantee that all PCI
917 read and write operations are serialized.
919 If Address > 0x0FFFFFFF, then ASSERT().
920 If Address is not aligned on a 16-bit boundary, then ASSERT().
922 @param Address The address that encodes the PCI Bus, Device, Function and
924 @param AndData The value to AND with the PCI configuration register.
925 @param OrData The value to OR with the result of the AND operation.
927 @retval 0xFFFF Invalid PCI address.
928 @retval other The value written back to the PCI configuration register.
933 PciExpressAndThenOr16 (
939 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
942 return MmioAndThenOr16 (
943 GetPciExpressAddress (Address
),
950 Reads a bit field of a PCI configuration register.
952 Reads the bit field in a 16-bit PCI configuration register. The bit field is
953 specified by the StartBit and the EndBit. The value of the bit field is
956 If Address > 0x0FFFFFFF, then ASSERT().
957 If Address is not aligned on a 16-bit boundary, then ASSERT().
958 If StartBit is greater than 15, then ASSERT().
959 If EndBit is greater than 15, then ASSERT().
960 If EndBit is less than StartBit, then ASSERT().
962 @param Address The PCI configuration register to read.
963 @param StartBit The ordinal of the least significant bit in the bit field.
965 @param EndBit The ordinal of the most significant bit in the bit field.
968 @retval 0xFFFF Invalid PCI address.
969 @retval other The value of the bit field read from the PCI configuration register.
974 PciExpressBitFieldRead16 (
980 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
983 return MmioBitFieldRead16 (
984 GetPciExpressAddress (Address
),
991 Writes a bit field to a PCI configuration register.
993 Writes Value to the bit field of the PCI configuration register. The bit
994 field is specified by the StartBit and the EndBit. All other bits in the
995 destination PCI configuration register are preserved. The new value of the
996 16-bit register is returned.
998 If Address > 0x0FFFFFFF, then ASSERT().
999 If Address is not aligned on a 16-bit boundary, then ASSERT().
1000 If StartBit is greater than 15, then ASSERT().
1001 If EndBit is greater than 15, then ASSERT().
1002 If EndBit is less than StartBit, then ASSERT().
1003 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1005 @param Address The PCI configuration register to write.
1006 @param StartBit The ordinal of the least significant bit in the bit field.
1008 @param EndBit The ordinal of the most significant bit in the bit field.
1010 @param Value The new value of the bit field.
1012 @retval 0xFFFF Invalid PCI address.
1013 @retval other The value written back to the PCI configuration register.
1018 PciExpressBitFieldWrite16 (
1025 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1028 return MmioBitFieldWrite16 (
1029 GetPciExpressAddress (Address
),
1037 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
1038 writes the result back to the bit field in the 16-bit port.
1040 Reads the 16-bit PCI configuration register specified by Address, performs a
1041 bitwise OR between the read result and the value specified by
1042 OrData, and writes the result to the 16-bit PCI configuration register
1043 specified by Address. The value written to the PCI configuration register is
1044 returned. This function must guarantee that all PCI read and write operations
1045 are serialized. Extra left bits in OrData are stripped.
1047 If Address > 0x0FFFFFFF, then ASSERT().
1048 If Address is not aligned on a 16-bit boundary, then ASSERT().
1049 If StartBit is greater than 15, then ASSERT().
1050 If EndBit is greater than 15, then ASSERT().
1051 If EndBit is less than StartBit, then ASSERT().
1052 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1054 @param Address The PCI configuration register to write.
1055 @param StartBit The ordinal of the least significant bit in the bit field.
1057 @param EndBit The ordinal of the most significant bit in the bit field.
1059 @param OrData The value to OR with the PCI configuration register.
1061 @retval 0xFFFF Invalid PCI address.
1062 @retval other The value written back to the PCI configuration register.
1067 PciExpressBitFieldOr16 (
1074 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1077 return MmioBitFieldOr16 (
1078 GetPciExpressAddress (Address
),
1086 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
1087 AND, and writes the result back to the bit field in the 16-bit register.
1089 Reads the 16-bit PCI configuration register specified by Address, performs a
1090 bitwise AND between the read result and the value specified by AndData, and
1091 writes the result to the 16-bit PCI configuration register specified by
1092 Address. The value written to the PCI configuration register is returned.
1093 This function must guarantee that all PCI read and write operations are
1094 serialized. Extra left bits in AndData are stripped.
1096 If Address > 0x0FFFFFFF, then ASSERT().
1097 If Address is not aligned on a 16-bit boundary, then ASSERT().
1098 If StartBit is greater than 15, then ASSERT().
1099 If EndBit is greater than 15, then ASSERT().
1100 If EndBit is less than StartBit, then ASSERT().
1101 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1103 @param Address The PCI configuration register to write.
1104 @param StartBit The ordinal of the least significant bit in the bit field.
1106 @param EndBit The ordinal of the most significant bit in the bit field.
1108 @param AndData The value to AND with the PCI configuration register.
1110 @retval 0xFFFF Invalid PCI address.
1111 @retval other The value written back to the PCI configuration register.
1116 PciExpressBitFieldAnd16 (
1123 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1126 return MmioBitFieldAnd16 (
1127 GetPciExpressAddress (Address
),
1135 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
1136 bitwise OR, and writes the result back to the bit field in the
1139 Reads the 16-bit PCI configuration register specified by Address, performs a
1140 bitwise AND followed by a bitwise OR between the read result and
1141 the value specified by AndData, and writes the result to the 16-bit PCI
1142 configuration register specified by Address. The value written to the PCI
1143 configuration register is returned. This function must guarantee that all PCI
1144 read and write operations are serialized. Extra left bits in both AndData and
1145 OrData are stripped.
1147 If Address > 0x0FFFFFFF, then ASSERT().
1148 If Address is not aligned on a 16-bit boundary, then ASSERT().
1149 If StartBit is greater than 15, then ASSERT().
1150 If EndBit is greater than 15, then ASSERT().
1151 If EndBit is less than StartBit, then ASSERT().
1152 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1153 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1155 @param Address The PCI configuration register to write.
1156 @param StartBit The ordinal of the least significant bit in the bit field.
1158 @param EndBit The ordinal of the most significant bit in the bit field.
1160 @param AndData The value to AND with the PCI configuration register.
1161 @param OrData The value to OR with the result of the AND operation.
1163 @retval 0xFFFF Invalid PCI address.
1164 @retval other The value written back to the PCI configuration register.
1169 PciExpressBitFieldAndThenOr16 (
1177 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1180 return MmioBitFieldAndThenOr16 (
1181 GetPciExpressAddress (Address
),
1190 Reads a 32-bit PCI configuration register.
1192 Reads and returns the 32-bit PCI configuration register specified by Address.
1193 This function must guarantee that all PCI read and write operations are
1196 If Address > 0x0FFFFFFF, then ASSERT().
1197 If Address is not aligned on a 32-bit boundary, then ASSERT().
1199 @param Address The address that encodes the PCI Bus, Device, Function and
1202 @retval 0xFFFF Invalid PCI address.
1203 @retval other The read value from the PCI configuration register.
1212 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1215 return MmioRead32 (GetPciExpressAddress (Address
));
1219 Writes a 32-bit PCI configuration register.
1221 Writes the 32-bit PCI configuration register specified by Address with the
1222 value specified by Value. Value is returned. This function must guarantee
1223 that all PCI read and write operations are serialized.
1225 If Address > 0x0FFFFFFF, then ASSERT().
1226 If Address is not aligned on a 32-bit boundary, then ASSERT().
1228 @param Address The address that encodes the PCI Bus, Device, Function and
1230 @param Value The value to write.
1232 @retval 0xFFFFFFFF Invalid PCI address.
1233 @retval other The value written to the PCI configuration register.
1243 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1246 return MmioWrite32 (GetPciExpressAddress (Address
), Value
);
1250 Performs a bitwise OR of a 32-bit PCI configuration register with
1253 Reads the 32-bit PCI configuration register specified by Address, performs a
1254 bitwise OR between the read result and the value specified by
1255 OrData, and writes the result to the 32-bit PCI configuration register
1256 specified by Address. The value written to the PCI configuration register is
1257 returned. This function must guarantee that all PCI read and write operations
1260 If Address > 0x0FFFFFFF, then ASSERT().
1261 If Address is not aligned on a 32-bit boundary, then ASSERT().
1263 @param Address The address that encodes the PCI Bus, Device, Function and
1265 @param OrData The value to OR with the PCI configuration register.
1267 @retval 0xFFFFFFFF Invalid PCI address.
1268 @retval other The value written back to the PCI configuration register.
1278 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1281 return MmioOr32 (GetPciExpressAddress (Address
), OrData
);
1285 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1288 Reads the 32-bit PCI configuration register specified by Address, performs a
1289 bitwise AND between the read result and the value specified by AndData, and
1290 writes the result to the 32-bit PCI configuration register specified by
1291 Address. The value written to the PCI configuration register is returned.
1292 This function must guarantee that all PCI read and write operations are
1295 If Address > 0x0FFFFFFF, then ASSERT().
1296 If Address is not aligned on a 32-bit boundary, then ASSERT().
1298 @param Address The address that encodes the PCI Bus, Device, Function and
1300 @param AndData The value to AND with the PCI configuration register.
1302 @retval 0xFFFFFFFF Invalid PCI address.
1303 @retval other The value written back to the PCI configuration register.
1313 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1316 return MmioAnd32 (GetPciExpressAddress (Address
), AndData
);
1320 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1321 value, followed a bitwise OR with another 32-bit value.
1323 Reads the 32-bit PCI configuration register specified by Address, performs a
1324 bitwise AND between the read result and the value specified by AndData,
1325 performs a bitwise OR between the result of the AND operation and
1326 the value specified by OrData, and writes the result to the 32-bit PCI
1327 configuration register specified by Address. The value written to the PCI
1328 configuration register is returned. This function must guarantee that all PCI
1329 read and write operations are serialized.
1331 If Address > 0x0FFFFFFF, then ASSERT().
1332 If Address is not aligned on a 32-bit boundary, then ASSERT().
1334 @param Address The address that encodes the PCI Bus, Device, Function and
1336 @param AndData The value to AND with the PCI configuration register.
1337 @param OrData The value to OR with the result of the AND operation.
1339 @retval 0xFFFFFFFF Invalid PCI address.
1340 @retval other The value written back to the PCI configuration register.
1345 PciExpressAndThenOr32 (
1351 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1354 return MmioAndThenOr32 (
1355 GetPciExpressAddress (Address
),
1362 Reads a bit field of a PCI configuration register.
1364 Reads the bit field in a 32-bit PCI configuration register. The bit field is
1365 specified by the StartBit and the EndBit. The value of the bit field is
1368 If Address > 0x0FFFFFFF, then ASSERT().
1369 If Address is not aligned on a 32-bit boundary, then ASSERT().
1370 If StartBit is greater than 31, then ASSERT().
1371 If EndBit is greater than 31, then ASSERT().
1372 If EndBit is less than StartBit, then ASSERT().
1374 @param Address The PCI configuration register to read.
1375 @param StartBit The ordinal of the least significant bit in the bit field.
1377 @param EndBit The ordinal of the most significant bit in the bit field.
1380 @retval 0xFFFFFFFF Invalid PCI address.
1381 @retval other The value of the bit field read from the PCI configuration register.
1386 PciExpressBitFieldRead32 (
1392 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1395 return MmioBitFieldRead32 (
1396 GetPciExpressAddress (Address
),
1403 Writes a bit field to a PCI configuration register.
1405 Writes Value to the bit field of the PCI configuration register. The bit
1406 field is specified by the StartBit and the EndBit. All other bits in the
1407 destination PCI configuration register are preserved. The new value of the
1408 32-bit register is returned.
1410 If Address > 0x0FFFFFFF, then ASSERT().
1411 If Address is not aligned on a 32-bit boundary, then ASSERT().
1412 If StartBit is greater than 31, then ASSERT().
1413 If EndBit is greater than 31, then ASSERT().
1414 If EndBit is less than StartBit, then ASSERT().
1415 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1417 @param Address The PCI configuration register to write.
1418 @param StartBit The ordinal of the least significant bit in the bit field.
1420 @param EndBit The ordinal of the most significant bit in the bit field.
1422 @param Value The new value of the bit field.
1424 @retval 0xFFFFFFFF Invalid PCI address.
1425 @retval other The value written back to the PCI configuration register.
1430 PciExpressBitFieldWrite32 (
1437 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1440 return MmioBitFieldWrite32 (
1441 GetPciExpressAddress (Address
),
1449 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1450 writes the result back to the bit field in the 32-bit port.
1452 Reads the 32-bit PCI configuration register specified by Address, performs a
1453 bitwise OR between the read result and the value specified by
1454 OrData, and writes the result to the 32-bit PCI configuration register
1455 specified by Address. The value written to the PCI configuration register is
1456 returned. This function must guarantee that all PCI read and write operations
1457 are serialized. Extra left bits in OrData are stripped.
1459 If Address > 0x0FFFFFFF, then ASSERT().
1460 If Address is not aligned on a 32-bit boundary, then ASSERT().
1461 If StartBit is greater than 31, then ASSERT().
1462 If EndBit is greater than 31, then ASSERT().
1463 If EndBit is less than StartBit, then ASSERT().
1464 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1466 @param Address The PCI configuration register to write.
1467 @param StartBit The ordinal of the least significant bit in the bit field.
1469 @param EndBit The ordinal of the most significant bit in the bit field.
1471 @param OrData The value to OR with the PCI configuration register.
1473 @retval 0xFFFFFFFF Invalid PCI address.
1474 @retval other The value written back to the PCI configuration register.
1479 PciExpressBitFieldOr32 (
1486 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1489 return MmioBitFieldOr32 (
1490 GetPciExpressAddress (Address
),
1498 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1499 AND, and writes the result back to the bit field in the 32-bit register.
1501 Reads the 32-bit PCI configuration register specified by Address, performs a
1502 bitwise AND between the read result and the value specified by AndData, and
1503 writes the result to the 32-bit PCI configuration register specified by
1504 Address. The value written to the PCI configuration register is returned.
1505 This function must guarantee that all PCI read and write operations are
1506 serialized. Extra left bits in AndData are stripped.
1508 If Address > 0x0FFFFFFF, then ASSERT().
1509 If Address is not aligned on a 32-bit boundary, then ASSERT().
1510 If StartBit is greater than 31, then ASSERT().
1511 If EndBit is greater than 31, then ASSERT().
1512 If EndBit is less than StartBit, then ASSERT().
1513 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1515 @param Address The PCI configuration register to write.
1516 @param StartBit The ordinal of the least significant bit in the bit field.
1518 @param EndBit The ordinal of the most significant bit in the bit field.
1520 @param AndData The value to AND with the PCI configuration register.
1522 @retval 0xFFFFFFFF Invalid PCI address.
1523 @retval other The value written back to the PCI configuration register.
1528 PciExpressBitFieldAnd32 (
1535 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1538 return MmioBitFieldAnd32 (
1539 GetPciExpressAddress (Address
),
1547 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1548 bitwise OR, and writes the result back to the bit field in the
1551 Reads the 32-bit PCI configuration register specified by Address, performs a
1552 bitwise AND followed by a bitwise OR between the read result and
1553 the value specified by AndData, and writes the result to the 32-bit PCI
1554 configuration register specified by Address. The value written to the PCI
1555 configuration register is returned. This function must guarantee that all PCI
1556 read and write operations are serialized. Extra left bits in both AndData and
1557 OrData are stripped.
1559 If Address > 0x0FFFFFFF, then ASSERT().
1560 If Address is not aligned on a 32-bit boundary, then ASSERT().
1561 If StartBit is greater than 31, then ASSERT().
1562 If EndBit is greater than 31, then ASSERT().
1563 If EndBit is less than StartBit, then ASSERT().
1564 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1565 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1567 @param Address The PCI configuration register to write.
1568 @param StartBit The ordinal of the least significant bit in the bit field.
1570 @param EndBit The ordinal of the most significant bit in the bit field.
1572 @param AndData The value to AND with the PCI configuration register.
1573 @param OrData The value to OR with the result of the AND operation.
1575 @retval 0xFFFFFFFF Invalid PCI address.
1576 @retval other The value written back to the PCI configuration register.
1581 PciExpressBitFieldAndThenOr32 (
1589 if (Address
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1592 return MmioBitFieldAndThenOr32 (
1593 GetPciExpressAddress (Address
),
1602 Reads a range of PCI configuration registers into a caller supplied buffer.
1604 Reads the range of PCI configuration registers specified by StartAddress and
1605 Size into the buffer specified by Buffer. This function only allows the PCI
1606 configuration registers from a single PCI function to be read. Size is
1607 returned. When possible 32-bit PCI configuration read cycles are used to read
1608 from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
1609 and 16-bit PCI configuration read cycles may be used at the beginning and the
1612 If StartAddress > 0x0FFFFFFF, then ASSERT().
1613 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1614 If Size > 0 and Buffer is NULL, then ASSERT().
1616 @param StartAddress The starting address that encodes the PCI Bus, Device,
1617 Function and Register.
1618 @param Size The size in bytes of the transfer.
1619 @param Buffer The pointer to a buffer receiving the data read.
1621 @retval 0xFFFFFFFF Invalid PCI address.
1622 @retval other Size read data from StartAddress.
1627 PciExpressReadBuffer (
1628 IN UINTN StartAddress
,
1636 // Make sure Address is valid
1638 ASSERT_INVALID_PCI_ADDRESS (StartAddress
);
1639 ASSERT (((StartAddress
& 0xFFF) + Size
) <= 0x1000);
1642 // Make sure the Address is in MMCONF address space
1644 if (StartAddress
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1652 ASSERT (Buffer
!= NULL
);
1655 // Save Size for return
1659 if ((StartAddress
& 1) != 0) {
1661 // Read a byte if StartAddress is byte aligned
1663 *(volatile UINT8
*)Buffer
= PciExpressRead8 (StartAddress
);
1664 StartAddress
+= sizeof (UINT8
);
1665 Size
-= sizeof (UINT8
);
1666 Buffer
= (UINT8
*)Buffer
+ 1;
1669 if (Size
>= sizeof (UINT16
) && (StartAddress
& 2) != 0) {
1671 // Read a word if StartAddress is word aligned
1673 WriteUnaligned16 ((UINT16
*) Buffer
, (UINT16
) PciExpressRead16 (StartAddress
));
1675 StartAddress
+= sizeof (UINT16
);
1676 Size
-= sizeof (UINT16
);
1677 Buffer
= (UINT16
*)Buffer
+ 1;
1680 while (Size
>= sizeof (UINT32
)) {
1682 // Read as many double words as possible
1684 WriteUnaligned32 ((UINT32
*) Buffer
, (UINT32
) PciExpressRead32 (StartAddress
));
1686 StartAddress
+= sizeof (UINT32
);
1687 Size
-= sizeof (UINT32
);
1688 Buffer
= (UINT32
*)Buffer
+ 1;
1691 if (Size
>= sizeof (UINT16
)) {
1693 // Read the last remaining word if exist
1695 WriteUnaligned16 ((UINT16
*) Buffer
, (UINT16
) PciExpressRead16 (StartAddress
));
1696 StartAddress
+= sizeof (UINT16
);
1697 Size
-= sizeof (UINT16
);
1698 Buffer
= (UINT16
*)Buffer
+ 1;
1701 if (Size
>= sizeof (UINT8
)) {
1703 // Read the last remaining byte if exist
1705 *(volatile UINT8
*)Buffer
= PciExpressRead8 (StartAddress
);
1712 Copies the data in a caller supplied buffer to a specified range of PCI
1713 configuration space.
1715 Writes the range of PCI configuration registers specified by StartAddress and
1716 Size from the buffer specified by Buffer. This function only allows the PCI
1717 configuration registers from a single PCI function to be written. Size is
1718 returned. When possible 32-bit PCI configuration write cycles are used to
1719 write from StartAddress to StartAddress + Size. Due to alignment restrictions,
1720 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1721 and the end of the range.
1723 If StartAddress > 0x0FFFFFFF, then ASSERT().
1724 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1725 If Size > 0 and Buffer is NULL, then ASSERT().
1727 @param StartAddress The starting address that encodes the PCI Bus, Device,
1728 Function and Register.
1729 @param Size The size in bytes of the transfer.
1730 @param Buffer The pointer to a buffer containing the data to write.
1732 @retval 0xFFFFFFFF Invalid PCI address.
1733 @retval other Size written to StartAddress.
1738 PciExpressWriteBuffer (
1739 IN UINTN StartAddress
,
1747 // Make sure Address is valid
1749 ASSERT_INVALID_PCI_ADDRESS (StartAddress
);
1750 ASSERT (((StartAddress
& 0xFFF) + Size
) <= 0x1000);
1753 // Make sure the Address is in MMCONF address space
1755 if (StartAddress
>= mDxeRuntimePciExpressLibPciExpressBaseSize
) {
1763 ASSERT (Buffer
!= NULL
);
1766 // Save Size for return
1770 if ((StartAddress
& 1) != 0) {
1772 // Write a byte if StartAddress is byte aligned
1774 PciExpressWrite8 (StartAddress
, *(UINT8
*)Buffer
);
1775 StartAddress
+= sizeof (UINT8
);
1776 Size
-= sizeof (UINT8
);
1777 Buffer
= (UINT8
*)Buffer
+ 1;
1780 if (Size
>= sizeof (UINT16
) && (StartAddress
& 2) != 0) {
1782 // Write a word if StartAddress is word aligned
1784 PciExpressWrite16 (StartAddress
, ReadUnaligned16 ((UINT16
*)Buffer
));
1785 StartAddress
+= sizeof (UINT16
);
1786 Size
-= sizeof (UINT16
);
1787 Buffer
= (UINT16
*)Buffer
+ 1;
1790 while (Size
>= sizeof (UINT32
)) {
1792 // Write as many double words as possible
1794 PciExpressWrite32 (StartAddress
, ReadUnaligned32 ((UINT32
*)Buffer
));
1795 StartAddress
+= sizeof (UINT32
);
1796 Size
-= sizeof (UINT32
);
1797 Buffer
= (UINT32
*)Buffer
+ 1;
1800 if (Size
>= sizeof (UINT16
)) {
1802 // Write the last remaining word if exist
1804 PciExpressWrite16 (StartAddress
, ReadUnaligned16 ((UINT16
*)Buffer
));
1805 StartAddress
+= sizeof (UINT16
);
1806 Size
-= sizeof (UINT16
);
1807 Buffer
= (UINT16
*)Buffer
+ 1;
1810 if (Size
>= sizeof (UINT8
)) {
1812 // Write the last remaining byte if exist
1814 PciExpressWrite8 (StartAddress
, *(UINT8
*)Buffer
);