]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciRootBridgeIo.c
12b2e18720a4066e8ebff801d26f3ac9f1e7b07b
[mirror_edk2.git] / QuarkPlatformPkg / Pci / Dxe / PciHostBridge / PciRootBridgeIo.c
1 /** @file
2 IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
3 Does not support configuration accesses to the extended PCI Express registers yet.
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9
10 **/
11
12 #include "PciRootBridge.h"
13
14 //
15 // Define PCI express offse
16 //
17 #define PCIE_OFF(Bus, Device, Function, Register) \
18 ((UINT64) ((UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12) + (UINTN) (Register)))
19
20 //
21 // Pci Root Bridge Io Module Variables
22 //
23 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
24 EFI_CPU_IO2_PROTOCOL *mCpuIo;
25
26 EFI_STATUS
27 SimpleIioRootBridgeConstructor (
28 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
29 IN EFI_HANDLE HostBridgeHandle,
30 IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture,
31 UINT64 AllocAttributes
32 )
33 /*++
34
35 Routine Description:
36
37 Construct the Pci Root Bridge Io protocol.
38
39 Arguments:
40
41 Protocol - Protocol to initialize.
42 HostBridgeHandle - Handle to the HostBridge.
43 ResAperture - Resource apperture of the root bridge.
44 AllocAttributes - Attribute of resouce allocated.
45
46 Returns:
47
48 EFI_SUCCESS - Success.
49 Others - Fail.
50
51 --*/
52 {
53 EFI_STATUS Status;
54 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
55 PCI_RESOURCE_TYPE Index;
56 UINT32 HecBase;
57 UINT32 HecSize;
58
59 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
60
61 //
62 // Initialize the apertures with default values
63 //
64 CopyMem (
65 &PrivateData->Aperture,
66 ResAperture,
67 sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
68 );
69
70 for (Index = TypeIo; Index < TypeMax; Index++) {
71 PrivateData->ResAllocNode[Index].Type = Index;
72 PrivateData->ResAllocNode[Index].Base = 0;
73 PrivateData->ResAllocNode[Index].Length = 0;
74 PrivateData->ResAllocNode[Index].Status = ResNone;
75 }
76
77 EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
78 PrivateData->PciAddress = 0xCF8;
79 PrivateData->PciData = 0xCFC;
80
81 PrivateData->RootBridgeAllocAttrib = AllocAttributes;
82 PrivateData->Attributes = 0;
83 PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
84 EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
85 EFI_PCI_ATTRIBUTE_ISA_IO_16 |
86 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
87 EFI_PCI_ATTRIBUTE_VGA_MEMORY |
88 EFI_PCI_ATTRIBUTE_VGA_IO_16;
89
90 //
91 // Don't support BASE above 4GB currently
92 // Position to bit 39:28
93 //
94 HecBase = (UINT32) PcdGet64 (PcdPciExpressBaseAddress);
95 HecSize = (UINT32) PcdGet64 (PcdPciExpressSize);
96
97 ASSERT ((HecBase & (HecSize - 1)) == 0);
98 ASSERT (HecBase != 0);
99
100 PrivateData->HecBase = HecBase;
101 PrivateData->HecLen = HecSize;
102
103 PrivateData->BusNumberAssigned = FALSE;
104 PrivateData->BusScanCount = 0;
105
106 Protocol->ParentHandle = HostBridgeHandle;
107
108 Protocol->PollMem = RootBridgeIoPollMem;
109 Protocol->PollIo = RootBridgeIoPollIo;
110
111 Protocol->Mem.Read = RootBridgeIoMemRead;
112 Protocol->Mem.Write = RootBridgeIoMemWrite;
113
114 Protocol->Io.Read = RootBridgeIoIoRead;
115 Protocol->Io.Write = RootBridgeIoIoWrite;
116
117 Protocol->CopyMem = RootBridgeIoCopyMem;
118
119 Protocol->Pci.Read = RootBridgeIoPciRead;
120 Protocol->Pci.Write = RootBridgeIoPciWrite;
121
122 Protocol->Map = RootBridgeIoMap;
123 Protocol->Unmap = RootBridgeIoUnmap;
124
125 Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
126 Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
127
128 Protocol->Flush = RootBridgeIoFlush;
129
130 Protocol->GetAttributes = RootBridgeIoGetAttributes;
131 Protocol->SetAttributes = RootBridgeIoSetAttributes;
132
133 Protocol->Configuration = RootBridgeIoConfiguration;
134
135 Protocol->SegmentNumber = 0;
136
137 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
138 ASSERT_EFI_ERROR (Status);
139
140 Status = gBS->LocateProtocol (
141 &gEfiCpuIo2ProtocolGuid,
142 NULL,
143 (VOID **) &mCpuIo
144 );
145 ASSERT_EFI_ERROR (Status);
146
147 return EFI_SUCCESS;
148 }
149
150 EFI_STATUS
151 EFIAPI
152 RootBridgeIoPollMem (
153 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
154 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
155 IN UINT64 Address,
156 IN UINT64 Mask,
157 IN UINT64 Value,
158 IN UINT64 Delay,
159 OUT UINT64 *Result
160 )
161 /*++
162
163 Routine Description:
164
165 Poll an address in memory mapped space until an exit condition is met
166 or a timeout occurs.
167
168 Arguments:
169
170 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
171 Width - Width of the memory operation.
172 Address - The base address of the memory operation.
173 Mask - Mask used for polling criteria.
174 Value - Comparison value used for polling exit criteria.
175 Delay - Number of 100ns units to poll.
176 Result - Pointer to the last value read from memory location.
177
178 Returns:
179
180 EFI_SUCCESS - Success.
181 EFI_INVALID_PARAMETER - Invalid parameter found.
182 EFI_TIMEOUT - Delay expired before a match occurred.
183 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
184
185 --*/
186 {
187 EFI_STATUS Status;
188 UINT64 NumberOfTicks;
189 UINT32 Remainder;
190
191 if (Result == NULL) {
192 return EFI_INVALID_PARAMETER;
193 }
194
195 if (Width < 0 || Width > EfiPciWidthUint64) {
196 return EFI_INVALID_PARAMETER;
197 }
198 //
199 // No matter what, always do a single poll.
200 //
201 Status = This->Mem.Read (
202 This,
203 Width,
204 Address,
205 1,
206 Result
207 );
208 if (EFI_ERROR (Status)) {
209 return Status;
210 }
211
212 if ((*Result & Mask) == Value) {
213 return EFI_SUCCESS;
214 }
215
216 if (Delay != 0) {
217 //
218 // Determine the proper # of metronome ticks to wait for polling the
219 // location. The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
220 // The "+1" to account for the possibility of the first tick being short
221 // because we started in the middle of a tick.
222 //
223 // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
224 // protocol definition is updated.
225 //
226 NumberOfTicks = DivU64x32Remainder (
227 Delay,
228 (UINT32) mMetronome->TickPeriod,
229 &Remainder
230 );
231 if (Remainder != 0) {
232 NumberOfTicks += 1;
233 }
234
235 NumberOfTicks += 1;
236
237 while (NumberOfTicks) {
238
239 mMetronome->WaitForTick (mMetronome, 1);
240
241 Status = This->Mem.Read (
242 This,
243 Width,
244 Address,
245 1,
246 Result
247 );
248 if (EFI_ERROR (Status)) {
249 return Status;
250 }
251
252 if ((*Result & Mask) == Value) {
253 return EFI_SUCCESS;
254 }
255
256 NumberOfTicks -= 1;
257 }
258 }
259
260 return EFI_TIMEOUT;
261 }
262
263 EFI_STATUS
264 EFIAPI
265 RootBridgeIoPollIo (
266 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
267 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
268 IN UINT64 Address,
269 IN UINT64 Mask,
270 IN UINT64 Value,
271 IN UINT64 Delay,
272 OUT UINT64 *Result
273 )
274 /*++
275
276 Routine Description:
277
278 Poll an address in I/O space until an exit condition is met
279 or a timeout occurs.
280
281 Arguments:
282
283 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
284 Width - Width of I/O operation.
285 Address - The base address of the I/O operation.
286 Mask - Mask used for polling criteria.
287 Value - Comparison value used for polling exit criteria.
288 Delay - Number of 100ns units to poll.
289 Result - Pointer to the last value read from memory location.
290
291 Returns:
292
293 EFI_SUCCESS - Success.
294 EFI_INVALID_PARAMETER - Invalid parameter found.
295 EFI_TIMEOUT - Delay expired before a match occurred.
296 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
297
298 --*/
299 {
300 EFI_STATUS Status;
301 UINT64 NumberOfTicks;
302 UINT32 Remainder;
303
304 //
305 // No matter what, always do a single poll.
306 //
307 if (Result == NULL) {
308 return EFI_INVALID_PARAMETER;
309 }
310
311 if (Width < 0 || Width > EfiPciWidthUint64) {
312 return EFI_INVALID_PARAMETER;
313 }
314
315 Status = This->Io.Read (
316 This,
317 Width,
318 Address,
319 1,
320 Result
321 );
322 if (EFI_ERROR (Status)) {
323 return Status;
324 }
325
326 if ((*Result & Mask) == Value) {
327 return EFI_SUCCESS;
328 }
329
330 if (Delay != 0) {
331 //
332 // Determine the proper # of metronome ticks to wait for polling the
333 // location. The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
334 // The "+1" to account for the possibility of the first tick being short
335 // because we started in the middle of a tick.
336 //
337 NumberOfTicks = DivU64x32Remainder (
338 Delay,
339 (UINT32) mMetronome->TickPeriod,
340 &Remainder
341 );
342 if (Remainder != 0) {
343 NumberOfTicks += 1;
344 }
345
346 NumberOfTicks += 1;
347
348 while (NumberOfTicks) {
349
350 mMetronome->WaitForTick (mMetronome, 1);
351
352 Status = This->Io.Read (
353 This,
354 Width,
355 Address,
356 1,
357 Result
358 );
359 if (EFI_ERROR (Status)) {
360 return Status;
361 }
362
363 if ((*Result & Mask) == Value) {
364 return EFI_SUCCESS;
365 }
366
367 NumberOfTicks -= 1;
368 }
369 }
370
371 return EFI_TIMEOUT;
372 }
373
374 EFI_STATUS
375 EFIAPI
376 RootBridgeIoMemRead (
377 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
378 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
379 IN UINT64 Address,
380 IN UINTN Count,
381 IN OUT VOID *Buffer
382 )
383 /*++
384
385 Routine Description:
386
387 Allow read from memory mapped I/O space.
388
389 Arguments:
390
391 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
392 Width - The width of memory operation.
393 Address - Base address of the memory operation.
394 Count - Number of memory opeartion to perform.
395 Buffer - The destination buffer to store data.
396
397 Returns:
398
399 EFI_SUCCESS - Success.
400 EFI_INVALID_PARAMETER - Invalid parameter found.
401 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
402
403 --*/
404 {
405 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
406 if (Buffer == NULL) {
407 return EFI_INVALID_PARAMETER;
408 }
409
410 if (Width < 0 ||
411 Width == EfiPciWidthUint64 ||
412 Width == EfiPciWidthFifoUint64 ||
413 Width == EfiPciWidthFillUint64 ||
414 Width >= EfiPciWidthMaximum
415 ) {
416 return EFI_INVALID_PARAMETER;
417 }
418
419 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
420 //
421 // Check memory access limit
422 //
423 if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
424 if (Address > PrivateData->Aperture.Mem64Limit) {
425 return EFI_INVALID_PARAMETER;
426 }
427 } else {
428 if (Address > PrivateData->Aperture.Mem32Limit) {
429 return EFI_INVALID_PARAMETER;
430 }
431 }
432
433 return mCpuIo->Mem.Read (
434 mCpuIo,
435 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
436 Address,
437 Count,
438 Buffer
439 );
440 }
441
442 EFI_STATUS
443 EFIAPI
444 RootBridgeIoMemWrite (
445 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
446 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
447 IN UINT64 Address,
448 IN UINTN Count,
449 IN OUT VOID *Buffer
450 )
451 /*++
452
453 Routine Description:
454
455 Allow write to memory mapped I/O space.
456
457 Arguments:
458
459 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
460 Width - The width of memory operation.
461 Address - Base address of the memory operation.
462 Count - Number of memory opeartion to perform.
463 Buffer - The source buffer to write data from.
464
465 Returns:
466
467 EFI_SUCCESS - Success.
468 EFI_INVALID_PARAMETER - Invalid parameter found.
469 EFI_OUT_OF_RESOURCES - Fail due to lack of resources.
470
471 --*/
472 {
473 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
474
475 if (Buffer == NULL) {
476 return EFI_INVALID_PARAMETER;
477 }
478
479 if (Width < 0 ||
480 Width == EfiPciWidthUint64 ||
481 Width == EfiPciWidthFifoUint64 ||
482 Width == EfiPciWidthFillUint64 ||
483 Width >= EfiPciWidthMaximum
484 ) {
485 return EFI_INVALID_PARAMETER;
486 }
487
488 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
489
490 //
491 // Check memory access limit
492 //
493 if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) {
494 if (Address > PrivateData->Aperture.Mem64Limit) {
495 return EFI_INVALID_PARAMETER;
496 }
497 } else {
498 if (Address > PrivateData->Aperture.Mem32Limit) {
499 return EFI_INVALID_PARAMETER;
500 }
501 }
502
503 return mCpuIo->Mem.Write (
504 mCpuIo,
505 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
506 Address,
507 Count,
508 Buffer
509 );
510 }
511
512 EFI_STATUS
513 EFIAPI
514 RootBridgeIoIoRead (
515 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
516 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
517 IN UINT64 Address,
518 IN UINTN Count,
519 IN OUT VOID *Buffer
520 )
521 /*++
522
523 Routine Description:
524
525 Enable a PCI driver to read PCI controller registers in the
526 PCI root bridge I/O space.
527
528 Arguments:
529
530 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
531 Width - Signifies the width of the memory operation.
532 Address - The base address of the I/O operation.
533 Count - The number of I/O operations to perform.
534 Buffer - The destination buffer to store the results.
535
536 Returns:
537
538 EFI_SUCCESS - The data was read from the PCI root bridge.
539 EFI_INVALID_PARAMETER - Invalid parameters found.
540 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
541 resources.
542 --*/
543 {
544
545 UINTN AlignMask;
546 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
547
548 if (Buffer == NULL) {
549 return EFI_INVALID_PARAMETER;
550 }
551
552 if (Width < 0 ||
553 Width == EfiPciWidthUint64 ||
554 Width == EfiPciWidthFifoUint64 ||
555 Width == EfiPciWidthFillUint64 ||
556 Width >= EfiPciWidthMaximum
557 ) {
558 return EFI_INVALID_PARAMETER;
559 }
560
561 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
562
563 //
564 // AlignMask = (1 << Width) - 1;
565 //
566 AlignMask = (1 << (Width & 0x03)) - 1;
567
568 //
569 // check Io access limit
570 //
571 if (Address > PrivateData->Aperture.IoLimit) {
572 return EFI_INVALID_PARAMETER;
573 }
574
575 if (Address & AlignMask) {
576 return EFI_INVALID_PARAMETER;
577 }
578
579 return mCpuIo->Io.Read (
580 mCpuIo,
581 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
582 Address,
583 Count,
584 Buffer
585 );
586
587 }
588
589 EFI_STATUS
590 EFIAPI
591 RootBridgeIoIoWrite (
592 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
593 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
594 IN UINT64 Address,
595 IN UINTN Count,
596 IN OUT VOID *Buffer
597 )
598 /*++
599
600 Routine Description:
601
602 Enable a PCI driver to write to PCI controller registers in the
603 PCI root bridge I/O space.
604
605 Arguments:
606
607 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
608 Width - Signifies the width of the memory operation.
609 Address - The base address of the I/O operation.
610 Count - The number of I/O operations to perform.
611 Buffer - The source buffer to write data from.
612
613 Returns:
614
615 EFI_SUCCESS - The data was written to the PCI root bridge.
616 EFI_INVALID_PARAMETER - Invalid parameters found.
617 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
618 resources.
619 --*/
620 {
621 UINTN AlignMask;
622 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
623
624 if (Buffer == NULL) {
625 return EFI_INVALID_PARAMETER;
626 }
627
628 if (Width < 0 ||
629 Width == EfiPciWidthUint64 ||
630 Width == EfiPciWidthFifoUint64 ||
631 Width == EfiPciWidthFillUint64 ||
632 Width >= EfiPciWidthMaximum
633 ) {
634 return EFI_INVALID_PARAMETER;
635 }
636
637 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
638
639 //
640 // AlignMask = (1 << Width) - 1;
641 //
642 AlignMask = (1 << (Width & 0x03)) - 1;
643
644 //
645 // Check Io access limit
646 //
647 if (Address > PrivateData->Aperture.IoLimit) {
648 return EFI_INVALID_PARAMETER;
649 }
650
651 if (Address & AlignMask) {
652 return EFI_INVALID_PARAMETER;
653 }
654
655 return mCpuIo->Io.Write (
656 mCpuIo,
657 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
658 Address,
659 Count,
660 Buffer
661 );
662
663 }
664
665 EFI_STATUS
666 EFIAPI
667 RootBridgeIoCopyMem (
668 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
669 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
670 IN UINT64 DestAddress,
671 IN UINT64 SrcAddress,
672 IN UINTN Count
673 )
674 /*++
675
676 Routine Description:
677
678 Copy one region of PCI root bridge memory space to be copied to
679 another region of PCI root bridge memory space.
680
681 Arguments:
682
683 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
684 Width - Signifies the width of the memory operation.
685 DestAddress - Destination address of the memory operation.
686 SrcAddress - Source address of the memory operation.
687 Count - Number of memory operations to perform.
688
689 Returns:
690
691 EFI_SUCCESS - The data was copied successfully.
692 EFI_INVALID_PARAMETER - Invalid parameters found.
693 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
694 resources.
695 --*/
696 {
697 EFI_STATUS Status;
698 BOOLEAN Direction;
699 UINTN Stride;
700 UINTN Index;
701 UINT64 Result;
702
703 if (Width < 0 || Width > EfiPciWidthUint64) {
704 return EFI_INVALID_PARAMETER;
705 }
706
707 if (DestAddress == SrcAddress) {
708 return EFI_SUCCESS;
709 }
710
711 Stride = (UINTN)1 << Width;
712
713 Direction = TRUE;
714 if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
715 Direction = FALSE;
716 SrcAddress = SrcAddress + (Count - 1) * Stride;
717 DestAddress = DestAddress + (Count - 1) * Stride;
718 }
719
720 for (Index = 0; Index < Count; Index++) {
721 Status = RootBridgeIoMemRead (
722 This,
723 Width,
724 SrcAddress,
725 1,
726 &Result
727 );
728 if (EFI_ERROR (Status)) {
729 return Status;
730 }
731
732 Status = RootBridgeIoMemWrite (
733 This,
734 Width,
735 DestAddress,
736 1,
737 &Result
738 );
739 if (EFI_ERROR (Status)) {
740 return Status;
741 }
742
743 if (Direction) {
744 SrcAddress += Stride;
745 DestAddress += Stride;
746 } else {
747 SrcAddress -= Stride;
748 DestAddress -= Stride;
749 }
750 }
751
752 return EFI_SUCCESS;
753 }
754
755 EFI_STATUS
756 RootBridgeIoPciRW (
757 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
758 IN BOOLEAN Write,
759 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
760 IN UINT64 UserAddress,
761 IN UINTN Count,
762 IN OUT VOID *UserBuffer
763 )
764 /*++
765
766 Routine Description:
767
768 Arguments:
769
770 Returns:
771
772 --*/
773 {
774 PCI_CONFIG_ACCESS_CF8 Pci;
775 PCI_CONFIG_ACCESS_CF8 PciAligned;
776 UINT32 Stride;
777 UINTN PciData;
778 UINTN PciDataStride;
779 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
780
781 if (Width >= EfiPciWidthMaximum) {
782 return EFI_INVALID_PARAMETER;
783 }
784
785 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
786
787 ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);
788
789 Stride = 1 << Width;
790
791 Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
792 Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
793 Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
794 Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
795 Pci.Bits.Reserved = 0;
796 Pci.Bits.Enable = 1;
797
798 //
799 // PCI Configure access are all 32-bit aligned, but by accessing the
800 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
801 // are possible on PCI.
802 //
803 // To read a byte of PCI configuration space you load 0xcf8 and
804 // read 0xcfc, 0xcfd, 0xcfe, 0xcff
805 //
806 PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03;
807
808 while (Count) {
809 PciAligned = Pci;
810 PciAligned.Bits.Reg &= 0xfc;
811 PciData = PrivateData->PciData + PciDataStride;
812 EfiAcquireLock(&PrivateData->PciLock);
813 This->Io.Write (This, EfiPciWidthUint32, \
814 PrivateData->PciAddress, 1, &PciAligned);
815 if (Write) {
816 This->Io.Write (This, Width, PciData, 1, UserBuffer);
817 } else {
818 This->Io.Read (This, Width, PciData, 1, UserBuffer);
819 }
820 EfiReleaseLock(&PrivateData->PciLock);
821 UserBuffer = ((UINT8 *)UserBuffer) + Stride;
822 PciDataStride = (PciDataStride + Stride) % 4;
823 Count -= 1;
824
825 //
826 // Only increment the PCI address if Width is not a FIFO.
827 //
828 if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
829 Pci.Bits.Reg += Stride;
830 }
831 }
832 return EFI_SUCCESS;
833 }
834
835 EFI_STATUS
836 EFIAPI
837 RootBridgeIoPciRead (
838 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
839 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
840 IN UINT64 Address,
841 IN UINTN Count,
842 IN OUT VOID *Buffer
843 )
844 /*++
845
846 Routine Description:
847
848 Allows read from PCI configuration space.
849
850 Arguments:
851
852 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
853 Width - Signifies the width of the memory operation.
854 Address - The address within the PCI configuration space
855 for the PCI controller.
856 Count - The number of PCI configuration operations
857 to perform.
858 Buffer - The destination buffer to store the results.
859
860 Returns:
861
862 EFI_SUCCESS - The data was read from the PCI root bridge.
863 EFI_INVALID_PARAMETER - Invalid parameters found.
864 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
865 resources.
866 --*/
867 {
868 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
869 UINT32 PciBus;
870 UINT32 PciDev;
871 UINT32 PciFn;
872 UINT32 PciExtReg;
873 UINT64 ExtConfigAdd;
874
875 if (Buffer == NULL) {
876 return EFI_INVALID_PARAMETER;
877 }
878
879 if (Width < 0 ||
880 Width == EfiPciWidthUint64 ||
881 Width == EfiPciWidthFifoUint64 ||
882 Width == EfiPciWidthFillUint64 ||
883 Width >= EfiPciWidthMaximum
884 ) {
885 return EFI_INVALID_PARAMETER;
886 }
887
888 //
889 // Read Pci configuration space
890 //
891 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
892
893 if (PrivateData->HecBase == 0) {
894 return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
895 }
896
897 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
898 PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
899 } else {
900 PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
901 }
902
903 PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
904 PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
905 PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
906
907 ExtConfigAdd = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
908
909 return mCpuIo->Mem.Read (
910 mCpuIo,
911 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
912 ExtConfigAdd,
913 Count,
914 Buffer
915 );
916 }
917
918 EFI_STATUS
919 EFIAPI
920 RootBridgeIoPciWrite (
921 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
922 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
923 IN UINT64 Address,
924 IN UINTN Count,
925 IN OUT VOID *Buffer
926 )
927 /*++
928
929 Routine Description:
930
931 Allows write to PCI configuration space.
932
933 Arguments:
934
935 This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
936 Width - Signifies the width of the memory operation.
937 Address - The address within the PCI configuration space
938 for the PCI controller.
939 Count - The number of PCI configuration operations
940 to perform.
941 Buffer - The source buffer to get the results.
942
943 Returns:
944
945 EFI_SUCCESS - The data was written to the PCI root bridge.
946 EFI_INVALID_PARAMETER - Invalid parameters found.
947 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of
948 resources.
949 --*/
950 {
951 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
952 UINT32 PciBus;
953 UINT32 PciDev;
954 UINT32 PciFn;
955 UINT32 PciExtReg;
956 UINT64 ExtConfigAdd;
957
958 if (Buffer == NULL) {
959 return EFI_INVALID_PARAMETER;
960 }
961
962 if (Width < 0 || Width >= EfiPciWidthMaximum) {
963 return EFI_INVALID_PARAMETER;
964 }
965
966 //
967 // Write Pci configuration space
968 //
969 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
970
971 if (PrivateData->HecBase == 0) {
972 return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
973 }
974
975 if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
976 PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
977 } else {
978 PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
979 }
980
981 PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
982 PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
983 PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
984
985 ExtConfigAdd = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg);
986
987 return mCpuIo->Mem.Write (
988 mCpuIo,
989 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
990 ExtConfigAdd,
991 Count,
992 Buffer
993 );
994 }
995
996 EFI_STATUS
997 EFIAPI
998 RootBridgeIoMap (
999 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1000 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
1001 IN VOID *HostAddress,
1002 IN OUT UINTN *NumberOfBytes,
1003 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
1004 OUT VOID **Mapping
1005 )
1006 /*++
1007
1008 Routine Description:
1009
1010 Provides the PCI controller-specific address needed to access
1011 system memory for DMA.
1012
1013 Arguments:
1014
1015 This - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1016 Operation - Indicate if the bus master is going to read or write
1017 to system memory.
1018 HostAddress - The system memory address to map on the PCI controller.
1019 NumberOfBytes - On input the number of bytes to map.
1020 On output the number of bytes that were mapped.
1021 DeviceAddress - The resulting map address for the bus master PCI
1022 controller to use to access the system memory's HostAddress.
1023 Mapping - The value to pass to Unmap() when the bus master DMA
1024 operation is complete.
1025
1026 Returns:
1027
1028 EFI_SUCCESS - Success.
1029 EFI_INVALID_PARAMETER - Invalid parameters found.
1030 EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common
1031 buffer.
1032 EFI_DEVICE_ERROR - The System hardware could not map the requested
1033 address.
1034 EFI_OUT_OF_RESOURCES - The request could not be completed due to
1035 lack of resources.
1036
1037 --*/
1038 {
1039 EFI_STATUS Status;
1040 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1041 MAP_INFO *MapInfo;
1042
1043 if (NumberOfBytes == NULL || Mapping == NULL || DeviceAddress == NULL || HostAddress == NULL) {
1044 return EFI_INVALID_PARAMETER;
1045 }
1046 //
1047 // Initialize the return values to their defaults
1048 //
1049 *Mapping = NULL;
1050
1051 //
1052 // Make sure that Operation is valid
1053 //
1054 if ((Operation < 0) || (Operation > EfiPciOperationBusMasterCommonBuffer64)) {
1055 return EFI_INVALID_PARAMETER;
1056 }
1057 //
1058 // Most PCAT like chipsets can not handle performing DMA above 4GB.
1059 // If any part of the DMA transfer being mapped is above 4GB, then
1060 // map the DMA transfer to a buffer below 4GB.
1061 //
1062 PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1063 if ((PhysicalAddress +*NumberOfBytes) > 0x100000000ULL) {
1064 //
1065 // Common Buffer operations can not be remapped. If the common buffer
1066 // if above 4GB, then it is not possible to generate a mapping, so return
1067 // an error.
1068 //
1069 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
1070 return EFI_INVALID_PARAMETER;
1071 }
1072 }
1073
1074 if ((PhysicalAddress + *NumberOfBytes) > (DMA_MEMORY_TOP+1)) {
1075
1076 //
1077 // Common Buffer operations can not be remapped.
1078 //
1079 if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
1080 *DeviceAddress = PhysicalAddress;
1081 return EFI_SUCCESS;
1082 }
1083 //
1084 // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1085 // called later.
1086 //
1087 Status = gBS->AllocatePool (
1088 EfiBootServicesData,
1089 sizeof (MAP_INFO),
1090 (VOID **) &MapInfo
1091 );
1092 if (EFI_ERROR (Status)) {
1093 *NumberOfBytes = 0;
1094 return Status;
1095 }
1096 //
1097 // Return a pointer to the MAP_INFO structure in Mapping
1098 //
1099 *Mapping = MapInfo;
1100
1101 //
1102 // Initialize the MAP_INFO structure
1103 //
1104 MapInfo->Operation = Operation;
1105 MapInfo->NumberOfBytes = *NumberOfBytes;
1106 MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
1107 MapInfo->HostAddress = PhysicalAddress;
1108 MapInfo->MappedHostAddress = DMA_MEMORY_TOP;
1109
1110 //
1111 // Allocate a buffer below DMA_MEMORY_TOP to map the transfer to.
1112 //
1113 Status = gBS->AllocatePages (
1114 AllocateMaxAddress,
1115 EfiBootServicesData,
1116 MapInfo->NumberOfPages,
1117 &MapInfo->MappedHostAddress
1118 );
1119 if (EFI_ERROR (Status)) {
1120 gBS->FreePool (MapInfo);
1121 *NumberOfBytes = 0;
1122 return Status;
1123 }
1124 //
1125 // If this is a read operation from the Bus Master's point of view,
1126 // then copy the contents of the real buffer into the mapped buffer
1127 // so the Bus Master can read the contents of the real buffer.
1128 //
1129 if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
1130 CopyMem (
1131 (VOID *) (UINTN) MapInfo->MappedHostAddress,
1132 (VOID *) (UINTN) MapInfo->HostAddress,
1133 MapInfo->NumberOfBytes
1134 );
1135 }
1136 //
1137 // The DeviceAddress is the address of the maped buffer below DMA_MEMORY_TOP
1138 //
1139 *DeviceAddress = MapInfo->MappedHostAddress;
1140 } else {
1141 //
1142 // The transfer is below DMA_MEMORY_TOP, so the DeviceAddress is simply the HostAddress
1143 //
1144 *DeviceAddress = PhysicalAddress;
1145 }
1146
1147 return EFI_SUCCESS;
1148 }
1149
1150 EFI_STATUS
1151 EFIAPI
1152 RootBridgeIoUnmap (
1153 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1154 IN VOID *Mapping
1155 )
1156 /*++
1157
1158 Routine Description:
1159
1160 Completes the Map() operation and releases any corresponding resources.
1161
1162 Arguments:
1163
1164 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1165 Mapping - The value returned from Map() operation.
1166
1167 Returns:
1168
1169 EFI_SUCCESS - The range was unmapped successfully.
1170 EFI_INVALID_PARAMETER - Mapping is not a value that was returned
1171 by Map operation.
1172 EFI_DEVICE_ERROR - The data was not committed to the target
1173 system memory.
1174
1175 --*/
1176 {
1177 MAP_INFO *MapInfo;
1178
1179 //
1180 // See if the Map() operation associated with this Unmap() required a mapping buffer.
1181 // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1182 //
1183 if (Mapping != NULL) {
1184 //
1185 // Get the MAP_INFO structure from Mapping
1186 //
1187 MapInfo = (MAP_INFO *) Mapping;
1188
1189 //
1190 // If this is a write operation from the Bus Master's point of view,
1191 // then copy the contents of the mapped buffer into the real buffer
1192 // so the processor can read the contents of the real buffer.
1193 //
1194 if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
1195 (MapInfo->Operation == EfiPciOperationBusMasterWrite64)
1196 ) {
1197 CopyMem (
1198 (VOID *) (UINTN) MapInfo->HostAddress,
1199 (VOID *) (UINTN) MapInfo->MappedHostAddress,
1200 MapInfo->NumberOfBytes
1201 );
1202 }
1203 //
1204 // Free the mapped buffer and the MAP_INFO structure.
1205 //
1206 gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
1207 gBS->FreePool (Mapping);
1208 }
1209
1210 return EFI_SUCCESS;
1211 }
1212
1213 EFI_STATUS
1214 EFIAPI
1215 RootBridgeIoAllocateBuffer (
1216 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1217 IN EFI_ALLOCATE_TYPE Type,
1218 IN EFI_MEMORY_TYPE MemoryType,
1219 IN UINTN Pages,
1220 OUT VOID **HostAddress,
1221 IN UINT64 Attributes
1222 )
1223 /*++
1224
1225 Routine Description:
1226
1227 Allocates pages that are suitable for a common buffer mapping.
1228
1229 Arguments:
1230
1231 This - Pointer to EFI_ROOT_BRIDGE_IO_PROTOCOL instance.
1232 Type - Not used and can be ignored.
1233 MemoryType - Type of memory to allocate.
1234 Pages - Number of pages to allocate.
1235 HostAddress - Pointer to store the base system memory address
1236 of the allocated range.
1237 Attributes - Requested bit mask of attributes of the allocated
1238 range.
1239
1240 Returns:
1241
1242 EFI_SUCCESS - The requested memory range were allocated.
1243 EFI_INVALID_PARAMETER - Invalid parameter found.
1244 EFI_UNSUPPORTED - Attributes is unsupported.
1245
1246 --*/
1247 {
1248 EFI_STATUS Status;
1249 EFI_PHYSICAL_ADDRESS PhysicalAddress;
1250
1251 //
1252 // Validate Attributes
1253 //
1254 if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
1255 return EFI_UNSUPPORTED;
1256 }
1257 //
1258 // Check for invalid inputs
1259 //
1260 if (HostAddress == NULL) {
1261 return EFI_INVALID_PARAMETER;
1262 }
1263 //
1264 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1265 //
1266 if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
1267 return EFI_INVALID_PARAMETER;
1268 }
1269 //
1270 // Limit allocations to memory below DMA_MEMORY_TOP
1271 //
1272 PhysicalAddress = DMA_MEMORY_TOP;
1273
1274 Status = gBS->AllocatePages (
1275 AllocateMaxAddress,
1276 MemoryType,
1277 Pages,
1278 &PhysicalAddress
1279 );
1280 if (EFI_ERROR (Status)) {
1281 return Status;
1282 }
1283
1284 *HostAddress = (VOID *) (UINTN) PhysicalAddress;
1285
1286 return EFI_SUCCESS;
1287 }
1288
1289 EFI_STATUS
1290 EFIAPI
1291 RootBridgeIoFreeBuffer (
1292 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1293 IN UINTN Pages,
1294 OUT VOID *HostAddress
1295 )
1296 /*++
1297
1298 Routine Description:
1299
1300 Free memory allocated in AllocateBuffer.
1301
1302 Arguments:
1303
1304 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1305 instance.
1306 Pages - Number of pages to free.
1307 HostAddress - The base system memory address of the
1308 allocated range.
1309
1310 Returns:
1311
1312 EFI_SUCCESS - Requested memory pages were freed.
1313 EFI_INVALID_PARAMETER - Invalid parameter found.
1314
1315 --*/
1316 {
1317 return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
1318 }
1319
1320 EFI_STATUS
1321 EFIAPI
1322 RootBridgeIoFlush (
1323 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
1324 )
1325 /*++
1326
1327 Routine Description:
1328
1329 Flushes all PCI posted write transactions from a PCI host
1330 bridge to system memory.
1331
1332 Arguments:
1333
1334 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1335
1336 Returns:
1337
1338 EFI_SUCCESS - PCI posted write transactions were flushed
1339 from PCI host bridge to system memory.
1340 EFI_DEVICE_ERROR - Fail due to hardware error.
1341
1342 --*/
1343 {
1344 //
1345 // not supported yet
1346 //
1347 return EFI_SUCCESS;
1348 }
1349
1350 EFI_STATUS
1351 EFIAPI
1352 RootBridgeIoGetAttributes (
1353 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1354 OUT UINT64 *Supported,
1355 OUT UINT64 *Attributes
1356 )
1357 /*++
1358
1359 Routine Description:
1360
1361 Get the attributes that a PCI root bridge supports and
1362 the attributes the PCI root bridge is currently using.
1363
1364 Arguments:
1365
1366 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
1367 instance.
1368 Supports - A pointer to the mask of attributes that
1369 this PCI root bridge supports.
1370 Attributes - A pointer to the mask of attributes that
1371 this PCI root bridge is currently using.
1372 Returns:
1373
1374 EFI_SUCCESS - Success.
1375 EFI_INVALID_PARAMETER - Invalid parameter found.
1376
1377 --*/
1378
1379 // GC_TODO: Supported - add argument and description to function comment
1380 //
1381 // GC_TODO: Supported - add argument and description to function comment
1382 //
1383 // GC_TODO: Supported - add argument and description to function comment
1384 //
1385 {
1386 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1387
1388 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1389
1390 if (Attributes == NULL && Supported == NULL) {
1391 return EFI_INVALID_PARAMETER;
1392 }
1393 //
1394 // Set the return value for Supported and Attributes
1395 //
1396 if (Supported) {
1397 *Supported = PrivateData->Supports;
1398 }
1399
1400 if (Attributes) {
1401 *Attributes = PrivateData->Attributes;
1402 }
1403
1404 return EFI_SUCCESS;
1405 }
1406
1407 EFI_STATUS
1408 EFIAPI
1409 RootBridgeIoSetAttributes (
1410 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1411 IN UINT64 Attributes,
1412 IN OUT UINT64 *ResourceBase,
1413 IN OUT UINT64 *ResourceLength
1414 )
1415 /*++
1416
1417 Routine Description:
1418
1419 Sets the attributes for a resource range on a PCI root bridge.
1420
1421 Arguments:
1422
1423 This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1424 Attributes - The mask of attributes to set.
1425 ResourceBase - Pointer to the base address of the resource range
1426 to be modified by the attributes specified by Attributes.
1427 ResourceLength - Pointer to the length of the resource range to be modified.
1428
1429 Returns:
1430 EFI_SUCCESS - Success.
1431 EFI_INVALID_PARAMETER - Invalid parameter found.
1432 EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon.
1433
1434 --*/
1435
1436 //
1437 // GC_TODO: EFI_UNSUPPORTED - add return value to function comment
1438 //
1439 {
1440 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
1441
1442 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1443
1444 if (Attributes != 0) {
1445 Attributes &= (PrivateData->Supports);
1446 if (Attributes == 0) {
1447 return EFI_UNSUPPORTED;
1448 }
1449 }
1450
1451 if (Attributes == PrivateData->Attributes) {
1452 return EFI_SUCCESS;
1453 }
1454 //
1455 // It is just a trick for some attribute can only be enabled or disabled
1456 // otherwise it can impact on other devices
1457 //
1458 PrivateData->Attributes = Attributes;
1459
1460 return EFI_SUCCESS;
1461 }
1462
1463 EFI_STATUS
1464 EFIAPI
1465 RootBridgeIoConfiguration (
1466 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
1467 OUT VOID **Resources
1468 )
1469 /*++
1470
1471 Routine Description:
1472
1473 Retrieves the current resource settings of this PCI root bridge
1474 in the form of a set of ACPI 2.0 resource descriptor.
1475
1476 Arguments:
1477
1478 This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1479 Resources - Pointer to the ACPI 2.0 resource descriptor that
1480 describe the current configuration of this PCI root
1481 bridge.
1482
1483 Returns:
1484
1485 EFI_SUCCESS - Success.
1486 EFI_UNSUPPORTED - Current configuration of the PCI root bridge
1487 could not be retrieved.
1488
1489 --*/
1490
1491 //
1492 // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1493 //
1494 {
1495 EFI_STATUS Status;
1496 UINTN Idx;
1497
1498 PCI_ROOT_BRIDGE_INSTANCE *RbPrivateData;
1499 PCI_RES_NODE *ResAllocNode;
1500 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;
1501
1502 //
1503 // Get this instance of the Root Bridge.
1504 //
1505 RbPrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1506
1507 //
1508 // If the pointer is not NULL, it points to a buffer already allocated.
1509 //
1510 if (RbPrivateData->ConfigBuffer == NULL) {
1511 Status = gBS->AllocatePool (
1512 EfiBootServicesData,
1513 TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
1514 &RbPrivateData->ConfigBuffer
1515 );
1516 if (EFI_ERROR (Status)) {
1517 return EFI_OUT_OF_RESOURCES;
1518 }
1519 }
1520
1521 Config = RbPrivateData->ConfigBuffer;
1522
1523 ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1524
1525 for (Idx = 0; Idx < TypeMax; Idx++) {
1526
1527 ResAllocNode = &RbPrivateData->ResAllocNode[Idx];
1528
1529 if (ResAllocNode->Status != ResAllocated) {
1530 continue;
1531 }
1532
1533 switch (ResAllocNode->Type) {
1534
1535 case TypeIo:
1536 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1537 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1538 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1539 Config->AddrRangeMin = ResAllocNode->Base;
1540 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1541 Config->AddrLen = ResAllocNode->Length;
1542 break;
1543
1544 case TypeMem32:
1545 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1546 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1547 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1548 Config->AddrSpaceGranularity = 32;
1549 Config->AddrRangeMin = ResAllocNode->Base;
1550 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1551 Config->AddrLen = ResAllocNode->Length;
1552 break;
1553
1554 case TypePMem32:
1555 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1556 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1557 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1558 Config->SpecificFlag = 6;
1559 Config->AddrSpaceGranularity = 32;
1560 Config->AddrRangeMin = ResAllocNode->Base;
1561 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1562 Config->AddrLen = ResAllocNode->Length;
1563 break;
1564
1565 case TypeMem64:
1566 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1567 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1568 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1569 Config->SpecificFlag = 6;
1570 Config->AddrSpaceGranularity = 64;
1571 Config->AddrRangeMin = ResAllocNode->Base;
1572 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1573 Config->AddrLen = ResAllocNode->Length;
1574 break;
1575
1576 case TypePMem64:
1577 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1578 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1579 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1580 Config->SpecificFlag = 6;
1581 Config->AddrSpaceGranularity = 64;
1582 Config->AddrRangeMin = ResAllocNode->Base;
1583 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1584 Config->AddrLen = ResAllocNode->Length;
1585 break;
1586
1587 case TypeBus:
1588 Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1589 Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1590 Config->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
1591 Config->AddrRangeMin = ResAllocNode->Base;
1592 Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
1593 Config->AddrLen = ResAllocNode->Length;
1594 break;
1595
1596 default:
1597 break;
1598 }
1599
1600 Config++;
1601 }
1602 //
1603 // Terminate the entries.
1604 //
1605 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc = ACPI_END_TAG_DESCRIPTOR;
1606 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum = 0x0;
1607
1608 *Resources = RbPrivateData->ConfigBuffer;
1609 return EFI_SUCCESS;
1610 }