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