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