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