1) Use FeatureFlag PcdPciBusHotplugDeviceSupport to merge LightPciLib.c with PcdLib.c.
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / LightPciLib.c
1 /*++
2
3 Copyright (c) 2006, 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 LightPciLib.c
15
16 Abstract:
17
18 Light 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 //
29 // Light PCI bus driver woundn't support hotplug device
30 // So just return
31 //
32 VOID
33 InstallHotPlugRequestProtocol (
34 IN EFI_STATUS *Status
35 )
36 /*++
37
38 Routine Description:
39
40
41 Arguments:
42
43 Returns:
44
45 None
46
47 --*/
48 // TODO: Status - add argument and description to function comment
49 {
50 return ;
51 }
52
53 //
54 // Light PCI bus driver woundn't support hotplug device
55 // So just skip install this GUID
56 //
57 VOID
58 InstallPciHotplugGuid (
59 IN PCI_IO_DEVICE *PciIoDevice
60 )
61 /*++
62
63 Routine Description:
64
65
66 Arguments:
67
68 Returns:
69
70 None
71
72 --*/
73 // TODO: PciIoDevice - add argument and description to function comment
74 {
75 return ;
76 }
77
78 //
79 // Light PCI bus driver woundn't support hotplug device
80 // So just skip uninstall the GUID
81 //
82 VOID
83 UninstallPciHotplugGuid (
84 IN PCI_IO_DEVICE *PciIoDevice
85 )
86 /*++
87
88 Routine Description:
89
90
91 Arguments:
92
93 Returns:
94
95 None
96
97 --*/
98 // TODO: PciIoDevice - add argument and description to function comment
99 {
100 return ;
101 }
102
103 //
104 // Light PCI bus driver woundn't support PCCard
105 // So it needn't get the bar of CardBus
106 //
107 VOID
108 GetBackPcCardBar (
109 IN PCI_IO_DEVICE *PciIoDevice
110 )
111 /*++
112
113 Routine Description:
114
115 TODO: Add function description
116
117 Arguments:
118
119 PciIoDevice - TODO: add argument description
120
121 Returns:
122
123 TODO: add return values
124
125 --*/
126 {
127 return ;
128 }
129
130 //
131 // Light PCI bus driver woundn't support resource reallocation
132 // So just return
133 //
134 EFI_STATUS
135 RemoveRejectedPciDevices (
136 EFI_HANDLE RootBridgeHandle,
137 IN PCI_IO_DEVICE *Bridge
138 )
139 /*++
140
141 Routine Description:
142
143 TODO: Add function description
144
145 Arguments:
146
147 RootBridgeHandle - TODO: add argument description
148 Bridge - TODO: add argument description
149
150 Returns:
151
152 EFI_SUCCESS - TODO: Add description for return value
153
154 --*/
155 {
156 return EFI_SUCCESS;
157 }
158
159 //
160 // Light PCI bus driver woundn't support resource reallocation
161 // Simplified the code
162 //
163 EFI_STATUS
164 PciHostBridgeResourceAllocator (
165 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
166 )
167 /*++
168
169 Routine Description:
170
171 Arguments:
172
173 Returns:
174
175 None
176
177 --*/
178 // TODO: PciResAlloc - add argument and description to function comment
179 // TODO: EFI_NOT_FOUND - add return value to function comment
180 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
181 // TODO: EFI_NOT_FOUND - add return value to function comment
182 // TODO: EFI_SUCCESS - add return value to function comment
183 {
184 PCI_IO_DEVICE *RootBridgeDev;
185 EFI_HANDLE RootBridgeHandle;
186 VOID *AcpiConfig;
187 EFI_STATUS Status;
188 UINT64 IoBase;
189 UINT64 Mem32Base;
190 UINT64 PMem32Base;
191 UINT64 Mem64Base;
192 UINT64 PMem64Base;
193 UINT64 MaxOptionRomSize;
194 PCI_RESOURCE_NODE *IoBridge;
195 PCI_RESOURCE_NODE *Mem32Bridge;
196 PCI_RESOURCE_NODE *PMem32Bridge;
197 PCI_RESOURCE_NODE *Mem64Bridge;
198 PCI_RESOURCE_NODE *PMem64Bridge;
199 PCI_RESOURCE_NODE IoPool;
200 PCI_RESOURCE_NODE Mem32Pool;
201 PCI_RESOURCE_NODE PMem32Pool;
202 PCI_RESOURCE_NODE Mem64Pool;
203 PCI_RESOURCE_NODE PMem64Pool;
204 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
205
206 //
207 // Initialize resource pool
208 //
209
210 InitializeResourcePool (&IoPool, PciBarTypeIo16);
211 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
212 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
213 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
214 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
215
216 RootBridgeDev = NULL;
217 RootBridgeHandle = 0;
218
219 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
220 //
221 // Get RootBridg Device by handle
222 //
223 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
224
225 if (RootBridgeDev == NULL) {
226 return EFI_NOT_FOUND;
227 }
228
229 //
230 // Get host bridge handle for status report
231 //
232 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
233
234 //
235 // Create the entire system resource map from the information collected by
236 // enumerator. Several resource tree was created
237 //
238
239 IoBridge = CreateResourceNode (
240 RootBridgeDev,
241 0,
242 0xFFF,
243 0,
244 PciBarTypeIo16,
245 PciResUsageTypical
246 );
247
248 Mem32Bridge = CreateResourceNode (
249 RootBridgeDev,
250 0,
251 0xFFFFF,
252 0,
253 PciBarTypeMem32,
254 PciResUsageTypical
255 );
256
257 PMem32Bridge = CreateResourceNode (
258 RootBridgeDev,
259 0,
260 0xFFFFF,
261 0,
262 PciBarTypePMem32,
263 PciResUsageTypical
264 );
265
266 Mem64Bridge = CreateResourceNode (
267 RootBridgeDev,
268 0,
269 0xFFFFF,
270 0,
271 PciBarTypeMem64,
272 PciResUsageTypical
273 );
274
275 PMem64Bridge = CreateResourceNode (
276 RootBridgeDev,
277 0,
278 0xFFFFF,
279 0,
280 PciBarTypePMem64,
281 PciResUsageTypical
282 );
283
284 //
285 // Create resourcemap by going through all the devices subject to this root bridge
286 //
287 Status = CreateResourceMap (
288 RootBridgeDev,
289 IoBridge,
290 Mem32Bridge,
291 PMem32Bridge,
292 Mem64Bridge,
293 PMem64Bridge
294 );
295
296 //
297 // Get the max ROM size that the root bridge can process
298 //
299 RootBridgeDev->RomSize = Mem32Bridge->Length;
300
301 //
302 // Get Max Option Rom size for current root bridge
303 //
304 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
305
306 //
307 // Enlarger the mem32 resource to accomdate the option rom
308 // if the mem32 resource is not enough to hold the rom
309 //
310 if (MaxOptionRomSize > Mem32Bridge->Length) {
311
312 Mem32Bridge->Length = MaxOptionRomSize;
313 RootBridgeDev->RomSize = MaxOptionRomSize;
314
315 //
316 // Alignment should be adjusted as well
317 //
318 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
319 Mem32Bridge->Alignment = MaxOptionRomSize - 1;
320 }
321 }
322
323 //
324 // Based on the all the resource tree, contruct ACPI resource node to
325 // submit the resource aperture to pci host bridge protocol
326 //
327 Status = ConstructAcpiResourceRequestor (
328 RootBridgeDev,
329 IoBridge,
330 Mem32Bridge,
331 PMem32Bridge,
332 Mem64Bridge,
333 PMem64Bridge,
334 &AcpiConfig
335 );
336
337 //
338 // Insert these resource nodes into the database
339 //
340 InsertResourceNode (&IoPool, IoBridge);
341 InsertResourceNode (&Mem32Pool, Mem32Bridge);
342 InsertResourceNode (&PMem32Pool, PMem32Bridge);
343 InsertResourceNode (&Mem64Pool, Mem64Bridge);
344 InsertResourceNode (&PMem64Pool, PMem64Bridge);
345
346 if (Status == EFI_SUCCESS) {
347 //
348 // Submit the resource requirement
349 //
350 Status = PciResAlloc->SubmitResources (
351 PciResAlloc,
352 RootBridgeDev->Handle,
353 AcpiConfig
354 );
355 }
356 //
357 // Free acpi resource node
358 //
359 if (AcpiConfig) {
360 gBS->FreePool (AcpiConfig);
361 }
362
363 if (EFI_ERROR (Status)) {
364 //
365 // Destroy all the resource tree
366 //
367 DestroyResourceTree (&IoPool);
368 DestroyResourceTree (&Mem32Pool);
369 DestroyResourceTree (&PMem32Pool);
370 DestroyResourceTree (&Mem64Pool);
371 DestroyResourceTree (&PMem64Pool);
372 return Status;
373 }
374 }
375 //
376 // End while
377 //
378
379 //
380 // Notify pci bus driver starts to program the resource
381 //
382 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
383
384 if (EFI_ERROR (Status)) {
385 //
386 // Allocation failed, then return
387 //
388 return EFI_OUT_OF_RESOURCES;
389 }
390 //
391 // Raise the EFI_IOB_PCI_RES_ALLOC status code
392 //
393 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
394 EFI_PROGRESS_CODE,
395 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
396 (VOID *) &ExtendedData,
397 sizeof (ExtendedData)
398 );
399
400 //
401 // Notify pci bus driver starts to program the resource
402 //
403 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
404
405 RootBridgeDev = NULL;
406
407 RootBridgeHandle = 0;
408
409 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
410 //
411 // Get RootBridg Device by handle
412 //
413 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
414
415 if (RootBridgeDev == NULL) {
416 return EFI_NOT_FOUND;
417 }
418
419 //
420 // Get acpi resource node for all the resource types
421 //
422 AcpiConfig = NULL;
423 Status = PciResAlloc->GetProposedResources (
424 PciResAlloc,
425 RootBridgeDev->Handle,
426 &AcpiConfig
427 );
428
429 if (EFI_ERROR (Status)) {
430 return Status;
431 }
432
433 //
434 // Get the resource base by interpreting acpi resource node
435 //
436 //
437 GetResourceBase (
438 AcpiConfig,
439 &IoBase,
440 &Mem32Base,
441 &PMem32Base,
442 &Mem64Base,
443 &PMem64Base
444 );
445
446 //
447 // Process option rom for this root bridge
448 //
449 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
450
451 //
452 // Create the entire system resource map from the information collected by
453 // enumerator. Several resource tree was created
454 //
455 Status = GetResourceMap (
456 RootBridgeDev,
457 &IoBridge,
458 &Mem32Bridge,
459 &PMem32Bridge,
460 &Mem64Bridge,
461 &PMem64Bridge,
462 &IoPool,
463 &Mem32Pool,
464 &PMem32Pool,
465 &Mem64Pool,
466 &PMem64Pool
467 );
468
469 if (EFI_ERROR (Status)) {
470 return Status;
471 }
472
473 //
474 // Program IO resources
475 //
476 ProgramResource (
477 IoBase,
478 IoBridge
479 );
480
481 //
482 // Program Mem32 resources
483 //
484 ProgramResource (
485 Mem32Base,
486 Mem32Bridge
487 );
488
489 //
490 // Program PMem32 resources
491 //
492 ProgramResource (
493 PMem32Base,
494 PMem32Bridge
495 );
496
497 //
498 // Program Mem64 resources
499 //
500 ProgramResource (
501 Mem64Base,
502 Mem64Bridge
503 );
504
505 //
506 // Program PMem64 resources
507 //
508 ProgramResource (
509 PMem64Base,
510 PMem64Bridge
511 );
512
513 if (AcpiConfig != NULL) {
514 gBS->FreePool (AcpiConfig);
515 }
516 }
517
518 //
519 // Destroy all the resource tree
520 //
521 DestroyResourceTree (&IoPool);
522 DestroyResourceTree (&Mem32Pool);
523 DestroyResourceTree (&PMem32Pool);
524 DestroyResourceTree (&Mem64Pool);
525 DestroyResourceTree (&PMem64Pool);
526
527 //
528 // Notify the resource allocation phase is to end
529 //
530 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
531
532 return EFI_SUCCESS;
533 }
534
535 EFI_STATUS
536 PciScanBus (
537 IN PCI_IO_DEVICE *Bridge,
538 IN UINT8 StartBusNumber,
539 OUT UINT8 *SubBusNumber,
540 OUT UINT8 *PaddedBusRange
541 )
542 /*++
543
544 Routine Description:
545
546 This routine is used to assign bus number to the given PCI bus system
547
548 Arguments:
549
550 Returns:
551
552 None
553
554 --*/
555 // TODO: Bridge - add argument and description to function comment
556 // TODO: StartBusNumber - add argument and description to function comment
557 // TODO: SubBusNumber - add argument and description to function comment
558 // TODO: PaddedBusRange - add argument and description to function comment
559 // TODO: EFI_DEVICE_ERROR - add return value to function comment
560 // TODO: EFI_SUCCESS - add return value to function comment
561 {
562 EFI_STATUS Status;
563 PCI_TYPE00 Pci;
564 UINT8 Device;
565 UINT8 Func;
566 UINT64 Address;
567 UINTN SecondBus;
568 UINT16 Register;
569 PCI_IO_DEVICE *PciDevice;
570 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
571
572 PciRootBridgeIo = Bridge->PciRootBridgeIo;
573 SecondBus = 0;
574 Register = 0;
575
576 ResetAllPpbBusReg (Bridge, StartBusNumber);
577
578 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
579 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
580
581 //
582 // Check to see whether a pci device is present
583 //
584 Status = PciDevicePresent (
585 PciRootBridgeIo,
586 &Pci,
587 StartBusNumber,
588 Device,
589 Func
590 );
591
592 if (!EFI_ERROR (Status) &&
593 (IS_PCI_BRIDGE (&Pci) ||
594 IS_CARDBUS_BRIDGE (&Pci))) {
595
596 //
597 // Get the bridge information
598 //
599 Status = PciSearchDevice (
600 Bridge,
601 &Pci,
602 StartBusNumber,
603 Device,
604 Func,
605 &PciDevice
606 );
607
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611
612 (*SubBusNumber)++;
613
614 SecondBus = (*SubBusNumber);
615
616 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
617
618 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
619
620 Status = PciRootBridgeIo->Pci.Write (
621 PciRootBridgeIo,
622 EfiPciWidthUint16,
623 Address,
624 1,
625 &Register
626 );
627
628 //
629 // Initialize SubBusNumber to SecondBus
630 //
631 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
632 Status = PciRootBridgeIo->Pci.Write (
633 PciRootBridgeIo,
634 EfiPciWidthUint8,
635 Address,
636 1,
637 SubBusNumber
638 );
639 //
640 // If it is PPB, resursively search down this bridge
641 //
642 if (IS_PCI_BRIDGE (&Pci)) {
643 //
644 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
645 // PCI configuration transaction to go through any PPB
646 //
647 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
648 Register = 0xFF;
649 Status = PciRootBridgeIo->Pci.Write (
650 PciRootBridgeIo,
651 EfiPciWidthUint8,
652 Address,
653 1,
654 &Register
655 );
656
657 PreprocessController (
658 PciDevice,
659 PciDevice->BusNumber,
660 PciDevice->DeviceNumber,
661 PciDevice->FunctionNumber,
662 EfiPciBeforeChildBusEnumeration
663 );
664
665 Status = PciScanBus (
666 PciDevice,
667 (UINT8) (SecondBus),
668 SubBusNumber,
669 PaddedBusRange
670 );
671
672 if (EFI_ERROR (Status)) {
673 return EFI_DEVICE_ERROR;
674 }
675 }
676
677 //
678 // Set the current maximum bus number under the PPB
679 //
680
681 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
682
683 Status = PciRootBridgeIo->Pci.Write (
684 PciRootBridgeIo,
685 EfiPciWidthUint8,
686 Address,
687 1,
688 SubBusNumber
689 );
690
691 }
692
693 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
694
695 //
696 // Skip sub functions, this is not a multi function device
697 //
698
699 Func = PCI_MAX_FUNC;
700 }
701 }
702 }
703
704 return EFI_SUCCESS;
705 }
706
707 //
708 // Light PCI bus driver woundn't support P2C
709 // Return instead
710 //
711 EFI_STATUS
712 PciHostBridgeP2CProcess (
713 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
714 )
715 /*++
716
717 Routine Description:
718
719 Arguments:
720
721 Returns:
722
723 None
724
725 --*/
726 // TODO: PciResAlloc - add argument and description to function comment
727 // TODO: EFI_SUCCESS - add return value to function comment
728 {
729 return EFI_SUCCESS;
730 }
731
732 //
733 // Light PCI bus driver woundn't support hotplug device
734 // Simplified the code
735 //
736 EFI_STATUS
737 PciHostBridgeEnumerator (
738 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
739 )
740 /*++
741
742 Routine Description:
743
744 This function is used to enumerate the entire host bridge
745 in a given platform
746
747 Arguments:
748
749 PciResAlloc A pointer to the protocol to allocate resource.
750
751 Returns:
752
753 None
754
755 --*/
756 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
757 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
758 // TODO: EFI_SUCCESS - add return value to function comment
759 {
760 EFI_HANDLE RootBridgeHandle;
761 PCI_IO_DEVICE *RootBridgeDev;
762 EFI_STATUS Status;
763 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
764 UINT16 MinBus;
765 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
766
767 InitializeHotPlugSupport ();
768
769 //
770 // Notify the bus allocation phase is about to start
771 //
772 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
773
774 RootBridgeHandle = NULL;
775 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
776
777 //
778 // if a root bridge instance is found, create root bridge device for it
779 //
780
781 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
782
783 if (RootBridgeDev == NULL) {
784 return EFI_OUT_OF_RESOURCES;
785 }
786
787 //
788 // Enumerate all the buses under this root bridge
789 //
790
791 Status = PciRootBridgeEnumerator (
792 PciResAlloc,
793 RootBridgeDev
794 );
795
796 if (EFI_ERROR (Status)) {
797 return Status;
798 }
799
800 DestroyRootBridge (RootBridgeDev);
801
802 //
803 // Error proccess here
804 //
805 }
806
807 //
808 // Notify the bus allocation phase is to end
809 //
810 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
811
812 //
813 // Notify the resource allocation phase is to start
814 //
815 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
816
817 RootBridgeHandle = NULL;
818 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
819
820 //
821 // if a root bridge instance is found, create root bridge device for it
822 //
823
824 RootBridgeDev = CreateRootBridge (RootBridgeHandle);
825
826 if (RootBridgeDev == NULL) {
827 return EFI_OUT_OF_RESOURCES;
828 }
829
830 Status = StartManagingRootBridge (RootBridgeDev);
831
832 if (EFI_ERROR (Status)) {
833 return Status;
834 }
835
836 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
837 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
838
839 if (EFI_ERROR (Status)) {
840 return Status;
841 }
842
843 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
844
845 if (EFI_ERROR (Status)) {
846 return Status;
847 }
848
849 //
850 // Determine root bridge attribute by calling interface of Pcihostbridge
851 // protocol
852 //
853 DetermineRootBridgeAttributes (
854 PciResAlloc,
855 RootBridgeDev
856 );
857
858 //
859 // Collect all the resource information under this root bridge
860 // A database that records all the information about pci device subject to this
861 // root bridge will then be created
862 //
863 Status = PciPciDeviceInfoCollector (
864 RootBridgeDev,
865 (UINT8) MinBus
866 );
867
868 if (EFI_ERROR (Status)) {
869 return Status;
870 }
871
872 InsertRootBridge (RootBridgeDev);
873
874 //
875 // Record the hostbridge handle
876 //
877 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
878 }
879
880 return EFI_SUCCESS;
881 }