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