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//
21PCI_ROOT_BRIDGE_DATA   *mPciRootBridgeData     = NULL;
22UINTN                  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**/
37EFI_STATUS
38EFIAPI
39PciSegmentLibConstructor (
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**/
116EFI_STATUS
117EFIAPI
118PciSegmentLibDestructor (
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**/
140EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *
141PciSegmentLibSearchForRootBridge (
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**/
181UINT32
182DxePciSegmentLibPciRootBridgeIoReadWorker (
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**/
220UINT32
221DxePciSegmentLibPciRootBridgeIoWriteWorker (
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**/
261RETURN_STATUS
262EFIAPI
263PciSegmentRegisterForRuntimeAccess (
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**/
284UINT8
285EFIAPI
286PciSegmentRead8 (
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**/
309UINT8
310EFIAPI
311PciSegmentWrite8 (
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**/
338UINT8
339EFIAPI
340PciSegmentOr8 (
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**/
364UINT8
365EFIAPI
366PciSegmentAnd8 (
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**/
394UINT8
395EFIAPI
396PciSegmentAndThenOr8 (
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**/
426UINT8
427EFIAPI
428PciSegmentBitFieldRead8 (
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**/
461UINT8
462EFIAPI
463PciSegmentBitFieldWrite8 (
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**/
503UINT8
504EFIAPI
505PciSegmentBitFieldOr8 (
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**/
545UINT8
546EFIAPI
547PciSegmentBitFieldAnd8 (
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**/
591UINT8
592EFIAPI
593PciSegmentBitFieldAndThenOr8 (
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**/
621UINT16
622EFIAPI
623PciSegmentRead16 (
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**/
647UINT16
648EFIAPI
649PciSegmentWrite16 (
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**/
680UINT16
681EFIAPI
682PciSegmentOr16 (
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**/
708UINT16
709EFIAPI
710PciSegmentAnd16 (
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**/
739UINT16
740EFIAPI
741PciSegmentAndThenOr16 (
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**/
772UINT16
773EFIAPI
774PciSegmentBitFieldRead16 (
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**/
808UINT16
809EFIAPI
810PciSegmentBitFieldWrite16 (
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**/
845UINT16
846EFIAPI
847PciSegmentBitFieldOr16 (
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**/
888UINT16
889EFIAPI
890PciSegmentBitFieldAnd16 (
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**/
934UINT16
935EFIAPI
936PciSegmentBitFieldAndThenOr16 (
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**/
964UINT32
965EFIAPI
966PciSegmentRead32 (
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**/
990UINT32
991EFIAPI
992PciSegmentWrite32 (
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**/
1020UINT32
1021EFIAPI
1022PciSegmentOr32 (
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**/
1048UINT32
1049EFIAPI
1050PciSegmentAnd32 (
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**/
1079UINT32
1080EFIAPI
1081PciSegmentAndThenOr32 (
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**/
1112UINT32
1113EFIAPI
1114PciSegmentBitFieldRead32 (
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**/
1148UINT32
1149EFIAPI
1150PciSegmentBitFieldWrite32 (
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**/
1190UINT32
1191EFIAPI
1192PciSegmentBitFieldOr32 (
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**/
1232UINT32
1233EFIAPI
1234PciSegmentBitFieldAnd32 (
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**/
1278UINT32
1279EFIAPI
1280PciSegmentBitFieldAndThenOr32 (
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**/
1317UINTN
1318EFIAPI
1319PciSegmentReadBuffer (
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**/
1415UINTN
1416EFIAPI
1417PciSegmentWriteBuffer (
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