• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <Base.h>
21 
22 #include <Library/BaseLib.h>
23 #include <Library/PciExpressLib.h>
24 #include <Library/IoLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/PcdLib.h>
27 
28 
29 /**
30   Assert the validity of a PCI address. A valid PCI address should contain 1's
31   only in the low 28 bits.
32 
33   @param  A The address to validate.
34 
35 **/
36 #define ASSERT_INVALID_PCI_ADDRESS(A) \
37   ASSERT (((A) & ~0xfffffff) == 0)
38 
39 /**
40   Registers a PCI device so PCI configuration registers may be accessed after
41   SetVirtualAddressMap().
42 
43   Registers the PCI device specified by Address so all the PCI configuration
44   registers associated with that PCI device may be accessed after SetVirtualAddressMap()
45   is called.
46 
47   If Address > 0x0FFFFFFF, then ASSERT().
48 
49   @param  Address The address that encodes the PCI Bus, Device, Function and
50                   Register.
51 
52   @retval RETURN_SUCCESS           The PCI device was registered for runtime access.
53   @retval RETURN_UNSUPPORTED       An attempt was made to call this function
54                                    after ExitBootServices().
55   @retval RETURN_UNSUPPORTED       The resources required to access the PCI device
56                                    at runtime could not be mapped.
57   @retval RETURN_OUT_OF_RESOURCES  There are not enough resources available to
58                                    complete the registration.
59 
60 **/
61 RETURN_STATUS
62 EFIAPI
PciExpressRegisterForRuntimeAccess(IN UINTN Address)63 PciExpressRegisterForRuntimeAccess (
64   IN UINTN  Address
65   )
66 {
67   ASSERT_INVALID_PCI_ADDRESS (Address);
68   return RETURN_UNSUPPORTED;
69 }
70 
71 /**
72   Gets the base address of PCI Express.
73 
74   This internal functions retrieves PCI Express Base Address via a PCD entry
75   PcdPciExpressBaseAddress.
76 
77   @return The base address of PCI Express.
78 
79 **/
80 VOID*
GetPciExpressBaseAddress(VOID)81 GetPciExpressBaseAddress (
82   VOID
83   )
84 {
85   return (VOID*)(UINTN) PcdGet64 (PcdPciExpressBaseAddress);
86 }
87 
88 /**
89   Reads an 8-bit PCI configuration register.
90 
91   Reads and returns the 8-bit PCI configuration register specified by Address.
92   This function must guarantee that all PCI read and write operations are
93   serialized.
94 
95   If Address > 0x0FFFFFFF, then ASSERT().
96 
97   @param  Address The address that encodes the PCI Bus, Device, Function and
98                   Register.
99 
100   @return The read value from the PCI configuration register.
101 
102 **/
103 UINT8
104 EFIAPI
PciExpressRead8(IN UINTN Address)105 PciExpressRead8 (
106   IN      UINTN                     Address
107   )
108 {
109   ASSERT_INVALID_PCI_ADDRESS (Address);
110   return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
111 }
112 
113 /**
114   Writes an 8-bit PCI configuration register.
115 
116   Writes the 8-bit PCI configuration register specified by Address with the
117   value specified by Value. Value is returned. This function must guarantee
118   that all PCI read and write operations are serialized.
119 
120   If Address > 0x0FFFFFFF, then ASSERT().
121 
122   @param  Address The address that encodes the PCI Bus, Device, Function and
123                   Register.
124   @param  Value   The value to write.
125 
126   @return The value written to the PCI configuration register.
127 
128 **/
129 UINT8
130 EFIAPI
PciExpressWrite8(IN UINTN Address,IN UINT8 Value)131 PciExpressWrite8 (
132   IN      UINTN                     Address,
133   IN      UINT8                     Value
134   )
135 {
136   ASSERT_INVALID_PCI_ADDRESS (Address);
137   return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
138 }
139 
140 /**
141   Performs a bitwise OR of an 8-bit PCI configuration register with
142   an 8-bit value.
143 
144   Reads the 8-bit PCI configuration register specified by Address, performs a
145   bitwise OR between the read result and the value specified by
146   OrData, and writes the result to the 8-bit PCI configuration register
147   specified by Address. The value written to the PCI configuration register is
148   returned. This function must guarantee that all PCI read and write operations
149   are serialized.
150 
151   If Address > 0x0FFFFFFF, then ASSERT().
152 
153   @param  Address The address that encodes the PCI Bus, Device, Function and
154                   Register.
155   @param  OrData  The value to OR with the PCI configuration register.
156 
157   @return The value written back to the PCI configuration register.
158 
159 **/
160 UINT8
161 EFIAPI
PciExpressOr8(IN UINTN Address,IN UINT8 OrData)162 PciExpressOr8 (
163   IN      UINTN                     Address,
164   IN      UINT8                     OrData
165   )
166 {
167   ASSERT_INVALID_PCI_ADDRESS (Address);
168   return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
169 }
170 
171 /**
172   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
173   value.
174 
175   Reads the 8-bit PCI configuration register specified by Address, performs a
176   bitwise AND between the read result and the value specified by AndData, and
177   writes the result to the 8-bit PCI configuration register specified by
178   Address. The value written to the PCI configuration register is returned.
179   This function must guarantee that all PCI read and write operations are
180   serialized.
181 
182   If Address > 0x0FFFFFFF, then ASSERT().
183 
184   @param  Address The address that encodes the PCI Bus, Device, Function and
185                   Register.
186   @param  AndData The value to AND with the PCI configuration register.
187 
188   @return The value written back to the PCI configuration register.
189 
190 **/
191 UINT8
192 EFIAPI
PciExpressAnd8(IN UINTN Address,IN UINT8 AndData)193 PciExpressAnd8 (
194   IN      UINTN                     Address,
195   IN      UINT8                     AndData
196   )
197 {
198   ASSERT_INVALID_PCI_ADDRESS (Address);
199   return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
200 }
201 
202 /**
203   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
204   value, followed a  bitwise OR with another 8-bit value.
205 
206   Reads the 8-bit PCI configuration register specified by Address, performs a
207   bitwise AND between the read result and the value specified by AndData,
208   performs a bitwise OR between the result of the AND operation and
209   the value specified by OrData, and writes the result to the 8-bit PCI
210   configuration register specified by Address. The value written to the PCI
211   configuration register is returned. This function must guarantee that all PCI
212   read and write operations are serialized.
213 
214   If Address > 0x0FFFFFFF, then ASSERT().
215 
216   @param  Address The address that encodes the PCI Bus, Device, Function and
217                   Register.
218   @param  AndData The value to AND with the PCI configuration register.
219   @param  OrData  The value to OR with the result of the AND operation.
220 
221   @return The value written back to the PCI configuration register.
222 
223 **/
224 UINT8
225 EFIAPI
PciExpressAndThenOr8(IN UINTN Address,IN UINT8 AndData,IN UINT8 OrData)226 PciExpressAndThenOr8 (
227   IN      UINTN                     Address,
228   IN      UINT8                     AndData,
229   IN      UINT8                     OrData
230   )
231 {
232   ASSERT_INVALID_PCI_ADDRESS (Address);
233   return MmioAndThenOr8 (
234            (UINTN) GetPciExpressBaseAddress () + Address,
235            AndData,
236            OrData
237            );
238 }
239 
240 /**
241   Reads a bit field of a PCI configuration register.
242 
243   Reads the bit field in an 8-bit PCI configuration register. The bit field is
244   specified by the StartBit and the EndBit. The value of the bit field is
245   returned.
246 
247   If Address > 0x0FFFFFFF, then ASSERT().
248   If StartBit is greater than 7, then ASSERT().
249   If EndBit is greater than 7, then ASSERT().
250   If EndBit is less than StartBit, then ASSERT().
251 
252   @param  Address   The PCI configuration register to read.
253   @param  StartBit  The ordinal of the least significant bit in the bit field.
254                     Range 0..7.
255   @param  EndBit    The ordinal of the most significant bit in the bit field.
256                     Range 0..7.
257 
258   @return The value of the bit field read from the PCI configuration register.
259 
260 **/
261 UINT8
262 EFIAPI
PciExpressBitFieldRead8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)263 PciExpressBitFieldRead8 (
264   IN      UINTN                     Address,
265   IN      UINTN                     StartBit,
266   IN      UINTN                     EndBit
267   )
268 {
269   ASSERT_INVALID_PCI_ADDRESS (Address);
270   return MmioBitFieldRead8 (
271            (UINTN) GetPciExpressBaseAddress () + Address,
272            StartBit,
273            EndBit
274            );
275 }
276 
277 /**
278   Writes a bit field to a PCI configuration register.
279 
280   Writes Value to the bit field of the PCI configuration register. The bit
281   field is specified by the StartBit and the EndBit. All other bits in the
282   destination PCI configuration register are preserved. The new value of the
283   8-bit register is returned.
284 
285   If Address > 0x0FFFFFFF, then ASSERT().
286   If StartBit is greater than 7, then ASSERT().
287   If EndBit is greater than 7, then ASSERT().
288   If EndBit is less than StartBit, then ASSERT().
289   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
290 
291   @param  Address   The PCI configuration register to write.
292   @param  StartBit  The ordinal of the least significant bit in the bit field.
293                     Range 0..7.
294   @param  EndBit    The ordinal of the most significant bit in the bit field.
295                     Range 0..7.
296   @param  Value     The new value of the bit field.
297 
298   @return The value written back to the PCI configuration register.
299 
300 **/
301 UINT8
302 EFIAPI
PciExpressBitFieldWrite8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 Value)303 PciExpressBitFieldWrite8 (
304   IN      UINTN                     Address,
305   IN      UINTN                     StartBit,
306   IN      UINTN                     EndBit,
307   IN      UINT8                     Value
308   )
309 {
310   ASSERT_INVALID_PCI_ADDRESS (Address);
311   return MmioBitFieldWrite8 (
312            (UINTN) GetPciExpressBaseAddress () + Address,
313            StartBit,
314            EndBit,
315            Value
316            );
317 }
318 
319 /**
320   Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
321   writes the result back to the bit field in the 8-bit port.
322 
323   Reads the 8-bit PCI configuration register specified by Address, performs a
324   bitwise OR between the read result and the value specified by
325   OrData, and writes the result to the 8-bit PCI configuration register
326   specified by Address. The value written to the PCI configuration register is
327   returned. This function must guarantee that all PCI read and write operations
328   are serialized. Extra left bits in OrData are stripped.
329 
330   If Address > 0x0FFFFFFF, then ASSERT().
331   If StartBit is greater than 7, then ASSERT().
332   If EndBit is greater than 7, then ASSERT().
333   If EndBit is less than StartBit, then ASSERT().
334   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
335 
336   @param  Address   The PCI configuration register to write.
337   @param  StartBit  The ordinal of the least significant bit in the bit field.
338                     Range 0..7.
339   @param  EndBit    The ordinal of the most significant bit in the bit field.
340                     Range 0..7.
341   @param  OrData    The value to OR with the PCI configuration register.
342 
343   @return The value written back to the PCI configuration register.
344 
345 **/
346 UINT8
347 EFIAPI
PciExpressBitFieldOr8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 OrData)348 PciExpressBitFieldOr8 (
349   IN      UINTN                     Address,
350   IN      UINTN                     StartBit,
351   IN      UINTN                     EndBit,
352   IN      UINT8                     OrData
353   )
354 {
355   ASSERT_INVALID_PCI_ADDRESS (Address);
356   return MmioBitFieldOr8 (
357            (UINTN) GetPciExpressBaseAddress () + Address,
358            StartBit,
359            EndBit,
360            OrData
361            );
362 }
363 
364 /**
365   Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
366   AND, and writes the result back to the bit field in the 8-bit register.
367 
368   Reads the 8-bit PCI configuration register specified by Address, performs a
369   bitwise AND between the read result and the value specified by AndData, and
370   writes the result to the 8-bit PCI configuration register specified by
371   Address. The value written to the PCI configuration register is returned.
372   This function must guarantee that all PCI read and write operations are
373   serialized. Extra left bits in AndData are stripped.
374 
375   If Address > 0x0FFFFFFF, then ASSERT().
376   If StartBit is greater than 7, then ASSERT().
377   If EndBit is greater than 7, then ASSERT().
378   If EndBit is less than StartBit, then ASSERT().
379   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
380 
381   @param  Address   The PCI configuration register to write.
382   @param  StartBit  The ordinal of the least significant bit in the bit field.
383                     Range 0..7.
384   @param  EndBit    The ordinal of the most significant bit in the bit field.
385                     Range 0..7.
386   @param  AndData   The value to AND with the PCI configuration register.
387 
388   @return The value written back to the PCI configuration register.
389 
390 **/
391 UINT8
392 EFIAPI
PciExpressBitFieldAnd8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData)393 PciExpressBitFieldAnd8 (
394   IN      UINTN                     Address,
395   IN      UINTN                     StartBit,
396   IN      UINTN                     EndBit,
397   IN      UINT8                     AndData
398   )
399 {
400   ASSERT_INVALID_PCI_ADDRESS (Address);
401   return MmioBitFieldAnd8 (
402            (UINTN) GetPciExpressBaseAddress () + Address,
403            StartBit,
404            EndBit,
405            AndData
406            );
407 }
408 
409 /**
410   Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
411   bitwise OR, and writes the result back to the bit field in the
412   8-bit port.
413 
414   Reads the 8-bit PCI configuration register specified by Address, performs a
415   bitwise AND followed by a bitwise OR between the read result and
416   the value specified by AndData, and writes the result to the 8-bit PCI
417   configuration register specified by Address. The value written to the PCI
418   configuration register is returned. This function must guarantee that all PCI
419   read and write operations are serialized. Extra left bits in both AndData and
420   OrData are stripped.
421 
422   If Address > 0x0FFFFFFF, then ASSERT().
423   If StartBit is greater than 7, then ASSERT().
424   If EndBit is greater than 7, then ASSERT().
425   If EndBit is less than StartBit, then ASSERT().
426   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
427   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
428 
429   @param  Address   The PCI configuration register to write.
430   @param  StartBit  The ordinal of the least significant bit in the bit field.
431                     Range 0..7.
432   @param  EndBit    The ordinal of the most significant bit in the bit field.
433                     Range 0..7.
434   @param  AndData   The value to AND with the PCI configuration register.
435   @param  OrData    The value to OR with the result of the AND operation.
436 
437   @return The value written back to the PCI configuration register.
438 
439 **/
440 UINT8
441 EFIAPI
PciExpressBitFieldAndThenOr8(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData,IN UINT8 OrData)442 PciExpressBitFieldAndThenOr8 (
443   IN      UINTN                     Address,
444   IN      UINTN                     StartBit,
445   IN      UINTN                     EndBit,
446   IN      UINT8                     AndData,
447   IN      UINT8                     OrData
448   )
449 {
450   ASSERT_INVALID_PCI_ADDRESS (Address);
451   return MmioBitFieldAndThenOr8 (
452            (UINTN) GetPciExpressBaseAddress () + Address,
453            StartBit,
454            EndBit,
455            AndData,
456            OrData
457            );
458 }
459 
460 /**
461   Reads a 16-bit PCI configuration register.
462 
463   Reads and returns the 16-bit PCI configuration register specified by Address.
464   This function must guarantee that all PCI read and write operations are
465   serialized.
466 
467   If Address > 0x0FFFFFFF, then ASSERT().
468   If Address is not aligned on a 16-bit boundary, then ASSERT().
469 
470   @param  Address The address that encodes the PCI Bus, Device, Function and
471                   Register.
472 
473   @return The read value from the PCI configuration register.
474 
475 **/
476 UINT16
477 EFIAPI
PciExpressRead16(IN UINTN Address)478 PciExpressRead16 (
479   IN      UINTN                     Address
480   )
481 {
482   ASSERT_INVALID_PCI_ADDRESS (Address);
483   return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
484 }
485 
486 /**
487   Writes a 16-bit PCI configuration register.
488 
489   Writes the 16-bit PCI configuration register specified by Address with the
490   value specified by Value. Value is returned. This function must guarantee
491   that all PCI read and write operations are serialized.
492 
493   If Address > 0x0FFFFFFF, then ASSERT().
494   If Address is not aligned on a 16-bit boundary, then ASSERT().
495 
496   @param  Address The address that encodes the PCI Bus, Device, Function and
497                   Register.
498   @param  Value   The value to write.
499 
500   @return The value written to the PCI configuration register.
501 
502 **/
503 UINT16
504 EFIAPI
PciExpressWrite16(IN UINTN Address,IN UINT16 Value)505 PciExpressWrite16 (
506   IN      UINTN                     Address,
507   IN      UINT16                    Value
508   )
509 {
510   ASSERT_INVALID_PCI_ADDRESS (Address);
511   return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
512 }
513 
514 /**
515   Performs a bitwise OR of a 16-bit PCI configuration register with
516   a 16-bit value.
517 
518   Reads the 16-bit PCI configuration register specified by Address, performs a
519   bitwise OR between the read result and the value specified by
520   OrData, and writes the result to the 16-bit PCI configuration register
521   specified by Address. The value written to the PCI configuration register is
522   returned. This function must guarantee that all PCI read and write operations
523   are serialized.
524 
525   If Address > 0x0FFFFFFF, then ASSERT().
526   If Address is not aligned on a 16-bit boundary, then ASSERT().
527 
528   @param  Address The address that encodes the PCI Bus, Device, Function and
529                   Register.
530   @param  OrData  The value to OR with the PCI configuration register.
531 
532   @return The value written back to the PCI configuration register.
533 
534 **/
535 UINT16
536 EFIAPI
PciExpressOr16(IN UINTN Address,IN UINT16 OrData)537 PciExpressOr16 (
538   IN      UINTN                     Address,
539   IN      UINT16                    OrData
540   )
541 {
542   ASSERT_INVALID_PCI_ADDRESS (Address);
543   return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
544 }
545 
546 /**
547   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
548   value.
549 
550   Reads the 16-bit PCI configuration register specified by Address, performs a
551   bitwise AND between the read result and the value specified by AndData, and
552   writes the result to the 16-bit PCI configuration register specified by
553   Address. The value written to the PCI configuration register is returned.
554   This function must guarantee that all PCI read and write operations are
555   serialized.
556 
557   If Address > 0x0FFFFFFF, then ASSERT().
558   If Address is not aligned on a 16-bit boundary, then ASSERT().
559 
560   @param  Address The address that encodes the PCI Bus, Device, Function and
561                   Register.
562   @param  AndData The value to AND with the PCI configuration register.
563 
564   @return The value written back to the PCI configuration register.
565 
566 **/
567 UINT16
568 EFIAPI
PciExpressAnd16(IN UINTN Address,IN UINT16 AndData)569 PciExpressAnd16 (
570   IN      UINTN                     Address,
571   IN      UINT16                    AndData
572   )
573 {
574   ASSERT_INVALID_PCI_ADDRESS (Address);
575   return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
576 }
577 
578 /**
579   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
580   value, followed a  bitwise OR with another 16-bit value.
581 
582   Reads the 16-bit PCI configuration register specified by Address, performs a
583   bitwise AND between the read result and the value specified by AndData,
584   performs a bitwise OR between the result of the AND operation and
585   the value specified by OrData, and writes the result to the 16-bit PCI
586   configuration register specified by Address. The value written to the PCI
587   configuration register is returned. This function must guarantee that all PCI
588   read and write operations are serialized.
589 
590   If Address > 0x0FFFFFFF, then ASSERT().
591   If Address is not aligned on a 16-bit boundary, then ASSERT().
592 
593   @param  Address The address that encodes the PCI Bus, Device, Function and
594                   Register.
595   @param  AndData The value to AND with the PCI configuration register.
596   @param  OrData  The value to OR with the result of the AND operation.
597 
598   @return The value written back to the PCI configuration register.
599 
600 **/
601 UINT16
602 EFIAPI
PciExpressAndThenOr16(IN UINTN Address,IN UINT16 AndData,IN UINT16 OrData)603 PciExpressAndThenOr16 (
604   IN      UINTN                     Address,
605   IN      UINT16                    AndData,
606   IN      UINT16                    OrData
607   )
608 {
609   ASSERT_INVALID_PCI_ADDRESS (Address);
610   return MmioAndThenOr16 (
611            (UINTN) GetPciExpressBaseAddress () + Address,
612            AndData,
613            OrData
614            );
615 }
616 
617 /**
618   Reads a bit field of a PCI configuration register.
619 
620   Reads the bit field in a 16-bit PCI configuration register. The bit field is
621   specified by the StartBit and the EndBit. The value of the bit field is
622   returned.
623 
624   If Address > 0x0FFFFFFF, then ASSERT().
625   If Address is not aligned on a 16-bit boundary, then ASSERT().
626   If StartBit is greater than 15, then ASSERT().
627   If EndBit is greater than 15, then ASSERT().
628   If EndBit is less than StartBit, then ASSERT().
629 
630   @param  Address   The PCI configuration register to read.
631   @param  StartBit  The ordinal of the least significant bit in the bit field.
632                     Range 0..15.
633   @param  EndBit    The ordinal of the most significant bit in the bit field.
634                     Range 0..15.
635 
636   @return The value of the bit field read from the PCI configuration register.
637 
638 **/
639 UINT16
640 EFIAPI
PciExpressBitFieldRead16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)641 PciExpressBitFieldRead16 (
642   IN      UINTN                     Address,
643   IN      UINTN                     StartBit,
644   IN      UINTN                     EndBit
645   )
646 {
647   ASSERT_INVALID_PCI_ADDRESS (Address);
648   return MmioBitFieldRead16 (
649            (UINTN) GetPciExpressBaseAddress () + Address,
650            StartBit,
651            EndBit
652            );
653 }
654 
655 /**
656   Writes a bit field to a PCI configuration register.
657 
658   Writes Value to the bit field of the PCI configuration register. The bit
659   field is specified by the StartBit and the EndBit. All other bits in the
660   destination PCI configuration register are preserved. The new value of the
661   16-bit register is returned.
662 
663   If Address > 0x0FFFFFFF, then ASSERT().
664   If Address is not aligned on a 16-bit boundary, then ASSERT().
665   If StartBit is greater than 15, then ASSERT().
666   If EndBit is greater than 15, then ASSERT().
667   If EndBit is less than StartBit, then ASSERT().
668   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
669 
670   @param  Address   The PCI configuration register to write.
671   @param  StartBit  The ordinal of the least significant bit in the bit field.
672                     Range 0..15.
673   @param  EndBit    The ordinal of the most significant bit in the bit field.
674                     Range 0..15.
675   @param  Value     The new value of the bit field.
676 
677   @return The value written back to the PCI configuration register.
678 
679 **/
680 UINT16
681 EFIAPI
PciExpressBitFieldWrite16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 Value)682 PciExpressBitFieldWrite16 (
683   IN      UINTN                     Address,
684   IN      UINTN                     StartBit,
685   IN      UINTN                     EndBit,
686   IN      UINT16                    Value
687   )
688 {
689   ASSERT_INVALID_PCI_ADDRESS (Address);
690   return MmioBitFieldWrite16 (
691            (UINTN) GetPciExpressBaseAddress () + Address,
692            StartBit,
693            EndBit,
694            Value
695            );
696 }
697 
698 /**
699   Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
700   writes the result back to the bit field in the 16-bit port.
701 
702   Reads the 16-bit PCI configuration register specified by Address, performs a
703   bitwise OR between the read result and the value specified by
704   OrData, and writes the result to the 16-bit PCI configuration register
705   specified by Address. The value written to the PCI configuration register is
706   returned. This function must guarantee that all PCI read and write operations
707   are serialized. Extra left bits in OrData are stripped.
708 
709   If Address > 0x0FFFFFFF, then ASSERT().
710   If Address is not aligned on a 16-bit boundary, then ASSERT().
711   If StartBit is greater than 15, then ASSERT().
712   If EndBit is greater than 15, then ASSERT().
713   If EndBit is less than StartBit, then ASSERT().
714   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
715 
716   @param  Address   The PCI configuration register to write.
717   @param  StartBit  The ordinal of the least significant bit in the bit field.
718                     Range 0..15.
719   @param  EndBit    The ordinal of the most significant bit in the bit field.
720                     Range 0..15.
721   @param  OrData    The value to OR with the PCI configuration register.
722 
723   @return The value written back to the PCI configuration register.
724 
725 **/
726 UINT16
727 EFIAPI
PciExpressBitFieldOr16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 OrData)728 PciExpressBitFieldOr16 (
729   IN      UINTN                     Address,
730   IN      UINTN                     StartBit,
731   IN      UINTN                     EndBit,
732   IN      UINT16                    OrData
733   )
734 {
735   ASSERT_INVALID_PCI_ADDRESS (Address);
736   return MmioBitFieldOr16 (
737            (UINTN) GetPciExpressBaseAddress () + Address,
738            StartBit,
739            EndBit,
740            OrData
741            );
742 }
743 
744 /**
745   Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
746   AND, and writes the result back to the bit field in the 16-bit register.
747 
748   Reads the 16-bit PCI configuration register specified by Address, performs a
749   bitwise AND between the read result and the value specified by AndData, and
750   writes the result to the 16-bit PCI configuration register specified by
751   Address. The value written to the PCI configuration register is returned.
752   This function must guarantee that all PCI read and write operations are
753   serialized. Extra left bits in AndData are stripped.
754 
755   If Address > 0x0FFFFFFF, then ASSERT().
756   If Address is not aligned on a 16-bit boundary, then ASSERT().
757   If StartBit is greater than 15, then ASSERT().
758   If EndBit is greater than 15, then ASSERT().
759   If EndBit is less than StartBit, then ASSERT().
760   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
761 
762   @param  Address   The PCI configuration register to write.
763   @param  StartBit  The ordinal of the least significant bit in the bit field.
764                     Range 0..15.
765   @param  EndBit    The ordinal of the most significant bit in the bit field.
766                     Range 0..15.
767   @param  AndData   The value to AND with the PCI configuration register.
768 
769   @return The value written back to the PCI configuration register.
770 
771 **/
772 UINT16
773 EFIAPI
PciExpressBitFieldAnd16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData)774 PciExpressBitFieldAnd16 (
775   IN      UINTN                     Address,
776   IN      UINTN                     StartBit,
777   IN      UINTN                     EndBit,
778   IN      UINT16                    AndData
779   )
780 {
781   ASSERT_INVALID_PCI_ADDRESS (Address);
782   return MmioBitFieldAnd16 (
783            (UINTN) GetPciExpressBaseAddress () + Address,
784            StartBit,
785            EndBit,
786            AndData
787            );
788 }
789 
790 /**
791   Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
792   bitwise OR, and writes the result back to the bit field in the
793   16-bit port.
794 
795   Reads the 16-bit PCI configuration register specified by Address, performs a
796   bitwise AND followed by a bitwise OR between the read result and
797   the value specified by AndData, and writes the result to the 16-bit PCI
798   configuration register specified by Address. The value written to the PCI
799   configuration register is returned. This function must guarantee that all PCI
800   read and write operations are serialized. Extra left bits in both AndData and
801   OrData are stripped.
802 
803   If Address > 0x0FFFFFFF, then ASSERT().
804   If Address is not aligned on a 16-bit boundary, then ASSERT().
805   If StartBit is greater than 15, then ASSERT().
806   If EndBit is greater than 15, then ASSERT().
807   If EndBit is less than StartBit, then ASSERT().
808   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
809   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
810 
811   @param  Address   The PCI configuration register to write.
812   @param  StartBit  The ordinal of the least significant bit in the bit field.
813                     Range 0..15.
814   @param  EndBit    The ordinal of the most significant bit in the bit field.
815                     Range 0..15.
816   @param  AndData   The value to AND with the PCI configuration register.
817   @param  OrData    The value to OR with the result of the AND operation.
818 
819   @return The value written back to the PCI configuration register.
820 
821 **/
822 UINT16
823 EFIAPI
PciExpressBitFieldAndThenOr16(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData,IN UINT16 OrData)824 PciExpressBitFieldAndThenOr16 (
825   IN      UINTN                     Address,
826   IN      UINTN                     StartBit,
827   IN      UINTN                     EndBit,
828   IN      UINT16                    AndData,
829   IN      UINT16                    OrData
830   )
831 {
832   ASSERT_INVALID_PCI_ADDRESS (Address);
833   return MmioBitFieldAndThenOr16 (
834            (UINTN) GetPciExpressBaseAddress () + Address,
835            StartBit,
836            EndBit,
837            AndData,
838            OrData
839            );
840 }
841 
842 /**
843   Reads a 32-bit PCI configuration register.
844 
845   Reads and returns the 32-bit PCI configuration register specified by Address.
846   This function must guarantee that all PCI read and write operations are
847   serialized.
848 
849   If Address > 0x0FFFFFFF, then ASSERT().
850   If Address is not aligned on a 32-bit boundary, then ASSERT().
851 
852   @param  Address The address that encodes the PCI Bus, Device, Function and
853                   Register.
854 
855   @return The read value from the PCI configuration register.
856 
857 **/
858 UINT32
859 EFIAPI
PciExpressRead32(IN UINTN Address)860 PciExpressRead32 (
861   IN      UINTN                     Address
862   )
863 {
864   ASSERT_INVALID_PCI_ADDRESS (Address);
865   return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
866 }
867 
868 /**
869   Writes a 32-bit PCI configuration register.
870 
871   Writes the 32-bit PCI configuration register specified by Address with the
872   value specified by Value. Value is returned. This function must guarantee
873   that all PCI read and write operations are serialized.
874 
875   If Address > 0x0FFFFFFF, then ASSERT().
876   If Address is not aligned on a 32-bit boundary, then ASSERT().
877 
878   @param  Address The address that encodes the PCI Bus, Device, Function and
879                   Register.
880   @param  Value   The value to write.
881 
882   @return The value written to the PCI configuration register.
883 
884 **/
885 UINT32
886 EFIAPI
PciExpressWrite32(IN UINTN Address,IN UINT32 Value)887 PciExpressWrite32 (
888   IN      UINTN                     Address,
889   IN      UINT32                    Value
890   )
891 {
892   ASSERT_INVALID_PCI_ADDRESS (Address);
893   return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
894 }
895 
896 /**
897   Performs a bitwise OR of a 32-bit PCI configuration register with
898   a 32-bit value.
899 
900   Reads the 32-bit PCI configuration register specified by Address, performs a
901   bitwise OR between the read result and the value specified by
902   OrData, and writes the result to the 32-bit PCI configuration register
903   specified by Address. The value written to the PCI configuration register is
904   returned. This function must guarantee that all PCI read and write operations
905   are serialized.
906 
907   If Address > 0x0FFFFFFF, then ASSERT().
908   If Address is not aligned on a 32-bit boundary, then ASSERT().
909 
910   @param  Address The address that encodes the PCI Bus, Device, Function and
911                   Register.
912   @param  OrData  The value to OR with the PCI configuration register.
913 
914   @return The value written back to the PCI configuration register.
915 
916 **/
917 UINT32
918 EFIAPI
PciExpressOr32(IN UINTN Address,IN UINT32 OrData)919 PciExpressOr32 (
920   IN      UINTN                     Address,
921   IN      UINT32                    OrData
922   )
923 {
924   ASSERT_INVALID_PCI_ADDRESS (Address);
925   return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
926 }
927 
928 /**
929   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
930   value.
931 
932   Reads the 32-bit PCI configuration register specified by Address, performs a
933   bitwise AND between the read result and the value specified by AndData, and
934   writes the result to the 32-bit PCI configuration register specified by
935   Address. The value written to the PCI configuration register is returned.
936   This function must guarantee that all PCI read and write operations are
937   serialized.
938 
939   If Address > 0x0FFFFFFF, then ASSERT().
940   If Address is not aligned on a 32-bit boundary, then ASSERT().
941 
942   @param  Address The address that encodes the PCI Bus, Device, Function and
943                   Register.
944   @param  AndData The value to AND with the PCI configuration register.
945 
946   @return The value written back to the PCI configuration register.
947 
948 **/
949 UINT32
950 EFIAPI
PciExpressAnd32(IN UINTN Address,IN UINT32 AndData)951 PciExpressAnd32 (
952   IN      UINTN                     Address,
953   IN      UINT32                    AndData
954   )
955 {
956   ASSERT_INVALID_PCI_ADDRESS (Address);
957   return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
958 }
959 
960 /**
961   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
962   value, followed a  bitwise OR with another 32-bit value.
963 
964   Reads the 32-bit PCI configuration register specified by Address, performs a
965   bitwise AND between the read result and the value specified by AndData,
966   performs a bitwise OR between the result of the AND operation and
967   the value specified by OrData, and writes the result to the 32-bit PCI
968   configuration register specified by Address. The value written to the PCI
969   configuration register is returned. This function must guarantee that all PCI
970   read and write operations are serialized.
971 
972   If Address > 0x0FFFFFFF, then ASSERT().
973   If Address is not aligned on a 32-bit boundary, then ASSERT().
974 
975   @param  Address The address that encodes the PCI Bus, Device, Function and
976                   Register.
977   @param  AndData The value to AND with the PCI configuration register.
978   @param  OrData  The value to OR with the result of the AND operation.
979 
980   @return The value written back to the PCI configuration register.
981 
982 **/
983 UINT32
984 EFIAPI
PciExpressAndThenOr32(IN UINTN Address,IN UINT32 AndData,IN UINT32 OrData)985 PciExpressAndThenOr32 (
986   IN      UINTN                     Address,
987   IN      UINT32                    AndData,
988   IN      UINT32                    OrData
989   )
990 {
991   ASSERT_INVALID_PCI_ADDRESS (Address);
992   return MmioAndThenOr32 (
993            (UINTN) GetPciExpressBaseAddress () + Address,
994            AndData,
995            OrData
996            );
997 }
998 
999 /**
1000   Reads a bit field of a PCI configuration register.
1001 
1002   Reads the bit field in a 32-bit PCI configuration register. The bit field is
1003   specified by the StartBit and the EndBit. The value of the bit field is
1004   returned.
1005 
1006   If Address > 0x0FFFFFFF, then ASSERT().
1007   If Address is not aligned on a 32-bit boundary, then ASSERT().
1008   If StartBit is greater than 31, then ASSERT().
1009   If EndBit is greater than 31, then ASSERT().
1010   If EndBit is less than StartBit, then ASSERT().
1011 
1012   @param  Address   The PCI configuration register to read.
1013   @param  StartBit  The ordinal of the least significant bit in the bit field.
1014                     Range 0..31.
1015   @param  EndBit    The ordinal of the most significant bit in the bit field.
1016                     Range 0..31.
1017 
1018   @return The value of the bit field read from the PCI configuration register.
1019 
1020 **/
1021 UINT32
1022 EFIAPI
PciExpressBitFieldRead32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit)1023 PciExpressBitFieldRead32 (
1024   IN      UINTN                     Address,
1025   IN      UINTN                     StartBit,
1026   IN      UINTN                     EndBit
1027   )
1028 {
1029   ASSERT_INVALID_PCI_ADDRESS (Address);
1030   return MmioBitFieldRead32 (
1031            (UINTN) GetPciExpressBaseAddress () + Address,
1032            StartBit,
1033            EndBit
1034            );
1035 }
1036 
1037 /**
1038   Writes a bit field to a PCI configuration register.
1039 
1040   Writes Value to the bit field of the PCI configuration register. The bit
1041   field is specified by the StartBit and the EndBit. All other bits in the
1042   destination PCI configuration register are preserved. The new value of the
1043   32-bit register is returned.
1044 
1045   If Address > 0x0FFFFFFF, then ASSERT().
1046   If Address is not aligned on a 32-bit boundary, then ASSERT().
1047   If StartBit is greater than 31, then ASSERT().
1048   If EndBit is greater than 31, then ASSERT().
1049   If EndBit is less than StartBit, then ASSERT().
1050   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1051 
1052   @param  Address   The PCI configuration register to write.
1053   @param  StartBit  The ordinal of the least significant bit in the bit field.
1054                     Range 0..31.
1055   @param  EndBit    The ordinal of the most significant bit in the bit field.
1056                     Range 0..31.
1057   @param  Value     The new value of the bit field.
1058 
1059   @return The value written back to the PCI configuration register.
1060 
1061 **/
1062 UINT32
1063 EFIAPI
PciExpressBitFieldWrite32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 Value)1064 PciExpressBitFieldWrite32 (
1065   IN      UINTN                     Address,
1066   IN      UINTN                     StartBit,
1067   IN      UINTN                     EndBit,
1068   IN      UINT32                    Value
1069   )
1070 {
1071   ASSERT_INVALID_PCI_ADDRESS (Address);
1072   return MmioBitFieldWrite32 (
1073            (UINTN) GetPciExpressBaseAddress () + Address,
1074            StartBit,
1075            EndBit,
1076            Value
1077            );
1078 }
1079 
1080 /**
1081   Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1082   writes the result back to the bit field in the 32-bit port.
1083 
1084   Reads the 32-bit PCI configuration register specified by Address, performs a
1085   bitwise OR between the read result and the value specified by
1086   OrData, and writes the result to the 32-bit PCI configuration register
1087   specified by Address. The value written to the PCI configuration register is
1088   returned. This function must guarantee that all PCI read and write operations
1089   are serialized. Extra left bits in OrData are stripped.
1090 
1091   If Address > 0x0FFFFFFF, then ASSERT().
1092   If Address is not aligned on a 32-bit boundary, then ASSERT().
1093   If StartBit is greater than 31, then ASSERT().
1094   If EndBit is greater than 31, then ASSERT().
1095   If EndBit is less than StartBit, then ASSERT().
1096   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1097 
1098   @param  Address   The PCI configuration register to write.
1099   @param  StartBit  The ordinal of the least significant bit in the bit field.
1100                     Range 0..31.
1101   @param  EndBit    The ordinal of the most significant bit in the bit field.
1102                     Range 0..31.
1103   @param  OrData    The value to OR with the PCI configuration register.
1104 
1105   @return The value written back to the PCI configuration register.
1106 
1107 **/
1108 UINT32
1109 EFIAPI
PciExpressBitFieldOr32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 OrData)1110 PciExpressBitFieldOr32 (
1111   IN      UINTN                     Address,
1112   IN      UINTN                     StartBit,
1113   IN      UINTN                     EndBit,
1114   IN      UINT32                    OrData
1115   )
1116 {
1117   ASSERT_INVALID_PCI_ADDRESS (Address);
1118   return MmioBitFieldOr32 (
1119            (UINTN) GetPciExpressBaseAddress () + Address,
1120            StartBit,
1121            EndBit,
1122            OrData
1123            );
1124 }
1125 
1126 /**
1127   Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1128   AND, and writes the result back to the bit field in the 32-bit register.
1129 
1130   Reads the 32-bit PCI configuration register specified by Address, performs a
1131   bitwise AND between the read result and the value specified by AndData, and
1132   writes the result to the 32-bit PCI configuration register specified by
1133   Address. The value written to the PCI configuration register is returned.
1134   This function must guarantee that all PCI read and write operations are
1135   serialized. Extra left bits in AndData are stripped.
1136 
1137   If Address > 0x0FFFFFFF, then ASSERT().
1138   If Address is not aligned on a 32-bit boundary, then ASSERT().
1139   If StartBit is greater than 31, then ASSERT().
1140   If EndBit is greater than 31, then ASSERT().
1141   If EndBit is less than StartBit, then ASSERT().
1142   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1143 
1144   @param  Address   The PCI configuration register to write.
1145   @param  StartBit  The ordinal of the least significant bit in the bit field.
1146                     Range 0..31.
1147   @param  EndBit    The ordinal of the most significant bit in the bit field.
1148                     Range 0..31.
1149   @param  AndData   The value to AND with the PCI configuration register.
1150 
1151   @return The value written back to the PCI configuration register.
1152 
1153 **/
1154 UINT32
1155 EFIAPI
PciExpressBitFieldAnd32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData)1156 PciExpressBitFieldAnd32 (
1157   IN      UINTN                     Address,
1158   IN      UINTN                     StartBit,
1159   IN      UINTN                     EndBit,
1160   IN      UINT32                    AndData
1161   )
1162 {
1163   ASSERT_INVALID_PCI_ADDRESS (Address);
1164   return MmioBitFieldAnd32 (
1165            (UINTN) GetPciExpressBaseAddress () + Address,
1166            StartBit,
1167            EndBit,
1168            AndData
1169            );
1170 }
1171 
1172 /**
1173   Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1174   bitwise OR, and writes the result back to the bit field in the
1175   32-bit port.
1176 
1177   Reads the 32-bit PCI configuration register specified by Address, performs a
1178   bitwise AND followed by a bitwise OR between the read result and
1179   the value specified by AndData, and writes the result to the 32-bit PCI
1180   configuration register specified by Address. The value written to the PCI
1181   configuration register is returned. This function must guarantee that all PCI
1182   read and write operations are serialized. Extra left bits in both AndData and
1183   OrData are stripped.
1184 
1185   If Address > 0x0FFFFFFF, then ASSERT().
1186   If Address is not aligned on a 32-bit boundary, then ASSERT().
1187   If StartBit is greater than 31, then ASSERT().
1188   If EndBit is greater than 31, then ASSERT().
1189   If EndBit is less than StartBit, then ASSERT().
1190   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1191   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1192 
1193   @param  Address   The PCI configuration register to write.
1194   @param  StartBit  The ordinal of the least significant bit in the bit field.
1195                     Range 0..31.
1196   @param  EndBit    The ordinal of the most significant bit in the bit field.
1197                     Range 0..31.
1198   @param  AndData   The value to AND with the PCI configuration register.
1199   @param  OrData    The value to OR with the result of the AND operation.
1200 
1201   @return The value written back to the PCI configuration register.
1202 
1203 **/
1204 UINT32
1205 EFIAPI
PciExpressBitFieldAndThenOr32(IN UINTN Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData,IN UINT32 OrData)1206 PciExpressBitFieldAndThenOr32 (
1207   IN      UINTN                     Address,
1208   IN      UINTN                     StartBit,
1209   IN      UINTN                     EndBit,
1210   IN      UINT32                    AndData,
1211   IN      UINT32                    OrData
1212   )
1213 {
1214   ASSERT_INVALID_PCI_ADDRESS (Address);
1215   return MmioBitFieldAndThenOr32 (
1216            (UINTN) GetPciExpressBaseAddress () + Address,
1217            StartBit,
1218            EndBit,
1219            AndData,
1220            OrData
1221            );
1222 }
1223 
1224 /**
1225   Reads a range of PCI configuration registers into a caller supplied buffer.
1226 
1227   Reads the range of PCI configuration registers specified by StartAddress and
1228   Size into the buffer specified by Buffer. This function only allows the PCI
1229   configuration registers from a single PCI function to be read. Size is
1230   returned. When possible 32-bit PCI configuration read cycles are used to read
1231   from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
1232   and 16-bit PCI configuration read cycles may be used at the beginning and the
1233   end of the range.
1234 
1235   If StartAddress > 0x0FFFFFFF, then ASSERT().
1236   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1237   If Size > 0 and Buffer is NULL, then ASSERT().
1238 
1239   @param  StartAddress  The starting address that encodes the PCI Bus, Device,
1240                         Function and Register.
1241   @param  Size          The size in bytes of the transfer.
1242   @param  Buffer        The pointer to a buffer receiving the data read.
1243 
1244   @return Size read data from StartAddress.
1245 
1246 **/
1247 UINTN
1248 EFIAPI
PciExpressReadBuffer(IN UINTN StartAddress,IN UINTN Size,OUT VOID * Buffer)1249 PciExpressReadBuffer (
1250   IN      UINTN                     StartAddress,
1251   IN      UINTN                     Size,
1252   OUT     VOID                      *Buffer
1253   )
1254 {
1255   UINTN   ReturnValue;
1256 
1257   ASSERT_INVALID_PCI_ADDRESS (StartAddress);
1258   ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1259 
1260   if (Size == 0) {
1261     return Size;
1262   }
1263 
1264   ASSERT (Buffer != NULL);
1265 
1266   //
1267   // Save Size for return
1268   //
1269   ReturnValue = Size;
1270 
1271   if ((StartAddress & 1) != 0) {
1272     //
1273     // Read a byte if StartAddress is byte aligned
1274     //
1275     *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1276     StartAddress += sizeof (UINT8);
1277     Size -= sizeof (UINT8);
1278     Buffer = (UINT8*)Buffer + 1;
1279   }
1280 
1281   if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1282     //
1283     // Read a word if StartAddress is word aligned
1284     //
1285     WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1286 
1287     StartAddress += sizeof (UINT16);
1288     Size -= sizeof (UINT16);
1289     Buffer = (UINT16*)Buffer + 1;
1290   }
1291 
1292   while (Size >= sizeof (UINT32)) {
1293     //
1294     // Read as many double words as possible
1295     //
1296     WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
1297 
1298     StartAddress += sizeof (UINT32);
1299     Size -= sizeof (UINT32);
1300     Buffer = (UINT32*)Buffer + 1;
1301   }
1302 
1303   if (Size >= sizeof (UINT16)) {
1304     //
1305     // Read the last remaining word if exist
1306     //
1307     WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1308     StartAddress += sizeof (UINT16);
1309     Size -= sizeof (UINT16);
1310     Buffer = (UINT16*)Buffer + 1;
1311   }
1312 
1313   if (Size >= sizeof (UINT8)) {
1314     //
1315     // Read the last remaining byte if exist
1316     //
1317     *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1318   }
1319 
1320   return ReturnValue;
1321 }
1322 
1323 /**
1324   Copies the data in a caller supplied buffer to a specified range of PCI
1325   configuration space.
1326 
1327   Writes the range of PCI configuration registers specified by StartAddress and
1328   Size from the buffer specified by Buffer. This function only allows the PCI
1329   configuration registers from a single PCI function to be written. Size is
1330   returned. When possible 32-bit PCI configuration write cycles are used to
1331   write from StartAdress to StartAddress + Size. Due to alignment restrictions,
1332   8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1333   and the end of the range.
1334 
1335   If StartAddress > 0x0FFFFFFF, then ASSERT().
1336   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1337   If Size > 0 and Buffer is NULL, then ASSERT().
1338 
1339   @param  StartAddress  The starting address that encodes the PCI Bus, Device,
1340                         Function and Register.
1341   @param  Size          The size in bytes of the transfer.
1342   @param  Buffer        The pointer to a buffer containing the data to write.
1343 
1344   @return Size written to StartAddress.
1345 
1346 **/
1347 UINTN
1348 EFIAPI
PciExpressWriteBuffer(IN UINTN StartAddress,IN UINTN Size,IN VOID * Buffer)1349 PciExpressWriteBuffer (
1350   IN      UINTN                     StartAddress,
1351   IN      UINTN                     Size,
1352   IN      VOID                      *Buffer
1353   )
1354 {
1355   UINTN                             ReturnValue;
1356 
1357   ASSERT_INVALID_PCI_ADDRESS (StartAddress);
1358   ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1359 
1360   if (Size == 0) {
1361     return 0;
1362   }
1363 
1364   ASSERT (Buffer != NULL);
1365 
1366   //
1367   // Save Size for return
1368   //
1369   ReturnValue = Size;
1370 
1371   if ((StartAddress & 1) != 0) {
1372     //
1373     // Write a byte if StartAddress is byte aligned
1374     //
1375     PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1376     StartAddress += sizeof (UINT8);
1377     Size -= sizeof (UINT8);
1378     Buffer = (UINT8*)Buffer + 1;
1379   }
1380 
1381   if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1382     //
1383     // Write a word if StartAddress is word aligned
1384     //
1385     PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1386     StartAddress += sizeof (UINT16);
1387     Size -= sizeof (UINT16);
1388     Buffer = (UINT16*)Buffer + 1;
1389   }
1390 
1391   while (Size >= sizeof (UINT32)) {
1392     //
1393     // Write as many double words as possible
1394     //
1395     PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
1396     StartAddress += sizeof (UINT32);
1397     Size -= sizeof (UINT32);
1398     Buffer = (UINT32*)Buffer + 1;
1399   }
1400 
1401   if (Size >= sizeof (UINT16)) {
1402     //
1403     // Write the last remaining word if exist
1404     //
1405     PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1406     StartAddress += sizeof (UINT16);
1407     Size -= sizeof (UINT16);
1408     Buffer = (UINT16*)Buffer + 1;
1409   }
1410 
1411   if (Size >= sizeof (UINT8)) {
1412     //
1413     // Write the last remaining byte if exist
1414     //
1415     PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1416   }
1417 
1418   return ReturnValue;
1419 }
1420