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