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