1) Use FeatureFlag PcdPciBusHotplugDeviceSupport to merge LightPciLib.c with PcdLib.c.
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciLib.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PciLib.c \r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver Lib file\r
19 It abstracts some functions that can be different \r
20 between light PCI bus driver and full PCI bus driver\r
21\r
22Revision History\r
23\r
24--*/\r
25\r
26#include "pcibus.h"\r
27\r
6874dbd0 28GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {\r
878ddf1f 29 PciHotPlugRequestNotify\r
30};\r
31\r
32\r
33VOID\r
34InstallHotPlugRequestProtocol (\r
35 IN EFI_STATUS *Status\r
36 )\r
37/*++\r
38\r
39Routine Description:\r
40\r
41Arguments:\r
42 Status - A pointer to the status.\r
43\r
44Returns:\r
45\r
46 None\r
47\r
48--*/\r
49{\r
50 EFI_HANDLE Handle;\r
51\r
6874dbd0 52 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
53 return;\r
54 }\r
55\r
878ddf1f 56 Handle = NULL;\r
57 *Status = gBS->InstallProtocolInterface (\r
58 &Handle,\r
59 &gEfiPciHotPlugRequestProtocolGuid,\r
60 EFI_NATIVE_INTERFACE,\r
61 &gPciHotPlugRequest\r
62 );\r
63}\r
64\r
65VOID\r
66InstallPciHotplugGuid (\r
67 IN PCI_IO_DEVICE *PciIoDevice\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73Arguments:\r
74\r
75 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
76\r
77Returns:\r
78\r
79 None\r
80\r
81--*/\r
82{\r
83 EFI_STATUS Status;\r
84\r
6874dbd0 85 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
86 return;\r
87 }\r
88\r
878ddf1f 89 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {\r
90\r
91 Status = gBS->InstallProtocolInterface (\r
92 &PciIoDevice->Handle,\r
93 &gEfiPciHotplugDeviceGuid,\r
94 EFI_NATIVE_INTERFACE,\r
95 NULL\r
96 );\r
97 }\r
98}\r
99\r
100VOID\r
101UninstallPciHotplugGuid (\r
102 IN PCI_IO_DEVICE *PciIoDevice\r
103 )\r
104/*++\r
105\r
106Routine Description:\r
107\r
108Arguments:\r
109\r
110 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
111\r
112Returns:\r
113\r
114 None\r
115\r
116--*/\r
117{\r
118 EFI_STATUS Status;\r
119\r
6874dbd0 120 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
121 return;\r
122 }\r
123\r
878ddf1f 124 Status = gBS->OpenProtocol (\r
125 PciIoDevice->Handle,\r
126 &gEfiPciHotplugDeviceGuid,\r
127 NULL,\r
128 NULL,\r
129 NULL,\r
130 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
131 );\r
132\r
133 if (Status == EFI_SUCCESS) {\r
134 //\r
135 // This may triger CardBus driver to stop for\r
136 // Pccard devices opened the GUID via BY_DRIVER\r
137 //\r
138 Status = gBS->UninstallProtocolInterface (\r
139 PciIoDevice->Handle,\r
140 &gEfiPciHotplugDeviceGuid,\r
141 NULL\r
142 );\r
143 }\r
144}\r
145\r
146VOID\r
147GetBackPcCardBar (\r
148 IN PCI_IO_DEVICE *PciIoDevice\r
149 )\r
150/*++\r
151\r
152Routine Description:\r
153\r
154\r
155Arguments:\r
156\r
157 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
158\r
159Returns:\r
160\r
161 None\r
162\r
163--*/\r
164{\r
165 UINT32 Address;\r
166\r
6874dbd0 167 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
168 return;\r
169 }\r
170\r
878ddf1f 171 //\r
172 // Read PciBar information from the bar register\r
173 //\r
174 if (!gFullEnumeration) {\r
175\r
176 Address = 0;\r
177 PciIoDevice->PciIo.Pci.Read (\r
178 &(PciIoDevice->PciIo),\r
179 EfiPciIoWidthUint32,\r
180 0x1c,\r
181 1,\r
182 &Address\r
183 );\r
184\r
185 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
186 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
187 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
188\r
189 Address = 0;\r
190 PciIoDevice->PciIo.Pci.Read (\r
191 &(PciIoDevice->PciIo),\r
192 EfiPciIoWidthUint32,\r
193 0x20,\r
194 1,\r
195 &Address\r
196 );\r
197 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
198 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
199 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
200\r
201 Address = 0;\r
202 PciIoDevice->PciIo.Pci.Read (\r
203 &(PciIoDevice->PciIo),\r
204 EfiPciIoWidthUint32,\r
205 0x2c,\r
206 1,\r
207 &Address\r
208 );\r
209 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
210 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
211 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
212\r
213 Address = 0;\r
214 PciIoDevice->PciIo.Pci.Read (\r
215 &(PciIoDevice->PciIo),\r
216 EfiPciIoWidthUint32,\r
217 0x34,\r
218 1,\r
219 &Address\r
220 );\r
221 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
222 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
223 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
224\r
225 }\r
226\r
227 if (gPciHotPlugInit != NULL) {\r
228 GetResourcePaddingForHpb (PciIoDevice);\r
229 }\r
230}\r
231\r
232EFI_STATUS\r
233RemoveRejectedPciDevices (\r
234 EFI_HANDLE RootBridgeHandle,\r
235 IN PCI_IO_DEVICE *Bridge\r
236 )\r
237/*++\r
238\r
239Routine Description:\r
240\r
241\r
242Arguments:\r
243\r
244 RootBridgeHandle - An efi handle.\r
245 Bridge - An pointer to the PCI_IO_DEVICE.\r
246\r
247Returns:\r
248\r
249 None\r
250\r
251--*/\r
252// TODO: EFI_SUCCESS - add return value to function comment\r
253{\r
254 PCI_IO_DEVICE *Temp;\r
255 LIST_ENTRY *CurrentLink;\r
256 LIST_ENTRY *LastLink;\r
257\r
6874dbd0 258 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
259 return EFI_SUCCESS;\r
260 }\r
261\r
878ddf1f 262 CurrentLink = Bridge->ChildList.ForwardLink;\r
263\r
264 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
265\r
266 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
267\r
268 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
269 //\r
270 // Remove rejected devices recusively\r
271 //\r
272 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
273 } else {\r
274 //\r
275 // Skip rejection for all PPBs, while detect rejection for others\r
276 //\r
277 if (IsPciDeviceRejected (Temp)) {\r
278 \r
279 //\r
280 // For P2C, remove all devices on it\r
281 //\r
282 \r
283 if (!IsListEmpty (&Temp->ChildList)) {\r
284 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
285 }\r
286 \r
287 //\r
288 // Finally remove itself\r
289 //\r
290 \r
291 LastLink = CurrentLink->BackLink;\r
292 RemoveEntryList (CurrentLink);\r
293 FreePciDevice (Temp);\r
294\r
295 CurrentLink = LastLink;\r
296 }\r
297 }\r
298\r
299 CurrentLink = CurrentLink->ForwardLink;\r
300 }\r
301\r
302 return EFI_SUCCESS;\r
303}\r
304\r
305EFI_STATUS\r
306PciHostBridgeResourceAllocator (\r
307 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
308 )\r
6874dbd0 309{\r
310 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
311 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (\r
312 PciResAlloc\r
313 );\r
314 } else {\r
315 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (\r
316 PciResAlloc\r
317 );\r
318 } \r
319}\r
320\r
321\r
322EFI_STATUS\r
323PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (\r
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
325 )\r
326/*++\r
327\r
328Routine Description:\r
329\r
330Arguments:\r
331\r
332Returns:\r
333\r
334 None\r
335\r
336--*/\r
337// TODO: PciResAlloc - add argument and description to function comment\r
338// TODO: EFI_NOT_FOUND - add return value to function comment\r
339// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
340// TODO: EFI_NOT_FOUND - add return value to function comment\r
341// TODO: EFI_SUCCESS - add return value to function comment\r
342{\r
343 PCI_IO_DEVICE *RootBridgeDev;\r
344 EFI_HANDLE RootBridgeHandle;\r
345 VOID *AcpiConfig;\r
346 EFI_STATUS Status;\r
347 UINT64 IoBase;\r
348 UINT64 Mem32Base;\r
349 UINT64 PMem32Base;\r
350 UINT64 Mem64Base;\r
351 UINT64 PMem64Base;\r
352 UINT64 MaxOptionRomSize;\r
353 PCI_RESOURCE_NODE *IoBridge;\r
354 PCI_RESOURCE_NODE *Mem32Bridge;\r
355 PCI_RESOURCE_NODE *PMem32Bridge;\r
356 PCI_RESOURCE_NODE *Mem64Bridge;\r
357 PCI_RESOURCE_NODE *PMem64Bridge;\r
358 PCI_RESOURCE_NODE IoPool;\r
359 PCI_RESOURCE_NODE Mem32Pool;\r
360 PCI_RESOURCE_NODE PMem32Pool;\r
361 PCI_RESOURCE_NODE Mem64Pool;\r
362 PCI_RESOURCE_NODE PMem64Pool;\r
363 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;\r
364\r
365 //\r
366 // Initialize resource pool\r
367 //\r
368 \r
369 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
370 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
371 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
372 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
373 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
374\r
375 RootBridgeDev = NULL;\r
376 RootBridgeHandle = 0;\r
377\r
378 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
379 //\r
380 // Get RootBridg Device by handle\r
381 //\r
382 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
383\r
384 if (RootBridgeDev == NULL) {\r
385 return EFI_NOT_FOUND;\r
386 }\r
387\r
388 //\r
389 // Get host bridge handle for status report\r
390 //\r
391 ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
392\r
393 //\r
394 // Create the entire system resource map from the information collected by\r
395 // enumerator. Several resource tree was created\r
396 //\r
397\r
398 IoBridge = CreateResourceNode (\r
399 RootBridgeDev,\r
400 0,\r
401 0xFFF,\r
402 0,\r
403 PciBarTypeIo16,\r
404 PciResUsageTypical\r
405 );\r
406\r
407 Mem32Bridge = CreateResourceNode (\r
408 RootBridgeDev,\r
409 0,\r
410 0xFFFFF,\r
411 0,\r
412 PciBarTypeMem32,\r
413 PciResUsageTypical\r
414 );\r
415\r
416 PMem32Bridge = CreateResourceNode (\r
417 RootBridgeDev,\r
418 0,\r
419 0xFFFFF,\r
420 0,\r
421 PciBarTypePMem32,\r
422 PciResUsageTypical\r
423 );\r
424\r
425 Mem64Bridge = CreateResourceNode (\r
426 RootBridgeDev,\r
427 0,\r
428 0xFFFFF,\r
429 0,\r
430 PciBarTypeMem64,\r
431 PciResUsageTypical\r
432 );\r
433\r
434 PMem64Bridge = CreateResourceNode (\r
435 RootBridgeDev,\r
436 0,\r
437 0xFFFFF,\r
438 0,\r
439 PciBarTypePMem64,\r
440 PciResUsageTypical\r
441 );\r
442\r
443 //\r
444 // Create resourcemap by going through all the devices subject to this root bridge\r
445 //\r
446 Status = CreateResourceMap (\r
447 RootBridgeDev,\r
448 IoBridge,\r
449 Mem32Bridge,\r
450 PMem32Bridge,\r
451 Mem64Bridge,\r
452 PMem64Bridge\r
453 );\r
454\r
455 //\r
456 // Get the max ROM size that the root bridge can process\r
457 //\r
458 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
459\r
460 //\r
461 // Get Max Option Rom size for current root bridge\r
462 //\r
463 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
464\r
465 //\r
466 // Enlarger the mem32 resource to accomdate the option rom\r
467 // if the mem32 resource is not enough to hold the rom\r
468 //\r
469 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
470\r
471 Mem32Bridge->Length = MaxOptionRomSize;\r
472 RootBridgeDev->RomSize = MaxOptionRomSize;\r
473\r
474 //\r
475 // Alignment should be adjusted as well\r
476 //\r
477 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
478 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
479 }\r
480 }\r
481 \r
482 //\r
483 // Based on the all the resource tree, contruct ACPI resource node to\r
484 // submit the resource aperture to pci host bridge protocol\r
485 //\r
486 Status = ConstructAcpiResourceRequestor (\r
487 RootBridgeDev,\r
488 IoBridge,\r
489 Mem32Bridge,\r
490 PMem32Bridge,\r
491 Mem64Bridge,\r
492 PMem64Bridge,\r
493 &AcpiConfig\r
494 );\r
495\r
496 //\r
497 // Insert these resource nodes into the database\r
498 //\r
499 InsertResourceNode (&IoPool, IoBridge);\r
500 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
501 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
502 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
503 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
504\r
505 if (Status == EFI_SUCCESS) {\r
506 //\r
507 // Submit the resource requirement\r
508 //\r
509 Status = PciResAlloc->SubmitResources (\r
510 PciResAlloc,\r
511 RootBridgeDev->Handle,\r
512 AcpiConfig\r
513 );\r
514 }\r
515 //\r
516 // Free acpi resource node\r
517 //\r
518 if (AcpiConfig) {\r
519 gBS->FreePool (AcpiConfig);\r
520 }\r
521\r
522 if (EFI_ERROR (Status)) {\r
523 //\r
524 // Destroy all the resource tree\r
525 //\r
526 DestroyResourceTree (&IoPool);\r
527 DestroyResourceTree (&Mem32Pool);\r
528 DestroyResourceTree (&PMem32Pool);\r
529 DestroyResourceTree (&Mem64Pool);\r
530 DestroyResourceTree (&PMem64Pool);\r
531 return Status;\r
532 }\r
533 }\r
534 //\r
535 // End while\r
536 //\r
537\r
538 //\r
539 // Notify pci bus driver starts to program the resource\r
540 //\r
541 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
542\r
543 if (EFI_ERROR (Status)) {\r
544 //\r
545 // Allocation failed, then return\r
546 //\r
547 return EFI_OUT_OF_RESOURCES;\r
548 }\r
549 //\r
550 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
551 //\r
552 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
553 EFI_PROGRESS_CODE,\r
554 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
555 (VOID *) &ExtendedData,\r
556 sizeof (ExtendedData)\r
557 );\r
558\r
559 //\r
560 // Notify pci bus driver starts to program the resource\r
561 //\r
562 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
563\r
564 RootBridgeDev = NULL;\r
565\r
566 RootBridgeHandle = 0;\r
567\r
568 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
569 //\r
570 // Get RootBridg Device by handle\r
571 //\r
572 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
573\r
574 if (RootBridgeDev == NULL) {\r
575 return EFI_NOT_FOUND;\r
576 }\r
577 \r
578 //\r
579 // Get acpi resource node for all the resource types\r
580 //\r
581 AcpiConfig = NULL;\r
582 Status = PciResAlloc->GetProposedResources (\r
583 PciResAlloc,\r
584 RootBridgeDev->Handle,\r
585 &AcpiConfig\r
586 );\r
587\r
588 if (EFI_ERROR (Status)) {\r
589 return Status;\r
590 }\r
591\r
592 //\r
593 // Get the resource base by interpreting acpi resource node\r
594 //\r
595 //\r
596 GetResourceBase (\r
597 AcpiConfig,\r
598 &IoBase,\r
599 &Mem32Base,\r
600 &PMem32Base,\r
601 &Mem64Base,\r
602 &PMem64Base\r
603 );\r
604\r
605 //\r
606 // Process option rom for this root bridge\r
607 //\r
608 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
609\r
610 //\r
611 // Create the entire system resource map from the information collected by\r
612 // enumerator. Several resource tree was created\r
613 //\r
614 Status = GetResourceMap (\r
615 RootBridgeDev,\r
616 &IoBridge,\r
617 &Mem32Bridge,\r
618 &PMem32Bridge,\r
619 &Mem64Bridge,\r
620 &PMem64Bridge,\r
621 &IoPool,\r
622 &Mem32Pool,\r
623 &PMem32Pool,\r
624 &Mem64Pool,\r
625 &PMem64Pool\r
626 );\r
627\r
628 if (EFI_ERROR (Status)) {\r
629 return Status;\r
630 }\r
631\r
632 //\r
633 // Program IO resources\r
634 //\r
635 ProgramResource (\r
636 IoBase,\r
637 IoBridge\r
638 );\r
639\r
640 //\r
641 // Program Mem32 resources\r
642 //\r
643 ProgramResource (\r
644 Mem32Base,\r
645 Mem32Bridge\r
646 );\r
647\r
648 //\r
649 // Program PMem32 resources\r
650 //\r
651 ProgramResource (\r
652 PMem32Base,\r
653 PMem32Bridge\r
654 );\r
655\r
656 //\r
657 // Program Mem64 resources\r
658 //\r
659 ProgramResource (\r
660 Mem64Base,\r
661 Mem64Bridge\r
662 );\r
663\r
664 //\r
665 // Program PMem64 resources\r
666 //\r
667 ProgramResource (\r
668 PMem64Base,\r
669 PMem64Bridge\r
670 );\r
671\r
672 if (AcpiConfig != NULL) {\r
673 gBS->FreePool (AcpiConfig);\r
674 }\r
675 }\r
676\r
677 //\r
678 // Destroy all the resource tree\r
679 //\r
680 DestroyResourceTree (&IoPool);\r
681 DestroyResourceTree (&Mem32Pool);\r
682 DestroyResourceTree (&PMem32Pool);\r
683 DestroyResourceTree (&Mem64Pool);\r
684 DestroyResourceTree (&PMem64Pool);\r
685\r
686 //\r
687 // Notify the resource allocation phase is to end\r
688 //\r
689 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
690\r
691 return EFI_SUCCESS;\r
692}\r
693\r
694\r
695EFI_STATUS\r
696PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (\r
697 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
698 )\r
878ddf1f 699/*++\r
700\r
701Routine Description:\r
702\r
703 Host brige resource allocator.\r
704\r
705Arguments:\r
706\r
707 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
708\r
709Returns:\r
710\r
711 EFI Status.\r
712\r
713--*/\r
714// TODO: EFI_NOT_FOUND - add return value to function comment\r
715// TODO: EFI_NOT_FOUND - add return value to function comment\r
716// TODO: EFI_NOT_FOUND - add return value to function comment\r
717// TODO: EFI_SUCCESS - add return value to function comment\r
718{\r
719 PCI_IO_DEVICE *RootBridgeDev;\r
720 EFI_HANDLE RootBridgeHandle;\r
721 VOID *AcpiConfig;\r
722 EFI_STATUS Status;\r
723 UINT64 IoBase;\r
724 UINT64 Mem32Base;\r
725 UINT64 PMem32Base;\r
726 UINT64 Mem64Base;\r
727 UINT64 PMem64Base;\r
728 UINT64 IoResStatus;\r
729 UINT64 Mem32ResStatus;\r
730 UINT64 PMem32ResStatus;\r
731 UINT64 Mem64ResStatus;\r
732 UINT64 PMem64ResStatus;\r
733 UINT64 MaxOptionRomSize;\r
734 PCI_RESOURCE_NODE *IoBridge;\r
735 PCI_RESOURCE_NODE *Mem32Bridge;\r
736 PCI_RESOURCE_NODE *PMem32Bridge;\r
737 PCI_RESOURCE_NODE *Mem64Bridge;\r
738 PCI_RESOURCE_NODE *PMem64Bridge;\r
739 PCI_RESOURCE_NODE IoPool;\r
740 PCI_RESOURCE_NODE Mem32Pool;\r
741 PCI_RESOURCE_NODE PMem32Pool;\r
742 PCI_RESOURCE_NODE Mem64Pool;\r
743 PCI_RESOURCE_NODE PMem64Pool;\r
744 BOOLEAN ReAllocate;\r
745 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;\r
746 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;\r
747\r
748 //\r
749 // Reallocate flag\r
750 //\r
751 ReAllocate = FALSE;\r
752\r
753 //\r
754 // It will try several times if the resource allocation fails\r
755 //\r
756 while (TRUE) {\r
757\r
758 //\r
759 // Initialize resource pool\r
760 // \r
761 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
762 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
763 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
764 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
765 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
766\r
767 RootBridgeDev = NULL;\r
768 RootBridgeHandle = 0;\r
769\r
770 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
771\r
772 //\r
773 // Get RootBridg Device by handle\r
774 //\r
775 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
776\r
777 if (RootBridgeDev == NULL) {\r
778 return EFI_NOT_FOUND;\r
779 }\r
780\r
781 //\r
782 // Create the entire system resource map from the information collected by\r
783 // enumerator. Several resource tree was created\r
784 //\r
785\r
786 IoBridge = CreateResourceNode (\r
787 RootBridgeDev,\r
788 0,\r
789 0xFFF,\r
790 0,\r
791 PciBarTypeIo16,\r
792 PciResUsageTypical\r
793 );\r
794\r
795 Mem32Bridge = CreateResourceNode (\r
796 RootBridgeDev,\r
797 0,\r
798 0xFFFFF,\r
799 0,\r
800 PciBarTypeMem32,\r
801 PciResUsageTypical\r
802 );\r
803\r
804 PMem32Bridge = CreateResourceNode (\r
805 RootBridgeDev,\r
806 0,\r
807 0xFFFFF,\r
808 0,\r
809 PciBarTypePMem32,\r
810 PciResUsageTypical\r
811 );\r
812\r
813 Mem64Bridge = CreateResourceNode (\r
814 RootBridgeDev,\r
815 0,\r
816 0xFFFFF,\r
817 0,\r
818 PciBarTypeMem64,\r
819 PciResUsageTypical\r
820 );\r
821\r
822 PMem64Bridge = CreateResourceNode (\r
823 RootBridgeDev,\r
824 0,\r
825 0xFFFFF,\r
826 0,\r
827 PciBarTypePMem64,\r
828 PciResUsageTypical\r
829 );\r
830\r
831 //\r
832 // Create resourcemap by going through all the devices subject to this root bridge\r
833 //\r
834 Status = CreateResourceMap (\r
835 RootBridgeDev,\r
836 IoBridge,\r
837 Mem32Bridge,\r
838 PMem32Bridge,\r
839 Mem64Bridge,\r
840 PMem64Bridge\r
841 );\r
842\r
843 //\r
844 // Get the max ROM size that the root bridge can process\r
845 //\r
846 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
847\r
848 //\r
849 // Skip to enlarge the resource request during realloction\r
850 //\r
851 if (!ReAllocate) {\r
852 //\r
853 // Get Max Option Rom size for current root bridge\r
854 //\r
855 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
856\r
857 //\r
858 // Enlarger the mem32 resource to accomdate the option rom\r
859 // if the mem32 resource is not enough to hold the rom\r
860 //\r
861 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
862\r
863 Mem32Bridge->Length = MaxOptionRomSize;\r
864 RootBridgeDev->RomSize = MaxOptionRomSize;\r
865\r
866 //\r
867 // Alignment should be adjusted as well\r
868 //\r
869 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
870 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
871 }\r
872 }\r
873 } \r
874 \r
875 //\r
876 // Based on the all the resource tree, contruct ACPI resource node to\r
877 // submit the resource aperture to pci host bridge protocol\r
878 //\r
879 Status = ConstructAcpiResourceRequestor (\r
880 RootBridgeDev,\r
881 IoBridge,\r
882 Mem32Bridge,\r
883 PMem32Bridge,\r
884 Mem64Bridge,\r
885 PMem64Bridge,\r
886 &AcpiConfig\r
887 );\r
888\r
889 //\r
890 // Insert these resource nodes into the database\r
891 //\r
892 InsertResourceNode (&IoPool, IoBridge);\r
893 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
894 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
895 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
896 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
897\r
898 if (Status == EFI_SUCCESS) {\r
899 //\r
900 // Submit the resource requirement\r
901 //\r
902 Status = PciResAlloc->SubmitResources (\r
903 PciResAlloc,\r
904 RootBridgeDev->Handle,\r
905 AcpiConfig\r
906 );\r
907 }\r
908\r
909 //\r
910 // Free acpi resource node\r
911 //\r
912 if (AcpiConfig != NULL) {\r
913 gBS->FreePool (AcpiConfig);\r
914 }\r
915\r
916 if (EFI_ERROR (Status)) {\r
917 //\r
918 // Destroy all the resource tree\r
919 //\r
920 DestroyResourceTree (&IoPool);\r
921 DestroyResourceTree (&Mem32Pool);\r
922 DestroyResourceTree (&PMem32Pool);\r
923 DestroyResourceTree (&Mem64Pool);\r
924 DestroyResourceTree (&PMem64Pool);\r
925 return Status;\r
926 }\r
927 }\r
928\r
929 //\r
930 // Notify pci bus driver starts to program the resource\r
931 //\r
932 \r
933 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
934\r
935 if (!EFI_ERROR (Status)) {\r
936 //\r
937 // Allocation succeed, then continue the following\r
938 //\r
939 break;\r
940 }\r
941 \r
942 //\r
943 // If the resource allocation is unsuccessful, free resources on bridge\r
944 //\r
945 \r
946 RootBridgeDev = NULL;\r
947 RootBridgeHandle = 0;\r
948\r
949 IoResStatus = EFI_RESOURCE_SATISFIED;\r
950 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
951 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
952 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
953 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
954\r
955 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
956 //\r
957 // Get RootBridg Device by handle\r
958 //\r
959 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
960 if (RootBridgeDev == NULL) {\r
961 return EFI_NOT_FOUND;\r
962 }\r
963 \r
964 //\r
965 // Get host bridge handle for status report\r
966 //\r
967 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
968\r
969 //\r
970 // Get acpi resource node for all the resource types\r
971 //\r
972 AcpiConfig = NULL;\r
973\r
974 Status = PciResAlloc->GetProposedResources (\r
975 PciResAlloc,\r
976 RootBridgeDev->Handle,\r
977 &AcpiConfig\r
978 );\r
979\r
980 if (EFI_ERROR (Status)) {\r
981 return Status;\r
982 }\r
983\r
984 if (AcpiConfig != NULL) {\r
985 //\r
986 // Adjust resource allocation policy for each RB\r
987 //\r
988 GetResourceAllocationStatus (\r
989 AcpiConfig,\r
990 &IoResStatus,\r
991 &Mem32ResStatus,\r
992 &PMem32ResStatus,\r
993 &Mem64ResStatus,\r
994 &PMem64ResStatus\r
995 );\r
996 gBS->FreePool (AcpiConfig);\r
997 }\r
998 }\r
999 //\r
1000 // End while\r
1001 //\r
1002\r
1003 //\r
1004 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
1005 //\r
1006 //\r
1007 // It is very difficult to follow the spec here\r
1008 // Device path , Bar index can not be get here\r
1009 //\r
1010 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
1011\r
1012 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1013 EFI_PROGRESS_CODE,\r
1014 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
1015 (VOID *) &AllocFailExtendedData,\r
1016 sizeof (AllocFailExtendedData)\r
1017 );\r
1018\r
1019 Status = PciHostBridgeAdjustAllocation (\r
1020 &IoPool,\r
1021 &Mem32Pool,\r
1022 &PMem32Pool,\r
1023 &Mem64Pool,\r
1024 &PMem64Pool,\r
1025 IoResStatus,\r
1026 Mem32ResStatus,\r
1027 PMem32ResStatus,\r
1028 Mem64ResStatus,\r
1029 PMem64ResStatus\r
1030 );\r
1031\r
1032 //\r
1033 // Destroy all the resource tree\r
1034 //\r
1035 DestroyResourceTree (&IoPool);\r
1036 DestroyResourceTree (&Mem32Pool);\r
1037 DestroyResourceTree (&PMem32Pool);\r
1038 DestroyResourceTree (&Mem64Pool);\r
1039 DestroyResourceTree (&PMem64Pool);\r
1040\r
1041 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
1042\r
1043 if (EFI_ERROR (Status)) {\r
1044 return Status;\r
1045 }\r
1046\r
1047 ReAllocate = TRUE;\r
1048\r
1049 }\r
1050 //\r
1051 // End main while\r
1052 //\r
1053\r
1054 //\r
1055 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
1056 //\r
1057 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1058 EFI_PROGRESS_CODE,\r
1059 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
1060 (VOID *) &HandleExtendedData,\r
1061 sizeof (HandleExtendedData)\r
1062 );\r
1063\r
1064 //\r
1065 // Notify pci bus driver starts to program the resource\r
1066 //\r
1067 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
1068\r
1069 RootBridgeDev = NULL;\r
1070\r
1071 RootBridgeHandle = 0;\r
1072\r
1073 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1074\r
1075 //\r
1076 // Get RootBridg Device by handle\r
1077 //\r
1078 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1079\r
1080 if (RootBridgeDev == NULL) {\r
1081 return EFI_NOT_FOUND;\r
1082 }\r
1083 \r
1084 //\r
1085 // Get acpi resource node for all the resource types\r
1086 //\r
1087 AcpiConfig = NULL;\r
1088 Status = PciResAlloc->GetProposedResources (\r
1089 PciResAlloc,\r
1090 RootBridgeDev->Handle,\r
1091 &AcpiConfig\r
1092 );\r
1093\r
1094 if (EFI_ERROR (Status)) {\r
1095 return Status;\r
1096 }\r
1097\r
1098 //\r
1099 // Get the resource base by interpreting acpi resource node\r
1100 //\r
1101 //\r
1102 GetResourceBase (\r
1103 AcpiConfig,\r
1104 &IoBase,\r
1105 &Mem32Base,\r
1106 &PMem32Base,\r
1107 &Mem64Base,\r
1108 &PMem64Base\r
1109 );\r
1110\r
1111 //\r
1112 // Process option rom for this root bridge\r
1113 //\r
1114 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
1115\r
1116 //\r
1117 // Create the entire system resource map from the information collected by\r
1118 // enumerator. Several resource tree was created\r
1119 //\r
1120 Status = GetResourceMap (\r
1121 RootBridgeDev,\r
1122 &IoBridge,\r
1123 &Mem32Bridge,\r
1124 &PMem32Bridge,\r
1125 &Mem64Bridge,\r
1126 &PMem64Bridge,\r
1127 &IoPool,\r
1128 &Mem32Pool,\r
1129 &PMem32Pool,\r
1130 &Mem64Pool,\r
1131 &PMem64Pool\r
1132 );\r
1133\r
1134 if (EFI_ERROR (Status)) {\r
1135 return Status;\r
1136 }\r
1137\r
1138 //\r
1139 // Program IO resources\r
1140 //\r
1141 ProgramResource (\r
1142 IoBase,\r
1143 IoBridge\r
1144 );\r
1145\r
1146 //\r
1147 // Program Mem32 resources\r
1148 //\r
1149 ProgramResource (\r
1150 Mem32Base,\r
1151 Mem32Bridge\r
1152 );\r
1153\r
1154 //\r
1155 // Program PMem32 resources\r
1156 //\r
1157 ProgramResource (\r
1158 PMem32Base,\r
1159 PMem32Bridge\r
1160 );\r
1161\r
1162 //\r
1163 // Program Mem64 resources\r
1164 //\r
1165 ProgramResource (\r
1166 Mem64Base,\r
1167 Mem64Bridge\r
1168 );\r
1169\r
1170 //\r
1171 // Program PMem64 resources\r
1172 //\r
1173 ProgramResource (\r
1174 PMem64Base,\r
1175 PMem64Bridge\r
1176 );\r
1177\r
1178 if (AcpiConfig != NULL) {\r
1179 gBS->FreePool (AcpiConfig);\r
1180 }\r
1181 }\r
1182\r
1183 //\r
1184 // Destroy all the resource tree\r
1185 //\r
1186 DestroyResourceTree (&IoPool);\r
1187 DestroyResourceTree (&Mem32Pool);\r
1188 DestroyResourceTree (&PMem32Pool);\r
1189 DestroyResourceTree (&Mem64Pool);\r
1190 DestroyResourceTree (&PMem64Pool);\r
1191\r
1192 //\r
1193 // Notify the resource allocation phase is to end\r
1194 //\r
1195 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
1196\r
1197 return EFI_SUCCESS;\r
1198}\r
1199\r
6874dbd0 1200\r
878ddf1f 1201EFI_STATUS\r
1202PciScanBus (\r
1203 IN PCI_IO_DEVICE *Bridge,\r
1204 IN UINT8 StartBusNumber,\r
1205 OUT UINT8 *SubBusNumber,\r
1206 OUT UINT8 *PaddedBusRange\r
1207 )\r
6874dbd0 1208{\r
1209 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1210 return PciScanBus_WithHotPlugDeviceSupport (\r
1211 Bridge, \r
1212 StartBusNumber, \r
1213 SubBusNumber, \r
1214 PaddedBusRange\r
1215 );\r
1216 } else {\r
1217 return PciScanBus_WithoutHotPlugDeviceSupport (\r
1218 Bridge, \r
1219 StartBusNumber, \r
1220 SubBusNumber, \r
1221 PaddedBusRange\r
1222 );\r
1223 }\r
1224}\r
1225\r
1226\r
1227EFI_STATUS\r
1228PciScanBus_WithoutHotPlugDeviceSupport (\r
1229 IN PCI_IO_DEVICE *Bridge,\r
1230 IN UINT8 StartBusNumber,\r
1231 OUT UINT8 *SubBusNumber,\r
1232 OUT UINT8 *PaddedBusRange\r
1233 )\r
1234/*++\r
1235\r
1236Routine Description:\r
1237\r
1238 This routine is used to assign bus number to the given PCI bus system\r
1239\r
1240Arguments:\r
1241\r
1242Returns:\r
1243\r
1244 None\r
1245\r
1246--*/\r
1247// TODO: Bridge - add argument and description to function comment\r
1248// TODO: StartBusNumber - add argument and description to function comment\r
1249// TODO: SubBusNumber - add argument and description to function comment\r
1250// TODO: PaddedBusRange - add argument and description to function comment\r
1251// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1252// TODO: EFI_SUCCESS - add return value to function comment\r
1253{\r
1254 EFI_STATUS Status;\r
1255 PCI_TYPE00 Pci;\r
1256 UINT8 Device;\r
1257 UINT8 Func;\r
1258 UINT64 Address;\r
1259 UINTN SecondBus;\r
1260 UINT16 Register;\r
1261 PCI_IO_DEVICE *PciDevice;\r
1262 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1263\r
1264 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1265 SecondBus = 0;\r
1266 Register = 0;\r
1267\r
1268 ResetAllPpbBusReg (Bridge, StartBusNumber);\r
1269\r
1270 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1271 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1272\r
1273 //\r
1274 // Check to see whether a pci device is present\r
1275 //\r
1276 Status = PciDevicePresent (\r
1277 PciRootBridgeIo,\r
1278 &Pci,\r
1279 StartBusNumber,\r
1280 Device,\r
1281 Func\r
1282 );\r
1283\r
1284 if (!EFI_ERROR (Status) && \r
1285 (IS_PCI_BRIDGE (&Pci) ||\r
1286 IS_CARDBUS_BRIDGE (&Pci))) {\r
1287\r
1288 //\r
1289 // Get the bridge information\r
1290 //\r
1291 Status = PciSearchDevice (\r
1292 Bridge,\r
1293 &Pci,\r
1294 StartBusNumber,\r
1295 Device,\r
1296 Func,\r
1297 &PciDevice\r
1298 );\r
1299\r
1300 if (EFI_ERROR (Status)) {\r
1301 return Status;\r
1302 }\r
1303\r
1304 (*SubBusNumber)++;\r
1305\r
1306 SecondBus = (*SubBusNumber);\r
1307\r
1308 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1309\r
1310 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1311\r
1312 Status = PciRootBridgeIo->Pci.Write (\r
1313 PciRootBridgeIo,\r
1314 EfiPciWidthUint16,\r
1315 Address,\r
1316 1,\r
1317 &Register\r
1318 );\r
1319\r
1320 //\r
1321 // Initialize SubBusNumber to SecondBus\r
1322 //\r
1323 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1324 Status = PciRootBridgeIo->Pci.Write (\r
1325 PciRootBridgeIo,\r
1326 EfiPciWidthUint8,\r
1327 Address,\r
1328 1,\r
1329 SubBusNumber\r
1330 );\r
1331 //\r
1332 // If it is PPB, resursively search down this bridge\r
1333 //\r
1334 if (IS_PCI_BRIDGE (&Pci)) {\r
1335 //\r
1336 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1337 // PCI configuration transaction to go through any PPB\r
1338 //\r
1339 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1340 Register = 0xFF;\r
1341 Status = PciRootBridgeIo->Pci.Write (\r
1342 PciRootBridgeIo,\r
1343 EfiPciWidthUint8,\r
1344 Address,\r
1345 1,\r
1346 &Register\r
1347 );\r
1348\r
1349 PreprocessController (\r
1350 PciDevice,\r
1351 PciDevice->BusNumber,\r
1352 PciDevice->DeviceNumber,\r
1353 PciDevice->FunctionNumber,\r
1354 EfiPciBeforeChildBusEnumeration\r
1355 );\r
1356\r
1357 Status = PciScanBus (\r
1358 PciDevice,\r
1359 (UINT8) (SecondBus),\r
1360 SubBusNumber,\r
1361 PaddedBusRange\r
1362 );\r
1363\r
1364 if (EFI_ERROR (Status)) {\r
1365 return EFI_DEVICE_ERROR;\r
1366 }\r
1367 }\r
1368\r
1369 //\r
1370 // Set the current maximum bus number under the PPB\r
1371 //\r
1372\r
1373 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1374\r
1375 Status = PciRootBridgeIo->Pci.Write (\r
1376 PciRootBridgeIo,\r
1377 EfiPciWidthUint8,\r
1378 Address,\r
1379 1,\r
1380 SubBusNumber\r
1381 );\r
1382\r
1383 }\r
1384\r
1385 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1386\r
1387 //\r
1388 // Skip sub functions, this is not a multi function device\r
1389 //\r
1390\r
1391 Func = PCI_MAX_FUNC;\r
1392 }\r
1393 }\r
1394 }\r
1395\r
1396 return EFI_SUCCESS;\r
1397}\r
1398\r
1399EFI_STATUS\r
1400PciScanBus_WithHotPlugDeviceSupport (\r
1401 IN PCI_IO_DEVICE *Bridge,\r
1402 IN UINT8 StartBusNumber,\r
1403 OUT UINT8 *SubBusNumber,\r
1404 OUT UINT8 *PaddedBusRange\r
1405 )\r
878ddf1f 1406/*++\r
1407\r
1408Routine Description:\r
1409\r
1410 This routine is used to assign bus number to the given PCI bus system\r
1411\r
1412Arguments:\r
1413\r
1414 Bridge - A pointer to the PCI_IO_DEVICE structure.\r
1415 StartBusNumber - The start bus number.\r
1416 SubBusNumber - A pointer to the sub bus number.\r
1417 PaddedBusRange - A pointer to the padded bus range.\r
1418\r
1419Returns:\r
1420\r
1421 None\r
1422\r
1423--*/\r
1424// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1425// TODO: EFI_SUCCESS - add return value to function comment\r
1426{\r
1427 EFI_STATUS Status;\r
1428 PCI_TYPE00 Pci;\r
1429 UINT8 Device;\r
1430 UINT8 Func;\r
1431 UINT64 Address;\r
1432 UINTN SecondBus;\r
1433 UINT16 Register;\r
1434 UINTN HpIndex;\r
1435 PCI_IO_DEVICE *PciDevice;\r
1436 EFI_EVENT Event;\r
1437 EFI_HPC_STATE State;\r
1438 UINT64 PciAddress;\r
1439 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
1440 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1441 UINT16 BusRange;\r
1442 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1443 BOOLEAN BusPadding;\r
1444\r
1445 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1446 SecondBus = 0;\r
1447 Register = 0;\r
1448 State = 0;\r
1449 Attributes = 0;\r
1450 BusRange = 0;\r
1451\r
1452 ResetAllPpbBusReg (Bridge, StartBusNumber);\r
1453\r
1454 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1455 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
1456\r
1457 //\r
1458 // Check to see whether a pci device is present\r
1459 //\r
1460 Status = PciDevicePresent (\r
1461 PciRootBridgeIo,\r
1462 &Pci,\r
1463 StartBusNumber,\r
1464 Device,\r
1465 Func\r
1466 );\r
1467\r
1468 if (EFI_ERROR (Status)) {\r
1469 if (Func == 0) {\r
1470 //\r
1471 // Skip sub functions, this is not a multi function device\r
1472 //\r
1473 Func = PCI_MAX_FUNC;\r
1474 }\r
1475\r
1476 continue;\r
1477 }\r
1478 \r
1479 //\r
1480 // Get the PCI device information\r
1481 //\r
1482 Status = PciSearchDevice (\r
1483 Bridge,\r
1484 &Pci,\r
1485 StartBusNumber,\r
1486 Device,\r
1487 Func,\r
1488 &PciDevice\r
1489 );\r
1490\r
1491 ASSERT (!EFI_ERROR (Status));\r
1492\r
1493 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
1494\r
1495 if (!IS_PCI_BRIDGE (&Pci)) {\r
1496 //\r
1497 // PCI bridges will be called later\r
1498 // Here just need for PCI device or PCI to cardbus controller\r
1499 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1500 //\r
1501 PreprocessController (\r
1502 PciDevice,\r
1503 PciDevice->BusNumber,\r
1504 PciDevice->DeviceNumber,\r
1505 PciDevice->FunctionNumber,\r
1506 EfiPciBeforeChildBusEnumeration\r
1507 );\r
1508 }\r
1509 \r
1510 //\r
1511 // For Pci Hotplug controller devcie only\r
1512 //\r
1513 if (gPciHotPlugInit != NULL) {\r
1514 //\r
1515 // Check if it is a Hotplug PCI controller\r
1516 //\r
1517 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
1518\r
1519 if (!gPciRootHpcData[HpIndex].Initialized) {\r
1520\r
1521 Status = CreateEventForHpc (HpIndex, &Event);\r
1522\r
1523 ASSERT (!EFI_ERROR (Status));\r
1524\r
1525 Status = gPciHotPlugInit->InitializeRootHpc (\r
1526 gPciHotPlugInit,\r
1527 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1528 PciAddress,\r
1529 Event,\r
1530 &State\r
1531 );\r
1532 \r
1533 PreprocessController (\r
1534 PciDevice,\r
1535 PciDevice->BusNumber,\r
1536 PciDevice->DeviceNumber,\r
1537 PciDevice->FunctionNumber,\r
1538 EfiPciBeforeChildBusEnumeration\r
1539 ); \r
1540 continue;\r
1541 }\r
1542 }\r
1543 }\r
1544\r
1545 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1546 //\r
1547 // For PPB\r
1548 // Get the bridge information\r
1549 //\r
1550 BusPadding = FALSE;\r
1551 if (gPciHotPlugInit != NULL) {\r
1552\r
1553 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
1554 \r
1555 //\r
1556 // If it is initialized, get the padded bus range\r
1557 //\r
1558 Status = gPciHotPlugInit->GetResourcePadding (\r
1559 gPciHotPlugInit,\r
1560 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
1561 PciAddress,\r
1562 &State,\r
1563 (VOID **) &Descriptors,\r
1564 &Attributes\r
1565 );\r
1566\r
1567 if (EFI_ERROR (Status)) {\r
1568 return Status;\r
1569 }\r
1570\r
1571 BusRange = 0;\r
1572 Status = PciGetBusRange (\r
1573 &Descriptors,\r
1574 NULL,\r
1575 NULL,\r
1576 &BusRange\r
1577 );\r
1578\r
1579 gBS->FreePool (Descriptors);\r
1580\r
1581 if (EFI_ERROR (Status)) {\r
1582 return Status;\r
1583 }\r
1584\r
1585 BusPadding = TRUE;\r
1586 }\r
1587 }\r
1588\r
1589 (*SubBusNumber)++;\r
1590 SecondBus = *SubBusNumber;\r
1591\r
1592 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
1593 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
1594\r
1595 Status = PciRootBridgeIo->Pci.Write (\r
1596 PciRootBridgeIo,\r
1597 EfiPciWidthUint16,\r
1598 Address,\r
1599 1,\r
1600 &Register\r
1601 );\r
1602\r
1603\r
1604 //\r
1605 // If it is PPB, resursively search down this bridge\r
1606 //\r
1607 if (IS_PCI_BRIDGE (&Pci)) {\r
1608 \r
1609 //\r
1610 // Initialize SubBusNumber to Maximum bus number\r
1611 //\r
1612 Register = 0xFF;\r
1613 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1614 Status = PciRootBridgeIo->Pci.Write (\r
1615 PciRootBridgeIo,\r
1616 EfiPciWidthUint8,\r
1617 Address,\r
1618 1,\r
1619 &Register\r
1620 );\r
1621\r
1622 //\r
1623 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1624 //\r
1625 PreprocessController (\r
1626 PciDevice,\r
1627 PciDevice->BusNumber,\r
1628 PciDevice->DeviceNumber,\r
1629 PciDevice->FunctionNumber,\r
1630 EfiPciBeforeChildBusEnumeration\r
1631 );\r
1632\r
1633 Status = PciScanBus (\r
1634 PciDevice,\r
1635 (UINT8) (SecondBus),\r
1636 SubBusNumber,\r
1637 PaddedBusRange\r
1638 );\r
1639\r
1640 if (EFI_ERROR (Status)) {\r
1641 return EFI_DEVICE_ERROR;\r
1642 }\r
1643 }\r
1644\r
1645 if (BusPadding) {\r
1646 //\r
1647 // Ensure the device is enabled and initialized\r
1648 //\r
1649 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1650 (State & EFI_HPC_STATE_ENABLED) &&\r
1651 (State & EFI_HPC_STATE_INITIALIZED) ) {\r
1652 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1653 } else {\r
1654 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1655 }\r
1656 }\r
1657\r
1658 //\r
1659 // Set the current maximum bus number under the PPB\r
1660 //\r
1661 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1662\r
1663 Status = PciRootBridgeIo->Pci.Write (\r
1664 PciRootBridgeIo,\r
1665 EfiPciWidthUint8,\r
1666 Address,\r
1667 1,\r
1668 SubBusNumber\r
1669 );\r
1670 }\r
1671\r
1672 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1673\r
1674 //\r
1675 // Skip sub functions, this is not a multi function device\r
1676 //\r
1677 Func = PCI_MAX_FUNC;\r
1678 }\r
1679\r
1680 }\r
1681 }\r
1682\r
1683 return EFI_SUCCESS;\r
1684}\r
1685\r
1686EFI_STATUS\r
1687PciRootBridgeP2CProcess (\r
1688 IN PCI_IO_DEVICE *Bridge\r
1689 )\r
1690/*++\r
1691\r
1692Routine Description:\r
1693 \r
1694 Process Option Rom on this host bridge\r
1695\r
1696Arguments:\r
1697\r
1698Returns:\r
1699\r
1700 None\r
1701\r
1702--*/\r
1703// TODO: Bridge - add argument and description to function comment\r
1704// TODO: EFI_SUCCESS - add return value to function comment\r
1705{\r
1706 LIST_ENTRY *CurrentLink;\r
1707 PCI_IO_DEVICE *Temp;\r
1708 EFI_HPC_STATE State;\r
1709 UINT64 PciAddress;\r
1710 EFI_STATUS Status;\r
1711\r
1712 CurrentLink = Bridge->ChildList.ForwardLink;\r
1713\r
1714 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
1715\r
1716 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1717\r
1718 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1719\r
1720 if (gPciHotPlugInit && Temp->Allocated) {\r
1721 \r
1722 //\r
1723 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1724 //\r
1725 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1726 EFI_PROGRESS_CODE,\r
1727 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
1728 Temp->DevicePath\r
1729 );\r
1730\r
1731 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1732 Status = gPciHotPlugInit->InitializeRootHpc (\r
1733 gPciHotPlugInit,\r
1734 Temp->DevicePath,\r
1735 PciAddress,\r
1736 NULL,\r
1737 &State\r
1738 );\r
1739\r
1740 if (!EFI_ERROR (Status)) {\r
1741 Status = PciBridgeEnumerator (Temp);\r
1742\r
1743 if (EFI_ERROR (Status)) {\r
1744 return Status;\r
1745 }\r
1746 }\r
1747\r
1748 CurrentLink = CurrentLink->ForwardLink;\r
1749 continue;\r
1750\r
1751 }\r
1752 }\r
1753\r
1754 if (!IsListEmpty (&Temp->ChildList)) {\r
1755 Status = PciRootBridgeP2CProcess (Temp);\r
1756 }\r
1757\r
1758 CurrentLink = CurrentLink->ForwardLink;\r
1759 }\r
1760\r
1761 return EFI_SUCCESS;\r
1762}\r
1763\r
1764EFI_STATUS\r
1765PciHostBridgeP2CProcess (\r
1766 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1767 )\r
1768/*++\r
1769\r
1770Routine Description:\r
1771 \r
1772Arguments:\r
1773\r
1774Returns:\r
1775\r
1776 None\r
1777\r
1778--*/\r
1779// TODO: PciResAlloc - add argument and description to function comment\r
1780// TODO: EFI_NOT_FOUND - add return value to function comment\r
1781// TODO: EFI_SUCCESS - add return value to function comment\r
1782{\r
1783 EFI_HANDLE RootBridgeHandle;\r
1784 PCI_IO_DEVICE *RootBridgeDev;\r
1785 EFI_STATUS Status;\r
1786\r
6874dbd0 1787 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1788 return EFI_SUCCESS;\r
1789 }\r
1790\r
878ddf1f 1791 RootBridgeHandle = NULL;\r
1792\r
1793 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1794\r
1795 //\r
1796 // Get RootBridg Device by handle\r
1797 //\r
1798 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1799\r
1800 if (RootBridgeDev == NULL) {\r
1801 return EFI_NOT_FOUND;\r
1802 }\r
1803\r
1804 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1805\r
1806 if (EFI_ERROR (Status)) {\r
1807 return Status;\r
1808 }\r
1809\r
1810 }\r
1811\r
1812 return EFI_SUCCESS;\r
1813}\r
1814\r
1815EFI_STATUS\r
1816PciHostBridgeEnumerator (\r
1817 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1818 )\r
1819/*++\r
1820\r
1821Routine Description:\r
1822\r
1823 This function is used to enumerate the entire host bridge \r
1824 in a given platform\r
1825\r
1826Arguments:\r
1827\r
1828 PciResAlloc - A pointer to the resource allocate protocol.\r
1829\r
1830Returns:\r
1831\r
1832 None\r
1833\r
1834--*/\r
1835// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1836// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1837// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1838// TODO: EFI_SUCCESS - add return value to function comment\r
1839{\r
1840 EFI_HANDLE RootBridgeHandle;\r
1841 PCI_IO_DEVICE *RootBridgeDev;\r
1842 EFI_STATUS Status;\r
1843 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1844 UINT16 MinBus;\r
1845 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1846\r
1847 InitializeHotPlugSupport ();\r
1848\r
1849 //\r
1850 // Notify the bus allocation phase is about to start\r
1851 //\r
1852 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1853\r
1854 RootBridgeHandle = NULL;\r
1855 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1856\r
1857 //\r
1858 // if a root bridge instance is found, create root bridge device for it\r
1859 //\r
1860\r
1861 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1862\r
1863 if (RootBridgeDev == NULL) {\r
1864 return EFI_OUT_OF_RESOURCES;\r
1865 }\r
1866\r
1867 //\r
1868 // Enumerate all the buses under this root bridge\r
1869 //\r
1870\r
1871 Status = PciRootBridgeEnumerator (\r
1872 PciResAlloc,\r
1873 RootBridgeDev\r
1874 );\r
1875\r
1876 if (EFI_ERROR (Status)) {\r
1877 return Status;\r
1878 }\r
1879\r
1880 DestroyRootBridge (RootBridgeDev);\r
1881\r
1882 //\r
1883 // Error proccess here\r
1884 //\r
1885 }\r
1886\r
6874dbd0 1887 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
878ddf1f 1888\r
6874dbd0 1889 // \r
1890 // Notify the bus allocation phase is finished for the first time\r
1891 // \r
1892 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1893 \r
1894 \r
1895 if (gPciHotPlugInit != NULL) {\r
878ddf1f 1896 //\r
6874dbd0 1897 // Wait for all HPC initialized\r
878ddf1f 1898 //\r
6874dbd0 1899 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
878ddf1f 1900\r
6874dbd0 1901 if (EFI_ERROR (Status)) {\r
1902 return Status;\r
878ddf1f 1903 }\r
1904\r
1905 //\r
6874dbd0 1906 // Notify the bus allocation phase is about to start for the 2nd time\r
878ddf1f 1907 //\r
6874dbd0 1908 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1909 \r
1910 RootBridgeHandle = NULL;\r
1911 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
878ddf1f 1912\r
6874dbd0 1913 //\r
1914 // if a root bridge instance is found, create root bridge device for it\r
1915 //\r
878ddf1f 1916\r
6874dbd0 1917 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1918\r
1919 if (RootBridgeDev == NULL) {\r
1920 return EFI_OUT_OF_RESOURCES;\r
1921 }\r
1922\r
1923 //\r
1924 // Enumerate all the buses under this root bridge\r
1925 //\r
1926\r
1927 Status = PciRootBridgeEnumerator (\r
1928 PciResAlloc,\r
1929 RootBridgeDev\r
1930 );\r
1931\r
1932 DestroyRootBridge (RootBridgeDev);\r
1933 if (EFI_ERROR (Status)) {\r
1934 return Status;\r
1935 }\r
878ddf1f 1936 }\r
6874dbd0 1937 \r
1938 //\r
1939 // Notify the bus allocation phase is to end\r
1940 //\r
1941 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
878ddf1f 1942 }\r
6874dbd0 1943 } else {\r
878ddf1f 1944 //\r
1945 // Notify the bus allocation phase is to end\r
1946 //\r
1947 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1948 }\r
1949\r
1950 //\r
1951 // Notify the resource allocation phase is to start\r
1952 //\r
1953 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1954\r
1955 RootBridgeHandle = NULL;\r
1956 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1957\r
1958 //\r
1959 // if a root bridge instance is found, create root bridge device for it\r
1960 //\r
1961\r
1962 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1963\r
1964 if (RootBridgeDev == NULL) {\r
1965 return EFI_OUT_OF_RESOURCES;\r
1966 }\r
1967\r
1968 Status = StartManagingRootBridge (RootBridgeDev);\r
1969\r
1970 if (EFI_ERROR (Status)) {\r
1971 return Status;\r
1972 }\r
1973\r
1974 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1975 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1976\r
1977 if (EFI_ERROR (Status)) {\r
1978 return Status;\r
1979 }\r
1980\r
1981 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1982\r
1983 if (EFI_ERROR (Status)) {\r
1984 return Status;\r
1985 }\r
1986\r
1987 //\r
1988 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1989 // protocol\r
1990 //\r
1991 DetermineRootBridgeAttributes (\r
1992 PciResAlloc,\r
1993 RootBridgeDev\r
1994 );\r
1995\r
1996 //\r
1997 // Collect all the resource information under this root bridge\r
1998 // A database that records all the information about pci device subject to this\r
1999 // root bridge will then be created\r
2000 //\r
2001 Status = PciPciDeviceInfoCollector (\r
2002 RootBridgeDev,\r
2003 (UINT8) MinBus\r
2004 );\r
2005\r
2006 if (EFI_ERROR (Status)) {\r
2007 return Status;\r
2008 }\r
2009\r
2010 InsertRootBridge (RootBridgeDev);\r
2011\r
2012 //\r
2013 // Record the hostbridge handle\r
2014 //\r
2015 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
2016 }\r
2017\r
2018 return EFI_SUCCESS;\r
2019}\r