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