]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciLib.c
update the comments on Event
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciLib.c
1 /** @file
2
3 PCI Bus Driver Lib file
4 It abstracts some functions that can be different
5 between light PCI bus driver and full PCI bus driver
6
7 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "PciBus.h"
19
20
21 /**
22 Retrieve the BAR information via PciIo interface.
23
24 @param PciIoDevice Pci device instance.
25 **/
26 VOID
27 GetBackPcCardBar (
28 IN PCI_IO_DEVICE *PciIoDevice
29 )
30 {
31 UINT32 Address;
32
33 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
34 return;
35 }
36
37 //
38 // Read PciBar information from the bar register
39 //
40 if (!gFullEnumeration) {
41
42 Address = 0;
43 PciIoRead (
44 &(PciIoDevice->PciIo),
45 EfiPciIoWidthUint32,
46 0x1c,
47 1,
48 &Address
49 );
50
51 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
52 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
53 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
54
55 Address = 0;
56 PciIoRead (
57 &(PciIoDevice->PciIo),
58 EfiPciIoWidthUint32,
59 0x20,
60 1,
61 &Address
62 );
63 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
64 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
65 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
66
67 Address = 0;
68 PciIoRead (
69 &(PciIoDevice->PciIo),
70 EfiPciIoWidthUint32,
71 0x2c,
72 1,
73 &Address
74 );
75 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
76 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
77 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
78
79 Address = 0;
80 PciIoRead (
81 &(PciIoDevice->PciIo),
82 EfiPciIoWidthUint32,
83 0x34,
84 1,
85 &Address
86 );
87 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
88 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
89 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
90
91 }
92
93 if (gPciHotPlugInit != NULL) {
94 GetResourcePaddingForHpb (PciIoDevice);
95 }
96 }
97
98 /**
99 Remove rejected pci device from specific root bridge
100 handle.
101
102 @param RootBridgeHandle specific parent root bridge handle.
103 @param Bridge Bridge device instance.
104
105 @retval EFI_SUCCESS Success operation.
106 **/
107 EFI_STATUS
108 RemoveRejectedPciDevices (
109 EFI_HANDLE RootBridgeHandle,
110 IN PCI_IO_DEVICE *Bridge
111 )
112 {
113 PCI_IO_DEVICE *Temp;
114 LIST_ENTRY *CurrentLink;
115 LIST_ENTRY *LastLink;
116
117 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
118 return EFI_SUCCESS;
119 }
120
121 CurrentLink = Bridge->ChildList.ForwardLink;
122
123 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
124
125 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
126
127 if (IS_PCI_BRIDGE (&Temp->Pci)) {
128 //
129 // Remove rejected devices recusively
130 //
131 RemoveRejectedPciDevices (RootBridgeHandle, Temp);
132 } else {
133 //
134 // Skip rejection for all PPBs, while detect rejection for others
135 //
136 if (IsPciDeviceRejected (Temp)) {
137
138 //
139 // For P2C, remove all devices on it
140 //
141 if (!IsListEmpty (&Temp->ChildList)) {
142 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
143 }
144
145 //
146 // Finally remove itself
147 //
148 LastLink = CurrentLink->BackLink;
149 RemoveEntryList (CurrentLink);
150 FreePciDevice (Temp);
151
152 CurrentLink = LastLink;
153 }
154 }
155
156 CurrentLink = CurrentLink->ForwardLink;
157 }
158
159 return EFI_SUCCESS;
160 }
161
162 /**
163 Wrapper function for allocating resource for pci host bridge.
164
165 @param PciResAlloc Point to protocol instance EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
166
167 **/
168 EFI_STATUS
169 PciHostBridgeResourceAllocator (
170 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
171 )
172 {
173 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
174 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
175 PciResAlloc
176 );
177 } else {
178 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
179 PciResAlloc
180 );
181 }
182 }
183
184 /**
185 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
186
187 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
188
189 @retval EFI_SUCCESS Success.
190 **/
191 EFI_STATUS
192 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
193 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
194 )
195 {
196 PCI_IO_DEVICE *RootBridgeDev;
197 EFI_HANDLE RootBridgeHandle;
198 VOID *AcpiConfig;
199 EFI_STATUS Status;
200 UINT64 IoBase;
201 UINT64 Mem32Base;
202 UINT64 PMem32Base;
203 UINT64 Mem64Base;
204 UINT64 PMem64Base;
205 UINT64 MaxOptionRomSize;
206 PCI_RESOURCE_NODE *IoBridge;
207 PCI_RESOURCE_NODE *Mem32Bridge;
208 PCI_RESOURCE_NODE *PMem32Bridge;
209 PCI_RESOURCE_NODE *Mem64Bridge;
210 PCI_RESOURCE_NODE *PMem64Bridge;
211 PCI_RESOURCE_NODE IoPool;
212 PCI_RESOURCE_NODE Mem32Pool;
213 PCI_RESOURCE_NODE PMem32Pool;
214 PCI_RESOURCE_NODE Mem64Pool;
215 PCI_RESOURCE_NODE PMem64Pool;
216 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData;
217
218 //
219 // Initialize resource pool
220 //
221
222 InitializeResourcePool (&IoPool, PciBarTypeIo16);
223 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
224 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
225 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
226 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
227
228 RootBridgeDev = NULL;
229 RootBridgeHandle = 0;
230
231 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
232 //
233 // Get RootBridg Device by handle
234 //
235 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
236
237 if (RootBridgeDev == NULL) {
238 return EFI_NOT_FOUND;
239 }
240
241 //
242 // Get host bridge handle for status report
243 //
244 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
245
246 //
247 // Create the entire system resource map from the information collected by
248 // enumerator. Several resource tree was created
249 //
250
251 IoBridge = CreateResourceNode (
252 RootBridgeDev,
253 0,
254 0xFFF,
255 0,
256 PciBarTypeIo16,
257 PciResUsageTypical
258 );
259
260 Mem32Bridge = CreateResourceNode (
261 RootBridgeDev,
262 0,
263 0xFFFFF,
264 0,
265 PciBarTypeMem32,
266 PciResUsageTypical
267 );
268
269 PMem32Bridge = CreateResourceNode (
270 RootBridgeDev,
271 0,
272 0xFFFFF,
273 0,
274 PciBarTypePMem32,
275 PciResUsageTypical
276 );
277
278 Mem64Bridge = CreateResourceNode (
279 RootBridgeDev,
280 0,
281 0xFFFFF,
282 0,
283 PciBarTypeMem64,
284 PciResUsageTypical
285 );
286
287 PMem64Bridge = CreateResourceNode (
288 RootBridgeDev,
289 0,
290 0xFFFFF,
291 0,
292 PciBarTypePMem64,
293 PciResUsageTypical
294 );
295
296 //
297 // Create resourcemap by going through all the devices subject to this root bridge
298 //
299 Status = CreateResourceMap (
300 RootBridgeDev,
301 IoBridge,
302 Mem32Bridge,
303 PMem32Bridge,
304 Mem64Bridge,
305 PMem64Bridge
306 );
307
308 //
309 // Get the max ROM size that the root bridge can process
310 //
311 RootBridgeDev->RomSize = Mem32Bridge->Length;
312
313 //
314 // Get Max Option Rom size for current root bridge
315 //
316 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
317
318 //
319 // Enlarger the mem32 resource to accomdate the option rom
320 // if the mem32 resource is not enough to hold the rom
321 //
322 if (MaxOptionRomSize > Mem32Bridge->Length) {
323
324 Mem32Bridge->Length = MaxOptionRomSize;
325 RootBridgeDev->RomSize = MaxOptionRomSize;
326
327 //
328 // Alignment should be adjusted as well
329 //
330 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
331 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
332 }
333 }
334
335 //
336 // Based on the all the resource tree, contruct ACPI resource node to
337 // submit the resource aperture to pci host bridge protocol
338 //
339 Status = ConstructAcpiResourceRequestor (
340 RootBridgeDev,
341 IoBridge,
342 Mem32Bridge,
343 PMem32Bridge,
344 Mem64Bridge,
345 PMem64Bridge,
346 &AcpiConfig
347 );
348
349 //
350 // Insert these resource nodes into the database
351 //
352 InsertResourceNode (&IoPool, IoBridge);
353 InsertResourceNode (&Mem32Pool, Mem32Bridge);
354 InsertResourceNode (&PMem32Pool, PMem32Bridge);
355 InsertResourceNode (&Mem64Pool, Mem64Bridge);
356 InsertResourceNode (&PMem64Pool, PMem64Bridge);
357
358 if (Status == EFI_SUCCESS) {
359 //
360 // Submit the resource requirement
361 //
362 Status = PciResAlloc->SubmitResources (
363 PciResAlloc,
364 RootBridgeDev->Handle,
365 AcpiConfig
366 );
367 }
368 //
369 // Free acpi resource node
370 //
371 if (AcpiConfig != NULL) {
372 FreePool (AcpiConfig);
373 }
374
375 if (EFI_ERROR (Status)) {
376 //
377 // Destroy all the resource tree
378 //
379 DestroyResourceTree (&IoPool);
380 DestroyResourceTree (&Mem32Pool);
381 DestroyResourceTree (&PMem32Pool);
382 DestroyResourceTree (&Mem64Pool);
383 DestroyResourceTree (&PMem64Pool);
384 return Status;
385 }
386 }
387 //
388 // End while
389 //
390
391 //
392 // Notify pci bus driver starts to program the resource
393 //
394 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
395
396 if (EFI_ERROR (Status)) {
397 //
398 // Allocation failed, then return
399 //
400 return EFI_OUT_OF_RESOURCES;
401 }
402 //
403 // Raise the EFI_IOB_PCI_RES_ALLOC status code
404 //
405 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
406 EFI_PROGRESS_CODE,
407 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
408 (VOID *) &ExtendedData,
409 sizeof (ExtendedData)
410 );
411
412 //
413 // Notify pci bus driver starts to program the resource
414 //
415 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
416
417 RootBridgeDev = NULL;
418
419 RootBridgeHandle = 0;
420
421 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
422 //
423 // Get RootBridg Device by handle
424 //
425 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
426
427 if (RootBridgeDev == NULL) {
428 return EFI_NOT_FOUND;
429 }
430
431 //
432 // Get acpi resource node for all the resource types
433 //
434 AcpiConfig = NULL;
435 Status = PciResAlloc->GetProposedResources (
436 PciResAlloc,
437 RootBridgeDev->Handle,
438 &AcpiConfig
439 );
440 if (EFI_ERROR (Status)) {
441 return Status;
442 }
443
444 //
445 // Get the resource base by interpreting acpi resource node
446 //
447 //
448 GetResourceBase (
449 AcpiConfig,
450 &IoBase,
451 &Mem32Base,
452 &PMem32Base,
453 &Mem64Base,
454 &PMem64Base
455 );
456
457 //
458 // Process option rom for this root bridge
459 //
460 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
461
462 //
463 // Create the entire system resource map from the information collected by
464 // enumerator. Several resource tree was created
465 //
466 Status = GetResourceMap (
467 RootBridgeDev,
468 &IoBridge,
469 &Mem32Bridge,
470 &PMem32Bridge,
471 &Mem64Bridge,
472 &PMem64Bridge,
473 &IoPool,
474 &Mem32Pool,
475 &PMem32Pool,
476 &Mem64Pool,
477 &PMem64Pool
478 );
479
480 if (EFI_ERROR (Status)) {
481 return Status;
482 }
483
484 //
485 // Program IO resources
486 //
487 ProgramResource (
488 IoBase,
489 IoBridge
490 );
491
492 //
493 // Program Mem32 resources
494 //
495 ProgramResource (
496 Mem32Base,
497 Mem32Bridge
498 );
499
500 //
501 // Program PMem32 resources
502 //
503 ProgramResource (
504 PMem32Base,
505 PMem32Bridge
506 );
507
508 //
509 // Program Mem64 resources
510 //
511 ProgramResource (
512 Mem64Base,
513 Mem64Bridge
514 );
515
516 //
517 // Program PMem64 resources
518 //
519 ProgramResource (
520 PMem64Base,
521 PMem64Bridge
522 );
523
524 FreePool (AcpiConfig);
525 }
526
527 //
528 // Destroy all the resource tree
529 //
530 DestroyResourceTree (&IoPool);
531 DestroyResourceTree (&Mem32Pool);
532 DestroyResourceTree (&PMem32Pool);
533 DestroyResourceTree (&Mem64Pool);
534 DestroyResourceTree (&PMem64Pool);
535
536 //
537 // Notify the resource allocation phase is to end
538 //
539 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
540
541 return EFI_SUCCESS;
542 }
543
544 /**
545 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
546
547 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
548
549 @retval EFI_SUCCESS Success.
550 **/
551 EFI_STATUS
552 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
553 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
554 )
555 {
556 PCI_IO_DEVICE *RootBridgeDev;
557 EFI_HANDLE RootBridgeHandle;
558 VOID *AcpiConfig;
559 EFI_STATUS Status;
560 UINT64 IoBase;
561 UINT64 Mem32Base;
562 UINT64 PMem32Base;
563 UINT64 Mem64Base;
564 UINT64 PMem64Base;
565 UINT64 IoResStatus;
566 UINT64 Mem32ResStatus;
567 UINT64 PMem32ResStatus;
568 UINT64 Mem64ResStatus;
569 UINT64 PMem64ResStatus;
570 UINT64 MaxOptionRomSize;
571 PCI_RESOURCE_NODE *IoBridge;
572 PCI_RESOURCE_NODE *Mem32Bridge;
573 PCI_RESOURCE_NODE *PMem32Bridge;
574 PCI_RESOURCE_NODE *Mem64Bridge;
575 PCI_RESOURCE_NODE *PMem64Bridge;
576 PCI_RESOURCE_NODE IoPool;
577 PCI_RESOURCE_NODE Mem32Pool;
578 PCI_RESOURCE_NODE PMem32Pool;
579 PCI_RESOURCE_NODE Mem64Pool;
580 PCI_RESOURCE_NODE PMem64Pool;
581 BOOLEAN ReAllocate;
582 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;
583 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
584
585 //
586 // Reallocate flag
587 //
588 ReAllocate = FALSE;
589
590 //
591 // It will try several times if the resource allocation fails
592 //
593 while (TRUE) {
594
595 //
596 // Initialize resource pool
597 //
598 InitializeResourcePool (&IoPool, PciBarTypeIo16);
599 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
600 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
601 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
602 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
603
604 RootBridgeDev = NULL;
605 RootBridgeHandle = 0;
606
607 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
608
609 //
610 // Get RootBridg Device by handle
611 //
612 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
613
614 if (RootBridgeDev == NULL) {
615 return EFI_NOT_FOUND;
616 }
617
618 //
619 // Create the entire system resource map from the information collected by
620 // enumerator. Several resource tree was created
621 //
622
623 IoBridge = CreateResourceNode (
624 RootBridgeDev,
625 0,
626 0xFFF,
627 0,
628 PciBarTypeIo16,
629 PciResUsageTypical
630 );
631
632 Mem32Bridge = CreateResourceNode (
633 RootBridgeDev,
634 0,
635 0xFFFFF,
636 0,
637 PciBarTypeMem32,
638 PciResUsageTypical
639 );
640
641 PMem32Bridge = CreateResourceNode (
642 RootBridgeDev,
643 0,
644 0xFFFFF,
645 0,
646 PciBarTypePMem32,
647 PciResUsageTypical
648 );
649
650 Mem64Bridge = CreateResourceNode (
651 RootBridgeDev,
652 0,
653 0xFFFFF,
654 0,
655 PciBarTypeMem64,
656 PciResUsageTypical
657 );
658
659 PMem64Bridge = CreateResourceNode (
660 RootBridgeDev,
661 0,
662 0xFFFFF,
663 0,
664 PciBarTypePMem64,
665 PciResUsageTypical
666 );
667
668 //
669 // Create resourcemap by going through all the devices subject to this root bridge
670 //
671 Status = CreateResourceMap (
672 RootBridgeDev,
673 IoBridge,
674 Mem32Bridge,
675 PMem32Bridge,
676 Mem64Bridge,
677 PMem64Bridge
678 );
679
680 //
681 // Get the max ROM size that the root bridge can process
682 //
683 RootBridgeDev->RomSize = Mem32Bridge->Length;
684
685 //
686 // Skip to enlarge the resource request during realloction
687 //
688 if (!ReAllocate) {
689 //
690 // Get Max Option Rom size for current root bridge
691 //
692 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
693
694 //
695 // Enlarger the mem32 resource to accomdate the option rom
696 // if the mem32 resource is not enough to hold the rom
697 //
698 if (MaxOptionRomSize > Mem32Bridge->Length) {
699
700 Mem32Bridge->Length = MaxOptionRomSize;
701 RootBridgeDev->RomSize = MaxOptionRomSize;
702
703 //
704 // Alignment should be adjusted as well
705 //
706 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
707 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
708 }
709 }
710 }
711
712 //
713 // Based on the all the resource tree, contruct ACPI resource node to
714 // submit the resource aperture to pci host bridge protocol
715 //
716 Status = ConstructAcpiResourceRequestor (
717 RootBridgeDev,
718 IoBridge,
719 Mem32Bridge,
720 PMem32Bridge,
721 Mem64Bridge,
722 PMem64Bridge,
723 &AcpiConfig
724 );
725
726 //
727 // Insert these resource nodes into the database
728 //
729 InsertResourceNode (&IoPool, IoBridge);
730 InsertResourceNode (&Mem32Pool, Mem32Bridge);
731 InsertResourceNode (&PMem32Pool, PMem32Bridge);
732 InsertResourceNode (&Mem64Pool, Mem64Bridge);
733 InsertResourceNode (&PMem64Pool, PMem64Bridge);
734
735 if (Status == EFI_SUCCESS) {
736 //
737 // Submit the resource requirement
738 //
739 Status = PciResAlloc->SubmitResources (
740 PciResAlloc,
741 RootBridgeDev->Handle,
742 AcpiConfig
743 );
744 }
745
746 //
747 // Free acpi resource node
748 //
749 if (AcpiConfig != NULL) {
750 FreePool (AcpiConfig);
751 }
752
753 if (EFI_ERROR (Status)) {
754 //
755 // Destroy all the resource tree
756 //
757 DestroyResourceTree (&IoPool);
758 DestroyResourceTree (&Mem32Pool);
759 DestroyResourceTree (&PMem32Pool);
760 DestroyResourceTree (&Mem64Pool);
761 DestroyResourceTree (&PMem64Pool);
762 return Status;
763 }
764 }
765
766 //
767 // Notify pci bus driver starts to program the resource
768 //
769
770 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
771
772 if (!EFI_ERROR (Status)) {
773 //
774 // Allocation succeed, then continue the following
775 //
776 break;
777 }
778
779 //
780 // If the resource allocation is unsuccessful, free resources on bridge
781 //
782
783 RootBridgeDev = NULL;
784 RootBridgeHandle = 0;
785
786 IoResStatus = EFI_RESOURCE_SATISFIED;
787 Mem32ResStatus = EFI_RESOURCE_SATISFIED;
788 PMem32ResStatus = EFI_RESOURCE_SATISFIED;
789 Mem64ResStatus = EFI_RESOURCE_SATISFIED;
790 PMem64ResStatus = EFI_RESOURCE_SATISFIED;
791
792 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
793 //
794 // Get RootBridg Device by handle
795 //
796 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
797 if (RootBridgeDev == NULL) {
798 return EFI_NOT_FOUND;
799 }
800
801 //
802 // Get host bridge handle for status report
803 //
804 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
805
806 //
807 // Get acpi resource node for all the resource types
808 //
809 AcpiConfig = NULL;
810
811 Status = PciResAlloc->GetProposedResources (
812 PciResAlloc,
813 RootBridgeDev->Handle,
814 &AcpiConfig
815 );
816
817 if (EFI_ERROR (Status)) {
818 return Status;
819 }
820
821 if (AcpiConfig != NULL) {
822 //
823 // Adjust resource allocation policy for each RB
824 //
825 GetResourceAllocationStatus (
826 AcpiConfig,
827 &IoResStatus,
828 &Mem32ResStatus,
829 &PMem32ResStatus,
830 &Mem64ResStatus,
831 &PMem64ResStatus
832 );
833 FreePool (AcpiConfig);
834 }
835 }
836 //
837 // End while
838 //
839
840 //
841 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
842 //
843 //
844 // It is very difficult to follow the spec here
845 // Device path , Bar index can not be get here
846 //
847 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
848
849 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
850 EFI_PROGRESS_CODE,
851 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
852 (VOID *) &AllocFailExtendedData,
853 sizeof (AllocFailExtendedData)
854 );
855
856 Status = PciHostBridgeAdjustAllocation (
857 &IoPool,
858 &Mem32Pool,
859 &PMem32Pool,
860 &Mem64Pool,
861 &PMem64Pool,
862 IoResStatus,
863 Mem32ResStatus,
864 PMem32ResStatus,
865 Mem64ResStatus,
866 PMem64ResStatus
867 );
868
869 //
870 // Destroy all the resource tree
871 //
872 DestroyResourceTree (&IoPool);
873 DestroyResourceTree (&Mem32Pool);
874 DestroyResourceTree (&PMem32Pool);
875 DestroyResourceTree (&Mem64Pool);
876 DestroyResourceTree (&PMem64Pool);
877
878 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
879
880 if (EFI_ERROR (Status)) {
881 return Status;
882 }
883
884 ReAllocate = TRUE;
885
886 }
887 //
888 // End main while
889 //
890
891 //
892 // Raise the EFI_IOB_PCI_RES_ALLOC status code
893 //
894 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
895 EFI_PROGRESS_CODE,
896 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
897 (VOID *) &HandleExtendedData,
898 sizeof (HandleExtendedData)
899 );
900
901 //
902 // Notify pci bus driver starts to program the resource
903 //
904 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
905
906 RootBridgeDev = NULL;
907
908 RootBridgeHandle = 0;
909
910 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
911
912 //
913 // Get RootBridg Device by handle
914 //
915 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
916
917 if (RootBridgeDev == NULL) {
918 return EFI_NOT_FOUND;
919 }
920
921 //
922 // Get acpi resource node for all the resource types
923 //
924 AcpiConfig = NULL;
925 Status = PciResAlloc->GetProposedResources (
926 PciResAlloc,
927 RootBridgeDev->Handle,
928 &AcpiConfig
929 );
930
931 if (EFI_ERROR (Status)) {
932 return Status;
933 }
934
935 //
936 // Get the resource base by interpreting acpi resource node
937 //
938 //
939 GetResourceBase (
940 AcpiConfig,
941 &IoBase,
942 &Mem32Base,
943 &PMem32Base,
944 &Mem64Base,
945 &PMem64Base
946 );
947
948 //
949 // Process option rom for this root bridge
950 //
951 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
952
953 //
954 // Create the entire system resource map from the information collected by
955 // enumerator. Several resource tree was created
956 //
957 Status = GetResourceMap (
958 RootBridgeDev,
959 &IoBridge,
960 &Mem32Bridge,
961 &PMem32Bridge,
962 &Mem64Bridge,
963 &PMem64Bridge,
964 &IoPool,
965 &Mem32Pool,
966 &PMem32Pool,
967 &Mem64Pool,
968 &PMem64Pool
969 );
970
971 if (EFI_ERROR (Status)) {
972 return Status;
973 }
974
975 //
976 // Program IO resources
977 //
978 ProgramResource (
979 IoBase,
980 IoBridge
981 );
982
983 //
984 // Program Mem32 resources
985 //
986 ProgramResource (
987 Mem32Base,
988 Mem32Bridge
989 );
990
991 //
992 // Program PMem32 resources
993 //
994 ProgramResource (
995 PMem32Base,
996 PMem32Bridge
997 );
998
999 //
1000 // Program Mem64 resources
1001 //
1002 ProgramResource (
1003 Mem64Base,
1004 Mem64Bridge
1005 );
1006
1007 //
1008 // Program PMem64 resources
1009 //
1010 ProgramResource (
1011 PMem64Base,
1012 PMem64Bridge
1013 );
1014
1015 FreePool (AcpiConfig);
1016 }
1017
1018 //
1019 // Destroy all the resource tree
1020 //
1021 DestroyResourceTree (&IoPool);
1022 DestroyResourceTree (&Mem32Pool);
1023 DestroyResourceTree (&PMem32Pool);
1024 DestroyResourceTree (&Mem64Pool);
1025 DestroyResourceTree (&PMem64Pool);
1026
1027 //
1028 // Notify the resource allocation phase is to end
1029 //
1030 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
1031
1032 return EFI_SUCCESS;
1033 }
1034
1035 /**
1036 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1037 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1038
1039 @param Bridge Bridge device instance.
1040 @param StartBusNumber start point.
1041 @param SubBusNumber Point to sub bus number.
1042 @param PaddedBusRange Customized bus number.
1043
1044 @retval EFI_SUCCESS Success.
1045 @retval EFI_DEVICE_ERROR Fail to scan bus.
1046 **/
1047 EFI_STATUS
1048 PciScanBus (
1049 IN PCI_IO_DEVICE *Bridge,
1050 IN UINT8 StartBusNumber,
1051 OUT UINT8 *SubBusNumber,
1052 OUT UINT8 *PaddedBusRange
1053 )
1054 {
1055 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1056 return PciScanBus_WithHotPlugDeviceSupport (
1057 Bridge,
1058 StartBusNumber,
1059 SubBusNumber,
1060 PaddedBusRange
1061 );
1062 } else {
1063 return PciScanBus_WithoutHotPlugDeviceSupport (
1064 Bridge,
1065 StartBusNumber,
1066 SubBusNumber,
1067 PaddedBusRange
1068 );
1069 }
1070 }
1071
1072 /**
1073 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1074 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1075
1076 @param Bridge Bridge device instance.
1077 @param StartBusNumber start point.
1078 @param SubBusNumber Point to sub bus number.
1079 @param PaddedBusRange Customized bus number.
1080
1081 @retval EFI_SUCCESS Success.
1082 @retval EFI_DEVICE_ERROR Fail to scan bus.
1083 **/
1084 EFI_STATUS
1085 PciScanBus_WithoutHotPlugDeviceSupport (
1086 IN PCI_IO_DEVICE *Bridge,
1087 IN UINT8 StartBusNumber,
1088 OUT UINT8 *SubBusNumber,
1089 OUT UINT8 *PaddedBusRange
1090 )
1091 {
1092 EFI_STATUS Status;
1093 PCI_TYPE00 Pci;
1094 UINT8 Device;
1095 UINT8 Func;
1096 UINT64 Address;
1097 UINTN SecondBus;
1098 UINT16 Register;
1099 PCI_IO_DEVICE *PciDevice;
1100 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1101
1102 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1103 SecondBus = 0;
1104 Register = 0;
1105
1106 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1107 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1108
1109 //
1110 // Check to see whether a pci device is present
1111 //
1112 Status = PciDevicePresent (
1113 PciRootBridgeIo,
1114 &Pci,
1115 StartBusNumber,
1116 Device,
1117 Func
1118 );
1119
1120 if (!EFI_ERROR (Status)) {
1121 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func));
1122
1123 if (IS_PCI_BRIDGE (&Pci) ||
1124 IS_CARDBUS_BRIDGE (&Pci)) {
1125
1126 //
1127 // Get the bridge information
1128 //
1129 Status = PciSearchDevice (
1130 Bridge,
1131 &Pci,
1132 StartBusNumber,
1133 Device,
1134 Func,
1135 &PciDevice
1136 );
1137
1138 if (EFI_ERROR (Status)) {
1139 return Status;
1140 }
1141
1142 //
1143 // Add feature to support customized secondary bus number
1144 //
1145 if (*SubBusNumber == 0) {
1146 *SubBusNumber = *PaddedBusRange;
1147 *PaddedBusRange = 0;
1148 }
1149
1150 (*SubBusNumber)++;
1151
1152 SecondBus = (*SubBusNumber);
1153
1154 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1155
1156 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1157
1158 Status = PciRootBridgeIoWrite (
1159 PciRootBridgeIo,
1160 &Pci,
1161 EfiPciWidthUint16,
1162 Address,
1163 1,
1164 &Register
1165 );
1166
1167 //
1168 // Initialize SubBusNumber to SecondBus
1169 //
1170 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1171 Status = PciRootBridgeIoWrite (
1172 PciRootBridgeIo,
1173 &Pci,
1174 EfiPciWidthUint8,
1175 Address,
1176 1,
1177 SubBusNumber
1178 );
1179 //
1180 // If it is PPB, resursively search down this bridge
1181 //
1182 if (IS_PCI_BRIDGE (&Pci)) {
1183 //
1184 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1185 // PCI configuration transaction to go through any PPB
1186 //
1187 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1188 Register = 0xFF;
1189 Status = PciRootBridgeIoWrite (
1190 PciRootBridgeIo,
1191 &Pci,
1192 EfiPciWidthUint8,
1193 Address,
1194 1,
1195 &Register
1196 );
1197
1198 PreprocessController (
1199 PciDevice,
1200 PciDevice->BusNumber,
1201 PciDevice->DeviceNumber,
1202 PciDevice->FunctionNumber,
1203 EfiPciBeforeChildBusEnumeration
1204 );
1205
1206 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));
1207 Status = PciScanBus (
1208 PciDevice,
1209 (UINT8) (SecondBus),
1210 SubBusNumber,
1211 PaddedBusRange
1212 );
1213
1214 if (EFI_ERROR (Status)) {
1215 return EFI_DEVICE_ERROR;
1216 }
1217 }
1218
1219 //
1220 // Set the current maximum bus number under the PPB
1221 //
1222
1223 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1224
1225 Status = PciRootBridgeIoWrite (
1226 PciRootBridgeIo,
1227 &Pci,
1228 EfiPciWidthUint8,
1229 Address,
1230 1,
1231 SubBusNumber
1232 );
1233
1234 }
1235 }
1236 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1237
1238 //
1239 // Skip sub functions, this is not a multi function device
1240 //
1241
1242 Func = PCI_MAX_FUNC;
1243 }
1244 }
1245 }
1246
1247 return EFI_SUCCESS;
1248 }
1249
1250 /**
1251 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1252 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1253
1254 @param Bridge Bridge device instance.
1255 @param StartBusNumber start point.
1256 @param SubBusNumber Point to sub bus number.
1257 @param PaddedBusRange Customized bus number.
1258
1259 @retval EFI_SUCCESS Success.
1260 @retval EFI_DEVICE_ERROR Fail to scan bus.
1261 **/
1262 EFI_STATUS
1263 PciScanBus_WithHotPlugDeviceSupport (
1264 IN PCI_IO_DEVICE *Bridge,
1265 IN UINT8 StartBusNumber,
1266 OUT UINT8 *SubBusNumber,
1267 OUT UINT8 *PaddedBusRange
1268 )
1269 {
1270 EFI_STATUS Status;
1271 PCI_TYPE00 Pci;
1272 UINT8 Device;
1273 UINT8 Func;
1274 UINT64 Address;
1275 UINTN SecondBus;
1276 UINT16 Register;
1277 UINTN HpIndex;
1278 PCI_IO_DEVICE *PciDevice;
1279 EFI_EVENT Event;
1280 EFI_HPC_STATE State;
1281 UINT64 PciAddress;
1282 EFI_HPC_PADDING_ATTRIBUTES Attributes;
1283 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1284 UINT16 BusRange;
1285 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1286 BOOLEAN BusPadding;
1287
1288 PciRootBridgeIo = Bridge->PciRootBridgeIo;
1289 SecondBus = 0;
1290 Register = 0;
1291 State = 0;
1292 Attributes = (EFI_HPC_PADDING_ATTRIBUTES) 0;
1293 BusRange = 0;
1294
1295 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1296 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1297
1298 //
1299 // Check to see whether a pci device is present
1300 //
1301 Status = PciDevicePresent (
1302 PciRootBridgeIo,
1303 &Pci,
1304 StartBusNumber,
1305 Device,
1306 Func
1307 );
1308
1309 if (EFI_ERROR (Status)) {
1310 if (Func == 0) {
1311 //
1312 // Skip sub functions, this is not a multi function device
1313 //
1314 Func = PCI_MAX_FUNC;
1315 }
1316
1317 continue;
1318 }
1319
1320 DEBUG((EFI_D_ERROR, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));
1321
1322 //
1323 // Get the PCI device information
1324 //
1325 Status = PciSearchDevice (
1326 Bridge,
1327 &Pci,
1328 StartBusNumber,
1329 Device,
1330 Func,
1331 &PciDevice
1332 );
1333
1334 ASSERT (!EFI_ERROR (Status));
1335
1336 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
1337
1338 if (!IS_PCI_BRIDGE (&Pci)) {
1339 //
1340 // PCI bridges will be called later
1341 // Here just need for PCI device or PCI to cardbus controller
1342 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1343 //
1344 PreprocessController (
1345 PciDevice,
1346 PciDevice->BusNumber,
1347 PciDevice->DeviceNumber,
1348 PciDevice->FunctionNumber,
1349 EfiPciBeforeChildBusEnumeration
1350 );
1351 }
1352
1353 //
1354 // For Pci Hotplug controller devcie only
1355 //
1356 if (gPciHotPlugInit != NULL) {
1357 //
1358 // Check if it is a Hotplug PCI controller
1359 //
1360 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
1361
1362 if (!gPciRootHpcData[HpIndex].Initialized) {
1363
1364 Status = CreateEventForHpc (HpIndex, &Event);
1365
1366 ASSERT (!EFI_ERROR (Status));
1367
1368 Status = gPciHotPlugInit->InitializeRootHpc (
1369 gPciHotPlugInit,
1370 gPciRootHpcPool[HpIndex].HpcDevicePath,
1371 PciAddress,
1372 Event,
1373 &State
1374 );
1375
1376 PreprocessController (
1377 PciDevice,
1378 PciDevice->BusNumber,
1379 PciDevice->DeviceNumber,
1380 PciDevice->FunctionNumber,
1381 EfiPciBeforeChildBusEnumeration
1382 );
1383 }
1384 }
1385 }
1386
1387 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
1388 //
1389 // For PPB
1390 // Get the bridge information
1391 //
1392 BusPadding = FALSE;
1393 if (gPciHotPlugInit != NULL) {
1394
1395 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
1396
1397 //
1398 // If it is initialized, get the padded bus range
1399 //
1400 Status = gPciHotPlugInit->GetResourcePadding (
1401 gPciHotPlugInit,
1402 gPciRootHpcPool[HpIndex].HpbDevicePath,
1403 PciAddress,
1404 &State,
1405 (VOID **) &Descriptors,
1406 &Attributes
1407 );
1408
1409 if (EFI_ERROR (Status)) {
1410 return Status;
1411 }
1412
1413 BusRange = 0;
1414 Status = PciGetBusRange (
1415 &Descriptors,
1416 NULL,
1417 NULL,
1418 &BusRange
1419 );
1420
1421 FreePool (Descriptors);
1422
1423 if (EFI_ERROR (Status)) {
1424 return Status;
1425 }
1426
1427 BusPadding = TRUE;
1428 }
1429 }
1430
1431 //
1432 // Add feature to support customized secondary bus number
1433 //
1434 if (*SubBusNumber == 0) {
1435 *SubBusNumber = *PaddedBusRange;
1436 *PaddedBusRange = 0;
1437 }
1438
1439 (*SubBusNumber)++;
1440 SecondBus = *SubBusNumber;
1441
1442 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1443 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
1444
1445 Status = PciRootBridgeIoWrite (
1446 PciRootBridgeIo,
1447 &Pci,
1448 EfiPciWidthUint16,
1449 Address,
1450 1,
1451 &Register
1452 );
1453
1454
1455 //
1456 // If it is PPB, resursively search down this bridge
1457 //
1458 if (IS_PCI_BRIDGE (&Pci)) {
1459
1460 //
1461 // Initialize SubBusNumber to Maximum bus number
1462 //
1463 Register = 0xFF;
1464 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1465 Status = PciRootBridgeIoWrite (
1466 PciRootBridgeIo,
1467 &Pci,
1468 EfiPciWidthUint8,
1469 Address,
1470 1,
1471 &Register
1472 );
1473
1474 //
1475 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1476 //
1477 PreprocessController (
1478 PciDevice,
1479 PciDevice->BusNumber,
1480 PciDevice->DeviceNumber,
1481 PciDevice->FunctionNumber,
1482 EfiPciBeforeChildBusEnumeration
1483 );
1484
1485 DEBUG((EFI_D_ERROR, "Scan PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber ));
1486 Status = PciScanBus (
1487 PciDevice,
1488 (UINT8) (SecondBus),
1489 SubBusNumber,
1490 PaddedBusRange
1491 );
1492
1493 if (EFI_ERROR (Status)) {
1494 return EFI_DEVICE_ERROR;
1495 }
1496 }
1497
1498 if (BusPadding) {
1499 //
1500 // Ensure the device is enabled and initialized
1501 //
1502 if ((Attributes == EfiPaddingPciRootBridge) &&
1503 (State & EFI_HPC_STATE_ENABLED) != 0 &&
1504 (State & EFI_HPC_STATE_INITIALIZED) != 0) {
1505 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
1506 } else {
1507 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
1508 }
1509 }
1510
1511 //
1512 // Set the current maximum bus number under the PPB
1513 //
1514 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
1515
1516 Status = PciRootBridgeIoWrite (
1517 PciRootBridgeIo,
1518 &Pci,
1519 EfiPciWidthUint8,
1520 Address,
1521 1,
1522 SubBusNumber
1523 );
1524 }
1525
1526 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1527
1528 //
1529 // Skip sub functions, this is not a multi function device
1530 //
1531 Func = PCI_MAX_FUNC;
1532 }
1533
1534 }
1535 }
1536
1537 return EFI_SUCCESS;
1538 }
1539
1540 /**
1541 Process Option Rom on this host bridge.
1542
1543 @param Bridge Pci bridge device instance.
1544
1545 @retval EFI_SUCCESS Success.
1546 **/
1547 EFI_STATUS
1548 PciRootBridgeP2CProcess (
1549 IN PCI_IO_DEVICE *Bridge
1550 )
1551 {
1552 LIST_ENTRY *CurrentLink;
1553 PCI_IO_DEVICE *Temp;
1554 EFI_HPC_STATE State;
1555 UINT64 PciAddress;
1556 EFI_STATUS Status;
1557
1558 CurrentLink = Bridge->ChildList.ForwardLink;
1559
1560 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1561
1562 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1563
1564 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1565
1566 if (gPciHotPlugInit != NULL && Temp->Allocated) {
1567
1568 //
1569 // Raise the EFI_IOB_PCI_HPC_INIT status code
1570 //
1571 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1572 EFI_PROGRESS_CODE,
1573 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
1574 Temp->DevicePath
1575 );
1576
1577 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1578 Status = gPciHotPlugInit->InitializeRootHpc (
1579 gPciHotPlugInit,
1580 Temp->DevicePath,
1581 PciAddress,
1582 NULL,
1583 &State
1584 );
1585
1586 if (!EFI_ERROR (Status)) {
1587 Status = PciBridgeEnumerator (Temp);
1588
1589 if (EFI_ERROR (Status)) {
1590 return Status;
1591 }
1592 }
1593
1594 CurrentLink = CurrentLink->ForwardLink;
1595 continue;
1596
1597 }
1598 }
1599
1600 if (!IsListEmpty (&Temp->ChildList)) {
1601 Status = PciRootBridgeP2CProcess (Temp);
1602 }
1603
1604 CurrentLink = CurrentLink->ForwardLink;
1605 }
1606
1607 return EFI_SUCCESS;
1608 }
1609
1610 /**
1611 Process Option Rom on this host bridge.
1612
1613 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1614
1615 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1616 @retval EFI_SUCCESS Success process.
1617 **/
1618 EFI_STATUS
1619 PciHostBridgeP2CProcess (
1620 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1621 )
1622 {
1623 EFI_HANDLE RootBridgeHandle;
1624 PCI_IO_DEVICE *RootBridgeDev;
1625 EFI_STATUS Status;
1626
1627 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1628 return EFI_SUCCESS;
1629 }
1630
1631 RootBridgeHandle = NULL;
1632
1633 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1634
1635 //
1636 // Get RootBridg Device by handle
1637 //
1638 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1639
1640 if (RootBridgeDev == NULL) {
1641 return EFI_NOT_FOUND;
1642 }
1643
1644 Status = PciRootBridgeP2CProcess (RootBridgeDev);
1645
1646 if (EFI_ERROR (Status)) {
1647 return Status;
1648 }
1649
1650 }
1651
1652 return EFI_SUCCESS;
1653 }
1654
1655 /**
1656 This function is used to enumerate the entire host bridge
1657 in a given platform.
1658
1659 @param PciResAlloc A pointer to the resource allocate protocol.
1660
1661 @retval EFI_OUT_OF_RESOURCES no enough resource.
1662 @retval EFI_SUCCESS Success.
1663
1664 **/
1665 EFI_STATUS
1666 PciHostBridgeEnumerator (
1667 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1668 )
1669 {
1670 EFI_HANDLE RootBridgeHandle;
1671 PCI_IO_DEVICE *RootBridgeDev;
1672 EFI_STATUS Status;
1673 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1674 UINT16 MinBus;
1675 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1676 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1677 UINT8 StartBusNumber;
1678 LIST_ENTRY RootBridgeList;
1679 LIST_ENTRY *Link;
1680
1681 InitializeHotPlugSupport ();
1682
1683 InitializeListHead (&RootBridgeList);
1684
1685 //
1686 // Notify the bus allocation phase is about to start
1687 //
1688 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1689
1690 DEBUG((EFI_D_ERROR, "PCI Bus First Scanning\n"));
1691 RootBridgeHandle = NULL;
1692 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1693
1694 //
1695 // if a root bridge instance is found, create root bridge device for it
1696 //
1697
1698 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1699
1700 if (RootBridgeDev == NULL) {
1701 return EFI_OUT_OF_RESOURCES;
1702 }
1703
1704 //
1705 // Enumerate all the buses under this root bridge
1706 //
1707
1708 Status = PciRootBridgeEnumerator (
1709 PciResAlloc,
1710 RootBridgeDev
1711 );
1712
1713 if (gPciHotPlugInit != NULL) {
1714 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1715 } else {
1716 DestroyRootBridge (RootBridgeDev);
1717 }
1718 if (EFI_ERROR (Status)) {
1719 return Status;
1720 }
1721 }
1722
1723 //
1724 // Notify the bus allocation phase is finished for the first time
1725 //
1726 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1727
1728 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1729
1730 if (gPciHotPlugInit != NULL) {
1731 //
1732 // Reset all assigned PCI bus number in all PPB
1733 //
1734 RootBridgeHandle = NULL;
1735 Link = GetFirstNode (&RootBridgeList);
1736 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1737 (!IsNull (&RootBridgeList, Link))) {
1738 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1739 //
1740 // Get the Bus information
1741 //
1742 Status = PciResAlloc->StartBusEnumeration (
1743 PciResAlloc,
1744 RootBridgeHandle,
1745 (VOID **) &Configuration
1746 );
1747 if (EFI_ERROR (Status)) {
1748 return Status;
1749 }
1750
1751 //
1752 // Get the bus number to start with
1753 //
1754 StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
1755
1756 ResetAllPpbBusNumber (
1757 RootBridgeDev,
1758 StartBusNumber
1759 );
1760
1761 FreePool (Configuration);
1762 Link = GetNextNode (&RootBridgeList, Link);
1763 DestroyRootBridge (RootBridgeDev);
1764 }
1765
1766 //
1767 // Wait for all HPC initialized
1768 //
1769 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1770
1771 if (EFI_ERROR (Status)) {
1772 return Status;
1773 }
1774
1775 //
1776 // Notify the bus allocation phase is about to start for the 2nd time
1777 //
1778 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1779
1780 DEBUG((EFI_D_ERROR, "PCI Bus Second Scanning\n"));
1781 RootBridgeHandle = NULL;
1782 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1783
1784 //
1785 // if a root bridge instance is found, create root bridge device for it
1786 //
1787
1788 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1789
1790 if (RootBridgeDev == NULL) {
1791 return EFI_OUT_OF_RESOURCES;
1792 }
1793
1794 //
1795 // Enumerate all the buses under this root bridge
1796 //
1797
1798 Status = PciRootBridgeEnumerator (
1799 PciResAlloc,
1800 RootBridgeDev
1801 );
1802
1803 DestroyRootBridge (RootBridgeDev);
1804 if (EFI_ERROR (Status)) {
1805 return Status;
1806 }
1807 }
1808
1809 //
1810 // Notify the bus allocation phase is to end for the 2nd time
1811 //
1812 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1813 }
1814 }
1815
1816 //
1817 // Notify the resource allocation phase is to start
1818 //
1819 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1820
1821 RootBridgeHandle = NULL;
1822 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1823
1824 //
1825 // if a root bridge instance is found, create root bridge device for it
1826 //
1827
1828 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1829
1830 if (RootBridgeDev == NULL) {
1831 return EFI_OUT_OF_RESOURCES;
1832 }
1833
1834 Status = StartManagingRootBridge (RootBridgeDev);
1835
1836 if (EFI_ERROR (Status)) {
1837 return Status;
1838 }
1839
1840 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1841 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1842
1843 if (EFI_ERROR (Status)) {
1844 return Status;
1845 }
1846
1847 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1848
1849 if (EFI_ERROR (Status)) {
1850 return Status;
1851 }
1852
1853 //
1854 // Determine root bridge attribute by calling interface of Pcihostbridge
1855 // protocol
1856 //
1857 DetermineRootBridgeAttributes (
1858 PciResAlloc,
1859 RootBridgeDev
1860 );
1861
1862 //
1863 // Collect all the resource information under this root bridge
1864 // A database that records all the information about pci device subject to this
1865 // root bridge will then be created
1866 //
1867 Status = PciPciDeviceInfoCollector (
1868 RootBridgeDev,
1869 (UINT8) MinBus
1870 );
1871
1872 if (EFI_ERROR (Status)) {
1873 return Status;
1874 }
1875
1876 InsertRootBridge (RootBridgeDev);
1877
1878 //
1879 // Record the hostbridge handle
1880 //
1881 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1882 }
1883
1884 return EFI_SUCCESS;
1885 }
1886
1887 /**
1888 Read PCI device configuration register by specified address.
1889
1890 This function check the incompatiblilites on PCI device. Return the register
1891 value.
1892
1893 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1894 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1895 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1896 @param Width Signifies the width of the memory operations.
1897 @param Address The address within the PCI configuration space for the PCI controller.
1898 @param Buffer For read operations, the destination buffer to store the results. For
1899 write operations, the source buffer to write data from.
1900
1901 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1902 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1903 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1904 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1905
1906 **/
1907 EFI_STATUS
1908 ReadConfigData (
1909 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
1910 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
1911 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
1912 IN UINT64 Width,
1913 IN UINT64 Address,
1914 IN OUT VOID *Buffer
1915 )
1916 {
1917 EFI_STATUS Status;
1918 UINT64 AccessWidth;
1919 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
1920 UINT64 AccessAddress;
1921 UINTN Stride;
1922 UINT64 TempBuffer;
1923 UINT8 *Pointer;
1924
1925 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
1926
1927 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
1928 //
1929 // check access compatibility at first time
1930 //
1931 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, Address & 0xff, Width, &PciRegisterAccessData);
1932
1933 if (Status == EFI_SUCCESS) {
1934 //
1935 // there exist incompatibility on this operation
1936 //
1937 AccessWidth = Width;
1938
1939 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
1940 AccessWidth = PciRegisterAccessData->Width;
1941 }
1942
1943 AccessAddress = Address & ~((1 << AccessWidth) - 1);
1944
1945 TempBuffer = 0;
1946 Stride = 0;
1947 Pointer = (UINT8 *) &TempBuffer;
1948
1949 while (1) {
1950
1951 if (PciRootBridgeIo != NULL) {
1952 Status = PciRootBridgeIo->Pci.Read (
1953 PciRootBridgeIo,
1954 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
1955 AccessAddress,
1956 1,
1957 Pointer
1958 );
1959 } else if (PciIo != NULL) {
1960 Status = PciIo->Pci.Read (
1961 PciIo,
1962 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
1963 (UINT32) AccessAddress,
1964 1,
1965 Pointer
1966 );
1967 }
1968
1969 if (Status != EFI_SUCCESS) {
1970 return Status;
1971 }
1972
1973 Stride = (UINTN)1 << AccessWidth;
1974 AccessAddress += Stride;
1975 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {
1976 //
1977 // if all datas have been read, exist
1978 //
1979 break;
1980 }
1981
1982 Pointer += Stride;
1983
1984 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
1985 //
1986 // if current offset doesn't reach the end
1987 //
1988 continue;
1989 }
1990
1991 FreePool (PciRegisterAccessData);
1992
1993 //
1994 // continue checking access incompatibility
1995 //
1996 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_READ, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
1997 if (Status == EFI_SUCCESS) {
1998 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
1999 AccessWidth = PciRegisterAccessData->Width;
2000 }
2001 }
2002 }
2003
2004 FreePool (PciRegisterAccessData);
2005
2006 switch (Width) {
2007 case EfiPciWidthUint8:
2008 * (UINT8 *) Buffer = (UINT8) TempBuffer;
2009 break;
2010 case EfiPciWidthUint16:
2011 * (UINT16 *) Buffer = (UINT16) TempBuffer;
2012 break;
2013 case EfiPciWidthUint32:
2014 * (UINT32 *) Buffer = (UINT32) TempBuffer;
2015 break;
2016 default:
2017 return EFI_UNSUPPORTED;
2018 }
2019
2020 return Status;
2021 }
2022 }
2023 //
2024 // AccessWidth incompatible check not supportted
2025 // or, there doesn't exist incompatibility on this operation
2026 //
2027 if (PciRootBridgeIo != NULL) {
2028 Status = PciRootBridgeIo->Pci.Read (
2029 PciRootBridgeIo,
2030 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
2031 Address,
2032 1,
2033 Buffer
2034 );
2035
2036 } else {
2037 Status = PciIo->Pci.Read (
2038 PciIo,
2039 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
2040 (UINT32) Address,
2041 1,
2042 Buffer
2043 );
2044 }
2045
2046 return Status;
2047 }
2048
2049 /**
2050 Update register value by checking PCI device incompatibility.
2051
2052 This function check register value incompatibilites on PCI device. Return the register
2053 value.
2054
2055 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2056 @param AccessType Access type, READ or WRITE.
2057 @param Width Signifies the width of the memory operations.
2058 @param Address The address within the PCI configuration space.
2059 @param Buffer Store the register data.
2060
2061 @retval EFI_SUCCESS The data has been updated.
2062
2063 **/
2064 EFI_STATUS
2065 UpdateConfigData (
2066 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
2067 IN UINT64 AccessType,
2068 IN UINT64 Width,
2069 IN UINT64 Address,
2070 IN OUT VOID *Buffer
2071 )
2072 {
2073 EFI_STATUS Status;
2074 EFI_PCI_REGISTER_VALUE_DATA *PciRegisterData;
2075 UINT32 AndValue;
2076 UINT32 OrValue;
2077 UINT32 TempValue;
2078
2079 //
2080 // check register value incompatibility
2081 //
2082 Status = PciRegisterUpdateCheck (PciDeviceInfo, AccessType, Address & 0xff, &PciRegisterData);
2083
2084 if (Status == EFI_SUCCESS) {
2085
2086 AndValue = ((UINT32) PciRegisterData->AndValue) >> (((UINT8) Address & 0x3) * 8);
2087 OrValue = ((UINT32) PciRegisterData->OrValue) >> (((UINT8) Address & 0x3) * 8);
2088
2089 TempValue = * (UINT32 *) Buffer;
2090 if (PciRegisterData->AndValue != VALUE_NOCARE) {
2091 TempValue &= AndValue;
2092 }
2093 if (PciRegisterData->OrValue != VALUE_NOCARE) {
2094 TempValue |= OrValue;
2095 }
2096
2097 switch (Width) {
2098 case EfiPciWidthUint8:
2099 *(UINT8 *)Buffer = (UINT8) TempValue;
2100 break;
2101
2102 case EfiPciWidthUint16:
2103 *(UINT16 *)Buffer = (UINT16) TempValue;
2104 break;
2105 case EfiPciWidthUint32:
2106 *(UINT32 *)Buffer = TempValue;
2107 break;
2108
2109 default:
2110 return EFI_UNSUPPORTED;
2111 }
2112
2113 FreePool (PciRegisterData);
2114 }
2115
2116 return Status;
2117 }
2118
2119 /**
2120 Write PCI device configuration register by specified address.
2121
2122 This function check the incompatiblilites on PCI device, and write date
2123 into register.
2124
2125 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2126 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2127 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2128 @param Width Signifies the width of the memory operations.
2129 @param Address The address within the PCI configuration space for the PCI controller.
2130 @param Buffer For read operations, the destination buffer to store the results. For
2131 write operations, the source buffer to write data from.
2132
2133 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2134 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2135 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2136 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2137
2138 **/
2139 EFI_STATUS
2140 WriteConfigData (
2141 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2142 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2143 IN EFI_PCI_DEVICE_INFO *PciDeviceInfo,
2144 IN UINT64 Width,
2145 IN UINT64 Address,
2146 IN VOID *Buffer
2147 )
2148 {
2149 EFI_STATUS Status;
2150 UINT64 AccessWidth;
2151 EFI_PCI_REGISTER_ACCESS_DATA *PciRegisterAccessData;
2152 UINT64 AccessAddress;
2153 UINTN Stride;
2154 UINT8 *Pointer;
2155 UINT64 Data;
2156 UINTN Shift;
2157
2158 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2159
2160 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT) {
2161 //
2162 // check access compatibility at first time
2163 //
2164 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, Address & 0xff, Width, &PciRegisterAccessData);
2165
2166 if (Status == EFI_SUCCESS) {
2167 //
2168 // there exist incompatibility on this operation
2169 //
2170 AccessWidth = Width;
2171
2172 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
2173 AccessWidth = PciRegisterAccessData->Width;
2174 }
2175
2176 AccessAddress = Address & ~((1 << AccessWidth) - 1);
2177
2178 Stride = 0;
2179 Pointer = (UINT8 *) &Buffer;
2180 Data = * (UINT64 *) Buffer;
2181
2182 while (1) {
2183
2184 if (AccessWidth > Width) {
2185 //
2186 // if actual access width is larger than orignal one, additional data need to be read back firstly
2187 //
2188 Status = ReadConfigData (PciRootBridgeIo, PciIo, PciDeviceInfo, AccessWidth, AccessAddress, &Data);
2189 if (Status != EFI_SUCCESS) {
2190 return Status;
2191 }
2192
2193 //
2194 // check data read incompatibility
2195 //
2196 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_READ, AccessWidth, AccessAddress & 0xff, &Data);
2197
2198 Shift = (UINTN)(Address - AccessAddress) * 8;
2199 switch (Width) {
2200 case EfiPciWidthUint8:
2201 Data = (* (UINT8 *) Buffer) << Shift | (Data & ~(0xff << Shift));
2202 break;
2203
2204 case EfiPciWidthUint16:
2205 Data = (* (UINT16 *) Buffer) << Shift | (Data & ~(0xffff << Shift));
2206 break;
2207 }
2208
2209 //
2210 // check data write incompatibility
2211 //
2212 UpdateConfigData (PciDeviceInfo, PCI_REGISTER_WRITE, AccessWidth, MultU64x32 (AccessAddress, 0xff), &Data);
2213 }
2214
2215 if (PciRootBridgeIo != NULL) {
2216 Status = PciRootBridgeIo->Pci.Write (
2217 PciRootBridgeIo,
2218 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) AccessWidth,
2219 AccessAddress,
2220 1,
2221 &Data
2222 );
2223 } else {
2224 Status = PciIo->Pci.Write (
2225 PciIo,
2226 (EFI_PCI_IO_PROTOCOL_WIDTH) AccessWidth,
2227 (UINT32) AccessAddress,
2228 1,
2229 &Data
2230 );
2231 }
2232
2233 if (Status != EFI_SUCCESS) {
2234 return Status;
2235 }
2236
2237 Data = RShiftU64 (Data, ((1 << AccessWidth) * 8));
2238
2239 Stride = (UINTN)1 << AccessWidth;
2240 AccessAddress += Stride;
2241 if (AccessAddress >= (Address + LShiftU64 (1ULL, (UINTN)Width))) {
2242 //
2243 // if all datas have been written, exist
2244 //
2245 break;
2246 }
2247
2248 Pointer += Stride;
2249
2250 if ((AccessAddress & 0xff) < PciRegisterAccessData->EndOffset) {
2251 //
2252 // if current offset doesn't reach the end
2253 //
2254 continue;
2255 }
2256
2257 FreePool (PciRegisterAccessData);
2258
2259 //
2260 // continue checking access incompatibility
2261 //
2262 Status = PciRegisterAccessCheck (PciDeviceInfo, PCI_REGISTER_WRITE, AccessAddress & 0xff, AccessWidth, &PciRegisterAccessData);
2263 if (Status == EFI_SUCCESS) {
2264 if (PciRegisterAccessData->Width != VALUE_NOCARE) {
2265 AccessWidth = PciRegisterAccessData->Width;
2266 }
2267 }
2268 };
2269
2270 FreePool (PciRegisterAccessData);
2271
2272 return Status;
2273 }
2274
2275 }
2276 //
2277 // AccessWidth incompatible check not supportted
2278 // or, there doesn't exist incompatibility on this operation
2279 //
2280 if (PciRootBridgeIo != NULL) {
2281 Status = PciRootBridgeIo->Pci.Write (
2282 PciRootBridgeIo,
2283 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
2284 Address,
2285 1,
2286 Buffer
2287 );
2288 } else {
2289 Status = PciIo->Pci.Write (
2290 PciIo,
2291 (EFI_PCI_IO_PROTOCOL_WIDTH) Width,
2292 (UINT32) Address,
2293 1,
2294 Buffer
2295 );
2296 }
2297
2298 return Status;
2299 }
2300
2301 /**
2302 Abstract PCI device device information.
2303
2304 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2305 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2306 @param Pci A pointer to PCI_TYPE00.
2307 @param Address The address within the PCI configuration space for the PCI controller.
2308 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2309
2310 @retval EFI_SUCCESS Pci device device information has been abstracted.
2311
2312 **/
2313 EFI_STATUS
2314 GetPciDeviceDeviceInfo (
2315 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2316 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2317 IN PCI_TYPE00 *Pci, OPTIONAL
2318 IN UINT64 Address, OPTIONAL
2319 OUT EFI_PCI_DEVICE_INFO *PciDeviceInfo
2320 )
2321 {
2322 EFI_STATUS Status;
2323 UINT64 PciAddress;
2324 UINT32 PciConfigData;
2325 PCI_IO_DEVICE *PciIoDevice;
2326
2327 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2328
2329 if (PciIo != NULL) {
2330 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2331
2332 //
2333 // get pointer to PCI_TYPE00 from PciIoDevice
2334 //
2335 Pci = &PciIoDevice->Pci;
2336 }
2337
2338 if (Pci == NULL) {
2339 //
2340 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2341 //
2342 PciAddress = Address & 0xffffffffffffff00ULL;
2343 Status = PciRootBridgeIo->Pci.Read (
2344 PciRootBridgeIo,
2345 EfiPciWidthUint32,
2346 PciAddress,
2347 1,
2348 &PciConfigData
2349 );
2350
2351 if (EFI_ERROR (Status)) {
2352 return Status;
2353 }
2354
2355 if ((PciConfigData & 0xffff) == 0xffff) {
2356 return EFI_NOT_FOUND;
2357 }
2358
2359 PciDeviceInfo->VendorID = PciConfigData & 0xffff;
2360 PciDeviceInfo->DeviceID = PciConfigData >> 16;
2361
2362 Status = PciRootBridgeIo->Pci.Read (
2363 PciRootBridgeIo,
2364 EfiPciWidthUint32,
2365 PciAddress + 8,
2366 1,
2367 &PciConfigData
2368 );
2369 if (EFI_ERROR (Status)) {
2370 return Status;
2371 }
2372
2373 PciDeviceInfo->RevisionID = PciConfigData & 0xf;
2374
2375 Status = PciRootBridgeIo->Pci.Read (
2376 PciRootBridgeIo,
2377 EfiPciWidthUint32,
2378 PciAddress + 0x2c,
2379 1,
2380 &PciConfigData
2381 );
2382
2383 if (EFI_ERROR (Status)) {
2384 return Status;
2385 }
2386
2387 PciDeviceInfo->SubsystemVendorID = PciConfigData & 0xffff;
2388 PciDeviceInfo->SubsystemID = PciConfigData >> 16;
2389
2390 } else {
2391 PciDeviceInfo->VendorID = Pci->Hdr.VendorId;
2392 PciDeviceInfo->DeviceID = Pci->Hdr.DeviceId;
2393 PciDeviceInfo->RevisionID = Pci->Hdr.RevisionID;
2394 PciDeviceInfo->SubsystemVendorID = Pci->Device.SubsystemVendorID;
2395 PciDeviceInfo->SubsystemID = Pci->Device.SubsystemID;
2396 }
2397
2398 return EFI_SUCCESS;
2399 }
2400
2401 /**
2402 Read PCI configuration space with incompatibility check.
2403
2404 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2405 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2406 @param Pci A pointer to PCI_TYPE00.
2407 @param Width Signifies the width of the memory operations.
2408 @param Address The address within the PCI configuration space for the PCI controller.
2409 @param Count The number of unit to be read.
2410 @param Buffer For read operations, the destination buffer to store the results. For
2411 write operations, the source buffer to write data from.
2412
2413 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2414 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2415 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2416 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2417
2418 **/
2419 EFI_STATUS
2420 PciIncompatibilityCheckRead (
2421 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2422 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2423 IN PCI_TYPE00 *Pci, OPTIONAL
2424 IN UINTN Width,
2425 IN UINT64 Address,
2426 IN UINTN Count,
2427 IN OUT VOID *Buffer
2428 )
2429 {
2430 EFI_STATUS Status;
2431 EFI_PCI_DEVICE_INFO PciDeviceInfo;
2432 UINT32 Stride;
2433
2434 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2435
2436 //
2437 // get PCI device device information
2438 //
2439 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
2440 if (Status != EFI_SUCCESS) {
2441 return Status;
2442 }
2443
2444 Stride = 1 << Width;
2445
2446 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *)Buffer + Stride) {
2447
2448 //
2449 // read configuration register
2450 //
2451 Status = ReadConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, (UINT64) Width, Address, Buffer);
2452
2453 if (Status != EFI_SUCCESS) {
2454 return Status;
2455 }
2456
2457 //
2458 // update the data read from configuration register
2459 //
2460 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
2461 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_READ, Width, Address & 0xff, Buffer);
2462 }
2463 }
2464
2465 return EFI_SUCCESS;
2466 }
2467
2468 /**
2469 Write PCI configuration space with incompatibility check.
2470
2471 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2472 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2473 @param Pci A pointer to PCI_TYPE00.
2474 @param Width Signifies the width of the memory operations.
2475 @param Address The address within the PCI configuration space for the PCI controller.
2476 @param Count The number of unit to be write.
2477 @param Buffer For read operations, the destination buffer to store the results. For
2478 write operations, the source buffer to write data from.
2479
2480 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2481 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2482 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2483 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2484
2485 **/
2486 EFI_STATUS
2487 PciIncompatibilityCheckWrite (
2488 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OPTIONAL
2489 IN EFI_PCI_IO_PROTOCOL *PciIo, OPTIONAL
2490 IN PCI_TYPE00 *Pci, OPTIONAL
2491 IN UINTN Width,
2492 IN UINT64 Address,
2493 IN UINTN Count,
2494 IN OUT VOID *Buffer
2495 )
2496 {
2497 EFI_STATUS Status;
2498 EFI_PCI_DEVICE_INFO PciDeviceInfo;
2499 UINT32 Stride;
2500 UINT64 Data;
2501
2502 ASSERT ((PciRootBridgeIo == NULL) ^ (PciIo == NULL));
2503
2504 //
2505 // get PCI device device information
2506 //
2507 Status = GetPciDeviceDeviceInfo (PciRootBridgeIo, PciIo, Pci, Address, &PciDeviceInfo);
2508 if (Status != EFI_SUCCESS) {
2509 return Status;
2510 }
2511
2512 Stride = 1 << Width;
2513
2514 for (; Count > 0; Count--, Address += Stride, Buffer = (UINT8 *) Buffer + Stride) {
2515
2516 Data = 0;
2517
2518 switch (Width) {
2519 case EfiPciWidthUint8:
2520 Data = * (UINT8 *) Buffer;
2521 break;
2522 case EfiPciWidthUint16:
2523 Data = * (UINT16 *) Buffer;
2524 break;
2525
2526 case EfiPciWidthUint32:
2527 Data = * (UINT32 *) Buffer;
2528 break;
2529
2530 default:
2531 return EFI_UNSUPPORTED;
2532 }
2533
2534 //
2535 // update the data writen into configuration register
2536 //
2537 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT) {
2538 UpdateConfigData (&PciDeviceInfo, PCI_REGISTER_WRITE, Width, Address & 0xff, &Data);
2539 }
2540
2541 //
2542 // write configuration register
2543 //
2544 Status = WriteConfigData (PciRootBridgeIo, PciIo, &PciDeviceInfo, Width, Address, &Data);
2545
2546 if (Status != EFI_SUCCESS) {
2547 return Status;
2548 }
2549 }
2550
2551 return EFI_SUCCESS;
2552 }
2553
2554 /**
2555 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2556
2557 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2558 @param Pci A pointer to PCI_TYPE00.
2559 @param Width Signifies the width of the memory operations.
2560 @param Address The address within the PCI configuration space for the PCI controller.
2561 @param Count The number of unit to be read.
2562 @param Buffer For read operations, the destination buffer to store the results. For
2563 write operations, the source buffer to write data from.
2564
2565 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2566 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2567 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2568 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2569
2570 **/
2571 EFI_STATUS
2572 PciRootBridgeIoRead (
2573 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
2574 IN PCI_TYPE00 *Pci, OPTIONAL
2575 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
2576 IN UINT64 Address,
2577 IN UINTN Count,
2578 IN OUT VOID *Buffer
2579 )
2580 {
2581 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
2582 //
2583 // if PCI incompatibility check enabled
2584 //
2585 return PciIncompatibilityCheckRead (
2586 PciRootBridgeIo,
2587 NULL,
2588 Pci,
2589 (UINTN) Width,
2590 Address,
2591 Count,
2592 Buffer
2593 );
2594 } else {
2595 return PciRootBridgeIo->Pci.Read (
2596 PciRootBridgeIo,
2597 Width,
2598 Address,
2599 Count,
2600 Buffer
2601 );
2602 }
2603 }
2604
2605 /**
2606 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2607
2608 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2609 @param Pci A pointer to PCI_TYPE00.
2610 @param Width Signifies the width of the memory operations.
2611 @param Address The address within the PCI configuration space for the PCI controller.
2612 @param Count The number of unit to be read.
2613 @param Buffer For read operations, the destination buffer to store the results. For
2614 write operations, the source buffer to write data from.
2615
2616 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2617 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2618 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2619 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2620
2621 **/
2622 EFI_STATUS
2623 PciRootBridgeIoWrite (
2624 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
2625 IN PCI_TYPE00 *Pci,
2626 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
2627 IN UINT64 Address,
2628 IN UINTN Count,
2629 IN OUT VOID *Buffer
2630 )
2631 {
2632 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
2633 //
2634 // if PCI incompatibility check enabled
2635 //
2636 return PciIncompatibilityCheckWrite (
2637 PciRootBridgeIo,
2638 NULL,
2639 Pci,
2640 Width,
2641 Address,
2642 Count,
2643 Buffer
2644 );
2645
2646 } else {
2647 return PciRootBridgeIo->Pci.Write (
2648 PciRootBridgeIo,
2649 Width,
2650 Address,
2651 Count,
2652 Buffer
2653 );
2654 }
2655 }
2656
2657 /**
2658 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2659
2660 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2661 @param Width Signifies the width of the memory operations.
2662 @param Address The address within the PCI configuration space for the PCI controller.
2663 @param Count The number of unit to be read.
2664 @param Buffer For read operations, the destination buffer to store the results. For
2665 write operations, the source buffer to write data from.
2666
2667 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2668 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2669 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2670 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2671
2672 **/
2673 EFI_STATUS
2674 PciIoRead (
2675 IN EFI_PCI_IO_PROTOCOL *PciIo,
2676 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
2677 IN UINT32 Address,
2678 IN UINTN Count,
2679 IN OUT VOID *Buffer
2680 )
2681 {
2682 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_READ_SUPPORT) {
2683 //
2684 // if PCI incompatibility check enabled
2685 //
2686 return PciIncompatibilityCheckRead (
2687 NULL,
2688 PciIo,
2689 NULL,
2690 (UINTN) Width,
2691 Address,
2692 Count,
2693 Buffer
2694 );
2695 } else {
2696 return PciIo->Pci.Read (
2697 PciIo,
2698 Width,
2699 Address,
2700 Count,
2701 Buffer
2702 );
2703 }
2704 }
2705
2706 /**
2707 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2708
2709 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2710 @param Width Signifies the width of the memory operations.
2711 @param Address The address within the PCI configuration space for the PCI controller.
2712 @param Count The number of unit to be read.
2713 @param Buffer For read operations, the destination buffer to store the results. For
2714 write operations, the source buffer to write data from.
2715
2716 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2717 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2718 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2719 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2720
2721 **/
2722 EFI_STATUS
2723 PciIoWrite (
2724 IN EFI_PCI_IO_PROTOCOL *PciIo,
2725 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
2726 IN UINT32 Address,
2727 IN UINTN Count,
2728 IN OUT VOID *Buffer
2729 )
2730 {
2731 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_WRITE_SUPPORT) {
2732
2733 //
2734 // if PCI incompatibility check enabled
2735 //
2736 return PciIncompatibilityCheckWrite (
2737 NULL,
2738 PciIo,
2739 NULL,
2740 Width,
2741 Address,
2742 Count,
2743 Buffer
2744 );
2745
2746 } else {
2747 return PciIo->Pci.Write (
2748 PciIo,
2749 Width,
2750 Address,
2751 Count,
2752 Buffer
2753 );
2754 }
2755 }
2756