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