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