1 /** @file
2   Functions in this library instance make use of MMIO functions in IoLib to
3   access memory mapped PCI configuration space.
4 
5   All assertions for I/O operations are handled in MMIO functions in the IoLib
6   Library.
7 
8   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
9   This program and the accompanying materials
10   are licensed and made available under the terms and conditions of the BSD License
11   which accompanies this distribution.  The full text of the license may be found at
12   http://opensource.org/licenses/bsd-license.php.
13 
14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 
17 **/
18 
19 
20 #include <PiDxe.h>
21 
22 #include <Guid/EventGroup.h>
23 
24 #include <Library/BaseLib.h>
25 #include <Library/PciExpressLib.h>
26 #include <Library/IoLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/PcdLib.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/DxeServicesTableLib.h>
32 #include <Library/UefiRuntimeLib.h>
33 
34 ///
35 /// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime
36 ///
37 typedef struct {
38   UINTN  PhysicalAddress;
39   UINTN  VirtualAddress;
40 } PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE;
41 
42 ///
43 /// Set Virtual Address Map Event
44 ///
45 EFI_EVENT                               mDxeRuntimePciExpressLibVirtualNotifyEvent = NULL;
46 
47 ///
48 /// Module global that contains the base physical address of the PCI Express MMIO range.
49 ///
50 UINTN                                   mDxeRuntimePciExpressLibPciExpressBaseAddress = 0;
51 
52 ///
53 /// The number of PCI devices that have been registered for runtime access.
54 ///
55 UINTN                                   mDxeRuntimePciExpressLibNumberOfRuntimeRanges = 0;
56 
57 ///
58 /// The table of PCI devices that have been registered for runtime access.
59 ///
60 PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE  *mDxeRuntimePciExpressLibRegistrationTable = NULL;
61 
62 ///
63 /// The table index of the most recent virtual address lookup.
64 ///
65 UINTN                                   mDxeRuntimePciExpressLibLastRuntimeRange = 0;
66 
67 
68 /**
69   Convert the physical PCI Express MMIO addresses for all registered PCI devices
70   to virtual addresses.
71 
72   @param[in]    Event   The event that is being processed.
73   @param[in]    Context The Event Context.
74 **/
75 VOID
76 EFIAPI
DxeRuntimePciExpressLibVirtualNotify(IN EFI_EVENT Event,IN VOID * Context)77 DxeRuntimePciExpressLibVirtualNotify (
78   IN EFI_EVENT  Event,
79   IN VOID       *Context
80   )
81 {
82   UINTN  Index;
83 
84   //
85   // If there have been no runtime registrations, then just return
86   //
87   if (mDxeRuntimePciExpressLibRegistrationTable == NULL) {
88     return;
89   }
90 
91   //
92   // Convert physical addresses associated with the set of registered PCI devices to
93   // virtual addresses.
94   //
95   for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
96     EfiConvertPointer (0, (VOID **) &(mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress));
97   }
98 
99   //
100   // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
101   //
102   EfiConvertPointer (0, (VOID **) &mDxeRuntimePciExpressLibRegistrationTable);
103 }
104 
105 /**
106   The constructor function caches the PCI Express Base Address and creates a
107   Set Virtual Address Map event to convert physical address to virtual addresses.
108 
109   @param  ImageHandle   The firmware allocated handle for the EFI image.
110   @param  SystemTable   A pointer to the EFI System Table.
111 
112   @retval EFI_SUCCESS   The constructor completed successfully.
113   @retval Other value   The constructor did not complete successfully.
114 
115 **/
116 EFI_STATUS
117 EFIAPI
DxeRuntimePciExpressLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)118 DxeRuntimePciExpressLibConstructor (
119   IN EFI_HANDLE        ImageHandle,
120   IN EFI_SYSTEM_TABLE  *SystemTable
121   )
122 {
123   EFI_STATUS  Status;
124 
125   //
126   // Cache the physical address of the PCI Express MMIO range into a module global variable
127   //
128   mDxeRuntimePciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
129 
130   //
131   // Register SetVirtualAddressMap () notify function
132   //
133   Status = gBS->CreateEventEx (
134                   EVT_NOTIFY_SIGNAL,
135                   TPL_NOTIFY,
136                   DxeRuntimePciExpressLibVirtualNotify,
137                   NULL,
138                   &gEfiEventVirtualAddressChangeGuid,
139                   &mDxeRuntimePciExpressLibVirtualNotifyEvent
140                   );
141   ASSERT_EFI_ERROR (Status);
142 
143   return Status;
144 }
145 
146 /**
147   The destructor function frees any allocated buffers and closes the Set Virtual
148   Address Map event.
149 
150   @param  ImageHandle   The firmware allocated handle for the EFI image.
151   @param  SystemTable   A pointer to the EFI System Table.
152 
153   @retval EFI_SUCCESS   The destructor completed successfully.
154   @retval Other value   The destructor did not complete successfully.
155 
156 **/
157 EFI_STATUS
158 EFIAPI
DxeRuntimePciExpressLibDestructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)159 DxeRuntimePciExpressLibDestructor (
160   IN EFI_HANDLE        ImageHandle,
161   IN EFI_SYSTEM_TABLE  *SystemTable
162   )
163 {
164   EFI_STATUS  Status;
165 
166   //
167   // If one or more PCI devices have been registered for runtime access, then
168   // free the registration table.
169   //
170   if (mDxeRuntimePciExpressLibRegistrationTable != NULL) {
171     FreePool (mDxeRuntimePciExpressLibRegistrationTable);
172   }
173 
174   //
175   // Close the Set Virtual Address Map event
176   //
177   Status = gBS->CloseEvent (mDxeRuntimePciExpressLibVirtualNotifyEvent);
178   ASSERT_EFI_ERROR (Status);
179 
180   return Status;
181 }
182 
183 /**
184   Gets the base address of PCI Express.
185 
186   This internal functions retrieves PCI Express Base Address via a PCD entry
187   PcdPciExpressBaseAddress.
188 
189   @param  Address  The address that encodes the PCI Bus, Device, Function and Register.
190   @return          The base address of PCI Express.
191 
192 **/
193 UINTN
GetPciExpressAddress(IN UINTN Address)194 GetPciExpressAddress (
195   IN UINTN  Address
196   )
197 {
198   UINTN  Index;
199 
200   //
201   // Make sure Address is valid
202   //
203   ASSERT (((Address) & ~0xfffffff) == 0);
204 
205   //
206   // Convert Address to a physical address in the MMIO PCI Express range
207   //
208   Address += mDxeRuntimePciExpressLibPciExpressBaseAddress;
209 
210   //
211   // If SetVirtualAddressMap() has not been called, then just return the physical address
212   //
213   if (!EfiGoneVirtual ()) {
214     return Address;
215   }
216 
217   //
218   // See if there is a physical address match at the exact same index as the last address match
219   //
220   if (mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].PhysicalAddress == (Address & (~0x00000fff))) {
221     //
222     // Convert the physical address to a virtual address and return the virtual address
223     //
224     return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].VirtualAddress;
225   }
226 
227   //
228   // Search the entire table for a physical address match
229   //
230   for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
231     if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == (Address & (~0x00000fff))) {
232       //
233       // Cache the matching index value
234       //
235       mDxeRuntimePciExpressLibLastRuntimeRange = Index;
236       //
237       // Convert the physical address to a virtual address and return the virtual address
238       //
239       return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress;
240     }
241   }
242 
243   //
244   // No match was found.  This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
245   //
246   ASSERT (FALSE);
247   CpuBreakpoint();
248 
249   //
250   // Return the physical address
251   //
252   return Address;
253 }
254 
255 /**
256   Registers a PCI device so PCI configuration registers may be accessed after
257   SetVirtualAddressMap().
258 
259   Registers the PCI device specified by Address so all the PCI configuration
260   registers associated with that PCI device may be accessed after SetVirtualAddressMap()
261   is called.
262 
263   If Address > 0x0FFFFFFF, then ASSERT().
264 
265   @param  Address The address that encodes the PCI Bus, Device, Function and
266                   Register.
267 
268   @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
269   @retval RETURN_UNSUPPORTED       An attempt was made to call this function
270                                    after ExitBootServices().
271   @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
272                                    at runtime could not be mapped.
273   @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
274                                    complete the registration.
275 
276 **/
277 RETURN_STATUS
278 EFIAPI
PciExpressRegisterForRuntimeAccess(IN UINTN Address)279 PciExpressRegisterForRuntimeAccess (
280   IN UINTN  Address
281   )
282 {
283   EFI_STATUS                       Status;
284   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;
285   UINTN                            Index;
286   VOID                             *NewTable;
287 
288   //
289   // Return an error if this function is called after ExitBootServices().
290   //
291   if (EfiAtRuntime ()) {
292     return RETURN_UNSUPPORTED;
293   }
294 
295   //
296   // Make sure Address is valid
297   //
298   ASSERT (((Address) & ~0xfffffff) == 0);
299 
300   //
301   // Convert Address to a physical address in the MMIO PCI Express range
302   // at the beginning of the PCI Configuration header for the specified
303   // PCI Bus/Dev/Func
304   //
305   Address = GetPciExpressAddress (Address & 0x0ffff000);
306 
307   //
308   // See if Address has already been registerd for runtime access
309   //
310   for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
311     if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == Address) {
312       return RETURN_SUCCESS;
313     }
314   }
315 
316   //
317   // Get the GCD Memory Descriptor for the PCI Express Bus/Dev/Func specified by Address
318   //
319   Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
320   if (EFI_ERROR (Status)) {
321     return RETURN_UNSUPPORTED;
322   }
323 
324   //
325   // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
326   // will allocate a virtual address range for the 4KB PCI Configuration Header.
327   //
328   Status = gDS->SetMemorySpaceAttributes (Address, 0x1000, Descriptor.Attributes | EFI_MEMORY_RUNTIME);
329   if (EFI_ERROR (Status)) {
330     return RETURN_UNSUPPORTED;
331   }
332 
333   //
334   // Grow the size of the registration table
335   //
336   NewTable = ReallocateRuntimePool (
337                (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 0) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE),
338                (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 1) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE),
339                mDxeRuntimePciExpressLibRegistrationTable
340                );
341   if (NewTable == NULL) {
342     return RETURN_OUT_OF_RESOURCES;
343   }
344   mDxeRuntimePciExpressLibRegistrationTable = NewTable;
345   mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].PhysicalAddress = Address;
346   mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].VirtualAddress  = Address;
347   mDxeRuntimePciExpressLibNumberOfRuntimeRanges++;
348 
349   return RETURN_SUCCESS;
350 }
351 
352 
353 /**
354   Reads an 8-bit PCI configuration register.
355 
356   Reads and returns the 8-bit PCI configuration register specified by Address.
357   This function must guarantee that all PCI read and write operations are
358   serialized.
359 
360   If Address > 0x0FFFFFFF, then ASSERT().
361 
362   @param  Address The address that encodes the PCI Bus, Device, Function and
363                   Register.
364 
365   @return The read value from the PCI configuration register.
366 
367 **/
368 UINT8
369 EFIAPI
PciExpressRead8(IN UINTN Address)370 PciExpressRead8 (
371   IN      UINTN                     Address
372   )
373 {
374   return MmioRead8 (GetPciExpressAddress (Address));
375 }
376 
377 /**
378   Writes an 8-bit PCI configuration register.
379 
380   Writes the 8-bit PCI configuration register specified by Address with the
381   value specified by Value. Value is returned. This function must guarantee
382   that all PCI read and write operations are serialized.
383 
384   If Address > 0x0FFFFFFF, then ASSERT().
385 
386   @param  Address The address that encodes the PCI Bus, Device, Function and
387                   Register.
388   @param  Value   The value to write.
389 
390   @return The value written to the PCI configuration register.
391 
392 **/
393 UINT8
394 EFIAPI
PciExpressWrite8(IN UINTN Address,IN UINT8 Value)395 PciExpressWrite8 (
396   IN      UINTN                     Address,
397   IN      UINT8                     Value
398   )
399 {
400   return MmioWrite8 (GetPciExpressAddress (Address), Value);
401 }
402 
403 /**
404   Performs a bitwise OR of an 8-bit PCI configuration register with
405   an 8-bit value.
406 
407   Reads the 8-bit PCI configuration register specified by Address, performs a
408   bitwise OR between the read result and the value specified by
409   OrData, and writes the result to the 8-bit PCI configuration register
410   specified by Address. The value written to the PCI configuration register is
411   returned. This function must guarantee that all PCI read and write operations
412   are serialized.
413 
414   If Address > 0x0FFFFFFF, then ASSERT().
415 
416   @param  Address The address that encodes the PCI Bus, Device, Function and
417                   Register.
418   @param  OrData  The value to OR with the PCI configuration register.
419 
420   @return The value written back to the PCI configuration register.
421 
422 **/
423 UINT8
424 EFIAPI
PciExpressOr8(IN UINTN Address,IN UINT8 OrData)425 PciExpressOr8 (
426   IN      UINTN                     Address,
427   IN      UINT8                     OrData
428   )
429 {
430   return MmioOr8 (GetPciExpressAddress (Address), OrData);
431 }
432 
433 /**
434   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
435   value.
436 
437   Reads the 8-bit PCI configuration register specified by Address, performs a
438   bitwise AND between the read result and the value specified by AndData, and
439   writes the result to the 8-bit PCI configuration register specified by
440   Address. The value written to the PCI configuration register is returned.
441   This function must guarantee that all PCI read and write operations are
442   serialized.
443 
444   If Address > 0x0FFFFFFF, then ASSERT().
445 
446   @param  Address The address that encodes the PCI Bus, Device, Function and
447                   Register.
448   @param  AndData The value to AND with the PCI configuration register.
449 
450   @return The value written back to the PCI configuration register.
451 
452 **/
453 UINT8
454 EFIAPI
PciExpressAnd8(IN UINTN Address,IN UINT8 AndData)455 PciExpressAnd8 (
456   IN      UINTN                     Address,
457   IN      UINT8                     AndData
458   )
459 {
460   return MmioAnd8 (GetPciExpressAddress (Address), AndData);
461 }
462 
463 /**
464   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
465   value, followed a  bitwise OR with another 8-bit value.
466 
467   Reads the 8-bit PCI configuration register specified by Address, performs a
468   bitwise AND between the read result and the value specified by AndData,
469   performs a bitwise OR between the result of the AND operation and
470   the value specified by OrData, and writes the result to the 8-bit PCI
471   configuration register specified by Address. The value written to the PCI
472   configuration register is returned. This function must guarantee that all PCI
473   read and write operations are serialized.
474 
475   If Address > 0x0FFFFFFF, then ASSERT().
476 
477   @param  Address The address that encodes the PCI Bus, Device, Function and
478                   Register.
479   @param  AndData The value to AND with the PCI configuration register.
480   @param  OrData  The value to OR with the result of the AND operation.
481 
482   @return The value written back to the PCI configuration register.
483 
484 **/
485 UINT8
486 EFIAPI
PciExpressAndThenOr8(IN UINTN Address,IN UINT8 AndData,IN UINT8 OrData)487 PciExpressAndThenOr8 (
488   IN      UINTN                     Address,
489   IN      UINT8                     AndData,
490   IN      UINT8                     OrData
491   )
492 {
493   return MmioAndThenOr8 (
494            GetPciExpressAddress (Address),
495            AndData,
496            OrData
497            );
498 }
499 
500 /**
501   Reads a bit field of a PCI configuration register.
502 
503   Reads the bit field in an 8-bit PCI configuration register. The bit field is
504   specified by the StartBit and the EndBit. The value of the bit field is
505   returned.
506 
507   If Address > 0x0FFFFFFF, then ASSERT().
508   If StartBit is greater than 7, then ASSERT().
509   If EndBit is greater than 7, then ASSERT().
510   If EndBit is less than StartBit, then ASSERT().
511 
512   @param  Address   The PCI configuration register to read.
513   @param  StartBit  The ordinal of the least significant bit in the bit field.
514                     Range 0..7.
515   @param  EndBit    The ordinal of the most significant bit in the bit field.
516                     Range 0..7.
517 
518   @return The value of the bit field read from the PCI configuration register.
519 
520 **/
521 UINT8
522 EFIAPI
PciExpressBitFieldRead8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)523 PciExpressBitFieldRead8 (
524   IN      UINTN                     Address,
525   IN      UINTN                     StartBit,
526   IN      UINTN                     EndBit
527   )
528 {
529   return MmioBitFieldRead8 (
530            GetPciExpressAddress (Address),
531            StartBit,
532            EndBit
533            );
534 }
535 
536 /**
537   Writes a bit field to a PCI configuration register.
538 
539   Writes Value to the bit field of the PCI configuration register. The bit
540   field is specified by the StartBit and the EndBit. All other bits in the
541   destination PCI configuration register are preserved. The new value of the
542   8-bit register is returned.
543 
544   If Address > 0x0FFFFFFF, then ASSERT().
545   If StartBit is greater than 7, then ASSERT().
546   If EndBit is greater than 7, then ASSERT().
547   If EndBit is less than StartBit, then ASSERT().
548   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
549 
550   @param  Address   The PCI configuration register to write.
551   @param  StartBit  The ordinal of the least significant bit in the bit field.
552                     Range 0..7.
553   @param  EndBit    The ordinal of the most significant bit in the bit field.
554                     Range 0..7.
555   @param  Value     The new value of the bit field.
556 
557   @return The value written back to the PCI configuration register.
558 
559 **/
560 UINT8
561 EFIAPI
PciExpressBitFieldWrite8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 Value)562 PciExpressBitFieldWrite8 (
563   IN      UINTN                     Address,
564   IN      UINTN                     StartBit,
565   IN      UINTN                     EndBit,
566   IN      UINT8                     Value
567   )
568 {
569   return MmioBitFieldWrite8 (
570            GetPciExpressAddress (Address),
571            StartBit,
572            EndBit,
573            Value
574            );
575 }
576 
577 /**
578   Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
579   writes the result back to the bit field in the 8-bit port.
580 
581   Reads the 8-bit PCI configuration register specified by Address, performs a
582   bitwise OR between the read result and the value specified by
583   OrData, and writes the result to the 8-bit PCI configuration register
584   specified by Address. The value written to the PCI configuration register is
585   returned. This function must guarantee that all PCI read and write operations
586   are serialized. Extra left bits in OrData are stripped.
587 
588   If Address > 0x0FFFFFFF, then ASSERT().
589   If StartBit is greater than 7, then ASSERT().
590   If EndBit is greater than 7, then ASSERT().
591   If EndBit is less than StartBit, then ASSERT().
592   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
593 
594   @param  Address   The PCI configuration register to write.
595   @param  StartBit  The ordinal of the least significant bit in the bit field.
596                     Range 0..7.
597   @param  EndBit    The ordinal of the most significant bit in the bit field.
598                     Range 0..7.
599   @param  OrData    The value to OR with the PCI configuration register.
600 
601   @return The value written back to the PCI configuration register.
602 
603 **/
604 UINT8
605 EFIAPI
PciExpressBitFieldOr8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 OrData)606 PciExpressBitFieldOr8 (
607   IN      UINTN                     Address,
608   IN      UINTN                     StartBit,
609   IN      UINTN                     EndBit,
610   IN      UINT8                     OrData
611   )
612 {
613   return MmioBitFieldOr8 (
614            GetPciExpressAddress (Address),
615            StartBit,
616            EndBit,
617            OrData
618            );
619 }
620 
621 /**
622   Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
623   AND, and writes the result back to the bit field in the 8-bit register.
624 
625   Reads the 8-bit PCI configuration register specified by Address, performs a
626   bitwise AND between the read result and the value specified by AndData, and
627   writes the result to the 8-bit PCI configuration register specified by
628   Address. The value written to the PCI configuration register is returned.
629   This function must guarantee that all PCI read and write operations are
630   serialized. Extra left bits in AndData are stripped.
631 
632   If Address > 0x0FFFFFFF, then ASSERT().
633   If StartBit is greater than 7, then ASSERT().
634   If EndBit is greater than 7, then ASSERT().
635   If EndBit is less than StartBit, then ASSERT().
636   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
637 
638   @param  Address   The PCI configuration register to write.
639   @param  StartBit  The ordinal of the least significant bit in the bit field.
640                     Range 0..7.
641   @param  EndBit    The ordinal of the most significant bit in the bit field.
642                     Range 0..7.
643   @param  AndData   The value to AND with the PCI configuration register.
644 
645   @return The value written back to the PCI configuration register.
646 
647 **/
648 UINT8
649 EFIAPI
PciExpressBitFieldAnd8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData)650 PciExpressBitFieldAnd8 (
651   IN      UINTN                     Address,
652   IN      UINTN                     StartBit,
653   IN      UINTN                     EndBit,
654   IN      UINT8                     AndData
655   )
656 {
657   return MmioBitFieldAnd8 (
658            GetPciExpressAddress (Address),
659            StartBit,
660            EndBit,
661            AndData
662            );
663 }
664 
665 /**
666   Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
667   bitwise OR, and writes the result back to the bit field in the
668   8-bit port.
669 
670   Reads the 8-bit PCI configuration register specified by Address, performs a
671   bitwise AND followed by a bitwise OR between the read result and
672   the value specified by AndData, and writes the result to the 8-bit PCI
673   configuration register specified by Address. The value written to the PCI
674   configuration register is returned. This function must guarantee that all PCI
675   read and write operations are serialized. Extra left bits in both AndData and
676   OrData are stripped.
677 
678   If Address > 0x0FFFFFFF, then ASSERT().
679   If StartBit is greater than 7, then ASSERT().
680   If EndBit is greater than 7, then ASSERT().
681   If EndBit is less than StartBit, then ASSERT().
682   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
683   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
684 
685   @param  Address   The PCI configuration register to write.
686   @param  StartBit  The ordinal of the least significant bit in the bit field.
687                     Range 0..7.
688   @param  EndBit    The ordinal of the most significant bit in the bit field.
689                     Range 0..7.
690   @param  AndData   The value to AND with the PCI configuration register.
691   @param  OrData    The value to OR with the result of the AND operation.
692 
693   @return The value written back to the PCI configuration register.
694 
695 **/
696 UINT8
697 EFIAPI
PciExpressBitFieldAndThenOr8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData,IN UINT8 OrData)698 PciExpressBitFieldAndThenOr8 (
699   IN      UINTN                     Address,
700   IN      UINTN                     StartBit,
701   IN      UINTN                     EndBit,
702   IN      UINT8                     AndData,
703   IN      UINT8                     OrData
704   )
705 {
706   return MmioBitFieldAndThenOr8 (
707            GetPciExpressAddress (Address),
708            StartBit,
709            EndBit,
710            AndData,
711            OrData
712            );
713 }
714 
715 /**
716   Reads a 16-bit PCI configuration register.
717 
718   Reads and returns the 16-bit PCI configuration register specified by Address.
719   This function must guarantee that all PCI read and write operations are
720   serialized.
721 
722   If Address > 0x0FFFFFFF, then ASSERT().
723   If Address is not aligned on a 16-bit boundary, then ASSERT().
724 
725   @param  Address The address that encodes the PCI Bus, Device, Function and
726                   Register.
727 
728   @return The read value from the PCI configuration register.
729 
730 **/
731 UINT16
732 EFIAPI
PciExpressRead16(IN UINTN Address)733 PciExpressRead16 (
734   IN      UINTN                     Address
735   )
736 {
737   return MmioRead16 (GetPciExpressAddress (Address));
738 }
739 
740 /**
741   Writes a 16-bit PCI configuration register.
742 
743   Writes the 16-bit PCI configuration register specified by Address with the
744   value specified by Value. Value is returned. This function must guarantee
745   that all PCI read and write operations are serialized.
746 
747   If Address > 0x0FFFFFFF, then ASSERT().
748   If Address is not aligned on a 16-bit boundary, then ASSERT().
749 
750   @param  Address The address that encodes the PCI Bus, Device, Function and
751                   Register.
752   @param  Value   The value to write.
753 
754   @return The value written to the PCI configuration register.
755 
756 **/
757 UINT16
758 EFIAPI
PciExpressWrite16(IN UINTN Address,IN UINT16 Value)759 PciExpressWrite16 (
760   IN      UINTN                     Address,
761   IN      UINT16                    Value
762   )
763 {
764   return MmioWrite16 (GetPciExpressAddress (Address), Value);
765 }
766 
767 /**
768   Performs a bitwise OR of a 16-bit PCI configuration register with
769   a 16-bit value.
770 
771   Reads the 16-bit PCI configuration register specified by Address, performs a
772   bitwise OR between the read result and the value specified by
773   OrData, and writes the result to the 16-bit PCI configuration register
774   specified by Address. The value written to the PCI configuration register is
775   returned. This function must guarantee that all PCI read and write operations
776   are serialized.
777 
778   If Address > 0x0FFFFFFF, then ASSERT().
779   If Address is not aligned on a 16-bit boundary, then ASSERT().
780 
781   @param  Address The address that encodes the PCI Bus, Device, Function and
782                   Register.
783   @param  OrData  The value to OR with the PCI configuration register.
784 
785   @return The value written back to the PCI configuration register.
786 
787 **/
788 UINT16
789 EFIAPI
PciExpressOr16(IN UINTN Address,IN UINT16 OrData)790 PciExpressOr16 (
791   IN      UINTN                     Address,
792   IN      UINT16                    OrData
793   )
794 {
795   return MmioOr16 (GetPciExpressAddress (Address), OrData);
796 }
797 
798 /**
799   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
800   value.
801 
802   Reads the 16-bit PCI configuration register specified by Address, performs a
803   bitwise AND between the read result and the value specified by AndData, and
804   writes the result to the 16-bit PCI configuration register specified by
805   Address. The value written to the PCI configuration register is returned.
806   This function must guarantee that all PCI read and write operations are
807   serialized.
808 
809   If Address > 0x0FFFFFFF, then ASSERT().
810   If Address is not aligned on a 16-bit boundary, then ASSERT().
811 
812   @param  Address The address that encodes the PCI Bus, Device, Function and
813                   Register.
814   @param  AndData The value to AND with the PCI configuration register.
815 
816   @return The value written back to the PCI configuration register.
817 
818 **/
819 UINT16
820 EFIAPI
PciExpressAnd16(IN UINTN Address,IN UINT16 AndData)821 PciExpressAnd16 (
822   IN      UINTN                     Address,
823   IN      UINT16                    AndData
824   )
825 {
826   return MmioAnd16 (GetPciExpressAddress (Address), AndData);
827 }
828 
829 /**
830   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
831   value, followed a  bitwise OR with another 16-bit value.
832 
833   Reads the 16-bit PCI configuration register specified by Address, performs a
834   bitwise AND between the read result and the value specified by AndData,
835   performs a bitwise OR between the result of the AND operation and
836   the value specified by OrData, and writes the result to the 16-bit PCI
837   configuration register specified by Address. The value written to the PCI
838   configuration register is returned. This function must guarantee that all PCI
839   read and write operations are serialized.
840 
841   If Address > 0x0FFFFFFF, then ASSERT().
842   If Address is not aligned on a 16-bit boundary, then ASSERT().
843 
844   @param  Address The address that encodes the PCI Bus, Device, Function and
845                   Register.
846   @param  AndData The value to AND with the PCI configuration register.
847   @param  OrData  The value to OR with the result of the AND operation.
848 
849   @return The value written back to the PCI configuration register.
850 
851 **/
852 UINT16
853 EFIAPI
PciExpressAndThenOr16(IN UINTN Address,IN UINT16 AndData,IN UINT16 OrData)854 PciExpressAndThenOr16 (
855   IN      UINTN                     Address,
856   IN      UINT16                    AndData,
857   IN      UINT16                    OrData
858   )
859 {
860   return MmioAndThenOr16 (
861            GetPciExpressAddress (Address),
862            AndData,
863            OrData
864            );
865 }
866 
867 /**
868   Reads a bit field of a PCI configuration register.
869 
870   Reads the bit field in a 16-bit PCI configuration register. The bit field is
871   specified by the StartBit and the EndBit. The value of the bit field is
872   returned.
873 
874   If Address > 0x0FFFFFFF, then ASSERT().
875   If Address is not aligned on a 16-bit boundary, then ASSERT().
876   If StartBit is greater than 15, then ASSERT().
877   If EndBit is greater than 15, then ASSERT().
878   If EndBit is less than StartBit, then ASSERT().
879 
880   @param  Address   The PCI configuration register to read.
881   @param  StartBit  The ordinal of the least significant bit in the bit field.
882                     Range 0..15.
883   @param  EndBit    The ordinal of the most significant bit in the bit field.
884                     Range 0..15.
885 
886   @return The value of the bit field read from the PCI configuration register.
887 
888 **/
889 UINT16
890 EFIAPI
PciExpressBitFieldRead16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)891 PciExpressBitFieldRead16 (
892   IN      UINTN                     Address,
893   IN      UINTN                     StartBit,
894   IN      UINTN                     EndBit
895   )
896 {
897   return MmioBitFieldRead16 (
898            GetPciExpressAddress (Address),
899            StartBit,
900            EndBit
901            );
902 }
903 
904 /**
905   Writes a bit field to a PCI configuration register.
906 
907   Writes Value to the bit field of the PCI configuration register. The bit
908   field is specified by the StartBit and the EndBit. All other bits in the
909   destination PCI configuration register are preserved. The new value of the
910   16-bit register is returned.
911 
912   If Address > 0x0FFFFFFF, then ASSERT().
913   If Address is not aligned on a 16-bit boundary, then ASSERT().
914   If StartBit is greater than 15, then ASSERT().
915   If EndBit is greater than 15, then ASSERT().
916   If EndBit is less than StartBit, then ASSERT().
917   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
918 
919   @param  Address   The PCI configuration register to write.
920   @param  StartBit  The ordinal of the least significant bit in the bit field.
921                     Range 0..15.
922   @param  EndBit    The ordinal of the most significant bit in the bit field.
923                     Range 0..15.
924   @param  Value     The new value of the bit field.
925 
926   @return The value written back to the PCI configuration register.
927 
928 **/
929 UINT16
930 EFIAPI
PciExpressBitFieldWrite16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 Value)931 PciExpressBitFieldWrite16 (
932   IN      UINTN                     Address,
933   IN      UINTN                     StartBit,
934   IN      UINTN                     EndBit,
935   IN      UINT16                    Value
936   )
937 {
938   return MmioBitFieldWrite16 (
939            GetPciExpressAddress (Address),
940            StartBit,
941            EndBit,
942            Value
943            );
944 }
945 
946 /**
947   Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
948   writes the result back to the bit field in the 16-bit port.
949 
950   Reads the 16-bit PCI configuration register specified by Address, performs a
951   bitwise OR between the read result and the value specified by
952   OrData, and writes the result to the 16-bit PCI configuration register
953   specified by Address. The value written to the PCI configuration register is
954   returned. This function must guarantee that all PCI read and write operations
955   are serialized. Extra left bits in OrData are stripped.
956 
957   If Address > 0x0FFFFFFF, then ASSERT().
958   If Address is not aligned on a 16-bit boundary, then ASSERT().
959   If StartBit is greater than 15, then ASSERT().
960   If EndBit is greater than 15, then ASSERT().
961   If EndBit is less than StartBit, then ASSERT().
962   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
963 
964   @param  Address   The PCI configuration register to write.
965   @param  StartBit  The ordinal of the least significant bit in the bit field.
966                     Range 0..15.
967   @param  EndBit    The ordinal of the most significant bit in the bit field.
968                     Range 0..15.
969   @param  OrData    The value to OR with the PCI configuration register.
970 
971   @return The value written back to the PCI configuration register.
972 
973 **/
974 UINT16
975 EFIAPI
PciExpressBitFieldOr16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 OrData)976 PciExpressBitFieldOr16 (
977   IN      UINTN                     Address,
978   IN      UINTN                     StartBit,
979   IN      UINTN                     EndBit,
980   IN      UINT16                    OrData
981   )
982 {
983   return MmioBitFieldOr16 (
984            GetPciExpressAddress (Address),
985            StartBit,
986            EndBit,
987            OrData
988            );
989 }
990 
991 /**
992   Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
993   AND, and writes the result back to the bit field in the 16-bit register.
994 
995   Reads the 16-bit PCI configuration register specified by Address, performs a
996   bitwise AND between the read result and the value specified by AndData, and
997   writes the result to the 16-bit PCI configuration register specified by
998   Address. The value written to the PCI configuration register is returned.
999   This function must guarantee that all PCI read and write operations are
1000   serialized. Extra left bits in AndData are stripped.
1001 
1002   If Address > 0x0FFFFFFF, then ASSERT().
1003   If Address is not aligned on a 16-bit boundary, then ASSERT().
1004   If StartBit is greater than 15, then ASSERT().
1005   If EndBit is greater than 15, then ASSERT().
1006   If EndBit is less than StartBit, then ASSERT().
1007   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1008 
1009   @param  Address   The PCI configuration register to write.
1010   @param  StartBit  The ordinal of the least significant bit in the bit field.
1011                     Range 0..15.
1012   @param  EndBit    The ordinal of the most significant bit in the bit field.
1013                     Range 0..15.
1014   @param  AndData   The value to AND with the PCI configuration register.
1015 
1016   @return The value written back to the PCI configuration register.
1017 
1018 **/
1019 UINT16
1020 EFIAPI
PciExpressBitFieldAnd16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData)1021 PciExpressBitFieldAnd16 (
1022   IN      UINTN                     Address,
1023   IN      UINTN                     StartBit,
1024   IN      UINTN                     EndBit,
1025   IN      UINT16                    AndData
1026   )
1027 {
1028   return MmioBitFieldAnd16 (
1029            GetPciExpressAddress (Address),
1030            StartBit,
1031            EndBit,
1032            AndData
1033            );
1034 }
1035 
1036 /**
1037   Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
1038   bitwise OR, and writes the result back to the bit field in the
1039   16-bit port.
1040 
1041   Reads the 16-bit PCI configuration register specified by Address, performs a
1042   bitwise AND followed by a bitwise OR between the read result and
1043   the value specified by AndData, and writes the result to the 16-bit PCI
1044   configuration register specified by Address. The value written to the PCI
1045   configuration register is returned. This function must guarantee that all PCI
1046   read and write operations are serialized. Extra left bits in both AndData and
1047   OrData are stripped.
1048 
1049   If Address > 0x0FFFFFFF, then ASSERT().
1050   If Address is not aligned on a 16-bit boundary, then ASSERT().
1051   If StartBit is greater than 15, then ASSERT().
1052   If EndBit is greater than 15, then ASSERT().
1053   If EndBit is less than StartBit, then ASSERT().
1054   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1055   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1056 
1057   @param  Address   The PCI configuration register to write.
1058   @param  StartBit  The ordinal of the least significant bit in the bit field.
1059                     Range 0..15.
1060   @param  EndBit    The ordinal of the most significant bit in the bit field.
1061                     Range 0..15.
1062   @param  AndData   The value to AND with the PCI configuration register.
1063   @param  OrData    The value to OR with the result of the AND operation.
1064 
1065   @return The value written back to the PCI configuration register.
1066 
1067 **/
1068 UINT16
1069 EFIAPI
PciExpressBitFieldAndThenOr16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData,IN UINT16 OrData)1070 PciExpressBitFieldAndThenOr16 (
1071   IN      UINTN                     Address,
1072   IN      UINTN                     StartBit,
1073   IN      UINTN                     EndBit,
1074   IN      UINT16                    AndData,
1075   IN      UINT16                    OrData
1076   )
1077 {
1078   return MmioBitFieldAndThenOr16 (
1079            GetPciExpressAddress (Address),
1080            StartBit,
1081            EndBit,
1082            AndData,
1083            OrData
1084            );
1085 }
1086 
1087 /**
1088   Reads a 32-bit PCI configuration register.
1089 
1090   Reads and returns the 32-bit PCI configuration register specified by Address.
1091   This function must guarantee that all PCI read and write operations are
1092   serialized.
1093 
1094   If Address > 0x0FFFFFFF, then ASSERT().
1095   If Address is not aligned on a 32-bit boundary, then ASSERT().
1096 
1097   @param  Address The address that encodes the PCI Bus, Device, Function and
1098                   Register.
1099 
1100   @return The read value from the PCI configuration register.
1101 
1102 **/
1103 UINT32
1104 EFIAPI
PciExpressRead32(IN UINTN Address)1105 PciExpressRead32 (
1106   IN      UINTN                     Address
1107   )
1108 {
1109   return MmioRead32 (GetPciExpressAddress (Address));
1110 }
1111 
1112 /**
1113   Writes a 32-bit PCI configuration register.
1114 
1115   Writes the 32-bit PCI configuration register specified by Address with the
1116   value specified by Value. Value is returned. This function must guarantee
1117   that all PCI read and write operations are serialized.
1118 
1119   If Address > 0x0FFFFFFF, then ASSERT().
1120   If Address is not aligned on a 32-bit boundary, then ASSERT().
1121 
1122   @param  Address The address that encodes the PCI Bus, Device, Function and
1123                   Register.
1124   @param  Value   The value to write.
1125 
1126   @return The value written to the PCI configuration register.
1127 
1128 **/
1129 UINT32
1130 EFIAPI
PciExpressWrite32(IN UINTN Address,IN UINT32 Value)1131 PciExpressWrite32 (
1132   IN      UINTN                     Address,
1133   IN      UINT32                    Value
1134   )
1135 {
1136   return MmioWrite32 (GetPciExpressAddress (Address), Value);
1137 }
1138 
1139 /**
1140   Performs a bitwise OR of a 32-bit PCI configuration register with
1141   a 32-bit value.
1142 
1143   Reads the 32-bit PCI configuration register specified by Address, performs a
1144   bitwise OR between the read result and the value specified by
1145   OrData, and writes the result to the 32-bit PCI configuration register
1146   specified by Address. The value written to the PCI configuration register is
1147   returned. This function must guarantee that all PCI read and write operations
1148   are serialized.
1149 
1150   If Address > 0x0FFFFFFF, then ASSERT().
1151   If Address is not aligned on a 32-bit boundary, then ASSERT().
1152 
1153   @param  Address The address that encodes the PCI Bus, Device, Function and
1154                   Register.
1155   @param  OrData  The value to OR with the PCI configuration register.
1156 
1157   @return The value written back to the PCI configuration register.
1158 
1159 **/
1160 UINT32
1161 EFIAPI
PciExpressOr32(IN UINTN Address,IN UINT32 OrData)1162 PciExpressOr32 (
1163   IN      UINTN                     Address,
1164   IN      UINT32                    OrData
1165   )
1166 {
1167   return MmioOr32 (GetPciExpressAddress (Address), OrData);
1168 }
1169 
1170 /**
1171   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1172   value.
1173 
1174   Reads the 32-bit PCI configuration register specified by Address, performs a
1175   bitwise AND between the read result and the value specified by AndData, and
1176   writes the result to the 32-bit PCI configuration register specified by
1177   Address. The value written to the PCI configuration register is returned.
1178   This function must guarantee that all PCI read and write operations are
1179   serialized.
1180 
1181   If Address > 0x0FFFFFFF, then ASSERT().
1182   If Address is not aligned on a 32-bit boundary, then ASSERT().
1183 
1184   @param  Address The address that encodes the PCI Bus, Device, Function and
1185                   Register.
1186   @param  AndData The value to AND with the PCI configuration register.
1187 
1188   @return The value written back to the PCI configuration register.
1189 
1190 **/
1191 UINT32
1192 EFIAPI
PciExpressAnd32(IN UINTN Address,IN UINT32 AndData)1193 PciExpressAnd32 (
1194   IN      UINTN                     Address,
1195   IN      UINT32                    AndData
1196   )
1197 {
1198   return MmioAnd32 (GetPciExpressAddress (Address), AndData);
1199 }
1200 
1201 /**
1202   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1203   value, followed a  bitwise OR with another 32-bit value.
1204 
1205   Reads the 32-bit PCI configuration register specified by Address, performs a
1206   bitwise AND between the read result and the value specified by AndData,
1207   performs a bitwise OR between the result of the AND operation and
1208   the value specified by OrData, and writes the result to the 32-bit PCI
1209   configuration register specified by Address. The value written to the PCI
1210   configuration register is returned. This function must guarantee that all PCI
1211   read and write operations are serialized.
1212 
1213   If Address > 0x0FFFFFFF, then ASSERT().
1214   If Address is not aligned on a 32-bit boundary, then ASSERT().
1215 
1216   @param  Address The address that encodes the PCI Bus, Device, Function and
1217                   Register.
1218   @param  AndData The value to AND with the PCI configuration register.
1219   @param  OrData  The value to OR with the result of the AND operation.
1220 
1221   @return The value written back to the PCI configuration register.
1222 
1223 **/
1224 UINT32
1225 EFIAPI
PciExpressAndThenOr32(IN UINTN Address,IN UINT32 AndData,IN UINT32 OrData)1226 PciExpressAndThenOr32 (
1227   IN      UINTN                     Address,
1228   IN      UINT32                    AndData,
1229   IN      UINT32                    OrData
1230   )
1231 {
1232   return MmioAndThenOr32 (
1233            GetPciExpressAddress (Address),
1234            AndData,
1235            OrData
1236            );
1237 }
1238 
1239 /**
1240   Reads a bit field of a PCI configuration register.
1241 
1242   Reads the bit field in a 32-bit PCI configuration register. The bit field is
1243   specified by the StartBit and the EndBit. The value of the bit field is
1244   returned.
1245 
1246   If Address > 0x0FFFFFFF, then ASSERT().
1247   If Address is not aligned on a 32-bit boundary, then ASSERT().
1248   If StartBit is greater than 31, then ASSERT().
1249   If EndBit is greater than 31, then ASSERT().
1250   If EndBit is less than StartBit, then ASSERT().
1251 
1252   @param  Address   The PCI configuration register to read.
1253   @param  StartBit  The ordinal of the least significant bit in the bit field.
1254                     Range 0..31.
1255   @param  EndBit    The ordinal of the most significant bit in the bit field.
1256                     Range 0..31.
1257 
1258   @return The value of the bit field read from the PCI configuration register.
1259 
1260 **/
1261 UINT32
1262 EFIAPI
PciExpressBitFieldRead32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)1263 PciExpressBitFieldRead32 (
1264   IN      UINTN                     Address,
1265   IN      UINTN                     StartBit,
1266   IN      UINTN                     EndBit
1267   )
1268 {
1269   return MmioBitFieldRead32 (
1270            GetPciExpressAddress (Address),
1271            StartBit,
1272            EndBit
1273            );
1274 }
1275 
1276 /**
1277   Writes a bit field to a PCI configuration register.
1278 
1279   Writes Value to the bit field of the PCI configuration register. The bit
1280   field is specified by the StartBit and the EndBit. All other bits in the
1281   destination PCI configuration register are preserved. The new value of the
1282   32-bit register is returned.
1283 
1284   If Address > 0x0FFFFFFF, then ASSERT().
1285   If Address is not aligned on a 32-bit boundary, then ASSERT().
1286   If StartBit is greater than 31, then ASSERT().
1287   If EndBit is greater than 31, then ASSERT().
1288   If EndBit is less than StartBit, then ASSERT().
1289   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1290 
1291   @param  Address   The PCI configuration register to write.
1292   @param  StartBit  The ordinal of the least significant bit in the bit field.
1293                     Range 0..31.
1294   @param  EndBit    The ordinal of the most significant bit in the bit field.
1295                     Range 0..31.
1296   @param  Value     The new value of the bit field.
1297 
1298   @return The value written back to the PCI configuration register.
1299 
1300 **/
1301 UINT32
1302 EFIAPI
PciExpressBitFieldWrite32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 Value)1303 PciExpressBitFieldWrite32 (
1304   IN      UINTN                     Address,
1305   IN      UINTN                     StartBit,
1306   IN      UINTN                     EndBit,
1307   IN      UINT32                    Value
1308   )
1309 {
1310   return MmioBitFieldWrite32 (
1311            GetPciExpressAddress (Address),
1312            StartBit,
1313            EndBit,
1314            Value
1315            );
1316 }
1317 
1318 /**
1319   Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1320   writes the result back to the bit field in the 32-bit port.
1321 
1322   Reads the 32-bit PCI configuration register specified by Address, performs a
1323   bitwise OR between the read result and the value specified by
1324   OrData, and writes the result to the 32-bit PCI configuration register
1325   specified by Address. The value written to the PCI configuration register is
1326   returned. This function must guarantee that all PCI read and write operations
1327   are serialized. Extra left bits in OrData are stripped.
1328 
1329   If Address > 0x0FFFFFFF, then ASSERT().
1330   If Address is not aligned on a 32-bit boundary, then ASSERT().
1331   If StartBit is greater than 31, then ASSERT().
1332   If EndBit is greater than 31, then ASSERT().
1333   If EndBit is less than StartBit, then ASSERT().
1334   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1335 
1336   @param  Address   The PCI configuration register to write.
1337   @param  StartBit  The ordinal of the least significant bit in the bit field.
1338                     Range 0..31.
1339   @param  EndBit    The ordinal of the most significant bit in the bit field.
1340                     Range 0..31.
1341   @param  OrData    The value to OR with the PCI configuration register.
1342 
1343   @return The value written back to the PCI configuration register.
1344 
1345 **/
1346 UINT32
1347 EFIAPI
PciExpressBitFieldOr32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 OrData)1348 PciExpressBitFieldOr32 (
1349   IN      UINTN                     Address,
1350   IN      UINTN                     StartBit,
1351   IN      UINTN                     EndBit,
1352   IN      UINT32                    OrData
1353   )
1354 {
1355   return MmioBitFieldOr32 (
1356            GetPciExpressAddress (Address),
1357            StartBit,
1358            EndBit,
1359            OrData
1360            );
1361 }
1362 
1363 /**
1364   Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1365   AND, and writes the result back to the bit field in the 32-bit register.
1366 
1367   Reads the 32-bit PCI configuration register specified by Address, performs a
1368   bitwise AND between the read result and the value specified by AndData, and
1369   writes the result to the 32-bit PCI configuration register specified by
1370   Address. The value written to the PCI configuration register is returned.
1371   This function must guarantee that all PCI read and write operations are
1372   serialized. Extra left bits in AndData are stripped.
1373 
1374   If Address > 0x0FFFFFFF, then ASSERT().
1375   If Address is not aligned on a 32-bit boundary, then ASSERT().
1376   If StartBit is greater than 31, then ASSERT().
1377   If EndBit is greater than 31, then ASSERT().
1378   If EndBit is less than StartBit, then ASSERT().
1379   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1380 
1381   @param  Address   The PCI configuration register to write.
1382   @param  StartBit  The ordinal of the least significant bit in the bit field.
1383                     Range 0..31.
1384   @param  EndBit    The ordinal of the most significant bit in the bit field.
1385                     Range 0..31.
1386   @param  AndData   The value to AND with the PCI configuration register.
1387 
1388   @return The value written back to the PCI configuration register.
1389 
1390 **/
1391 UINT32
1392 EFIAPI
PciExpressBitFieldAnd32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData)1393 PciExpressBitFieldAnd32 (
1394   IN      UINTN                     Address,
1395   IN      UINTN                     StartBit,
1396   IN      UINTN                     EndBit,
1397   IN      UINT32                    AndData
1398   )
1399 {
1400   return MmioBitFieldAnd32 (
1401            GetPciExpressAddress (Address),
1402            StartBit,
1403            EndBit,
1404            AndData
1405            );
1406 }
1407 
1408 /**
1409   Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1410   bitwise OR, and writes the result back to the bit field in the
1411   32-bit port.
1412 
1413   Reads the 32-bit PCI configuration register specified by Address, performs a
1414   bitwise AND followed by a bitwise OR between the read result and
1415   the value specified by AndData, and writes the result to the 32-bit PCI
1416   configuration register specified by Address. The value written to the PCI
1417   configuration register is returned. This function must guarantee that all PCI
1418   read and write operations are serialized. Extra left bits in both AndData and
1419   OrData are stripped.
1420 
1421   If Address > 0x0FFFFFFF, then ASSERT().
1422   If Address is not aligned on a 32-bit boundary, then ASSERT().
1423   If StartBit is greater than 31, then ASSERT().
1424   If EndBit is greater than 31, then ASSERT().
1425   If EndBit is less than StartBit, then ASSERT().
1426   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1427   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1428 
1429   @param  Address   The PCI configuration register to write.
1430   @param  StartBit  The ordinal of the least significant bit in the bit field.
1431                     Range 0..31.
1432   @param  EndBit    The ordinal of the most significant bit in the bit field.
1433                     Range 0..31.
1434   @param  AndData   The value to AND with the PCI configuration register.
1435   @param  OrData    The value to OR with the result of the AND operation.
1436 
1437   @return The value written back to the PCI configuration register.
1438 
1439 **/
1440 UINT32
1441 EFIAPI
PciExpressBitFieldAndThenOr32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData,IN UINT32 OrData)1442 PciExpressBitFieldAndThenOr32 (
1443   IN      UINTN                     Address,
1444   IN      UINTN                     StartBit,
1445   IN      UINTN                     EndBit,
1446   IN      UINT32                    AndData,
1447   IN      UINT32                    OrData
1448   )
1449 {
1450   return MmioBitFieldAndThenOr32 (
1451            GetPciExpressAddress (Address),
1452            StartBit,
1453            EndBit,
1454            AndData,
1455            OrData
1456            );
1457 }
1458 
1459 /**
1460   Reads a range of PCI configuration registers into a caller supplied buffer.
1461 
1462   Reads the range of PCI configuration registers specified by StartAddress and
1463   Size into the buffer specified by Buffer. This function only allows the PCI
1464   configuration registers from a single PCI function to be read. Size is
1465   returned. When possible 32-bit PCI configuration read cycles are used to read
1466   from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
1467   and 16-bit PCI configuration read cycles may be used at the beginning and the
1468   end of the range.
1469 
1470   If StartAddress > 0x0FFFFFFF, then ASSERT().
1471   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1472   If Size > 0 and Buffer is NULL, then ASSERT().
1473 
1474   @param  StartAddress  The starting address that encodes the PCI Bus, Device,
1475                         Function and Register.
1476   @param  Size          The size in bytes of the transfer.
1477   @param  Buffer        The pointer to a buffer receiving the data read.
1478 
1479   @return Size read data from StartAddress.
1480 
1481 **/
1482 UINTN
1483 EFIAPI
PciExpressReadBuffer(IN UINTN StartAddress,IN UINTN Size,OUT VOID * Buffer)1484 PciExpressReadBuffer (
1485   IN      UINTN                     StartAddress,
1486   IN      UINTN                     Size,
1487   OUT     VOID                      *Buffer
1488   )
1489 {
1490   UINTN   ReturnValue;
1491 
1492   //
1493   // Make sure Address is valid
1494   //
1495   ASSERT (((StartAddress) & ~0xfffffff) == 0);
1496   ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1497 
1498   if (Size == 0) {
1499     return Size;
1500   }
1501 
1502   ASSERT (Buffer != NULL);
1503 
1504   //
1505   // Save Size for return
1506   //
1507   ReturnValue = Size;
1508 
1509   if ((StartAddress & 1) != 0) {
1510     //
1511     // Read a byte if StartAddress is byte aligned
1512     //
1513     *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1514     StartAddress += sizeof (UINT8);
1515     Size -= sizeof (UINT8);
1516     Buffer = (UINT8*)Buffer + 1;
1517   }
1518 
1519   if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1520     //
1521     // Read a word if StartAddress is word aligned
1522     //
1523     WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1524 
1525     StartAddress += sizeof (UINT16);
1526     Size -= sizeof (UINT16);
1527     Buffer = (UINT16*)Buffer + 1;
1528   }
1529 
1530   while (Size >= sizeof (UINT32)) {
1531     //
1532     // Read as many double words as possible
1533     //
1534     WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
1535 
1536     StartAddress += sizeof (UINT32);
1537     Size -= sizeof (UINT32);
1538     Buffer = (UINT32*)Buffer + 1;
1539   }
1540 
1541   if (Size >= sizeof (UINT16)) {
1542     //
1543     // Read the last remaining word if exist
1544     //
1545     WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1546     StartAddress += sizeof (UINT16);
1547     Size -= sizeof (UINT16);
1548     Buffer = (UINT16*)Buffer + 1;
1549   }
1550 
1551   if (Size >= sizeof (UINT8)) {
1552     //
1553     // Read the last remaining byte if exist
1554     //
1555     *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1556   }
1557 
1558   return ReturnValue;
1559 }
1560 
1561 /**
1562   Copies the data in a caller supplied buffer to a specified range of PCI
1563   configuration space.
1564 
1565   Writes the range of PCI configuration registers specified by StartAddress and
1566   Size from the buffer specified by Buffer. This function only allows the PCI
1567   configuration registers from a single PCI function to be written. Size is
1568   returned. When possible 32-bit PCI configuration write cycles are used to
1569   write from StartAdress to StartAddress + Size. Due to alignment restrictions,
1570   8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1571   and the end of the range.
1572 
1573   If StartAddress > 0x0FFFFFFF, then ASSERT().
1574   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1575   If Size > 0 and Buffer is NULL, then ASSERT().
1576 
1577   @param  StartAddress  The starting address that encodes the PCI Bus, Device,
1578                         Function and Register.
1579   @param  Size          The size in bytes of the transfer.
1580   @param  Buffer        The pointer to a buffer containing the data to write.
1581 
1582   @return Size written to StartAddress.
1583 
1584 **/
1585 UINTN
1586 EFIAPI
PciExpressWriteBuffer(IN UINTN StartAddress,IN UINTN Size,IN VOID * Buffer)1587 PciExpressWriteBuffer (
1588   IN      UINTN                     StartAddress,
1589   IN      UINTN                     Size,
1590   IN      VOID                      *Buffer
1591   )
1592 {
1593   UINTN                             ReturnValue;
1594 
1595   //
1596   // Make sure Address is valid
1597   //
1598   ASSERT (((StartAddress) & ~0xfffffff) == 0);
1599   ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1600 
1601   if (Size == 0) {
1602     return 0;
1603   }
1604 
1605   ASSERT (Buffer != NULL);
1606 
1607   //
1608   // Save Size for return
1609   //
1610   ReturnValue = Size;
1611 
1612   if ((StartAddress & 1) != 0) {
1613     //
1614     // Write a byte if StartAddress is byte aligned
1615     //
1616     PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1617     StartAddress += sizeof (UINT8);
1618     Size -= sizeof (UINT8);
1619     Buffer = (UINT8*)Buffer + 1;
1620   }
1621 
1622   if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1623     //
1624     // Write a word if StartAddress is word aligned
1625     //
1626     PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1627     StartAddress += sizeof (UINT16);
1628     Size -= sizeof (UINT16);
1629     Buffer = (UINT16*)Buffer + 1;
1630   }
1631 
1632   while (Size >= sizeof (UINT32)) {
1633     //
1634     // Write as many double words as possible
1635     //
1636     PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
1637     StartAddress += sizeof (UINT32);
1638     Size -= sizeof (UINT32);
1639     Buffer = (UINT32*)Buffer + 1;
1640   }
1641 
1642   if (Size >= sizeof (UINT16)) {
1643     //
1644     // Write the last remaining word if exist
1645     //
1646     PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1647     StartAddress += sizeof (UINT16);
1648     Size -= sizeof (UINT16);
1649     Buffer = (UINT16*)Buffer + 1;
1650   }
1651 
1652   if (Size >= sizeof (UINT8)) {
1653     //
1654     // Write the last remaining byte if exist
1655     //
1656     PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1657   }
1658 
1659   return ReturnValue;
1660 }
1661