]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c
MdePkg: PciExpressLib support variable size MMCONF
[mirror_edk2.git] / MdePkg / Library / DxeRuntimePciExpressLib / PciExpressLib.c
1 /** @file
2 Functions in this library instance make use of MMIO functions in IoLib to
3 access memory mapped PCI configuration space.
4
5 All assertions for I/O operations are handled in MMIO functions in the IoLib
6 Library.
7
8 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12
13
14 #include <PiDxe.h>
15
16 #include <Guid/EventGroup.h>
17
18 #include <Library/BaseLib.h>
19 #include <Library/PciExpressLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/DxeServicesTableLib.h>
26 #include <Library/UefiRuntimeLib.h>
27
28 /**
29 Assert the validity of a PCI address. A valid PCI address should contain 1's
30 only in the low 28 bits.
31
32 @param A The address to validate.
33
34 **/
35 #define ASSERT_INVALID_PCI_ADDRESS(A) \
36 ASSERT (((A) & ~0xfffffff) == 0)
37
38 ///
39 /// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime
40 ///
41 typedef struct {
42 UINTN PhysicalAddress;
43 UINTN VirtualAddress;
44 } PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE;
45
46 ///
47 /// Set Virtual Address Map Event
48 ///
49 EFI_EVENT mDxeRuntimePciExpressLibVirtualNotifyEvent = NULL;
50
51 ///
52 /// Module global that contains the base physical address and size of the PCI Express MMIO range.
53 ///
54 UINTN mDxeRuntimePciExpressLibPciExpressBaseAddress = 0;
55 UINTN mDxeRuntimePciExpressLibPciExpressBaseSize = 0;
56
57 ///
58 /// The number of PCI devices that have been registered for runtime access.
59 ///
60 UINTN mDxeRuntimePciExpressLibNumberOfRuntimeRanges = 0;
61
62 ///
63 /// The table of PCI devices that have been registered for runtime access.
64 ///
65 PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE *mDxeRuntimePciExpressLibRegistrationTable = NULL;
66
67 ///
68 /// The table index of the most recent virtual address lookup.
69 ///
70 UINTN mDxeRuntimePciExpressLibLastRuntimeRange = 0;
71
72
73 /**
74 Convert the physical PCI Express MMIO addresses for all registered PCI devices
75 to virtual addresses.
76
77 @param[in] Event The event that is being processed.
78 @param[in] Context The Event Context.
79 **/
80 VOID
81 EFIAPI
82 DxeRuntimePciExpressLibVirtualNotify (
83 IN EFI_EVENT Event,
84 IN VOID *Context
85 )
86 {
87 UINTN Index;
88
89 //
90 // If there have been no runtime registrations, then just return
91 //
92 if (mDxeRuntimePciExpressLibRegistrationTable == NULL) {
93 return;
94 }
95
96 //
97 // Convert physical addresses associated with the set of registered PCI devices to
98 // virtual addresses.
99 //
100 for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
101 EfiConvertPointer (0, (VOID **) &(mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress));
102 }
103
104 //
105 // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
106 //
107 EfiConvertPointer (0, (VOID **) &mDxeRuntimePciExpressLibRegistrationTable);
108 }
109
110 /**
111 The constructor function caches the PCI Express Base Address and creates a
112 Set Virtual Address Map event to convert physical address to virtual addresses.
113
114 @param ImageHandle The firmware allocated handle for the EFI image.
115 @param SystemTable A pointer to the EFI System Table.
116
117 @retval EFI_SUCCESS The constructor completed successfully.
118 @retval Other value The constructor did not complete successfully.
119
120 **/
121 EFI_STATUS
122 EFIAPI
123 DxeRuntimePciExpressLibConstructor (
124 IN EFI_HANDLE ImageHandle,
125 IN EFI_SYSTEM_TABLE *SystemTable
126 )
127 {
128 EFI_STATUS Status;
129
130 //
131 // Cache the physical address of the PCI Express MMIO range into a module global variable
132 //
133 mDxeRuntimePciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
134 mDxeRuntimePciExpressLibPciExpressBaseSize = (UINTN) PcdGet64 (PcdPciExpressBaseSize);
135
136 //
137 // Register SetVirtualAddressMap () notify function
138 //
139 Status = gBS->CreateEvent (
140 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
141 TPL_NOTIFY,
142 DxeRuntimePciExpressLibVirtualNotify,
143 NULL,
144 &mDxeRuntimePciExpressLibVirtualNotifyEvent
145 );
146 ASSERT_EFI_ERROR (Status);
147
148 return Status;
149 }
150
151 /**
152 The destructor function frees any allocated buffers and closes the Set Virtual
153 Address Map event.
154
155 @param ImageHandle The firmware allocated handle for the EFI image.
156 @param SystemTable A pointer to the EFI System Table.
157
158 @retval EFI_SUCCESS The destructor completed successfully.
159 @retval Other value The destructor did not complete successfully.
160
161 **/
162 EFI_STATUS
163 EFIAPI
164 DxeRuntimePciExpressLibDestructor (
165 IN EFI_HANDLE ImageHandle,
166 IN EFI_SYSTEM_TABLE *SystemTable
167 )
168 {
169 EFI_STATUS Status;
170
171 //
172 // If one or more PCI devices have been registered for runtime access, then
173 // free the registration table.
174 //
175 if (mDxeRuntimePciExpressLibRegistrationTable != NULL) {
176 FreePool (mDxeRuntimePciExpressLibRegistrationTable);
177 }
178
179 //
180 // Close the Set Virtual Address Map event
181 //
182 Status = gBS->CloseEvent (mDxeRuntimePciExpressLibVirtualNotifyEvent);
183 ASSERT_EFI_ERROR (Status);
184
185 return Status;
186 }
187
188 /**
189 Gets the base address of PCI Express.
190
191 This internal functions retrieves PCI Express Base Address via a PCD entry
192 PcdPciExpressBaseAddress.
193
194 If Address > 0x0FFFFFFF, then ASSERT().
195
196 @param Address The address that encodes the PCI Bus, Device, Function and Register.
197
198 @retval (UINTN)-1 Invalid PCI address.
199 @retval other The base address of PCI Express.
200
201 **/
202 UINTN
203 GetPciExpressAddress (
204 IN UINTN Address
205 )
206 {
207 UINTN Index;
208
209 //
210 // Make sure Address is valid
211 //
212 ASSERT_INVALID_PCI_ADDRESS (Address);
213
214 //
215 // Make sure the Address is in MMCONF address space
216 //
217 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
218 return (UINTN) -1;
219 }
220
221 //
222 // Convert Address to a physical address in the MMIO PCI Express range
223 //
224 Address += mDxeRuntimePciExpressLibPciExpressBaseAddress;
225
226 //
227 // If SetVirtualAddressMap() has not been called, then just return the physical address
228 //
229 if (!EfiGoneVirtual ()) {
230 return Address;
231 }
232
233 //
234 // See if there is a physical address match at the exact same index as the last address match
235 //
236 if (mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].PhysicalAddress == (Address & (~0x00000fff))) {
237 //
238 // Convert the physical address to a virtual address and return the virtual address
239 //
240 return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibLastRuntimeRange].VirtualAddress;
241 }
242
243 //
244 // Search the entire table for a physical address match
245 //
246 for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
247 if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == (Address & (~0x00000fff))) {
248 //
249 // Cache the matching index value
250 //
251 mDxeRuntimePciExpressLibLastRuntimeRange = Index;
252 //
253 // Convert the physical address to a virtual address and return the virtual address
254 //
255 return (Address & 0x00000fff) + mDxeRuntimePciExpressLibRegistrationTable[Index].VirtualAddress;
256 }
257 }
258
259 //
260 // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
261 //
262 CpuBreakpoint();
263
264 //
265 // Return the physical address
266 //
267 return Address;
268 }
269
270 /**
271 Registers a PCI device so PCI configuration registers may be accessed after
272 SetVirtualAddressMap().
273
274 Registers the PCI device specified by Address so all the PCI configuration
275 registers associated with that PCI device may be accessed after SetVirtualAddressMap()
276 is called.
277
278 If Address > 0x0FFFFFFF, then ASSERT().
279
280 @param Address The address that encodes the PCI Bus, Device, Function and
281 Register.
282
283 @retval RETURN_SUCCESS The PCI device was registered for runtime access.
284 @retval RETURN_UNSUPPORTED An attempt was made to call this function
285 after ExitBootServices().
286 @retval RETURN_UNSUPPORTED The resources required to access the PCI device
287 at runtime could not be mapped.
288 @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
289 complete the registration.
290
291 **/
292 RETURN_STATUS
293 EFIAPI
294 PciExpressRegisterForRuntimeAccess (
295 IN UINTN Address
296 )
297 {
298 EFI_STATUS Status;
299 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
300 UINTN Index;
301 VOID *NewTable;
302
303 //
304 // Return an error if this function is called after ExitBootServices().
305 //
306 if (EfiAtRuntime ()) {
307 return RETURN_UNSUPPORTED;
308 }
309
310 //
311 // Make sure Address is valid
312 //
313 ASSERT_INVALID_PCI_ADDRESS (Address);
314
315 //
316 // Make sure the Address is in MMCONF address space
317 //
318 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
319 return RETURN_UNSUPPORTED;
320 }
321
322 //
323 // Convert Address to a physical address in the MMIO PCI Express range
324 // at the beginning of the PCI Configuration header for the specified
325 // PCI Bus/Dev/Func
326 //
327 Address = GetPciExpressAddress (Address & 0x0ffff000);
328
329 //
330 // See if Address has already been registered for runtime access
331 //
332 for (Index = 0; Index < mDxeRuntimePciExpressLibNumberOfRuntimeRanges; Index++) {
333 if (mDxeRuntimePciExpressLibRegistrationTable[Index].PhysicalAddress == Address) {
334 return RETURN_SUCCESS;
335 }
336 }
337
338 //
339 // Get the GCD Memory Descriptor for the PCI Express Bus/Dev/Func specified by Address
340 //
341 Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
342 if (EFI_ERROR (Status)) {
343 return RETURN_UNSUPPORTED;
344 }
345
346 //
347 // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
348 // will allocate a virtual address range for the 4KB PCI Configuration Header.
349 //
350 Status = gDS->SetMemorySpaceAttributes (Address, 0x1000, Descriptor.Attributes | EFI_MEMORY_RUNTIME);
351 if (EFI_ERROR (Status)) {
352 return RETURN_UNSUPPORTED;
353 }
354
355 //
356 // Grow the size of the registration table
357 //
358 NewTable = ReallocateRuntimePool (
359 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 0) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE),
360 (mDxeRuntimePciExpressLibNumberOfRuntimeRanges + 1) * sizeof (PCI_EXPRESS_RUNTIME_REGISTRATION_TABLE),
361 mDxeRuntimePciExpressLibRegistrationTable
362 );
363 if (NewTable == NULL) {
364 return RETURN_OUT_OF_RESOURCES;
365 }
366 mDxeRuntimePciExpressLibRegistrationTable = NewTable;
367 mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].PhysicalAddress = Address;
368 mDxeRuntimePciExpressLibRegistrationTable[mDxeRuntimePciExpressLibNumberOfRuntimeRanges].VirtualAddress = Address;
369 mDxeRuntimePciExpressLibNumberOfRuntimeRanges++;
370
371 return RETURN_SUCCESS;
372 }
373
374
375 /**
376 Reads an 8-bit PCI configuration register.
377
378 Reads and returns the 8-bit PCI configuration register specified by Address.
379 This function must guarantee that all PCI read and write operations are
380 serialized.
381
382 If Address > 0x0FFFFFFF, then ASSERT().
383
384 @param Address The address that encodes the PCI Bus, Device, Function and
385 Register.
386 @retval 0xFF Invalid PCI address.
387 @retval other The read value from the PCI configuration register.
388
389 **/
390 UINT8
391 EFIAPI
392 PciExpressRead8 (
393 IN UINTN Address
394 )
395 {
396 ASSERT_INVALID_PCI_ADDRESS (Address);
397 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
398 return (UINT8) -1;
399 }
400 return MmioRead8 (GetPciExpressAddress (Address));
401 }
402
403 /**
404 Writes an 8-bit PCI configuration register.
405
406 Writes the 8-bit PCI configuration register specified by Address with the
407 value specified by Value. Value is returned. This function must guarantee
408 that all PCI read and write operations are serialized.
409
410 If Address > 0x0FFFFFFF, then ASSERT().
411
412 @param Address The address that encodes the PCI Bus, Device, Function and
413 Register.
414 @param Value The value to write.
415
416 @retval 0xFF Invalid PCI address.
417 @retval other The value written to the PCI configuration register.
418
419 **/
420 UINT8
421 EFIAPI
422 PciExpressWrite8 (
423 IN UINTN Address,
424 IN UINT8 Value
425 )
426 {
427 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
428 return (UINT8) -1;
429 }
430 return MmioWrite8 (GetPciExpressAddress (Address), Value);
431 }
432
433 /**
434 Performs a bitwise OR of an 8-bit PCI configuration register with
435 an 8-bit value.
436
437 Reads the 8-bit PCI configuration register specified by Address, performs a
438 bitwise OR between the read result and the value specified by
439 OrData, and writes the result to the 8-bit PCI configuration register
440 specified by Address. The value written to the PCI configuration register is
441 returned. This function must guarantee that all PCI read and write operations
442 are serialized.
443
444 If Address > 0x0FFFFFFF, then ASSERT().
445
446 @param Address The address that encodes the PCI Bus, Device, Function and
447 Register.
448 @param OrData The value to OR with the PCI configuration register.
449
450 @retval 0xFF Invalid PCI address.
451 @retval other The value written back to the PCI configuration register.
452
453 **/
454 UINT8
455 EFIAPI
456 PciExpressOr8 (
457 IN UINTN Address,
458 IN UINT8 OrData
459 )
460 {
461 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
462 return (UINT8) -1;
463 }
464 return MmioOr8 (GetPciExpressAddress (Address), OrData);
465 }
466
467 /**
468 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
469 value.
470
471 Reads the 8-bit PCI configuration register specified by Address, performs a
472 bitwise AND between the read result and the value specified by AndData, and
473 writes the result to the 8-bit PCI configuration register specified by
474 Address. The value written to the PCI configuration register is returned.
475 This function must guarantee that all PCI read and write operations are
476 serialized.
477
478 If Address > 0x0FFFFFFF, then ASSERT().
479
480 @param Address The address that encodes the PCI Bus, Device, Function and
481 Register.
482 @param AndData The value to AND with the PCI configuration register.
483
484 @retval 0xFF Invalid PCI address.
485 @retval other The value written back to the PCI configuration register.
486
487 **/
488 UINT8
489 EFIAPI
490 PciExpressAnd8 (
491 IN UINTN Address,
492 IN UINT8 AndData
493 )
494 {
495 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
496 return (UINT8) -1;
497 }
498 return MmioAnd8 (GetPciExpressAddress (Address), AndData);
499 }
500
501 /**
502 Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
503 value, followed a bitwise OR with another 8-bit value.
504
505 Reads the 8-bit PCI configuration register specified by Address, performs a
506 bitwise AND between the read result and the value specified by AndData,
507 performs a bitwise OR between the result of the AND operation and
508 the value specified by OrData, and writes the result to the 8-bit PCI
509 configuration register specified by Address. The value written to the PCI
510 configuration register is returned. This function must guarantee that all PCI
511 read and write operations are serialized.
512
513 If Address > 0x0FFFFFFF, then ASSERT().
514
515 @param Address The address that encodes the PCI Bus, Device, Function and
516 Register.
517 @param AndData The value to AND with the PCI configuration register.
518 @param OrData The value to OR with the result of the AND operation.
519
520 @retval 0xFF Invalid PCI address.
521 @retval other The value written back to the PCI configuration register.
522
523 **/
524 UINT8
525 EFIAPI
526 PciExpressAndThenOr8 (
527 IN UINTN Address,
528 IN UINT8 AndData,
529 IN UINT8 OrData
530 )
531 {
532 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
533 return (UINT8) -1;
534 }
535 return MmioAndThenOr8 (
536 GetPciExpressAddress (Address),
537 AndData,
538 OrData
539 );
540 }
541
542 /**
543 Reads a bit field of a PCI configuration register.
544
545 Reads the bit field in an 8-bit PCI configuration register. The bit field is
546 specified by the StartBit and the EndBit. The value of the bit field is
547 returned.
548
549 If Address > 0x0FFFFFFF, then ASSERT().
550 If StartBit is greater than 7, then ASSERT().
551 If EndBit is greater than 7, then ASSERT().
552 If EndBit is less than StartBit, then ASSERT().
553
554 @param Address The PCI configuration register to read.
555 @param StartBit The ordinal of the least significant bit in the bit field.
556 Range 0..7.
557 @param EndBit The ordinal of the most significant bit in the bit field.
558 Range 0..7.
559
560 @retval 0xFF Invalid PCI address.
561 @retval other The value of the bit field read from the PCI configuration register.
562
563 **/
564 UINT8
565 EFIAPI
566 PciExpressBitFieldRead8 (
567 IN UINTN Address,
568 IN UINTN StartBit,
569 IN UINTN EndBit
570 )
571 {
572 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
573 return (UINT8) -1;
574 }
575 return MmioBitFieldRead8 (
576 GetPciExpressAddress (Address),
577 StartBit,
578 EndBit
579 );
580 }
581
582 /**
583 Writes a bit field to a PCI configuration register.
584
585 Writes Value to the bit field of the PCI configuration register. The bit
586 field is specified by the StartBit and the EndBit. All other bits in the
587 destination PCI configuration register are preserved. The new value of the
588 8-bit register is returned.
589
590 If Address > 0x0FFFFFFF, then ASSERT().
591 If StartBit is greater than 7, then ASSERT().
592 If EndBit is greater than 7, then ASSERT().
593 If EndBit is less than StartBit, then ASSERT().
594 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
595
596 @param Address The PCI configuration register to write.
597 @param StartBit The ordinal of the least significant bit in the bit field.
598 Range 0..7.
599 @param EndBit The ordinal of the most significant bit in the bit field.
600 Range 0..7.
601 @param Value The new value of the bit field.
602
603 @retval 0xFF Invalid PCI address.
604 @retval other The value written back to the PCI configuration register.
605
606 **/
607 UINT8
608 EFIAPI
609 PciExpressBitFieldWrite8 (
610 IN UINTN Address,
611 IN UINTN StartBit,
612 IN UINTN EndBit,
613 IN UINT8 Value
614 )
615 {
616 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
617 return (UINT8) -1;
618 }
619 return MmioBitFieldWrite8 (
620 GetPciExpressAddress (Address),
621 StartBit,
622 EndBit,
623 Value
624 );
625 }
626
627 /**
628 Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
629 writes the result back to the bit field in the 8-bit port.
630
631 Reads the 8-bit PCI configuration register specified by Address, performs a
632 bitwise OR between the read result and the value specified by
633 OrData, and writes the result to the 8-bit PCI configuration register
634 specified by Address. The value written to the PCI configuration register is
635 returned. This function must guarantee that all PCI read and write operations
636 are serialized. Extra left bits in OrData are stripped.
637
638 If Address > 0x0FFFFFFF, then ASSERT().
639 If StartBit is greater than 7, then ASSERT().
640 If EndBit is greater than 7, then ASSERT().
641 If EndBit is less than StartBit, then ASSERT().
642 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
643
644 @param Address The PCI configuration register to write.
645 @param StartBit The ordinal of the least significant bit in the bit field.
646 Range 0..7.
647 @param EndBit The ordinal of the most significant bit in the bit field.
648 Range 0..7.
649 @param OrData The value to OR with the PCI configuration register.
650
651 @retval 0xFF Invalid PCI address.
652 @retval other The value written back to the PCI configuration register.
653
654 **/
655 UINT8
656 EFIAPI
657 PciExpressBitFieldOr8 (
658 IN UINTN Address,
659 IN UINTN StartBit,
660 IN UINTN EndBit,
661 IN UINT8 OrData
662 )
663 {
664 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
665 return (UINT8) -1;
666 }
667 return MmioBitFieldOr8 (
668 GetPciExpressAddress (Address),
669 StartBit,
670 EndBit,
671 OrData
672 );
673 }
674
675 /**
676 Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
677 AND, and writes the result back to the bit field in the 8-bit register.
678
679 Reads the 8-bit PCI configuration register specified by Address, performs a
680 bitwise AND between the read result and the value specified by AndData, and
681 writes the result to the 8-bit PCI configuration register specified by
682 Address. The value written to the PCI configuration register is returned.
683 This function must guarantee that all PCI read and write operations are
684 serialized. Extra left bits in AndData are stripped.
685
686 If Address > 0x0FFFFFFF, then ASSERT().
687 If StartBit is greater than 7, then ASSERT().
688 If EndBit is greater than 7, then ASSERT().
689 If EndBit is less than StartBit, then ASSERT().
690 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
691
692 @param Address The PCI configuration register to write.
693 @param StartBit The ordinal of the least significant bit in the bit field.
694 Range 0..7.
695 @param EndBit The ordinal of the most significant bit in the bit field.
696 Range 0..7.
697 @param AndData The value to AND with the PCI configuration register.
698
699 @retval 0xFF Invalid PCI address.
700 @retval other The value written back to the PCI configuration register.
701
702 **/
703 UINT8
704 EFIAPI
705 PciExpressBitFieldAnd8 (
706 IN UINTN Address,
707 IN UINTN StartBit,
708 IN UINTN EndBit,
709 IN UINT8 AndData
710 )
711 {
712 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
713 return (UINT8) -1;
714 }
715 return MmioBitFieldAnd8 (
716 GetPciExpressAddress (Address),
717 StartBit,
718 EndBit,
719 AndData
720 );
721 }
722
723 /**
724 Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
725 bitwise OR, and writes the result back to the bit field in the
726 8-bit port.
727
728 Reads the 8-bit PCI configuration register specified by Address, performs a
729 bitwise AND followed by a bitwise OR between the read result and
730 the value specified by AndData, and writes the result to the 8-bit PCI
731 configuration register specified by Address. The value written to the PCI
732 configuration register is returned. This function must guarantee that all PCI
733 read and write operations are serialized. Extra left bits in both AndData and
734 OrData are stripped.
735
736 If Address > 0x0FFFFFFF, then ASSERT().
737 If StartBit is greater than 7, then ASSERT().
738 If EndBit is greater than 7, then ASSERT().
739 If EndBit is less than StartBit, then ASSERT().
740 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
741 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
742
743 @param Address The PCI configuration register to write.
744 @param StartBit The ordinal of the least significant bit in the bit field.
745 Range 0..7.
746 @param EndBit The ordinal of the most significant bit in the bit field.
747 Range 0..7.
748 @param AndData The value to AND with the PCI configuration register.
749 @param OrData The value to OR with the result of the AND operation.
750
751 @retval 0xFF Invalid PCI address.
752 @retval other The value written back to the PCI configuration register.
753
754 **/
755 UINT8
756 EFIAPI
757 PciExpressBitFieldAndThenOr8 (
758 IN UINTN Address,
759 IN UINTN StartBit,
760 IN UINTN EndBit,
761 IN UINT8 AndData,
762 IN UINT8 OrData
763 )
764 {
765 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
766 return (UINT8) -1;
767 }
768 return MmioBitFieldAndThenOr8 (
769 GetPciExpressAddress (Address),
770 StartBit,
771 EndBit,
772 AndData,
773 OrData
774 );
775 }
776
777 /**
778 Reads a 16-bit PCI configuration register.
779
780 Reads and returns the 16-bit PCI configuration register specified by Address.
781 This function must guarantee that all PCI read and write operations are
782 serialized.
783
784 If Address > 0x0FFFFFFF, then ASSERT().
785 If Address is not aligned on a 16-bit boundary, then ASSERT().
786
787 @param Address The address that encodes the PCI Bus, Device, Function and
788 Register.
789
790 @retval 0xFFFF Invalid PCI address.
791 @retval other The read value from the PCI configuration register.
792
793 **/
794 UINT16
795 EFIAPI
796 PciExpressRead16 (
797 IN UINTN Address
798 )
799 {
800 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
801 return (UINT16) -1;
802 }
803 return MmioRead16 (GetPciExpressAddress (Address));
804 }
805
806 /**
807 Writes a 16-bit PCI configuration register.
808
809 Writes the 16-bit PCI configuration register specified by Address with the
810 value specified by Value. Value is returned. This function must guarantee
811 that all PCI read and write operations are serialized.
812
813 If Address > 0x0FFFFFFF, then ASSERT().
814 If Address is not aligned on a 16-bit boundary, then ASSERT().
815
816 @param Address The address that encodes the PCI Bus, Device, Function and
817 Register.
818 @param Value The value to write.
819
820 @retval 0xFFFF Invalid PCI address.
821 @retval other The value written to the PCI configuration register.
822
823 **/
824 UINT16
825 EFIAPI
826 PciExpressWrite16 (
827 IN UINTN Address,
828 IN UINT16 Value
829 )
830 {
831 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
832 return (UINT16) -1;
833 }
834 return MmioWrite16 (GetPciExpressAddress (Address), Value);
835 }
836
837 /**
838 Performs a bitwise OR of a 16-bit PCI configuration register with
839 a 16-bit value.
840
841 Reads the 16-bit PCI configuration register specified by Address, performs a
842 bitwise OR between the read result and the value specified by
843 OrData, and writes the result to the 16-bit PCI configuration register
844 specified by Address. The value written to the PCI configuration register is
845 returned. This function must guarantee that all PCI read and write operations
846 are serialized.
847
848 If Address > 0x0FFFFFFF, then ASSERT().
849 If Address is not aligned on a 16-bit boundary, then ASSERT().
850
851 @param Address The address that encodes the PCI Bus, Device, Function and
852 Register.
853 @param OrData The value to OR with the PCI configuration register.
854
855 @retval 0xFFFF Invalid PCI address.
856 @retval other The value written back to the PCI configuration register.
857
858 **/
859 UINT16
860 EFIAPI
861 PciExpressOr16 (
862 IN UINTN Address,
863 IN UINT16 OrData
864 )
865 {
866 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
867 return (UINT16) -1;
868 }
869 return MmioOr16 (GetPciExpressAddress (Address), OrData);
870 }
871
872 /**
873 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
874 value.
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.
882
883 If Address > 0x0FFFFFFF, then ASSERT().
884 If Address is not aligned on a 16-bit boundary, then ASSERT().
885
886 @param Address The address that encodes the PCI Bus, Device, Function and
887 Register.
888 @param AndData The value to AND with the PCI configuration register.
889
890 @retval 0xFFFF Invalid PCI address.
891 @retval other The value written back to the PCI configuration register.
892
893 **/
894 UINT16
895 EFIAPI
896 PciExpressAnd16 (
897 IN UINTN Address,
898 IN UINT16 AndData
899 )
900 {
901 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
902 return (UINT16) -1;
903 }
904 return MmioAnd16 (GetPciExpressAddress (Address), AndData);
905 }
906
907 /**
908 Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
909 value, followed a bitwise OR with another 16-bit value.
910
911 Reads the 16-bit PCI configuration register specified by Address, performs a
912 bitwise AND between the read result and the value specified by AndData,
913 performs a bitwise OR between the result of the AND operation and
914 the value specified by OrData, and writes the result to the 16-bit PCI
915 configuration register specified by Address. The value written to the PCI
916 configuration register is returned. This function must guarantee that all PCI
917 read and write operations are serialized.
918
919 If Address > 0x0FFFFFFF, then ASSERT().
920 If Address is not aligned on a 16-bit boundary, then ASSERT().
921
922 @param Address The address that encodes the PCI Bus, Device, Function and
923 Register.
924 @param AndData The value to AND with the PCI configuration register.
925 @param OrData The value to OR with the result of the AND operation.
926
927 @retval 0xFFFF Invalid PCI address.
928 @retval other The value written back to the PCI configuration register.
929
930 **/
931 UINT16
932 EFIAPI
933 PciExpressAndThenOr16 (
934 IN UINTN Address,
935 IN UINT16 AndData,
936 IN UINT16 OrData
937 )
938 {
939 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
940 return (UINT16) -1;
941 }
942 return MmioAndThenOr16 (
943 GetPciExpressAddress (Address),
944 AndData,
945 OrData
946 );
947 }
948
949 /**
950 Reads a bit field of a PCI configuration register.
951
952 Reads the bit field in a 16-bit PCI configuration register. The bit field is
953 specified by the StartBit and the EndBit. The value of the bit field is
954 returned.
955
956 If Address > 0x0FFFFFFF, then ASSERT().
957 If Address is not aligned on a 16-bit boundary, then ASSERT().
958 If StartBit is greater than 15, then ASSERT().
959 If EndBit is greater than 15, then ASSERT().
960 If EndBit is less than StartBit, then ASSERT().
961
962 @param Address The PCI configuration register to read.
963 @param StartBit The ordinal of the least significant bit in the bit field.
964 Range 0..15.
965 @param EndBit The ordinal of the most significant bit in the bit field.
966 Range 0..15.
967
968 @retval 0xFFFF Invalid PCI address.
969 @retval other The value of the bit field read from the PCI configuration register.
970
971 **/
972 UINT16
973 EFIAPI
974 PciExpressBitFieldRead16 (
975 IN UINTN Address,
976 IN UINTN StartBit,
977 IN UINTN EndBit
978 )
979 {
980 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
981 return (UINT16) -1;
982 }
983 return MmioBitFieldRead16 (
984 GetPciExpressAddress (Address),
985 StartBit,
986 EndBit
987 );
988 }
989
990 /**
991 Writes a bit field to a PCI configuration register.
992
993 Writes Value to the bit field of the PCI configuration register. The bit
994 field is specified by the StartBit and the EndBit. All other bits in the
995 destination PCI configuration register are preserved. The new value of the
996 16-bit register is returned.
997
998 If Address > 0x0FFFFFFF, then ASSERT().
999 If Address is not aligned on a 16-bit boundary, then ASSERT().
1000 If StartBit is greater than 15, then ASSERT().
1001 If EndBit is greater than 15, then ASSERT().
1002 If EndBit is less than StartBit, then ASSERT().
1003 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1004
1005 @param Address The PCI configuration register to write.
1006 @param StartBit The ordinal of the least significant bit in the bit field.
1007 Range 0..15.
1008 @param EndBit The ordinal of the most significant bit in the bit field.
1009 Range 0..15.
1010 @param Value The new value of the bit field.
1011
1012 @retval 0xFFFF Invalid PCI address.
1013 @retval other The value written back to the PCI configuration register.
1014
1015 **/
1016 UINT16
1017 EFIAPI
1018 PciExpressBitFieldWrite16 (
1019 IN UINTN Address,
1020 IN UINTN StartBit,
1021 IN UINTN EndBit,
1022 IN UINT16 Value
1023 )
1024 {
1025 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1026 return (UINT16) -1;
1027 }
1028 return MmioBitFieldWrite16 (
1029 GetPciExpressAddress (Address),
1030 StartBit,
1031 EndBit,
1032 Value
1033 );
1034 }
1035
1036 /**
1037 Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
1038 writes the result back to the bit field in the 16-bit port.
1039
1040 Reads the 16-bit PCI configuration register specified by Address, performs a
1041 bitwise OR between the read result and the value specified by
1042 OrData, and writes the result to the 16-bit PCI configuration register
1043 specified by Address. The value written to the PCI configuration register is
1044 returned. This function must guarantee that all PCI read and write operations
1045 are serialized. Extra left bits in OrData are stripped.
1046
1047 If Address > 0x0FFFFFFF, then ASSERT().
1048 If Address is not aligned on a 16-bit boundary, then ASSERT().
1049 If StartBit is greater than 15, then ASSERT().
1050 If EndBit is greater than 15, then ASSERT().
1051 If EndBit is less than StartBit, then ASSERT().
1052 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1053
1054 @param Address The PCI configuration register to write.
1055 @param StartBit The ordinal of the least significant bit in the bit field.
1056 Range 0..15.
1057 @param EndBit The ordinal of the most significant bit in the bit field.
1058 Range 0..15.
1059 @param OrData The value to OR with the PCI configuration register.
1060
1061 @retval 0xFFFF Invalid PCI address.
1062 @retval other The value written back to the PCI configuration register.
1063
1064 **/
1065 UINT16
1066 EFIAPI
1067 PciExpressBitFieldOr16 (
1068 IN UINTN Address,
1069 IN UINTN StartBit,
1070 IN UINTN EndBit,
1071 IN UINT16 OrData
1072 )
1073 {
1074 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1075 return (UINT16) -1;
1076 }
1077 return MmioBitFieldOr16 (
1078 GetPciExpressAddress (Address),
1079 StartBit,
1080 EndBit,
1081 OrData
1082 );
1083 }
1084
1085 /**
1086 Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
1087 AND, and writes the result back to the bit field in the 16-bit register.
1088
1089 Reads the 16-bit PCI configuration register specified by Address, performs a
1090 bitwise AND between the read result and the value specified by AndData, and
1091 writes the result to the 16-bit PCI configuration register specified by
1092 Address. The value written to the PCI configuration register is returned.
1093 This function must guarantee that all PCI read and write operations are
1094 serialized. Extra left bits in AndData are stripped.
1095
1096 If Address > 0x0FFFFFFF, then ASSERT().
1097 If Address is not aligned on a 16-bit boundary, then ASSERT().
1098 If StartBit is greater than 15, then ASSERT().
1099 If EndBit is greater than 15, then ASSERT().
1100 If EndBit is less than StartBit, then ASSERT().
1101 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1102
1103 @param Address The PCI configuration register to write.
1104 @param StartBit The ordinal of the least significant bit in the bit field.
1105 Range 0..15.
1106 @param EndBit The ordinal of the most significant bit in the bit field.
1107 Range 0..15.
1108 @param AndData The value to AND with the PCI configuration register.
1109
1110 @retval 0xFFFF Invalid PCI address.
1111 @retval other The value written back to the PCI configuration register.
1112
1113 **/
1114 UINT16
1115 EFIAPI
1116 PciExpressBitFieldAnd16 (
1117 IN UINTN Address,
1118 IN UINTN StartBit,
1119 IN UINTN EndBit,
1120 IN UINT16 AndData
1121 )
1122 {
1123 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1124 return (UINT16) -1;
1125 }
1126 return MmioBitFieldAnd16 (
1127 GetPciExpressAddress (Address),
1128 StartBit,
1129 EndBit,
1130 AndData
1131 );
1132 }
1133
1134 /**
1135 Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
1136 bitwise OR, and writes the result back to the bit field in the
1137 16-bit port.
1138
1139 Reads the 16-bit PCI configuration register specified by Address, performs a
1140 bitwise AND followed by a bitwise OR between the read result and
1141 the value specified by AndData, and writes the result to the 16-bit PCI
1142 configuration register specified by Address. The value written to the PCI
1143 configuration register is returned. This function must guarantee that all PCI
1144 read and write operations are serialized. Extra left bits in both AndData and
1145 OrData are stripped.
1146
1147 If Address > 0x0FFFFFFF, then ASSERT().
1148 If Address is not aligned on a 16-bit boundary, then ASSERT().
1149 If StartBit is greater than 15, then ASSERT().
1150 If EndBit is greater than 15, then ASSERT().
1151 If EndBit is less than StartBit, then ASSERT().
1152 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1153 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1154
1155 @param Address The PCI configuration register to write.
1156 @param StartBit The ordinal of the least significant bit in the bit field.
1157 Range 0..15.
1158 @param EndBit The ordinal of the most significant bit in the bit field.
1159 Range 0..15.
1160 @param AndData The value to AND with the PCI configuration register.
1161 @param OrData The value to OR with the result of the AND operation.
1162
1163 @retval 0xFFFF Invalid PCI address.
1164 @retval other The value written back to the PCI configuration register.
1165
1166 **/
1167 UINT16
1168 EFIAPI
1169 PciExpressBitFieldAndThenOr16 (
1170 IN UINTN Address,
1171 IN UINTN StartBit,
1172 IN UINTN EndBit,
1173 IN UINT16 AndData,
1174 IN UINT16 OrData
1175 )
1176 {
1177 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1178 return (UINT16) -1;
1179 }
1180 return MmioBitFieldAndThenOr16 (
1181 GetPciExpressAddress (Address),
1182 StartBit,
1183 EndBit,
1184 AndData,
1185 OrData
1186 );
1187 }
1188
1189 /**
1190 Reads a 32-bit PCI configuration register.
1191
1192 Reads and returns the 32-bit PCI configuration register specified by Address.
1193 This function must guarantee that all PCI read and write operations are
1194 serialized.
1195
1196 If Address > 0x0FFFFFFF, then ASSERT().
1197 If Address is not aligned on a 32-bit boundary, then ASSERT().
1198
1199 @param Address The address that encodes the PCI Bus, Device, Function and
1200 Register.
1201
1202 @retval 0xFFFF Invalid PCI address.
1203 @retval other The read value from the PCI configuration register.
1204
1205 **/
1206 UINT32
1207 EFIAPI
1208 PciExpressRead32 (
1209 IN UINTN Address
1210 )
1211 {
1212 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1213 return (UINT32) -1;
1214 }
1215 return MmioRead32 (GetPciExpressAddress (Address));
1216 }
1217
1218 /**
1219 Writes a 32-bit PCI configuration register.
1220
1221 Writes the 32-bit PCI configuration register specified by Address with the
1222 value specified by Value. Value is returned. This function must guarantee
1223 that all PCI read and write operations are serialized.
1224
1225 If Address > 0x0FFFFFFF, then ASSERT().
1226 If Address is not aligned on a 32-bit boundary, then ASSERT().
1227
1228 @param Address The address that encodes the PCI Bus, Device, Function and
1229 Register.
1230 @param Value The value to write.
1231
1232 @retval 0xFFFFFFFF Invalid PCI address.
1233 @retval other The value written to the PCI configuration register.
1234
1235 **/
1236 UINT32
1237 EFIAPI
1238 PciExpressWrite32 (
1239 IN UINTN Address,
1240 IN UINT32 Value
1241 )
1242 {
1243 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1244 return (UINT32) -1;
1245 }
1246 return MmioWrite32 (GetPciExpressAddress (Address), Value);
1247 }
1248
1249 /**
1250 Performs a bitwise OR of a 32-bit PCI configuration register with
1251 a 32-bit value.
1252
1253 Reads the 32-bit PCI configuration register specified by Address, performs a
1254 bitwise OR between the read result and the value specified by
1255 OrData, and writes the result to the 32-bit PCI configuration register
1256 specified by Address. The value written to the PCI configuration register is
1257 returned. This function must guarantee that all PCI read and write operations
1258 are serialized.
1259
1260 If Address > 0x0FFFFFFF, then ASSERT().
1261 If Address is not aligned on a 32-bit boundary, then ASSERT().
1262
1263 @param Address The address that encodes the PCI Bus, Device, Function and
1264 Register.
1265 @param OrData The value to OR with the PCI configuration register.
1266
1267 @retval 0xFFFFFFFF Invalid PCI address.
1268 @retval other The value written back to the PCI configuration register.
1269
1270 **/
1271 UINT32
1272 EFIAPI
1273 PciExpressOr32 (
1274 IN UINTN Address,
1275 IN UINT32 OrData
1276 )
1277 {
1278 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1279 return (UINT32) -1;
1280 }
1281 return MmioOr32 (GetPciExpressAddress (Address), OrData);
1282 }
1283
1284 /**
1285 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1286 value.
1287
1288 Reads the 32-bit PCI configuration register specified by Address, performs a
1289 bitwise AND between the read result and the value specified by AndData, and
1290 writes the result to the 32-bit PCI configuration register specified by
1291 Address. The value written to the PCI configuration register is returned.
1292 This function must guarantee that all PCI read and write operations are
1293 serialized.
1294
1295 If Address > 0x0FFFFFFF, then ASSERT().
1296 If Address is not aligned on a 32-bit boundary, then ASSERT().
1297
1298 @param Address The address that encodes the PCI Bus, Device, Function and
1299 Register.
1300 @param AndData The value to AND with the PCI configuration register.
1301
1302 @retval 0xFFFFFFFF Invalid PCI address.
1303 @retval other The value written back to the PCI configuration register.
1304
1305 **/
1306 UINT32
1307 EFIAPI
1308 PciExpressAnd32 (
1309 IN UINTN Address,
1310 IN UINT32 AndData
1311 )
1312 {
1313 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1314 return (UINT32) -1;
1315 }
1316 return MmioAnd32 (GetPciExpressAddress (Address), AndData);
1317 }
1318
1319 /**
1320 Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
1321 value, followed a bitwise OR with another 32-bit value.
1322
1323 Reads the 32-bit PCI configuration register specified by Address, performs a
1324 bitwise AND between the read result and the value specified by AndData,
1325 performs a bitwise OR between the result of the AND operation and
1326 the value specified by OrData, and writes the result to the 32-bit PCI
1327 configuration register specified by Address. The value written to the PCI
1328 configuration register is returned. This function must guarantee that all PCI
1329 read and write operations are serialized.
1330
1331 If Address > 0x0FFFFFFF, then ASSERT().
1332 If Address is not aligned on a 32-bit boundary, then ASSERT().
1333
1334 @param Address The address that encodes the PCI Bus, Device, Function and
1335 Register.
1336 @param AndData The value to AND with the PCI configuration register.
1337 @param OrData The value to OR with the result of the AND operation.
1338
1339 @retval 0xFFFFFFFF Invalid PCI address.
1340 @retval other The value written back to the PCI configuration register.
1341
1342 **/
1343 UINT32
1344 EFIAPI
1345 PciExpressAndThenOr32 (
1346 IN UINTN Address,
1347 IN UINT32 AndData,
1348 IN UINT32 OrData
1349 )
1350 {
1351 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1352 return (UINT32) -1;
1353 }
1354 return MmioAndThenOr32 (
1355 GetPciExpressAddress (Address),
1356 AndData,
1357 OrData
1358 );
1359 }
1360
1361 /**
1362 Reads a bit field of a PCI configuration register.
1363
1364 Reads the bit field in a 32-bit PCI configuration register. The bit field is
1365 specified by the StartBit and the EndBit. The value of the bit field is
1366 returned.
1367
1368 If Address > 0x0FFFFFFF, then ASSERT().
1369 If Address is not aligned on a 32-bit boundary, then ASSERT().
1370 If StartBit is greater than 31, then ASSERT().
1371 If EndBit is greater than 31, then ASSERT().
1372 If EndBit is less than StartBit, then ASSERT().
1373
1374 @param Address The PCI configuration register to read.
1375 @param StartBit The ordinal of the least significant bit in the bit field.
1376 Range 0..31.
1377 @param EndBit The ordinal of the most significant bit in the bit field.
1378 Range 0..31.
1379
1380 @retval 0xFFFFFFFF Invalid PCI address.
1381 @retval other The value of the bit field read from the PCI configuration register.
1382
1383 **/
1384 UINT32
1385 EFIAPI
1386 PciExpressBitFieldRead32 (
1387 IN UINTN Address,
1388 IN UINTN StartBit,
1389 IN UINTN EndBit
1390 )
1391 {
1392 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1393 return (UINT32) -1;
1394 }
1395 return MmioBitFieldRead32 (
1396 GetPciExpressAddress (Address),
1397 StartBit,
1398 EndBit
1399 );
1400 }
1401
1402 /**
1403 Writes a bit field to a PCI configuration register.
1404
1405 Writes Value to the bit field of the PCI configuration register. The bit
1406 field is specified by the StartBit and the EndBit. All other bits in the
1407 destination PCI configuration register are preserved. The new value of the
1408 32-bit register is returned.
1409
1410 If Address > 0x0FFFFFFF, then ASSERT().
1411 If Address is not aligned on a 32-bit boundary, then ASSERT().
1412 If StartBit is greater than 31, then ASSERT().
1413 If EndBit is greater than 31, then ASSERT().
1414 If EndBit is less than StartBit, then ASSERT().
1415 If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1416
1417 @param Address The PCI configuration register to write.
1418 @param StartBit The ordinal of the least significant bit in the bit field.
1419 Range 0..31.
1420 @param EndBit The ordinal of the most significant bit in the bit field.
1421 Range 0..31.
1422 @param Value The new value of the bit field.
1423
1424 @retval 0xFFFFFFFF Invalid PCI address.
1425 @retval other The value written back to the PCI configuration register.
1426
1427 **/
1428 UINT32
1429 EFIAPI
1430 PciExpressBitFieldWrite32 (
1431 IN UINTN Address,
1432 IN UINTN StartBit,
1433 IN UINTN EndBit,
1434 IN UINT32 Value
1435 )
1436 {
1437 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1438 return (UINT32) -1;
1439 }
1440 return MmioBitFieldWrite32 (
1441 GetPciExpressAddress (Address),
1442 StartBit,
1443 EndBit,
1444 Value
1445 );
1446 }
1447
1448 /**
1449 Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
1450 writes the result back to the bit field in the 32-bit port.
1451
1452 Reads the 32-bit PCI configuration register specified by Address, performs a
1453 bitwise OR between the read result and the value specified by
1454 OrData, and writes the result to the 32-bit PCI configuration register
1455 specified by Address. The value written to the PCI configuration register is
1456 returned. This function must guarantee that all PCI read and write operations
1457 are serialized. Extra left bits in OrData are stripped.
1458
1459 If Address > 0x0FFFFFFF, then ASSERT().
1460 If Address is not aligned on a 32-bit boundary, then ASSERT().
1461 If StartBit is greater than 31, then ASSERT().
1462 If EndBit is greater than 31, then ASSERT().
1463 If EndBit is less than StartBit, then ASSERT().
1464 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1465
1466 @param Address The PCI configuration register to write.
1467 @param StartBit The ordinal of the least significant bit in the bit field.
1468 Range 0..31.
1469 @param EndBit The ordinal of the most significant bit in the bit field.
1470 Range 0..31.
1471 @param OrData The value to OR with the PCI configuration register.
1472
1473 @retval 0xFFFFFFFF Invalid PCI address.
1474 @retval other The value written back to the PCI configuration register.
1475
1476 **/
1477 UINT32
1478 EFIAPI
1479 PciExpressBitFieldOr32 (
1480 IN UINTN Address,
1481 IN UINTN StartBit,
1482 IN UINTN EndBit,
1483 IN UINT32 OrData
1484 )
1485 {
1486 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1487 return (UINT32) -1;
1488 }
1489 return MmioBitFieldOr32 (
1490 GetPciExpressAddress (Address),
1491 StartBit,
1492 EndBit,
1493 OrData
1494 );
1495 }
1496
1497 /**
1498 Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1499 AND, and writes the result back to the bit field in the 32-bit register.
1500
1501 Reads the 32-bit PCI configuration register specified by Address, performs a
1502 bitwise AND between the read result and the value specified by AndData, and
1503 writes the result to the 32-bit PCI configuration register specified by
1504 Address. The value written to the PCI configuration register is returned.
1505 This function must guarantee that all PCI read and write operations are
1506 serialized. Extra left bits in AndData are stripped.
1507
1508 If Address > 0x0FFFFFFF, then ASSERT().
1509 If Address is not aligned on a 32-bit boundary, then ASSERT().
1510 If StartBit is greater than 31, then ASSERT().
1511 If EndBit is greater than 31, then ASSERT().
1512 If EndBit is less than StartBit, then ASSERT().
1513 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1514
1515 @param Address The PCI configuration register to write.
1516 @param StartBit The ordinal of the least significant bit in the bit field.
1517 Range 0..31.
1518 @param EndBit The ordinal of the most significant bit in the bit field.
1519 Range 0..31.
1520 @param AndData The value to AND with the PCI configuration register.
1521
1522 @retval 0xFFFFFFFF Invalid PCI address.
1523 @retval other The value written back to the PCI configuration register.
1524
1525 **/
1526 UINT32
1527 EFIAPI
1528 PciExpressBitFieldAnd32 (
1529 IN UINTN Address,
1530 IN UINTN StartBit,
1531 IN UINTN EndBit,
1532 IN UINT32 AndData
1533 )
1534 {
1535 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1536 return (UINT32) -1;
1537 }
1538 return MmioBitFieldAnd32 (
1539 GetPciExpressAddress (Address),
1540 StartBit,
1541 EndBit,
1542 AndData
1543 );
1544 }
1545
1546 /**
1547 Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1548 bitwise OR, and writes the result back to the bit field in the
1549 32-bit port.
1550
1551 Reads the 32-bit PCI configuration register specified by Address, performs a
1552 bitwise AND followed by a bitwise OR between the read result and
1553 the value specified by AndData, and writes the result to the 32-bit PCI
1554 configuration register specified by Address. The value written to the PCI
1555 configuration register is returned. This function must guarantee that all PCI
1556 read and write operations are serialized. Extra left bits in both AndData and
1557 OrData are stripped.
1558
1559 If Address > 0x0FFFFFFF, then ASSERT().
1560 If Address is not aligned on a 32-bit boundary, then ASSERT().
1561 If StartBit is greater than 31, then ASSERT().
1562 If EndBit is greater than 31, then ASSERT().
1563 If EndBit is less than StartBit, then ASSERT().
1564 If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1565 If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1566
1567 @param Address The PCI configuration register to write.
1568 @param StartBit The ordinal of the least significant bit in the bit field.
1569 Range 0..31.
1570 @param EndBit The ordinal of the most significant bit in the bit field.
1571 Range 0..31.
1572 @param AndData The value to AND with the PCI configuration register.
1573 @param OrData The value to OR with the result of the AND operation.
1574
1575 @retval 0xFFFFFFFF Invalid PCI address.
1576 @retval other The value written back to the PCI configuration register.
1577
1578 **/
1579 UINT32
1580 EFIAPI
1581 PciExpressBitFieldAndThenOr32 (
1582 IN UINTN Address,
1583 IN UINTN StartBit,
1584 IN UINTN EndBit,
1585 IN UINT32 AndData,
1586 IN UINT32 OrData
1587 )
1588 {
1589 if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1590 return (UINT32) -1;
1591 }
1592 return MmioBitFieldAndThenOr32 (
1593 GetPciExpressAddress (Address),
1594 StartBit,
1595 EndBit,
1596 AndData,
1597 OrData
1598 );
1599 }
1600
1601 /**
1602 Reads a range of PCI configuration registers into a caller supplied buffer.
1603
1604 Reads the range of PCI configuration registers specified by StartAddress and
1605 Size into the buffer specified by Buffer. This function only allows the PCI
1606 configuration registers from a single PCI function to be read. Size is
1607 returned. When possible 32-bit PCI configuration read cycles are used to read
1608 from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
1609 and 16-bit PCI configuration read cycles may be used at the beginning and the
1610 end of the range.
1611
1612 If StartAddress > 0x0FFFFFFF, then ASSERT().
1613 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1614 If Size > 0 and Buffer is NULL, then ASSERT().
1615
1616 @param StartAddress The starting address that encodes the PCI Bus, Device,
1617 Function and Register.
1618 @param Size The size in bytes of the transfer.
1619 @param Buffer The pointer to a buffer receiving the data read.
1620
1621 @retval 0xFFFFFFFF Invalid PCI address.
1622 @retval other Size read data from StartAddress.
1623
1624 **/
1625 UINTN
1626 EFIAPI
1627 PciExpressReadBuffer (
1628 IN UINTN StartAddress,
1629 IN UINTN Size,
1630 OUT VOID *Buffer
1631 )
1632 {
1633 UINTN ReturnValue;
1634
1635 //
1636 // Make sure Address is valid
1637 //
1638 ASSERT_INVALID_PCI_ADDRESS (StartAddress);
1639 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1640
1641 //
1642 // Make sure the Address is in MMCONF address space
1643 //
1644 if (StartAddress >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1645 return (UINTN) -1;
1646 }
1647
1648 if (Size == 0) {
1649 return Size;
1650 }
1651
1652 ASSERT (Buffer != NULL);
1653
1654 //
1655 // Save Size for return
1656 //
1657 ReturnValue = Size;
1658
1659 if ((StartAddress & 1) != 0) {
1660 //
1661 // Read a byte if StartAddress is byte aligned
1662 //
1663 *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1664 StartAddress += sizeof (UINT8);
1665 Size -= sizeof (UINT8);
1666 Buffer = (UINT8*)Buffer + 1;
1667 }
1668
1669 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1670 //
1671 // Read a word if StartAddress is word aligned
1672 //
1673 WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1674
1675 StartAddress += sizeof (UINT16);
1676 Size -= sizeof (UINT16);
1677 Buffer = (UINT16*)Buffer + 1;
1678 }
1679
1680 while (Size >= sizeof (UINT32)) {
1681 //
1682 // Read as many double words as possible
1683 //
1684 WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
1685
1686 StartAddress += sizeof (UINT32);
1687 Size -= sizeof (UINT32);
1688 Buffer = (UINT32*)Buffer + 1;
1689 }
1690
1691 if (Size >= sizeof (UINT16)) {
1692 //
1693 // Read the last remaining word if exist
1694 //
1695 WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
1696 StartAddress += sizeof (UINT16);
1697 Size -= sizeof (UINT16);
1698 Buffer = (UINT16*)Buffer + 1;
1699 }
1700
1701 if (Size >= sizeof (UINT8)) {
1702 //
1703 // Read the last remaining byte if exist
1704 //
1705 *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
1706 }
1707
1708 return ReturnValue;
1709 }
1710
1711 /**
1712 Copies the data in a caller supplied buffer to a specified range of PCI
1713 configuration space.
1714
1715 Writes the range of PCI configuration registers specified by StartAddress and
1716 Size from the buffer specified by Buffer. This function only allows the PCI
1717 configuration registers from a single PCI function to be written. Size is
1718 returned. When possible 32-bit PCI configuration write cycles are used to
1719 write from StartAddress to StartAddress + Size. Due to alignment restrictions,
1720 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1721 and the end of the range.
1722
1723 If StartAddress > 0x0FFFFFFF, then ASSERT().
1724 If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1725 If Size > 0 and Buffer is NULL, then ASSERT().
1726
1727 @param StartAddress The starting address that encodes the PCI Bus, Device,
1728 Function and Register.
1729 @param Size The size in bytes of the transfer.
1730 @param Buffer The pointer to a buffer containing the data to write.
1731
1732 @retval 0xFFFFFFFF Invalid PCI address.
1733 @retval other Size written to StartAddress.
1734
1735 **/
1736 UINTN
1737 EFIAPI
1738 PciExpressWriteBuffer (
1739 IN UINTN StartAddress,
1740 IN UINTN Size,
1741 IN VOID *Buffer
1742 )
1743 {
1744 UINTN ReturnValue;
1745
1746 //
1747 // Make sure Address is valid
1748 //
1749 ASSERT_INVALID_PCI_ADDRESS (StartAddress);
1750 ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
1751
1752 //
1753 // Make sure the Address is in MMCONF address space
1754 //
1755 if (StartAddress >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
1756 return (UINTN) -1;
1757 }
1758
1759 if (Size == 0) {
1760 return 0;
1761 }
1762
1763 ASSERT (Buffer != NULL);
1764
1765 //
1766 // Save Size for return
1767 //
1768 ReturnValue = Size;
1769
1770 if ((StartAddress & 1) != 0) {
1771 //
1772 // Write a byte if StartAddress is byte aligned
1773 //
1774 PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1775 StartAddress += sizeof (UINT8);
1776 Size -= sizeof (UINT8);
1777 Buffer = (UINT8*)Buffer + 1;
1778 }
1779
1780 if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
1781 //
1782 // Write a word if StartAddress is word aligned
1783 //
1784 PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1785 StartAddress += sizeof (UINT16);
1786 Size -= sizeof (UINT16);
1787 Buffer = (UINT16*)Buffer + 1;
1788 }
1789
1790 while (Size >= sizeof (UINT32)) {
1791 //
1792 // Write as many double words as possible
1793 //
1794 PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
1795 StartAddress += sizeof (UINT32);
1796 Size -= sizeof (UINT32);
1797 Buffer = (UINT32*)Buffer + 1;
1798 }
1799
1800 if (Size >= sizeof (UINT16)) {
1801 //
1802 // Write the last remaining word if exist
1803 //
1804 PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
1805 StartAddress += sizeof (UINT16);
1806 Size -= sizeof (UINT16);
1807 Buffer = (UINT16*)Buffer + 1;
1808 }
1809
1810 if (Size >= sizeof (UINT8)) {
1811 //
1812 // Write the last remaining byte if exist
1813 //
1814 PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
1815 }
1816
1817 return ReturnValue;
1818 }