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