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