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