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