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