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