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