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