]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/DxePciLibEsal/PciLib.c
8cc1a506f85a78aad299747b83dacfe2529afffb
[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 - 2011, 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
396 @param Address PCI configuration register to write.
397 @param StartBit The ordinal of the least significant bit in the bit field.
398 Range 0..7.
399 @param EndBit The ordinal of the most significant bit in the bit field.
400 Range 0..7.
401 @param Value New value of the bit field.
402
403 @return The value written back to the PCI configuration register.
404
405 **/
406 UINT8
407 EFIAPI
408 PciBitFieldWrite8 (
409 IN UINTN Address,
410 IN UINTN StartBit,
411 IN UINTN EndBit,
412 IN UINT8 Value
413 )
414 {
415 return PciWrite8 (
416 Address,
417 BitFieldWrite8 (PciRead8 (Address), StartBit, EndBit, Value)
418 );
419 }
420
421 /**
422 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
423 writes the result back to the bit field in the 8-bit port.
424
425 Reads the 8-bit PCI configuration register specified by Address, performs a
426 bitwise OR between the read result and the value specified by
427 OrData, and writes the result to the 8-bit PCI configuration register
428 specified by Address. The value written to the PCI configuration register is
429 returned. This function must guarantee that all PCI read and write operations
430 are serialized. Extra left bits in OrData are stripped.
431
432 If Address > 0x0FFFFFFF, then ASSERT().
433 If StartBit is greater than 7, then ASSERT().
434 If EndBit is greater than 7, then ASSERT().
435 If EndBit is less than StartBit, then ASSERT().
436
437 @param Address PCI configuration register to write.
438 @param StartBit The ordinal of the least significant bit in the bit field.
439 Range 0..7.
440 @param EndBit The ordinal of the most significant bit in the bit field.
441 Range 0..7.
442 @param OrData The value to OR with the PCI configuration register.
443
444 @return The value written back to the PCI configuration register.
445
446 **/
447 UINT8
448 EFIAPI
449 PciBitFieldOr8 (
450 IN UINTN Address,
451 IN UINTN StartBit,
452 IN UINTN EndBit,
453 IN UINT8 OrData
454 )
455 {
456 return PciWrite8 (
457 Address,
458 BitFieldOr8 (PciRead8 (Address), StartBit, EndBit, OrData)
459 );
460 }
461
462 /**
463 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
464 AND, and writes the result back to the bit field in the 8-bit register.
465
466 Reads the 8-bit PCI configuration register specified by Address, performs a
467 bitwise AND between the read result and the value specified by AndData, and
468 writes the result to the 8-bit PCI configuration register specified by
469 Address. The value written to the PCI configuration register is returned.
470 This function must guarantee that all PCI read and write operations are
471 serialized. Extra left bits in AndData are stripped.
472
473 If Address > 0x0FFFFFFF, then ASSERT().
474 If StartBit is greater than 7, then ASSERT().
475 If EndBit is greater than 7, then ASSERT().
476 If EndBit is less than StartBit, then ASSERT().
477
478 @param Address PCI configuration register to write.
479 @param StartBit The ordinal of the least significant bit in the bit field.
480 Range 0..7.
481 @param EndBit The ordinal of the most significant bit in the bit field.
482 Range 0..7.
483 @param AndData The value to AND with the PCI configuration register.
484
485 @return The value written back to the PCI configuration register.
486
487 **/
488 UINT8
489 EFIAPI
490 PciBitFieldAnd8 (
491 IN UINTN Address,
492 IN UINTN StartBit,
493 IN UINTN EndBit,
494 IN UINT8 AndData
495 )
496 {
497 return PciWrite8 (
498 Address,
499 BitFieldAnd8 (PciRead8 (Address), StartBit, EndBit, AndData)
500 );
501 }
502
503 /**
504 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
505 bitwise OR, and writes the result back to the bit field in the
506 8-bit port.
507
508 Reads the 8-bit PCI configuration register specified by Address, performs a
509 bitwise AND followed by a bitwise OR between the read result and
510 the value specified by AndData, and writes the result to the 8-bit PCI
511 configuration register specified by Address. The value written to the PCI
512 configuration register is returned. This function must guarantee that all PCI
513 read and write operations are serialized. Extra left bits in both AndData and
514 OrData are stripped.
515
516 If Address > 0x0FFFFFFF, then ASSERT().
517 If StartBit is greater than 7, then ASSERT().
518 If EndBit is greater than 7, then ASSERT().
519 If EndBit is less than StartBit, then ASSERT().
520
521 @param Address PCI configuration register to write.
522 @param StartBit The ordinal of the least significant bit in the bit field.
523 Range 0..7.
524 @param EndBit The ordinal of the most significant bit in the bit field.
525 Range 0..7.
526 @param AndData The value to AND with the PCI configuration register.
527 @param OrData The value to OR with the result of the AND operation.
528
529 @return The value written back to the PCI configuration register.
530
531 **/
532 UINT8
533 EFIAPI
534 PciBitFieldAndThenOr8 (
535 IN UINTN Address,
536 IN UINTN StartBit,
537 IN UINTN EndBit,
538 IN UINT8 AndData,
539 IN UINT8 OrData
540 )
541 {
542 return PciWrite8 (
543 Address,
544 BitFieldAndThenOr8 (PciRead8 (Address), StartBit, EndBit, AndData, OrData)
545 );
546 }
547
548 /**
549 Reads a 16-bit PCI configuration register.
550
551 Reads and returns the 16-bit PCI configuration register specified by Address.
552 This function must guarantee that all PCI read and write operations are
553 serialized.
554
555 If Address > 0x0FFFFFFF, then ASSERT().
556 If Address is not aligned on a 16-bit boundary, then ASSERT().
557
558 @param Address Address that encodes the PCI Bus, Device, Function and
559 Register.
560
561 @return The value read from the PCI configuration register.
562
563 **/
564 UINT16
565 EFIAPI
566 PciRead16 (
567 IN UINTN Address
568 )
569 {
570 ASSERT_INVALID_PCI_ADDRESS (Address, 1);
571
572 return (UINT16) DxePciLibEsalReadWorker (Address, 2);
573 }
574
575 /**
576 Writes a 16-bit PCI configuration register.
577
578 Writes the 16-bit PCI configuration register specified by Address with the
579 value specified by Value. Value is returned. This function must guarantee
580 that all PCI read and write operations are serialized.
581
582 If Address > 0x0FFFFFFF, then ASSERT().
583 If Address is not aligned on a 16-bit boundary, then ASSERT().
584
585 @param Address Address that encodes the PCI Bus, Device, Function and
586 Register.
587 @param Data The value to write.
588
589 @return The value written to the PCI configuration register.
590
591 **/
592 UINT16
593 EFIAPI
594 PciWrite16 (
595 IN UINTN Address,
596 IN UINT16 Data
597 )
598 {
599 ASSERT_INVALID_PCI_ADDRESS (Address, 1);
600
601 return (UINT16) DxePciLibEsalWriteWorker (Address, 2, Data);
602 }
603
604 /**
605 Performs a bitwise OR of a 16-bit PCI configuration register with
606 a 16-bit value.
607
608 Reads the 16-bit PCI configuration register specified by Address, performs a
609 bitwise OR between the read result and the value specified by
610 OrData, and writes the result to the 16-bit PCI configuration register
611 specified by Address. The value written to the PCI configuration register is
612 returned. This function must guarantee that all PCI read and write operations
613 are serialized.
614
615 If Address > 0x0FFFFFFF, then ASSERT().
616 If Address is not aligned on a 16-bit boundary, then ASSERT().
617
618 @param Address Address that encodes the PCI Bus, Device, Function and
619 Register.
620 @param OrData The value to OR with the PCI configuration register.
621
622 @return The value written back to the PCI configuration register.
623
624 **/
625 UINT16
626 EFIAPI
627 PciOr16 (
628 IN UINTN Address,
629 IN UINT16 OrData
630 )
631 {
632 return PciWrite16 (Address, (UINT16)(PciRead16 (Address) | OrData));
633 }
634
635 /**
636 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
637 value.
638
639 Reads the 16-bit PCI configuration register specified by Address, performs a
640 bitwise AND between the read result and the value specified by AndData, and
641 writes the result to the 16-bit PCI configuration register specified by
642 Address. The value written to the PCI configuration register is returned.
643 This function must guarantee that all PCI read and write operations are
644 serialized.
645
646 If Address > 0x0FFFFFFF, then ASSERT().
647 If Address is not aligned on a 16-bit boundary, then ASSERT().
648
649 @param Address Address that encodes the PCI Bus, Device, Function and
650 Register.
651 @param AndData The value to AND with the PCI configuration register.
652
653 @return The value written back to the PCI configuration register.
654
655 **/
656 UINT16
657 EFIAPI
658 PciAnd16 (
659 IN UINTN Address,
660 IN UINT16 AndData
661 )
662 {
663 return PciWrite16 (Address, (UINT16)(PciRead16 (Address) & AndData));
664 }
665
666 /**
667 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
668 value, followed a bitwise OR with another 16-bit value.
669
670 Reads the 16-bit PCI configuration register specified by Address, performs a
671 bitwise AND between the read result and the value specified by AndData,
672 performs a bitwise OR between the result of the AND operation and
673 the value specified by OrData, and writes the result to the 16-bit PCI
674 configuration register specified by Address. The value written to the PCI
675 configuration register is returned. This function must guarantee that all PCI
676 read and write operations are serialized.
677
678 If Address > 0x0FFFFFFF, then ASSERT().
679 If Address is not aligned on a 16-bit boundary, then ASSERT().
680
681 @param Address Address that encodes the PCI Bus, Device, Function and
682 Register.
683 @param AndData The value to AND with the PCI configuration register.
684 @param OrData The value to OR with the result of the AND operation.
685
686 @return The value written back to the PCI configuration register.
687
688 **/
689 UINT16
690 EFIAPI
691 PciAndThenOr16 (
692 IN UINTN Address,
693 IN UINT16 AndData,
694 IN UINT16 OrData
695 )
696 {
697 return PciWrite16 (Address, (UINT16)((PciRead16 (Address) & AndData) | OrData));
698 }
699
700 /**
701 Reads a bit field of a PCI configuration register.
702
703 Reads the bit field in a 16-bit PCI configuration register. The bit field is
704 specified by the StartBit and the EndBit. The value of the bit field is
705 returned.
706
707 If Address > 0x0FFFFFFF, then ASSERT().
708 If Address is not aligned on a 16-bit boundary, then ASSERT().
709 If StartBit is greater than 15, then ASSERT().
710 If EndBit is greater than 15, then ASSERT().
711 If EndBit is less than StartBit, then ASSERT().
712
713 @param Address PCI configuration register to read.
714 @param StartBit The ordinal of the least significant bit in the bit field.
715 Range 0..15.
716 @param EndBit The ordinal of the most significant bit in the bit field.
717 Range 0..15.
718
719 @return The value of the bit field read from the PCI configuration register.
720
721 **/
722 UINT16
723 EFIAPI
724 PciBitFieldRead16 (
725 IN UINTN Address,
726 IN UINTN StartBit,
727 IN UINTN EndBit
728 )
729 {
730 return BitFieldRead16 (PciRead16 (Address), StartBit, EndBit);
731 }
732
733 /**
734 Writes a bit field to a PCI configuration register.
735
736 Writes Value to the bit field of the PCI configuration register. The bit
737 field is specified by the StartBit and the EndBit. All other bits in the
738 destination PCI configuration register are preserved. The new value of the
739 16-bit register is returned.
740
741 If Address > 0x0FFFFFFF, then ASSERT().
742 If Address is not aligned on a 16-bit boundary, then ASSERT().
743 If StartBit is greater than 15, then ASSERT().
744 If EndBit is greater than 15, then ASSERT().
745 If EndBit is less than StartBit, then ASSERT().
746
747 @param Address 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 Value New value of the bit field.
753
754 @return The value written back to the PCI configuration register.
755
756 **/
757 UINT16
758 EFIAPI
759 PciBitFieldWrite16 (
760 IN UINTN Address,
761 IN UINTN StartBit,
762 IN UINTN EndBit,
763 IN UINT16 Value
764 )
765 {
766 return PciWrite16 (
767 Address,
768 BitFieldWrite16 (PciRead16 (Address), StartBit, EndBit, Value)
769 );
770 }
771
772 /**
773 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
774 writes the result back to the bit field in the 16-bit port.
775
776 Reads the 16-bit PCI configuration register specified by Address, performs a
777 bitwise OR between the read result and the value specified by
778 OrData, and writes the result to the 16-bit PCI configuration register
779 specified by Address. The value written to the PCI configuration register is
780 returned. This function must guarantee that all PCI read and write operations
781 are serialized. Extra left bits in OrData 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
789 @param Address PCI configuration register to write.
790 @param StartBit The ordinal of the least significant bit in the bit field.
791 Range 0..15.
792 @param EndBit The ordinal of the most significant bit in the bit field.
793 Range 0..15.
794 @param OrData The value to OR with the PCI configuration register.
795
796 @return The value written back to the PCI configuration register.
797
798 **/
799 UINT16
800 EFIAPI
801 PciBitFieldOr16 (
802 IN UINTN Address,
803 IN UINTN StartBit,
804 IN UINTN EndBit,
805 IN UINT16 OrData
806 )
807 {
808 return PciWrite16 (
809 Address,
810 BitFieldOr16 (PciRead16 (Address), StartBit, EndBit, OrData)
811 );
812 }
813
814 /**
815 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
816 AND, and writes the result back to the bit field in the 16-bit register.
817
818 Reads the 16-bit PCI configuration register specified by Address, performs a
819 bitwise AND between the read result and the value specified by AndData, and
820 writes the result to the 16-bit PCI configuration register specified by
821 Address. The value written to the PCI configuration register is returned.
822 This function must guarantee that all PCI read and write operations are
823 serialized. Extra left bits in AndData are stripped.
824
825 If Address > 0x0FFFFFFF, then ASSERT().
826 If Address is not aligned on a 16-bit boundary, then ASSERT().
827 If StartBit is greater than 15, then ASSERT().
828 If EndBit is greater than 15, then ASSERT().
829 If EndBit is less than StartBit, then ASSERT().
830
831 @param Address PCI configuration register to write.
832 @param StartBit The ordinal of the least significant bit in the bit field.
833 Range 0..15.
834 @param EndBit The ordinal of the most significant bit in the bit field.
835 Range 0..15.
836 @param AndData The value to AND with the PCI configuration register.
837
838 @return The value written back to the PCI configuration register.
839
840 **/
841 UINT16
842 EFIAPI
843 PciBitFieldAnd16 (
844 IN UINTN Address,
845 IN UINTN StartBit,
846 IN UINTN EndBit,
847 IN UINT16 AndData
848 )
849 {
850 return PciWrite16 (
851 Address,
852 BitFieldAnd16 (PciRead16 (Address), StartBit, EndBit, AndData)
853 );
854 }
855
856 /**
857 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
858 bitwise OR, and writes the result back to the bit field in the
859 16-bit port.
860
861 Reads the 16-bit PCI configuration register specified by Address, performs a
862 bitwise AND followed by a bitwise OR between the read result and
863 the value specified by AndData, and writes the result to the 16-bit PCI
864 configuration register specified by Address. The value written to the PCI
865 configuration register is returned. This function must guarantee that all PCI
866 read and write operations are serialized. Extra left bits in both AndData and
867 OrData are stripped.
868
869 If Address > 0x0FFFFFFF, then ASSERT().
870 If Address is not aligned on a 16-bit boundary, then ASSERT().
871 If StartBit is greater than 15, then ASSERT().
872 If EndBit is greater than 15, then ASSERT().
873 If EndBit is less than StartBit, then ASSERT().
874
875 @param Address PCI configuration register to write.
876 @param StartBit The ordinal of the least significant bit in the bit field.
877 Range 0..15.
878 @param EndBit The ordinal of the most significant bit in the bit field.
879 Range 0..15.
880 @param AndData The value to AND with the PCI configuration register.
881 @param OrData The value to OR with the result of the AND operation.
882
883 @return The value written back to the PCI configuration register.
884
885 **/
886 UINT16
887 EFIAPI
888 PciBitFieldAndThenOr16 (
889 IN UINTN Address,
890 IN UINTN StartBit,
891 IN UINTN EndBit,
892 IN UINT16 AndData,
893 IN UINT16 OrData
894 )
895 {
896 return PciWrite16 (
897 Address,
898 BitFieldAndThenOr16 (PciRead16 (Address), StartBit, EndBit, AndData, OrData)
899 );
900 }
901
902 /**
903 Reads a 32-bit PCI configuration register.
904
905 Reads and returns the 32-bit PCI configuration register specified by Address.
906 This function must guarantee that all PCI read and write operations are
907 serialized.
908
909 If Address > 0x0FFFFFFF, then ASSERT().
910 If Address is not aligned on a 32-bit boundary, then ASSERT().
911
912 @param Address Address that encodes the PCI Bus, Device, Function and
913 Register.
914
915 @return The value read from the PCI configuration register.
916
917 **/
918 UINT32
919 EFIAPI
920 PciRead32 (
921 IN UINTN Address
922 )
923 {
924 ASSERT_INVALID_PCI_ADDRESS (Address, 3);
925
926 return DxePciLibEsalReadWorker (Address, 4);
927 }
928
929 /**
930 Writes a 32-bit PCI configuration register.
931
932 Writes the 32-bit PCI configuration register specified by Address with the
933 value specified by Value. Value is returned. This function must guarantee
934 that all PCI read and write operations are serialized.
935
936 If Address > 0x0FFFFFFF, then ASSERT().
937 If Address is not aligned on a 32-bit boundary, then ASSERT().
938
939 @param Address Address that encodes the PCI Bus, Device, Function and
940 Register.
941 @param Data The value to write.
942
943 @return The value written to the PCI configuration register.
944
945 **/
946 UINT32
947 EFIAPI
948 PciWrite32 (
949 IN UINTN Address,
950 IN UINT32 Data
951 )
952 {
953 ASSERT_INVALID_PCI_ADDRESS (Address, 3);
954
955 return DxePciLibEsalWriteWorker (Address, 4, Data);
956 }
957
958 /**
959 Performs a bitwise OR of a 32-bit PCI configuration register with
960 a 32-bit value.
961
962 Reads the 32-bit PCI configuration register specified by Address, performs a
963 bitwise OR between the read result and the value specified by
964 OrData, and writes the result to the 32-bit PCI configuration register
965 specified by Address. The value written to the PCI configuration register is
966 returned. This function must guarantee that all PCI read and write operations
967 are serialized.
968
969 If Address > 0x0FFFFFFF, then ASSERT().
970 If Address is not aligned on a 32-bit boundary, then ASSERT().
971
972 @param Address Address that encodes the PCI Bus, Device, Function and
973 Register.
974 @param OrData The value to OR with the PCI configuration register.
975
976 @return The value written back to the PCI configuration register.
977
978 **/
979 UINT32
980 EFIAPI
981 PciOr32 (
982 IN UINTN Address,
983 IN UINT32 OrData
984 )
985 {
986 return PciWrite32 (Address, PciRead32 (Address) | OrData);
987 }
988
989 /**
990 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
991 value.
992
993 Reads the 32-bit PCI configuration register specified by Address, performs a
994 bitwise AND between the read result and the value specified by AndData, and
995 writes the result to the 32-bit PCI configuration register specified by
996 Address. The value written to the PCI configuration register is returned.
997 This function must guarantee that all PCI read and write operations are
998 serialized.
999
1000 If Address > 0x0FFFFFFF, then ASSERT().
1001 If Address is not aligned on a 32-bit boundary, then ASSERT().
1002
1003 @param Address Address that encodes the PCI Bus, Device, Function and
1004 Register.
1005 @param AndData The value to AND with the PCI configuration register.
1006
1007 @return The value written back to the PCI configuration register.
1008
1009 **/
1010 UINT32
1011 EFIAPI
1012 PciAnd32 (
1013 IN UINTN Address,
1014 IN UINT32 AndData
1015 )
1016 {
1017 return PciWrite32 (Address, PciRead32 (Address) & AndData);
1018 }
1019
1020 /**
1021 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1022 value, followed a bitwise OR with another 32-bit value.
1023
1024 Reads the 32-bit PCI configuration register specified by Address, performs a
1025 bitwise AND between the read result and the value specified by AndData,
1026 performs a bitwise OR between the result of the AND operation and
1027 the value specified by OrData, and writes the result to the 32-bit PCI
1028 configuration register specified by Address. The value written to the PCI
1029 configuration register is returned. This function must guarantee that all PCI
1030 read and write operations are serialized.
1031
1032 If Address > 0x0FFFFFFF, then ASSERT().
1033 If Address is not aligned on a 32-bit boundary, then ASSERT().
1034
1035 @param Address Address that encodes the PCI Bus, Device, Function and
1036 Register.
1037 @param AndData The value to AND with the PCI configuration register.
1038 @param OrData The value to OR with the result of the AND operation.
1039
1040 @return The value written back to the PCI configuration register.
1041
1042 **/
1043 UINT32
1044 EFIAPI
1045 PciAndThenOr32 (
1046 IN UINTN Address,
1047 IN UINT32 AndData,
1048 IN UINT32 OrData
1049 )
1050 {
1051 return PciWrite32 (Address, (PciRead32 (Address) & AndData) | OrData);
1052 }
1053
1054 /**
1055 Reads a bit field of a PCI configuration register.
1056
1057 Reads the bit field in a 32-bit PCI configuration register. The bit field is
1058 specified by the StartBit and the EndBit. The value of the bit field is
1059 returned.
1060
1061 If Address > 0x0FFFFFFF, then ASSERT().
1062 If Address is not aligned on a 32-bit boundary, then ASSERT().
1063 If StartBit is greater than 31, then ASSERT().
1064 If EndBit is greater than 31, then ASSERT().
1065 If EndBit is less than StartBit, then ASSERT().
1066
1067 @param Address PCI configuration register to read.
1068 @param StartBit The ordinal of the least significant bit in the bit field.
1069 Range 0..31.
1070 @param EndBit The ordinal of the most significant bit in the bit field.
1071 Range 0..31.
1072
1073 @return The value of the bit field read from the PCI configuration register.
1074
1075 **/
1076 UINT32
1077 EFIAPI
1078 PciBitFieldRead32 (
1079 IN UINTN Address,
1080 IN UINTN StartBit,
1081 IN UINTN EndBit
1082 )
1083 {
1084 return BitFieldRead32 (PciRead32 (Address), StartBit, EndBit);
1085 }
1086
1087 /**
1088 Writes a bit field to a PCI configuration register.
1089
1090 Writes Value to the bit field of the PCI configuration register. The bit
1091 field is specified by the StartBit and the EndBit. All other bits in the
1092 destination PCI configuration register are preserved. The new value of the
1093 32-bit register is returned.
1094
1095 If Address > 0x0FFFFFFF, then ASSERT().
1096 If Address is not aligned on a 32-bit boundary, then ASSERT().
1097 If StartBit is greater than 31, then ASSERT().
1098 If EndBit is greater than 31, then ASSERT().
1099 If EndBit is less than StartBit, then ASSERT().
1100
1101 @param Address PCI configuration register to write.
1102 @param StartBit The ordinal of the least significant bit in the bit field.
1103 Range 0..31.
1104 @param EndBit The ordinal of the most significant bit in the bit field.
1105 Range 0..31.
1106 @param Value New value of the bit field.
1107
1108 @return The value written back to the PCI configuration register.
1109
1110 **/
1111 UINT32
1112 EFIAPI
1113 PciBitFieldWrite32 (
1114 IN UINTN Address,
1115 IN UINTN StartBit,
1116 IN UINTN EndBit,
1117 IN UINT32 Value
1118 )
1119 {
1120 return PciWrite32 (
1121 Address,
1122 BitFieldWrite32 (PciRead32 (Address), StartBit, EndBit, Value)
1123 );
1124 }
1125
1126 /**
1127 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1128 writes the result back to the bit field in the 32-bit port.
1129
1130 Reads the 32-bit PCI configuration register specified by Address, performs a
1131 bitwise OR between the read result and the value specified by
1132 OrData, and writes the result to the 32-bit PCI configuration register
1133 specified by Address. The value written to the PCI configuration register is
1134 returned. This function must guarantee that all PCI read and write operations
1135 are serialized. Extra left bits in OrData are stripped.
1136
1137 If Address > 0x0FFFFFFF, then ASSERT().
1138 If Address is not aligned on a 32-bit boundary, then ASSERT().
1139 If StartBit is greater than 31, then ASSERT().
1140 If EndBit is greater than 31, then ASSERT().
1141 If EndBit is less than StartBit, then ASSERT().
1142
1143 @param Address PCI configuration register to write.
1144 @param StartBit The ordinal of the least significant bit in the bit field.
1145 Range 0..31.
1146 @param EndBit The ordinal of the most significant bit in the bit field.
1147 Range 0..31.
1148 @param OrData The value to OR with the PCI configuration register.
1149
1150 @return The value written back to the PCI configuration register.
1151
1152 **/
1153 UINT32
1154 EFIAPI
1155 PciBitFieldOr32 (
1156 IN UINTN Address,
1157 IN UINTN StartBit,
1158 IN UINTN EndBit,
1159 IN UINT32 OrData
1160 )
1161 {
1162 return PciWrite32 (
1163 Address,
1164 BitFieldOr32 (PciRead32 (Address), StartBit, EndBit, OrData)
1165 );
1166 }
1167
1168 /**
1169 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1170 AND, and writes the result back to the bit field in the 32-bit register.
1171
1172 Reads the 32-bit PCI configuration register specified by Address, performs a
1173 bitwise AND between the read result and the value specified by AndData, and
1174 writes the result to the 32-bit PCI configuration register specified by
1175 Address. The value written to the PCI configuration register is returned.
1176 This function must guarantee that all PCI read and write operations are
1177 serialized. Extra left bits in AndData are stripped.
1178
1179 If Address > 0x0FFFFFFF, then ASSERT().
1180 If Address is not aligned on a 32-bit boundary, then ASSERT().
1181 If StartBit is greater than 31, then ASSERT().
1182 If EndBit is greater than 31, then ASSERT().
1183 If EndBit is less than StartBit, then ASSERT().
1184
1185 @param Address PCI configuration register to write.
1186 @param StartBit The ordinal of the least significant bit in the bit field.
1187 Range 0..31.
1188 @param EndBit The ordinal of the most significant bit in the bit field.
1189 Range 0..31.
1190 @param AndData The value to AND with the PCI configuration register.
1191
1192 @return The value written back to the PCI configuration register.
1193
1194 **/
1195 UINT32
1196 EFIAPI
1197 PciBitFieldAnd32 (
1198 IN UINTN Address,
1199 IN UINTN StartBit,
1200 IN UINTN EndBit,
1201 IN UINT32 AndData
1202 )
1203 {
1204 return PciWrite32 (
1205 Address,
1206 BitFieldAnd32 (PciRead32 (Address), StartBit, EndBit, AndData)
1207 );
1208 }
1209
1210 /**
1211 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1212 bitwise OR, and writes the result back to the bit field in the
1213 32-bit port.
1214
1215 Reads the 32-bit PCI configuration register specified by Address, performs a
1216 bitwise AND followed by a bitwise OR between the read result and
1217 the value specified by AndData, and writes the result to the 32-bit PCI
1218 configuration register specified by Address. The value written to the PCI
1219 configuration register is returned. This function must guarantee that all PCI
1220 read and write operations are serialized. Extra left bits in both AndData and
1221 OrData are stripped.
1222
1223 If Address > 0x0FFFFFFF, then ASSERT().
1224 If Address is not aligned on a 32-bit boundary, then ASSERT().
1225 If StartBit is greater than 31, then ASSERT().
1226 If EndBit is greater than 31, then ASSERT().
1227 If EndBit is less than StartBit, then ASSERT().
1228
1229 @param Address PCI configuration register to write.
1230 @param StartBit The ordinal of the least significant bit in the bit field.
1231 Range 0..31.
1232 @param EndBit The ordinal of the most significant bit in the bit field.
1233 Range 0..31.
1234 @param AndData The value to AND with the PCI configuration register.
1235 @param OrData The value to OR with the result of the AND operation.
1236
1237 @return The value written back to the PCI configuration register.
1238
1239 **/
1240 UINT32
1241 EFIAPI
1242 PciBitFieldAndThenOr32 (
1243 IN UINTN Address,
1244 IN UINTN StartBit,
1245 IN UINTN EndBit,
1246 IN UINT32 AndData,
1247 IN UINT32 OrData
1248 )
1249 {
1250 return PciWrite32 (
1251 Address,
1252 BitFieldAndThenOr32 (PciRead32 (Address), StartBit, EndBit, AndData, OrData)
1253 );
1254 }
1255
1256 /**
1257 Reads a range of PCI configuration registers into a caller supplied buffer.
1258
1259 Reads the range of PCI configuration registers specified by StartAddress and
1260 Size into the buffer specified by Buffer. This function only allows the PCI
1261 configuration registers from a single PCI function to be read. Size is
1262 returned. When possible 32-bit PCI configuration read cycles are used to read
1263 from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
1264 and 16-bit PCI configuration read cycles may be used at the beginning and the
1265 end of the range.
1266
1267 If StartAddress > 0x0FFFFFFF, then ASSERT().
1268 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1269 If Size > 0 and Buffer is NULL, then ASSERT().
1270
1271 @param StartAddress Starting address that encodes the PCI Bus, Device,
1272 Function and Register.
1273 @param Size Size in bytes of the transfer.
1274 @param Buffer Pointer to a buffer receiving the data read.
1275
1276 @return Size
1277
1278 **/
1279 UINTN
1280 EFIAPI
1281 PciReadBuffer (
1282 IN UINTN StartAddress,
1283 IN UINTN Size,
1284 OUT VOID *Buffer
1285 )
1286 {
1287 UINTN ReturnValue;
1288
1289 ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0);
1290 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100);
1291
1292 if (Size == 0) {
1293 return Size;
1294 }
1295
1296 ASSERT (Buffer != NULL);
1297
1298 //
1299 // Save Size for return
1300 //
1301 ReturnValue = Size;
1302
1303 if ((StartAddress & 1) != 0) {
1304 //
1305 // Read a byte if StartAddress is byte aligned
1306 //
1307 *(volatile UINT8 *)Buffer = PciRead8 (StartAddress);
1308 StartAddress += sizeof (UINT8);
1309 Size -= sizeof (UINT8);
1310 Buffer = (UINT8*)Buffer + 1;
1311 }
1312
1313 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1314 //
1315 // Read a word if StartAddress is word aligned
1316 //
1317 *(volatile UINT16 *)Buffer = PciRead16 (StartAddress);
1318 StartAddress += sizeof (UINT16);
1319 Size -= sizeof (UINT16);
1320 Buffer = (UINT16*)Buffer + 1;
1321 }
1322
1323 while (Size >= sizeof (UINT32)) {
1324 //
1325 // Read as many double words as possible
1326 //
1327 *(volatile UINT32 *)Buffer = PciRead32 (StartAddress);
1328 StartAddress += sizeof (UINT32);
1329 Size -= sizeof (UINT32);
1330 Buffer = (UINT32*)Buffer + 1;
1331 }
1332
1333 if (Size >= sizeof (UINT16)) {
1334 //
1335 // Read the last remaining word if exist
1336 //
1337 *(volatile UINT16 *)Buffer = PciRead16 (StartAddress);
1338 StartAddress += sizeof (UINT16);
1339 Size -= sizeof (UINT16);
1340 Buffer = (UINT16*)Buffer + 1;
1341 }
1342
1343 if (Size >= sizeof (UINT8)) {
1344 //
1345 // Read the last remaining byte if exist
1346 //
1347 *(volatile UINT8 *)Buffer = PciRead8 (StartAddress);
1348 }
1349
1350 return ReturnValue;
1351 }
1352
1353 /**
1354 Copies the data in a caller supplied buffer to a specified range of PCI
1355 configuration space.
1356
1357 Writes the range of PCI configuration registers specified by StartAddress and
1358 Size from the buffer specified by Buffer. This function only allows the PCI
1359 configuration registers from a single PCI function to be written. Size is
1360 returned. When possible 32-bit PCI configuration write cycles are used to
1361 write from StartAdress to StartAddress + Size. Due to alignment restrictions,
1362 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1363 and the end of the range.
1364
1365 If StartAddress > 0x0FFFFFFF, then ASSERT().
1366 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1367 If Size > 0 and Buffer is NULL, then ASSERT().
1368
1369 @param StartAddress Starting address that encodes the PCI Bus, Device,
1370 Function and Register.
1371 @param Size Size in bytes of the transfer.
1372 @param Buffer Pointer to a buffer containing the data to write.
1373
1374 @return Size
1375
1376 **/
1377 UINTN
1378 EFIAPI
1379 PciWriteBuffer (
1380 IN UINTN StartAddress,
1381 IN UINTN Size,
1382 IN VOID *Buffer
1383 )
1384 {
1385 UINTN ReturnValue;
1386
1387 ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0);
1388 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x100);
1389
1390 if (Size == 0) {
1391 return 0;
1392 }
1393
1394 ASSERT (Buffer != NULL);
1395
1396 //
1397 // Save Size for return
1398 //
1399 ReturnValue = Size;
1400
1401 if ((StartAddress & 1) != 0) {
1402 //
1403 // Write a byte if StartAddress is byte aligned
1404 //
1405 PciWrite8 (StartAddress, *(UINT8*)Buffer);
1406 StartAddress += sizeof (UINT8);
1407 Size -= sizeof (UINT8);
1408 Buffer = (UINT8*)Buffer + 1;
1409 }
1410
1411 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1412 //
1413 // Write a word if StartAddress is word aligned
1414 //
1415 PciWrite16 (StartAddress, *(UINT16*)Buffer);
1416 StartAddress += sizeof (UINT16);
1417 Size -= sizeof (UINT16);
1418 Buffer = (UINT16*)Buffer + 1;
1419 }
1420
1421 while (Size >= sizeof (UINT32)) {
1422 //
1423 // Write as many double words as possible
1424 //
1425 PciWrite32 (StartAddress, *(UINT32*)Buffer);
1426 StartAddress += sizeof (UINT32);
1427 Size -= sizeof (UINT32);
1428 Buffer = (UINT32*)Buffer + 1;
1429 }
1430
1431 if (Size >= sizeof (UINT16)) {
1432 //
1433 // Write the last remaining word if exist
1434 //
1435 PciWrite16 (StartAddress, *(UINT16*)Buffer);
1436 StartAddress += sizeof (UINT16);
1437 Size -= sizeof (UINT16);
1438 Buffer = (UINT16*)Buffer + 1;
1439 }
1440
1441 if (Size >= sizeof (UINT8)) {
1442 //
1443 // Write the last remaining byte if exist
1444 //
1445 PciWrite8 (StartAddress, *(UINT8*)Buffer);
1446 }
1447
1448 return ReturnValue;
1449 }