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