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