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