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///
37typedef struct {
38  UINTN  PhysicalAddress;
39  UINTN  VirtualAddress;
40} PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE;
41
42///
43/// Set Virtual Address Map Event
44///
45EFI_EVENT                               mDxeRuntimePciExpressLibVirtualNotifyEvent = NULL;
46
47///
48/// Module global that contains the base physical address of the PCI Express MMIO range.
49///
50UINTN                                   mDxeRuntimePciExpressLibPciExpressBaseAddress = 0;
51
52///
53/// The number of PCI devices that have been registered for runtime access.
54///
55UINTN                                   mDxeRuntimePciExpressLibNumberOfRuntimeRanges = 0;
56
57///
58/// The table of PCI devices that have been registered for runtime access.
59///
60PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE  *mDxeRuntimePciExpressLibRegistrationTable = NULL;
61
62///
63/// The table index of the most recent virtual address lookup.
64///
65UINTN                                   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**/
75VOID
76EFIAPI
77DxeRuntimePciExpressLibVirtualNotify (
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**/
116EFI_STATUS
117EFIAPI
118DxeRuntimePciExpressLibConstructor (
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**/
157EFI_STATUS
158EFIAPI
159DxeRuntimePciExpressLibDestructor (
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**/
193UINTN
194GetPciExpressAddress (
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**/
277RETURN_STATUS
278EFIAPI
279PciExpressRegisterForRuntimeAccess (
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**/
368UINT8
369EFIAPI
370PciExpressRead8 (
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**/
393UINT8
394EFIAPI
395PciExpressWrite8 (
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**/
423UINT8
424EFIAPI
425PciExpressOr8 (
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**/
453UINT8
454EFIAPI
455PciExpressAnd8 (
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**/
485UINT8
486EFIAPI
487PciExpressAndThenOr8 (
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**/
521UINT8
522EFIAPI
523PciExpressBitFieldRead8 (
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**/
560UINT8
561EFIAPI
562PciExpressBitFieldWrite8 (
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**/
604UINT8
605EFIAPI
606PciExpressBitFieldOr8 (
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**/
648UINT8
649EFIAPI
650PciExpressBitFieldAnd8 (
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**/
696UINT8
697EFIAPI
698PciExpressBitFieldAndThenOr8 (
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**/
731UINT16
732EFIAPI
733PciExpressRead16 (
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**/
757UINT16
758EFIAPI
759PciExpressWrite16 (
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**/
788UINT16
789EFIAPI
790PciExpressOr16 (
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**/
819UINT16
820EFIAPI
821PciExpressAnd16 (
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**/
852UINT16
853EFIAPI
854PciExpressAndThenOr16 (
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**/
889UINT16
890EFIAPI
891PciExpressBitFieldRead16 (
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**/
929UINT16
930EFIAPI
931PciExpressBitFieldWrite16 (
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**/
974UINT16
975EFIAPI
976PciExpressBitFieldOr16 (
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**/
1019UINT16
1020EFIAPI
1021PciExpressBitFieldAnd16 (
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**/
1068UINT16
1069EFIAPI
1070PciExpressBitFieldAndThenOr16 (
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**/
1103UINT32
1104EFIAPI
1105PciExpressRead32 (
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**/
1129UINT32
1130EFIAPI
1131PciExpressWrite32 (
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**/
1160UINT32
1161EFIAPI
1162PciExpressOr32 (
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**/
1191UINT32
1192EFIAPI
1193PciExpressAnd32 (
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**/
1224UINT32
1225EFIAPI
1226PciExpressAndThenOr32 (
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**/
1261UINT32
1262EFIAPI
1263PciExpressBitFieldRead32 (
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**/
1301UINT32
1302EFIAPI
1303PciExpressBitFieldWrite32 (
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**/
1346UINT32
1347EFIAPI
1348PciExpressBitFieldOr32 (
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**/
1391UINT32
1392EFIAPI
1393PciExpressBitFieldAnd32 (
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**/
1440UINT32
1441EFIAPI
1442PciExpressBitFieldAndThenOr32 (
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**/
1482UINTN
1483EFIAPI
1484PciExpressReadBuffer (
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**/
1585UINTN
1586EFIAPI
1587PciExpressWriteBuffer (
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