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