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