]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/DxePciSegmentLibEsal/PciLib.c
07ddd8fd0a7682f8e75a368b8ecc01f5dbb0d61d
[mirror_edk2.git] / MdePkg / Library / DxePciSegmentLibEsal / PciLib.c
1 /** @file
2 DXE PCI Segment 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/PciSegmentLib.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 Segment address.
26 A valid PCI Segment address should not contain 1's in bits 31:28
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_SEGMENT_ADDRESS(A,M) \
33 ASSERT (((A) & (0xf0000000 | (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_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS0(Address) (((Address >> 8) & 0xff000000) | (((Address) >> 4) & 0x00ffff00) | ((Address) & 0xff))
60 #define CONVERT_PCI_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS1(Address) (((Address >> 4) & 0xffff0000000) | ((Address) & 0xfffffff))
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 DxePciSegmentLibEsalReadWorker (
84 IN UINT64 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_SEGMENT_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_SEGMENT_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 DxePciSegmentLibEsalWriteWorker (
140 IN UINT64 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_SEGMENT_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_SEGMENT_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 Reads an 8-bit PCI configuration register.
178
179 Reads and returns the 8-bit PCI configuration register specified by Address.
180 This function must guarantee that all PCI read and write operations are
181 serialized.
182
183 If any reserved bits in Address are set, then ASSERT().
184
185 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
186 Register.
187
188 @return The value read from the PCI configuration register.
189
190 **/
191 UINT8
192 EFIAPI
193 PciSegmentRead8 (
194 IN UINT64 Address
195 )
196 {
197 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
198
199 return (UINT8) DxePciSegmentLibEsalReadWorker (Address, 1);
200 }
201
202 /**
203 Writes an 8-bit PCI configuration register.
204
205 Writes the 8-bit PCI configuration register specified by Address with the
206 value specified by Value. Value is returned. This function must guarantee
207 that all PCI read and write operations are serialized.
208
209 If any reserved bits in Address are set, then ASSERT().
210
211 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
212 Register.
213 @param Data The value to write.
214
215 @return The value written to the PCI configuration register.
216
217 **/
218 UINT8
219 EFIAPI
220 PciSegmentWrite8 (
221 IN UINT64 Address,
222 IN UINT8 Data
223 )
224 {
225 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
226
227 return (UINT8) DxePciSegmentLibEsalWriteWorker (Address, 1, Data);
228 }
229
230 /**
231 Performs a bitwise OR of an 8-bit PCI configuration register with
232 an 8-bit value.
233
234 Reads the 8-bit PCI configuration register specified by Address, performs a
235 bitwise OR between the read result and the value specified by
236 OrData, and writes the result to the 8-bit PCI configuration register
237 specified by Address. The value written to the PCI configuration register is
238 returned. This function must guarantee that all PCI read and write operations
239 are serialized.
240
241 If any reserved bits in Address are set, then ASSERT().
242
243 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
244 Register.
245 @param OrData The value to OR with the PCI configuration register.
246
247 @return The value written back to the PCI configuration register.
248
249 **/
250 UINT8
251 EFIAPI
252 PciSegmentOr8 (
253 IN UINT64 Address,
254 IN UINT8 OrData
255 )
256 {
257 return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) | OrData));
258 }
259
260 /**
261 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
262 value.
263
264 Reads the 8-bit PCI configuration register specified by Address, performs a
265 bitwise AND between the read result and the value specified by AndData, and
266 writes the result to the 8-bit PCI configuration register specified by
267 Address. The value written to the PCI configuration register is returned.
268 This function must guarantee that all PCI read and write operations are
269 serialized.
270
271 If any reserved bits in Address are set, then ASSERT().
272
273 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
274 Register.
275 @param AndData The value to AND with the PCI configuration register.
276
277 @return The value written back to the PCI configuration register.
278
279 **/
280 UINT8
281 EFIAPI
282 PciSegmentAnd8 (
283 IN UINT64 Address,
284 IN UINT8 AndData
285 )
286 {
287 return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData));
288 }
289
290 /**
291 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
292 value, followed a bitwise OR with another 8-bit value.
293
294 Reads the 8-bit PCI configuration register specified by Address, performs a
295 bitwise AND between the read result and the value specified by AndData,
296 performs a bitwise OR between the result of the AND operation and
297 the value specified by OrData, and writes the result to the 8-bit PCI
298 configuration register specified by Address. The value written to the PCI
299 configuration register is returned. This function must guarantee that all PCI
300 read and write operations are serialized.
301
302 If any reserved bits in Address are set, then ASSERT().
303
304 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
305 Register.
306 @param AndData The value to AND with the PCI configuration register.
307 @param OrData The value to OR with the result of the AND operation.
308
309 @return The value written back to the PCI configuration register.
310
311 **/
312 UINT8
313 EFIAPI
314 PciSegmentAndThenOr8 (
315 IN UINT64 Address,
316 IN UINT8 AndData,
317 IN UINT8 OrData
318 )
319 {
320 return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData));
321 }
322
323 /**
324 Reads a bit field of a PCI configuration register.
325
326 Reads the bit field in an 8-bit PCI configuration register. The bit field is
327 specified by the StartBit and the EndBit. The value of the bit field is
328 returned.
329
330 If any reserved bits in Address are set, then ASSERT().
331 If StartBit is greater than 7, then ASSERT().
332 If EndBit is greater than 7, then ASSERT().
333 If EndBit is less than StartBit, then ASSERT().
334
335 @param Address PCI configuration register to read.
336 @param StartBit The ordinal of the least significant bit in the bit field.
337 Range 0..7.
338 @param EndBit The ordinal of the most significant bit in the bit field.
339 Range 0..7.
340
341 @return The value of the bit field read from the PCI configuration register.
342
343 **/
344 UINT8
345 EFIAPI
346 PciSegmentBitFieldRead8 (
347 IN UINT64 Address,
348 IN UINTN StartBit,
349 IN UINTN EndBit
350 )
351 {
352 return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit);
353 }
354
355 /**
356 Writes a bit field to a PCI configuration register.
357
358 Writes Value to the bit field of the PCI configuration register. The bit
359 field is specified by the StartBit and the EndBit. All other bits in the
360 destination PCI configuration register are preserved. The new value of the
361 8-bit register is returned.
362
363 If any reserved bits in Address are set, then ASSERT().
364 If StartBit is greater than 7, then ASSERT().
365 If EndBit is greater than 7, then ASSERT().
366 If EndBit is less than StartBit, then ASSERT().
367 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
368
369 @param Address PCI configuration register to write.
370 @param StartBit The ordinal of the least significant bit in the bit field.
371 Range 0..7.
372 @param EndBit The ordinal of the most significant bit in the bit field.
373 Range 0..7.
374 @param Value New value of the bit field.
375
376 @return The value written back to the PCI configuration register.
377
378 **/
379 UINT8
380 EFIAPI
381 PciSegmentBitFieldWrite8 (
382 IN UINT64 Address,
383 IN UINTN StartBit,
384 IN UINTN EndBit,
385 IN UINT8 Value
386 )
387 {
388 return PciSegmentWrite8 (
389 Address,
390 BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value)
391 );
392 }
393
394 /**
395 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
396 writes the result back to the bit field in the 8-bit port.
397
398 Reads the 8-bit PCI configuration register specified by Address, performs a
399 bitwise OR between the read result and the value specified by
400 OrData, and writes the result to the 8-bit PCI configuration register
401 specified by Address. The value written to the PCI configuration register is
402 returned. This function must guarantee that all PCI read and write operations
403 are serialized. Extra left bits in OrData are stripped.
404
405 If any reserved bits in Address are set, then ASSERT().
406 If StartBit is greater than 7, then ASSERT().
407 If EndBit is greater than 7, then ASSERT().
408 If EndBit is less than StartBit, then ASSERT().
409 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
410
411 @param Address PCI configuration register to write.
412 @param StartBit The ordinal of the least significant bit in the bit field.
413 Range 0..7.
414 @param EndBit The ordinal of the most significant bit in the bit field.
415 Range 0..7.
416 @param OrData The value to OR with the PCI configuration register.
417
418 @return The value written back to the PCI configuration register.
419
420 **/
421 UINT8
422 EFIAPI
423 PciSegmentBitFieldOr8 (
424 IN UINT64 Address,
425 IN UINTN StartBit,
426 IN UINTN EndBit,
427 IN UINT8 OrData
428 )
429 {
430 return PciSegmentWrite8 (
431 Address,
432 BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData)
433 );
434 }
435
436 /**
437 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
438 AND, and writes the result back to the bit field in the 8-bit register.
439
440 Reads the 8-bit PCI configuration register specified by Address, performs a
441 bitwise AND between the read result and the value specified by AndData, and
442 writes the result to the 8-bit PCI configuration register specified by
443 Address. The value written to the PCI configuration register is returned.
444 This function must guarantee that all PCI read and write operations are
445 serialized. Extra left bits in AndData are stripped.
446
447 If any reserved bits in Address are set, then ASSERT().
448 If StartBit is greater than 7, then ASSERT().
449 If EndBit is greater than 7, then ASSERT().
450 If EndBit is less than StartBit, then ASSERT().
451 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
452
453 @param Address PCI configuration register to write.
454 @param StartBit The ordinal of the least significant bit in the bit field.
455 Range 0..7.
456 @param EndBit The ordinal of the most significant bit in the bit field.
457 Range 0..7.
458 @param AndData The value to AND with the PCI configuration register.
459
460 @return The value written back to the PCI configuration register.
461
462 **/
463 UINT8
464 EFIAPI
465 PciSegmentBitFieldAnd8 (
466 IN UINT64 Address,
467 IN UINTN StartBit,
468 IN UINTN EndBit,
469 IN UINT8 AndData
470 )
471 {
472 return PciSegmentWrite8 (
473 Address,
474 BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData)
475 );
476 }
477
478 /**
479 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
480 bitwise OR, and writes the result back to the bit field in the
481 8-bit port.
482
483 Reads the 8-bit PCI configuration register specified by Address, performs a
484 bitwise AND followed by a bitwise OR between the read result and
485 the value specified by AndData, and writes the result to the 8-bit PCI
486 configuration register specified by Address. The value written to the PCI
487 configuration register is returned. This function must guarantee that all PCI
488 read and write operations are serialized. Extra left bits in both AndData and
489 OrData are stripped.
490
491 If any reserved bits in Address are set, then ASSERT().
492 If StartBit is greater than 7, then ASSERT().
493 If EndBit is greater than 7, then ASSERT().
494 If EndBit is less than StartBit, then ASSERT().
495 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
496 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
497
498 @param Address PCI configuration register to write.
499 @param StartBit The ordinal of the least significant bit in the bit field.
500 Range 0..7.
501 @param EndBit The ordinal of the most significant bit in the bit field.
502 Range 0..7.
503 @param AndData The value to AND with the PCI configuration register.
504 @param OrData The value to OR with the result of the AND operation.
505
506 @return The value written back to the PCI configuration register.
507
508 **/
509 UINT8
510 EFIAPI
511 PciSegmentBitFieldAndThenOr8 (
512 IN UINT64 Address,
513 IN UINTN StartBit,
514 IN UINTN EndBit,
515 IN UINT8 AndData,
516 IN UINT8 OrData
517 )
518 {
519 return PciSegmentWrite8 (
520 Address,
521 BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData)
522 );
523 }
524
525 /**
526 Reads a 16-bit PCI configuration register.
527
528 Reads and returns the 16-bit PCI configuration register specified by Address.
529 This function must guarantee that all PCI read and write operations are
530 serialized.
531
532 If any reserved bits in Address are set, then ASSERT().
533
534 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
535 Register.
536
537 @return The value read from the PCI configuration register.
538
539 **/
540 UINT16
541 EFIAPI
542 PciSegmentRead16 (
543 IN UINT64 Address
544 )
545 {
546 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
547
548 return (UINT16) DxePciSegmentLibEsalReadWorker (Address, 2);
549 }
550
551 /**
552 Writes a 16-bit PCI configuration register.
553
554 Writes the 16-bit PCI configuration register specified by Address with the
555 value specified by Value. Value is returned. This function must guarantee
556 that all PCI read and write operations are serialized.
557
558 If any reserved bits in Address are set, then ASSERT().
559
560 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
561 Register.
562 @param Data The value to write.
563
564 @return The value written to the PCI configuration register.
565
566 **/
567 UINT16
568 EFIAPI
569 PciSegmentWrite16 (
570 IN UINT64 Address,
571 IN UINT16 Data
572 )
573 {
574 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
575
576 return (UINT16) DxePciSegmentLibEsalWriteWorker (Address, 2, Data);
577 }
578
579 /**
580 Performs a bitwise OR of a 16-bit PCI configuration register with
581 a 16-bit value.
582
583 Reads the 16-bit PCI configuration register specified by Address, performs a
584 bitwise OR between the read result and the value specified by
585 OrData, and writes the result to the 16-bit PCI configuration register
586 specified by Address. The value written to the PCI configuration register is
587 returned. This function must guarantee that all PCI read and write operations
588 are serialized.
589
590 If any reserved bits in Address are set, then ASSERT().
591
592 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
593 Register.
594 @param OrData The value to OR with the PCI configuration register.
595
596 @return The value written back to the PCI configuration register.
597
598 **/
599 UINT16
600 EFIAPI
601 PciSegmentOr16 (
602 IN UINT64 Address,
603 IN UINT16 OrData
604 )
605 {
606 return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData));
607 }
608
609 /**
610 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
611 value.
612
613 Reads the 16-bit PCI configuration register specified by Address, performs a
614 bitwise AND between the read result and the value specified by AndData, and
615 writes the result to the 16-bit PCI configuration register specified by
616 Address. The value written to the PCI configuration register is returned.
617 This function must guarantee that all PCI read and write operations are
618 serialized.
619
620 If any reserved bits in Address are set, then ASSERT().
621
622 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
623 Register.
624 @param AndData The value to AND with the PCI configuration register.
625
626 @return The value written back to the PCI configuration register.
627
628 **/
629 UINT16
630 EFIAPI
631 PciSegmentAnd16 (
632 IN UINT64 Address,
633 IN UINT16 AndData
634 )
635 {
636 return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData));
637 }
638
639 /**
640 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
641 value, followed a bitwise OR with another 16-bit value.
642
643 Reads the 16-bit PCI configuration register specified by Address, performs a
644 bitwise AND between the read result and the value specified by AndData,
645 performs a bitwise OR between the result of the AND operation and
646 the value specified by OrData, and writes the result to the 16-bit PCI
647 configuration register specified by Address. The value written to the PCI
648 configuration register is returned. This function must guarantee that all PCI
649 read and write operations are serialized.
650
651 If any reserved bits in Address are set, then ASSERT().
652
653 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
654 Register.
655 @param AndData The value to AND with the PCI configuration register.
656 @param OrData The value to OR with the result of the AND operation.
657
658 @return The value written back to the PCI configuration register.
659
660 **/
661 UINT16
662 EFIAPI
663 PciSegmentAndThenOr16 (
664 IN UINT64 Address,
665 IN UINT16 AndData,
666 IN UINT16 OrData
667 )
668 {
669 return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData));
670 }
671
672 /**
673 Reads a bit field of a PCI configuration register.
674
675 Reads the bit field in a 16-bit PCI configuration register. The bit field is
676 specified by the StartBit and the EndBit. The value of the bit field is
677 returned.
678
679 If any reserved bits in Address are set, then ASSERT().
680 If StartBit is greater than 15, then ASSERT().
681 If EndBit is greater than 15, then ASSERT().
682 If EndBit is less than StartBit, then ASSERT().
683
684 @param Address PCI configuration register to read.
685 @param StartBit The ordinal of the least significant bit in the bit field.
686 Range 0..15.
687 @param EndBit The ordinal of the most significant bit in the bit field.
688 Range 0..15.
689
690 @return The value of the bit field read from the PCI configuration register.
691
692 **/
693 UINT16
694 EFIAPI
695 PciSegmentBitFieldRead16 (
696 IN UINT64 Address,
697 IN UINTN StartBit,
698 IN UINTN EndBit
699 )
700 {
701 return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit);
702 }
703
704 /**
705 Writes a bit field to a PCI configuration register.
706
707 Writes Value to the bit field of the PCI configuration register. The bit
708 field is specified by the StartBit and the EndBit. All other bits in the
709 destination PCI configuration register are preserved. The new value of the
710 16-bit register is returned.
711
712 If any reserved bits in Address are set, then ASSERT().
713 If StartBit is greater than 15, then ASSERT().
714 If EndBit is greater than 15, then ASSERT().
715 If EndBit is less than StartBit, then ASSERT().
716 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
717
718 @param Address PCI configuration register to write.
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 @param Value New value of the bit field.
724
725 @return The value written back to the PCI configuration register.
726
727 **/
728 UINT16
729 EFIAPI
730 PciSegmentBitFieldWrite16 (
731 IN UINT64 Address,
732 IN UINTN StartBit,
733 IN UINTN EndBit,
734 IN UINT16 Value
735 )
736 {
737 return PciSegmentWrite16 (
738 Address,
739 BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value)
740 );
741 }
742
743 /**
744 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
745 writes the result back to the bit field in the 16-bit port.
746
747 Reads the 16-bit PCI configuration register specified by Address, performs a
748 bitwise OR between the read result and the value specified by
749 OrData, and writes the result to the 16-bit PCI configuration register
750 specified by Address. The value written to the PCI configuration register is
751 returned. This function must guarantee that all PCI read and write operations
752 are serialized. Extra left bits in OrData are stripped.
753
754 If any reserved bits in Address are set, then ASSERT().
755 If StartBit is greater than 15, then ASSERT().
756 If EndBit is greater than 15, then ASSERT().
757 If EndBit is less than StartBit, then ASSERT().
758 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
759
760 @param Address PCI configuration register to write.
761 @param StartBit The ordinal of the least significant bit in the bit field.
762 Range 0..15.
763 @param EndBit The ordinal of the most significant bit in the bit field.
764 Range 0..15.
765 @param OrData The value to OR with the PCI configuration register.
766
767 @return The value written back to the PCI configuration register.
768
769 **/
770 UINT16
771 EFIAPI
772 PciSegmentBitFieldOr16 (
773 IN UINT64 Address,
774 IN UINTN StartBit,
775 IN UINTN EndBit,
776 IN UINT16 OrData
777 )
778 {
779 return PciSegmentWrite16 (
780 Address,
781 BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData)
782 );
783 }
784
785 /**
786 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
787 AND, and writes the result back to the bit field in the 16-bit register.
788
789 Reads the 16-bit PCI configuration register specified by Address, performs a
790 bitwise AND between the read result and the value specified by AndData, and
791 writes the result to the 16-bit PCI configuration register specified by
792 Address. The value written to the PCI configuration register is returned.
793 This function must guarantee that all PCI read and write operations are
794 serialized. Extra left bits in AndData are stripped.
795
796 If any reserved bits in Address are set, then ASSERT().
797 If StartBit is greater than 15, then ASSERT().
798 If EndBit is greater than 15, then ASSERT().
799 If EndBit is less than StartBit, then ASSERT().
800 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
801
802 @param Address PCI configuration register to write.
803 @param StartBit The ordinal of the least significant bit in the bit field.
804 Range 0..15.
805 @param EndBit The ordinal of the most significant bit in the bit field.
806 Range 0..15.
807 @param AndData The value to AND with the PCI configuration register.
808
809 @return The value written back to the PCI configuration register.
810
811 **/
812 UINT16
813 EFIAPI
814 PciSegmentBitFieldAnd16 (
815 IN UINT64 Address,
816 IN UINTN StartBit,
817 IN UINTN EndBit,
818 IN UINT16 AndData
819 )
820 {
821 return PciSegmentWrite16 (
822 Address,
823 BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData)
824 );
825 }
826
827 /**
828 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
829 bitwise OR, and writes the result back to the bit field in the
830 16-bit port.
831
832 Reads the 16-bit PCI configuration register specified by Address, performs a
833 bitwise AND followed by a bitwise OR between the read result and
834 the value specified by AndData, and writes the result to the 16-bit PCI
835 configuration register specified by Address. The value written to the PCI
836 configuration register is returned. This function must guarantee that all PCI
837 read and write operations are serialized. Extra left bits in both AndData and
838 OrData are stripped.
839
840 If any reserved bits in Address are set, then ASSERT().
841 If StartBit is greater than 15, then ASSERT().
842 If EndBit is greater than 15, then ASSERT().
843 If EndBit is less than StartBit, then ASSERT().
844 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
845 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
846
847 @param Address PCI configuration register to write.
848 @param StartBit The ordinal of the least significant bit in the bit field.
849 Range 0..15.
850 @param EndBit The ordinal of the most significant bit in the bit field.
851 Range 0..15.
852 @param AndData The value to AND with the PCI configuration register.
853 @param OrData The value to OR with the result of the AND operation.
854
855 @return The value written back to the PCI configuration register.
856
857 **/
858 UINT16
859 EFIAPI
860 PciSegmentBitFieldAndThenOr16 (
861 IN UINT64 Address,
862 IN UINTN StartBit,
863 IN UINTN EndBit,
864 IN UINT16 AndData,
865 IN UINT16 OrData
866 )
867 {
868 return PciSegmentWrite16 (
869 Address,
870 BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData)
871 );
872 }
873
874 /**
875 Reads a 32-bit PCI configuration register.
876
877 Reads and returns the 32-bit PCI configuration register specified by Address.
878 This function must guarantee that all PCI read and write operations are
879 serialized.
880
881 If any reserved bits in Address are set, then ASSERT().
882
883 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
884 Register.
885
886 @return The value read from the PCI configuration register.
887
888 **/
889 UINT32
890 EFIAPI
891 PciSegmentRead32 (
892 IN UINT64 Address
893 )
894 {
895 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
896
897 return DxePciSegmentLibEsalReadWorker (Address, 4);
898 }
899
900 /**
901 Writes a 32-bit PCI configuration register.
902
903 Writes the 32-bit PCI configuration register specified by Address with the
904 value specified by Value. Value is returned. This function must guarantee
905 that all PCI read and write operations are serialized.
906
907 If any reserved bits in Address are set, then ASSERT().
908
909 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
910 Register.
911 @param Data The value to write.
912
913 @return The value written to the PCI configuration register.
914
915 **/
916 UINT32
917 EFIAPI
918 PciSegmentWrite32 (
919 IN UINT64 Address,
920 IN UINT32 Data
921 )
922 {
923 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
924
925 return DxePciSegmentLibEsalWriteWorker (Address, 4, Data);
926 }
927
928 /**
929 Performs a bitwise OR of a 32-bit PCI configuration register with
930 a 32-bit value.
931
932 Reads the 32-bit PCI configuration register specified by Address, performs a
933 bitwise OR between the read result and the value specified by
934 OrData, and writes the result to the 32-bit PCI configuration register
935 specified by Address. The value written to the PCI configuration register is
936 returned. This function must guarantee that all PCI read and write operations
937 are serialized.
938
939 If any reserved bits in Address are set, then ASSERT().
940
941 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
942 Register.
943 @param OrData The value to OR with the PCI configuration register.
944
945 @return The value written back to the PCI configuration register.
946
947 **/
948 UINT32
949 EFIAPI
950 PciSegmentOr32 (
951 IN UINT64 Address,
952 IN UINT32 OrData
953 )
954 {
955 return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData);
956 }
957
958 /**
959 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
960 value.
961
962 Reads the 32-bit PCI configuration register specified by Address, performs a
963 bitwise AND between the read result and the value specified by AndData, and
964 writes the result to the 32-bit PCI configuration register specified by
965 Address. The value written to the PCI configuration register is returned.
966 This function must guarantee that all PCI read and write operations are
967 serialized.
968
969 If any reserved bits in Address are set, then ASSERT().
970
971 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
972 Register.
973 @param AndData The value to AND with the PCI configuration register.
974
975 @return The value written back to the PCI configuration register.
976
977 **/
978 UINT32
979 EFIAPI
980 PciSegmentAnd32 (
981 IN UINT64 Address,
982 IN UINT32 AndData
983 )
984 {
985 return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData);
986 }
987
988 /**
989 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
990 value, followed a bitwise OR with another 32-bit value.
991
992 Reads the 32-bit PCI configuration register specified by Address, performs a
993 bitwise AND between the read result and the value specified by AndData,
994 performs a bitwise OR between the result of the AND operation and
995 the value specified by OrData, and writes the result to the 32-bit PCI
996 configuration register specified by Address. The value written to the PCI
997 configuration register is returned. This function must guarantee that all PCI
998 read and write operations are serialized.
999
1000 If any reserved bits in Address are set, then ASSERT().
1001
1002 @param Address Address that encodes the PCI Segment, Bus, Device, Function and
1003 Register.
1004 @param AndData The value to AND with the PCI configuration register.
1005 @param OrData The value to OR with the result of the AND operation.
1006
1007 @return The value written back to the PCI configuration register.
1008
1009 **/
1010 UINT32
1011 EFIAPI
1012 PciSegmentAndThenOr32 (
1013 IN UINT64 Address,
1014 IN UINT32 AndData,
1015 IN UINT32 OrData
1016 )
1017 {
1018 return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData);
1019 }
1020
1021 /**
1022 Reads a bit field of a PCI configuration register.
1023
1024 Reads the bit field in a 32-bit PCI configuration register. The bit field is
1025 specified by the StartBit and the EndBit. The value of the bit field is
1026 returned.
1027
1028 If any reserved bits in Address are set, then ASSERT().
1029 If StartBit is greater than 31, then ASSERT().
1030 If EndBit is greater than 31, then ASSERT().
1031 If EndBit is less than StartBit, then ASSERT().
1032
1033 @param Address PCI configuration register to read.
1034 @param StartBit The ordinal of the least significant bit in the bit field.
1035 Range 0..31.
1036 @param EndBit The ordinal of the most significant bit in the bit field.
1037 Range 0..31.
1038
1039 @return The value of the bit field read from the PCI configuration register.
1040
1041 **/
1042 UINT32
1043 EFIAPI
1044 PciSegmentBitFieldRead32 (
1045 IN UINT64 Address,
1046 IN UINTN StartBit,
1047 IN UINTN EndBit
1048 )
1049 {
1050 return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit);
1051 }
1052
1053 /**
1054 Writes a bit field to a PCI configuration register.
1055
1056 Writes Value to the bit field of the PCI configuration register. The bit
1057 field is specified by the StartBit and the EndBit. All other bits in the
1058 destination PCI configuration register are preserved. The new value of the
1059 32-bit register is returned.
1060
1061 If any reserved bits in Address are set, then ASSERT().
1062 If StartBit is greater than 31, then ASSERT().
1063 If EndBit is greater than 31, then ASSERT().
1064 If EndBit is less than StartBit, then ASSERT().
1065 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1066
1067 @param Address PCI configuration register to write.
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 @param Value New value of the bit field.
1073
1074 @return The value written back to the PCI configuration register.
1075
1076 **/
1077 UINT32
1078 EFIAPI
1079 PciSegmentBitFieldWrite32 (
1080 IN UINT64 Address,
1081 IN UINTN StartBit,
1082 IN UINTN EndBit,
1083 IN UINT32 Value
1084 )
1085 {
1086 return PciSegmentWrite32 (
1087 Address,
1088 BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value)
1089 );
1090 }
1091
1092 /**
1093 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1094 writes the result back to the bit field in the 32-bit port.
1095
1096 Reads the 32-bit PCI configuration register specified by Address, performs a
1097 bitwise OR between the read result and the value specified by
1098 OrData, and writes the result to the 32-bit PCI configuration register
1099 specified by Address. The value written to the PCI configuration register is
1100 returned. This function must guarantee that all PCI read and write operations
1101 are serialized. Extra left bits in OrData are stripped.
1102
1103 If any reserved bits in Address are set, then ASSERT().
1104 If StartBit is greater than 31, then ASSERT().
1105 If EndBit is greater than 31, then ASSERT().
1106 If EndBit is less than StartBit, then ASSERT().
1107 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1108
1109 @param Address PCI configuration register to write.
1110 @param StartBit The ordinal of the least significant bit in the bit field.
1111 Range 0..31.
1112 @param EndBit The ordinal of the most significant bit in the bit field.
1113 Range 0..31.
1114 @param OrData The value to OR with the PCI configuration register.
1115
1116 @return The value written back to the PCI configuration register.
1117
1118 **/
1119 UINT32
1120 EFIAPI
1121 PciSegmentBitFieldOr32 (
1122 IN UINT64 Address,
1123 IN UINTN StartBit,
1124 IN UINTN EndBit,
1125 IN UINT32 OrData
1126 )
1127 {
1128 return PciSegmentWrite32 (
1129 Address,
1130 BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData)
1131 );
1132 }
1133
1134 /**
1135 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1136 AND, and writes the result back to the bit field in the 32-bit register.
1137
1138 Reads the 32-bit PCI configuration register specified by Address, performs a
1139 bitwise AND between the read result and the value specified by AndData, and
1140 writes the result to the 32-bit PCI configuration register specified by
1141 Address. The value written to the PCI configuration register is returned.
1142 This function must guarantee that all PCI read and write operations are
1143 serialized. Extra left bits in AndData are stripped.
1144
1145 If any reserved bits in Address are set, then ASSERT().
1146 If StartBit is greater than 31, then ASSERT().
1147 If EndBit is greater than 31, then ASSERT().
1148 If EndBit is less than StartBit, then ASSERT().
1149 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1150
1151 @param Address PCI configuration register to write.
1152 @param StartBit The ordinal of the least significant bit in the bit field.
1153 Range 0..31.
1154 @param EndBit The ordinal of the most significant bit in the bit field.
1155 Range 0..31.
1156 @param AndData The value to AND with the PCI configuration register.
1157
1158 @return The value written back to the PCI configuration register.
1159
1160 **/
1161 UINT32
1162 EFIAPI
1163 PciSegmentBitFieldAnd32 (
1164 IN UINT64 Address,
1165 IN UINTN StartBit,
1166 IN UINTN EndBit,
1167 IN UINT32 AndData
1168 )
1169 {
1170 return PciSegmentWrite32 (
1171 Address,
1172 BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData)
1173 );
1174 }
1175
1176 /**
1177 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1178 bitwise OR, and writes the result back to the bit field in the
1179 32-bit port.
1180
1181 Reads the 32-bit PCI configuration register specified by Address, performs a
1182 bitwise AND followed by a bitwise OR between the read result and
1183 the value specified by AndData, and writes the result to the 32-bit PCI
1184 configuration register specified by Address. The value written to the PCI
1185 configuration register is returned. This function must guarantee that all PCI
1186 read and write operations are serialized. Extra left bits in both AndData and
1187 OrData are stripped.
1188
1189 If any reserved bits in Address are set, then ASSERT().
1190 If StartBit is greater than 31, then ASSERT().
1191 If EndBit is greater than 31, then ASSERT().
1192 If EndBit is less than StartBit, then ASSERT().
1193 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1194 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1195
1196 @param Address PCI configuration register to write.
1197 @param StartBit The ordinal of the least significant bit in the bit field.
1198 Range 0..31.
1199 @param EndBit The ordinal of the most significant bit in the bit field.
1200 Range 0..31.
1201 @param AndData The value to AND with the PCI configuration register.
1202 @param OrData The value to OR with the result of the AND operation.
1203
1204 @return The value written back to the PCI configuration register.
1205
1206 **/
1207 UINT32
1208 EFIAPI
1209 PciSegmentBitFieldAndThenOr32 (
1210 IN UINT64 Address,
1211 IN UINTN StartBit,
1212 IN UINTN EndBit,
1213 IN UINT32 AndData,
1214 IN UINT32 OrData
1215 )
1216 {
1217 return PciSegmentWrite32 (
1218 Address,
1219 BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData)
1220 );
1221 }
1222
1223 /**
1224 Reads a range of PCI configuration registers into a caller supplied buffer.
1225
1226 Reads the range of PCI configuration registers specified by StartAddress and
1227 Size into the buffer specified by Buffer. This function only allows the PCI
1228 configuration registers from a single PCI function to be read. Size is
1229 returned. When possible 32-bit PCI configuration read cycles are used to read
1230 from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
1231 and 16-bit PCI configuration read cycles may be used at the beginning and the
1232 end of the range.
1233
1234 If StartAddress > 0x0FFFFFFF, then ASSERT().
1235 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1236 If Size > 0 and Buffer is NULL, then ASSERT().
1237
1238 @param StartAddress Starting Address that encodes the PCI Segment, Bus, Device,
1239 Function and Register.
1240 @param Size Size in bytes of the transfer.
1241 @param Buffer Pointer to a buffer receiving the data read.
1242
1243 @return Size
1244
1245 **/
1246 UINTN
1247 EFIAPI
1248 PciSegmentReadBuffer (
1249 IN UINT64 StartAddress,
1250 IN UINTN Size,
1251 OUT VOID *Buffer
1252 )
1253 {
1254 UINTN ReturnValue;
1255
1256 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
1257 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1258
1259 if (Size == 0) {
1260 return Size;
1261 }
1262
1263 ASSERT (Buffer != NULL);
1264
1265 //
1266 // Save Size for return
1267 //
1268 ReturnValue = Size;
1269
1270 if ((StartAddress & 1) != 0) {
1271 //
1272 // Read a byte if StartAddress is byte aligned
1273 //
1274 *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
1275 StartAddress += sizeof (UINT8);
1276 Size -= sizeof (UINT8);
1277 Buffer = (UINT8*)Buffer + 1;
1278 }
1279
1280 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1281 //
1282 // Read a word if StartAddress is word aligned
1283 //
1284 *(volatile UINT16 *)Buffer = PciSegmentRead16 (StartAddress);
1285 StartAddress += sizeof (UINT16);
1286 Size -= sizeof (UINT16);
1287 Buffer = (UINT16*)Buffer + 1;
1288 }
1289
1290 while (Size >= sizeof (UINT32)) {
1291 //
1292 // Read as many double words as possible
1293 //
1294 *(volatile UINT32 *)Buffer = PciSegmentRead32 (StartAddress);
1295 StartAddress += sizeof (UINT32);
1296 Size -= sizeof (UINT32);
1297 Buffer = (UINT32*)Buffer + 1;
1298 }
1299
1300 if (Size >= sizeof (UINT16)) {
1301 //
1302 // Read the last remaining word if exist
1303 //
1304 *(volatile UINT16 *)Buffer = PciSegmentRead16 (StartAddress);
1305 StartAddress += sizeof (UINT16);
1306 Size -= sizeof (UINT16);
1307 Buffer = (UINT16*)Buffer + 1;
1308 }
1309
1310 if (Size >= sizeof (UINT8)) {
1311 //
1312 // Read the last remaining byte if exist
1313 //
1314 *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
1315 }
1316
1317 return ReturnValue;
1318 }
1319
1320 /**
1321 Copies the data in a caller supplied buffer to a specified range of PCI
1322 configuration space.
1323
1324 Writes the range of PCI configuration registers specified by StartAddress and
1325 Size from the buffer specified by Buffer. This function only allows the PCI
1326 configuration registers from a single PCI function to be written. Size is
1327 returned. When possible 32-bit PCI configuration write cycles are used to
1328 write from StartAdress to StartAddress + Size. Due to alignment restrictions,
1329 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1330 and the end of the range.
1331
1332 If StartAddress > 0x0FFFFFFF, then ASSERT().
1333 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1334 If Size > 0 and Buffer is NULL, then ASSERT().
1335
1336 @param StartAddress Starting Address that encodes the PCI Segment, Bus, Device,
1337 Function and Register.
1338 @param Size Size in bytes of the transfer.
1339 @param Buffer Pointer to a buffer containing the data to write.
1340
1341 @return Size
1342
1343 **/
1344 UINTN
1345 EFIAPI
1346 PciSegmentWriteBuffer (
1347 IN UINT64 StartAddress,
1348 IN UINTN Size,
1349 IN VOID *Buffer
1350 )
1351 {
1352 UINTN ReturnValue;
1353
1354 ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
1355 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1356
1357 if (Size == 0) {
1358 return 0;
1359 }
1360
1361 ASSERT (Buffer != NULL);
1362
1363 //
1364 // Save Size for return
1365 //
1366 ReturnValue = Size;
1367
1368 if ((StartAddress & 1) != 0) {
1369 //
1370 // Write a byte if StartAddress is byte aligned
1371 //
1372 PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);
1373 StartAddress += sizeof (UINT8);
1374 Size -= sizeof (UINT8);
1375 Buffer = (UINT8*)Buffer + 1;
1376 }
1377
1378 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1379 //
1380 // Write a word if StartAddress is word aligned
1381 //
1382 PciSegmentWrite16 (StartAddress, *(UINT16*)Buffer);
1383 StartAddress += sizeof (UINT16);
1384 Size -= sizeof (UINT16);
1385 Buffer = (UINT16*)Buffer + 1;
1386 }
1387
1388 while (Size >= sizeof (UINT32)) {
1389 //
1390 // Write as many double words as possible
1391 //
1392 PciSegmentWrite32 (StartAddress, *(UINT32*)Buffer);
1393 StartAddress += sizeof (UINT32);
1394 Size -= sizeof (UINT32);
1395 Buffer = (UINT32*)Buffer + 1;
1396 }
1397
1398 if (Size >= sizeof (UINT16)) {
1399 //
1400 // Write the last remaining word if exist
1401 //
1402 PciSegmentWrite16 (StartAddress, *(UINT16*)Buffer);
1403 StartAddress += sizeof (UINT16);
1404 Size -= sizeof (UINT16);
1405 Buffer = (UINT16*)Buffer + 1;
1406 }
1407
1408 if (Size >= sizeof (UINT8)) {
1409 //
1410 // Write the last remaining byte if exist
1411 //
1412 PciSegmentWrite8 (StartAddress, *(UINT8*)Buffer);
1413 }
1414
1415 return ReturnValue;
1416 }