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