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