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