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