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