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