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