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