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