]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c
Initial import.
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciEnumerator.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 PciEnumerator.c\r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "Pcibus.h"\r
25#include "PciEnumerator.h"\r
26#include "PciResourceSupport.h"\r
27#include "PciOptionRomSupport.h"\r
28\r
29EFI_STATUS\r
30PciEnumerator (\r
31 IN EFI_HANDLE Controller\r
32 )\r
33/*++\r
34\r
35Routine Description:\r
36\r
37 This routine is used to enumerate entire pci bus system \r
38 in a given platform\r
39\r
40Arguments:\r
41\r
42Returns:\r
43\r
44 None\r
45\r
46--*/\r
47// TODO: Controller - add argument and description to function comment\r
48// TODO: EFI_SUCCESS - add return value to function comment\r
49// TODO: EFI_SUCCESS - add return value to function comment\r
50{\r
51\r
52 EFI_HANDLE HostBridgeHandle;\r
53 EFI_STATUS Status;\r
54 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
55 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
56\r
57 //\r
58 // If PCI bus has already done the full enumeration, never do it again\r
59 //\r
60 if (!gFullEnumeration) {\r
61 return PciEnumeratorLight (Controller);\r
62 }\r
63\r
64 //\r
65 // If this host bridge has been already enumerated, then return successfully\r
66 //\r
67 if (RootBridgeExisted (Controller)) {\r
68 return EFI_SUCCESS;\r
69 }\r
70\r
71 //\r
72 // Get the rootbridge Io protocol to find the host bridge handle\r
73 //\r
74 Status = gBS->OpenProtocol (\r
75 Controller,\r
76 &gEfiPciRootBridgeIoProtocolGuid,\r
77 (VOID **) &PciRootBridgeIo,\r
78 gPciBusDriverBinding.DriverBindingHandle,\r
79 Controller,\r
80 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
81 );\r
82\r
83 if (EFI_ERROR (Status)) {\r
84 return Status;\r
85 }\r
86\r
87 //\r
88 // Get the host bridge handle\r
89 //\r
90 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
91\r
92 //\r
93 // Get the pci host bridge resource allocation protocol\r
94 //\r
95 Status = gBS->OpenProtocol (\r
96 HostBridgeHandle,\r
97 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
98 (VOID **) &PciResAlloc,\r
99 gPciBusDriverBinding.DriverBindingHandle,\r
100 Controller,\r
101 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
102 );\r
103\r
104 if (EFI_ERROR (Status)) {\r
105 return Status;\r
106 }\r
107\r
108 //\r
109 // Notify the pci bus enumeration is about to begin\r
110 //\r
111 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
112\r
113 //\r
114 // Start the bus allocation phase\r
115 //\r
116 Status = PciHostBridgeEnumerator (PciResAlloc);\r
117\r
118 if (EFI_ERROR (Status)) {\r
119 return Status;\r
120 }\r
121 \r
122 //\r
123 // Submit the resource request\r
124 //\r
125 Status = PciHostBridgeResourceAllocator (PciResAlloc);\r
126\r
127 if (EFI_ERROR (Status)) {\r
128 return Status;\r
129 }\r
130 \r
131 //\r
132 // Process P2C\r
133 //\r
134 Status = PciHostBridgeP2CProcess (PciResAlloc);\r
135\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139 \r
140 //\r
141 // Process attributes for devices on this host bridge\r
142 //\r
143 Status = PciHostBridgeDeviceAttribute (PciResAlloc);\r
144 if (EFI_ERROR (Status)) {\r
145 return Status;\r
146 }\r
147\r
148 gFullEnumeration = FALSE;\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153EFI_STATUS\r
154PciRootBridgeEnumerator (\r
155 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
156 IN PCI_IO_DEVICE *RootBridgeDev\r
157 )\r
158/*++\r
159\r
160Routine Description:\r
161\r
162Arguments:\r
163\r
164Returns:\r
165\r
166 None\r
167\r
168--*/\r
169// TODO: PciResAlloc - add argument and description to function comment\r
170// TODO: RootBridgeDev - add argument and description to function comment\r
171// TODO: EFI_SUCCESS - add return value to function comment\r
172{\r
173 EFI_STATUS Status;\r
174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;\r
175 UINT8 SubBusNumber;\r
176 UINT8 StartBusNumber;\r
177 UINT8 PaddedBusRange;\r
178 EFI_HANDLE RootBridgeHandle;\r
179\r
180 SubBusNumber = 0;\r
181 StartBusNumber = 0;\r
182 PaddedBusRange = 0;\r
183\r
184 //\r
185 // Get the root bridge handle\r
186 //\r
187 RootBridgeHandle = RootBridgeDev->Handle;\r
188\r
189 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
190 EFI_PROGRESS_CODE,\r
191 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
192 RootBridgeDev->DevicePath\r
193 );\r
194\r
195 //\r
196 // Get the Bus information\r
197 //\r
198 Status = PciResAlloc->StartBusEnumeration (\r
199 PciResAlloc,\r
200 RootBridgeHandle,\r
201 (VOID **) &pConfiguration\r
202 );\r
203\r
204 if (EFI_ERROR (Status)) {\r
205 return Status;\r
206 }\r
207\r
208 //\r
209 // Get the bus number to start with\r
210 //\r
211 StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);\r
212\r
213 //\r
214 // Initialize the subordinate bus number\r
215 //\r
216 SubBusNumber = StartBusNumber;\r
217\r
218 //\r
219 // Assign bus number\r
220 //\r
221 Status = PciScanBus (\r
222 RootBridgeDev,\r
223 (UINT8) (pConfiguration->AddrRangeMin),\r
224 &SubBusNumber,\r
225 &PaddedBusRange\r
226 );\r
227\r
228 if (EFI_ERROR (Status)) {\r
229 return Status;\r
230 }\r
231\r
232\r
233 //\r
234 // Assign max bus number scanned\r
235 //\r
236 pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
237\r
238 //\r
239 // Set bus number\r
240 //\r
241 Status = PciResAlloc->SetBusNumbers (\r
242 PciResAlloc,\r
243 RootBridgeHandle,\r
244 pConfiguration\r
245 );\r
246\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
250\r
251 return EFI_SUCCESS;\r
252}\r
253\r
254EFI_STATUS\r
255ProcessOptionRom (\r
256 IN PCI_IO_DEVICE *Bridge,\r
257 IN UINT64 RomBase,\r
258 IN UINT64 MaxLength\r
259 )\r
260/*++\r
261\r
262Routine Description:\r
263\r
264 This routine is used to process option rom on a certain root bridge\r
265\r
266Arguments:\r
267\r
268Returns:\r
269\r
270 None\r
271\r
272--*/\r
273// TODO: Bridge - add argument and description to function comment\r
274// TODO: RomBase - add argument and description to function comment\r
275// TODO: MaxLength - add argument and description to function comment\r
276// TODO: EFI_SUCCESS - add return value to function comment\r
277{\r
278 LIST_ENTRY *CurrentLink;\r
279 PCI_IO_DEVICE *Temp;\r
280 EFI_STATUS Status;\r
281\r
282 //\r
283 // Go through bridges to reach all devices\r
284 //\r
285 CurrentLink = Bridge->ChildList.ForwardLink;\r
286 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
287 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
288 if (!IsListEmpty (&Temp->ChildList)) {\r
289 \r
290 //\r
291 // Go further to process the option rom under this bridge\r
292 //\r
293 Status = ProcessOptionRom (Temp, RomBase, MaxLength);\r
294 }\r
295\r
296 if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {\r
297 \r
298 //\r
299 // Load and process the option rom\r
300 //\r
301 Status = LoadOpRomImage (Temp, RomBase);\r
302 if (Status == EFI_SUCCESS) {\r
303 Status = ProcessOpRomImage (Temp);\r
304 }\r
305 }\r
306\r
307 CurrentLink = CurrentLink->ForwardLink;\r
308 }\r
309\r
310 return EFI_SUCCESS;\r
311}\r
312\r
313EFI_STATUS\r
314PciAssignBusNumber (\r
315 IN PCI_IO_DEVICE *Bridge,\r
316 IN UINT8 StartBusNumber,\r
317 OUT UINT8 *SubBusNumber\r
318 )\r
319/*++\r
320\r
321Routine Description:\r
322\r
323 This routine is used to assign bus number to the given PCI bus system\r
324\r
325Arguments:\r
326\r
327Returns:\r
328\r
329 None\r
330\r
331--*/\r
332// TODO: Bridge - add argument and description to function comment\r
333// TODO: StartBusNumber - add argument and description to function comment\r
334// TODO: SubBusNumber - add argument and description to function comment\r
335// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
336// TODO: EFI_SUCCESS - add return value to function comment\r
337{\r
338 EFI_STATUS Status;\r
339 PCI_TYPE00 Pci;\r
340 UINT8 Device;\r
341 UINT8 Func;\r
342 UINT64 Address;\r
343 UINTN SecondBus;\r
344 UINT16 Register;\r
345 UINT8 Register8;\r
346 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
347\r
348 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
349\r
350 SecondBus = 0;\r
351 Register = 0;\r
352\r
353 *SubBusNumber = StartBusNumber;\r
354\r
355 //\r
356 // First check to see whether the parent is ppb\r
357 //\r
358 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
359 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
360\r
361 //\r
362 // Check to see whether a pci device is present\r
363 //\r
364\r
365 Status = PciDevicePresent (\r
366 PciRootBridgeIo,\r
367 &Pci,\r
368 StartBusNumber,\r
369 Device,\r
370 Func\r
371 );\r
372\r
373 if (!EFI_ERROR (Status) &&\r
374 (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
375\r
376 //\r
377 // Reserved one bus for cardbus bridge\r
378 //\r
379 SecondBus = ++(*SubBusNumber);\r
380\r
381 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
382\r
383 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
384\r
385 Status = PciRootBridgeIo->Pci.Write (\r
386 PciRootBridgeIo,\r
387 EfiPciWidthUint16,\r
388 Address,\r
389 1,\r
390 &Register\r
391 );\r
392\r
393 //\r
394 // Initialize SubBusNumber to SecondBus\r
395 //\r
396 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
397 Status = PciRootBridgeIo->Pci.Write (\r
398 PciRootBridgeIo,\r
399 EfiPciWidthUint8,\r
400 Address,\r
401 1,\r
402 SubBusNumber\r
403 );\r
404 //\r
405 // If it is PPB, resursively search down this bridge\r
406 //\r
407 if (IS_PCI_BRIDGE (&Pci)) {\r
408\r
409 Register8 = 0xFF;\r
410 Status = PciRootBridgeIo->Pci.Write (\r
411 PciRootBridgeIo,\r
412 EfiPciWidthUint8,\r
413 Address,\r
414 1,\r
415 &Register8\r
416 );\r
417\r
418 Status = PciAssignBusNumber (\r
419 Bridge,\r
420 (UINT8) (SecondBus),\r
421 SubBusNumber\r
422 );\r
423\r
424 if (EFI_ERROR (Status)) {\r
425 return EFI_DEVICE_ERROR;\r
426 }\r
427 }\r
428\r
429 //\r
430 // Set the current maximum bus number under the PPB\r
431 //\r
432\r
433 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
434\r
435 Status = PciRootBridgeIo->Pci.Write (\r
436 PciRootBridgeIo,\r
437 EfiPciWidthUint8,\r
438 Address,\r
439 1,\r
440 SubBusNumber\r
441 );\r
442\r
443 }\r
444\r
445 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
446\r
447 //\r
448 // Skip sub functions, this is not a multi function device\r
449 //\r
450\r
451 Func = PCI_MAX_FUNC;\r
452 }\r
453 }\r
454 }\r
455\r
456 return EFI_SUCCESS;\r
457}\r
458\r
459EFI_STATUS\r
460DetermineRootBridgeAttributes (\r
461 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
462 IN PCI_IO_DEVICE *RootBridgeDev\r
463 )\r
464/*++\r
465\r
466Routine Description:\r
467\r
468 This routine is used to determine the root bridge attribute by interfacing\r
469 the host bridge resource allocation protocol.\r
470\r
471Arguments:\r
472\r
473Returns:\r
474\r
475 None\r
476\r
477--*/\r
478// TODO: PciResAlloc - add argument and description to function comment\r
479// TODO: RootBridgeDev - add argument and description to function comment\r
480// TODO: EFI_SUCCESS - add return value to function comment\r
481{\r
482 UINT64 Attributes;\r
483 EFI_STATUS Status;\r
484 EFI_HANDLE RootBridgeHandle;\r
485\r
486 Attributes = 0;\r
487 RootBridgeHandle = RootBridgeDev->Handle;\r
488\r
489 //\r
490 // Get root bridge attribute by calling into pci host bridge resource allocation protocol\r
491 //\r
492 Status = PciResAlloc->GetAllocAttributes (\r
493 PciResAlloc,\r
494 RootBridgeHandle,\r
495 &Attributes\r
496 );\r
497\r
498 if (EFI_ERROR (Status)) {\r
499 return Status;\r
500 }\r
501\r
502 //\r
503 // Here is the point where PCI bus driver calls HOST bridge allocation protocol\r
504 // Currently we hardcoded for ea815\r
505 //\r
506 \r
507 if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {\r
508 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;\r
509 }\r
510\r
511 if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {\r
512 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
513 }\r
514\r
515 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
516 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
517 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
518\r
519 return EFI_SUCCESS;\r
520}\r
521\r
522UINT64\r
523GetMaxOptionRomSize (\r
524 IN PCI_IO_DEVICE *Bridge\r
525 )\r
526/*++\r
527\r
528Routine Description:\r
529 \r
530 Get Max Option Rom size on this bridge\r
531\r
532Arguments:\r
533\r
534Returns:\r
535\r
536 None\r
537\r
538--*/\r
539// TODO: Bridge - add argument and description to function comment\r
540{\r
541 LIST_ENTRY *CurrentLink;\r
542 PCI_IO_DEVICE *Temp;\r
543 UINT64 MaxOptionRomSize;\r
544 UINT64 TempOptionRomSize;\r
545\r
546 MaxOptionRomSize = 0;\r
547\r
548 //\r
549 // Go through bridges to reach all devices\r
550 //\r
551 CurrentLink = Bridge->ChildList.ForwardLink;\r
552 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
553 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
554 if (!IsListEmpty (&Temp->ChildList)) {\r
555 \r
556 //\r
557 // Get max option rom size under this bridge\r
558 //\r
559 TempOptionRomSize = GetMaxOptionRomSize (Temp);\r
560\r
561 //\r
562 // Compare with the option rom size of the bridge\r
563 // Get the larger one\r
564 //\r
565 if (Temp->RomSize > TempOptionRomSize) {\r
566 TempOptionRomSize = Temp->RomSize;\r
567 }\r
568\r
569 } else {\r
570 \r
571 //\r
572 // For devices get the rom size directly\r
573 //\r
574 TempOptionRomSize = Temp->RomSize;\r
575 }\r
576 \r
577 //\r
578 // Get the largest rom size on this bridge\r
579 //\r
580 if (TempOptionRomSize > MaxOptionRomSize) {\r
581 MaxOptionRomSize = TempOptionRomSize;\r
582 }\r
583\r
584 CurrentLink = CurrentLink->ForwardLink;\r
585 }\r
586\r
587 return MaxOptionRomSize;\r
588}\r
589\r
590EFI_STATUS\r
591PciHostBridgeDeviceAttribute (\r
592 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
593 )\r
594/*++\r
595\r
596Routine Description:\r
597 \r
598 Process attributes of devices on this host bridge\r
599\r
600Arguments:\r
601\r
602Returns:\r
603\r
604 None\r
605\r
606--*/\r
607// TODO: PciResAlloc - add argument and description to function comment\r
608// TODO: EFI_NOT_FOUND - add return value to function comment\r
609// TODO: EFI_SUCCESS - add return value to function comment\r
610{\r
611 EFI_HANDLE RootBridgeHandle;\r
612 PCI_IO_DEVICE *RootBridgeDev;\r
613 EFI_STATUS Status;\r
614\r
615 RootBridgeHandle = NULL;\r
616\r
617 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
618\r
619 //\r
620 // Get RootBridg Device by handle\r
621 //\r
622 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
623\r
624 if (RootBridgeDev == NULL) {\r
625 return EFI_NOT_FOUND;\r
626 }\r
627\r
628 //\r
629 // Set the attributes for devcies behind the Root Bridge\r
630 //\r
631 Status = DetermineDeviceAttribute (RootBridgeDev);\r
632 if (EFI_ERROR (Status)) {\r
633 return Status;\r
634 }\r
635\r
636 }\r
637\r
638 return EFI_SUCCESS;\r
639}\r
640\r
641EFI_STATUS\r
642GetResourceAllocationStatus (\r
643 VOID *AcpiConfig,\r
644 OUT UINT64 *IoResStatus,\r
645 OUT UINT64 *Mem32ResStatus,\r
646 OUT UINT64 *PMem32ResStatus,\r
647 OUT UINT64 *Mem64ResStatus,\r
648 OUT UINT64 *PMem64ResStatus\r
649 )\r
650/*++\r
651\r
652Routine Description:\r
653 \r
654 Get resource allocation status from the ACPI pointer\r
655\r
656Arguments:\r
657\r
658Returns:\r
659\r
660 None\r
661\r
662--*/\r
663// TODO: AcpiConfig - add argument and description to function comment\r
664// TODO: IoResStatus - add argument and description to function comment\r
665// TODO: Mem32ResStatus - add argument and description to function comment\r
666// TODO: PMem32ResStatus - add argument and description to function comment\r
667// TODO: Mem64ResStatus - add argument and description to function comment\r
668// TODO: PMem64ResStatus - add argument and description to function comment\r
669// TODO: EFI_SUCCESS - add return value to function comment\r
670{\r
671\r
672 UINT8 *Temp;\r
673 UINT64 ResStatus;\r
674 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;\r
675\r
676 Temp = (UINT8 *) AcpiConfig;\r
677\r
678 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
679\r
680 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
681 ResStatus = ptr->AddrTranslationOffset;\r
682\r
683 switch (ptr->ResType) {\r
684 case 0:\r
685 if (ptr->AddrSpaceGranularity == 32) {\r
686 if (ptr->SpecificFlag == 0x06) {\r
687 //\r
688 // Pmem32\r
689 //\r
690 *PMem32ResStatus = ResStatus;\r
691 } else {\r
692 //\r
693 // Mem32\r
694 //\r
695 *Mem32ResStatus = ResStatus;\r
696 }\r
697 }\r
698\r
699 if (ptr->AddrSpaceGranularity == 64) {\r
700 if (ptr->SpecificFlag == 0x06) {\r
701 //\r
702 // PMem64\r
703 //\r
704 *PMem64ResStatus = ResStatus;\r
705 } else {\r
706 //\r
707 // Mem64\r
708 //\r
709 *Mem64ResStatus = ResStatus;\r
710 }\r
711 }\r
712\r
713 break;\r
714\r
715 case 1:\r
716 //\r
717 // Io\r
718 //\r
719 *IoResStatus = ResStatus;\r
720 break;\r
721\r
722 default:\r
723 break;\r
724 }\r
725\r
726 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
727 }\r
728\r
729 return EFI_SUCCESS;\r
730}\r
731\r
732EFI_STATUS\r
733RejectPciDevice (\r
734 IN PCI_IO_DEVICE *PciDevice\r
735 )\r
736/*++\r
737\r
738Routine Description:\r
739 \r
740 Remove a PCI device from device pool and mark its bar\r
741\r
742Arguments:\r
743\r
744Returns:\r
745\r
746 None\r
747\r
748--*/\r
749// TODO: PciDevice - add argument and description to function comment\r
750// TODO: EFI_SUCCESS - add return value to function comment\r
751// TODO: EFI_ABORTED - add return value to function comment\r
752// TODO: EFI_SUCCESS - add return value to function comment\r
753// TODO: EFI_ABORTED - add return value to function comment\r
754{\r
755 PCI_IO_DEVICE *Bridge;\r
756 PCI_IO_DEVICE *Temp;\r
757 LIST_ENTRY *CurrentLink;\r
758\r
759 //\r
760 // Remove the padding resource from a bridge\r
761 //\r
762 if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \\r
763 PciDevice->ResourcePaddingDescriptors ) {\r
764 gBS->FreePool (PciDevice->ResourcePaddingDescriptors);\r
765 PciDevice->ResourcePaddingDescriptors = NULL;\r
766 return EFI_SUCCESS;\r
767 }\r
768\r
769 //\r
770 // Skip RB and PPB\r
771 //\r
772 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {\r
773 return EFI_ABORTED;\r
774 }\r
775\r
776 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {\r
777 //\r
778 // Get the root bridge device\r
779 //\r
780 Bridge = PciDevice;\r
781 while (Bridge->Parent) {\r
782 Bridge = Bridge->Parent;\r
783 }\r
784\r
785 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);\r
786\r
787 //\r
788 // Mark its bar\r
789 //\r
790 InitializeP2C (PciDevice);\r
791 }\r
792 \r
793 //\r
794 // Remove the device\r
795 //\r
796 Bridge = PciDevice->Parent;\r
797 CurrentLink = Bridge->ChildList.ForwardLink;\r
798 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
799 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
800 if (Temp == PciDevice) {\r
801 InitializePciDevice (Temp);\r
802 RemoveEntryList (CurrentLink);\r
803 FreePciDevice (Temp);\r
804 return EFI_SUCCESS;\r
805 }\r
806\r
807 CurrentLink = CurrentLink->ForwardLink;\r
808 }\r
809\r
810 return EFI_ABORTED;\r
811}\r
812\r
813BOOLEAN\r
814IsRejectiveDevice (\r
815 IN PCI_RESOURCE_NODE *PciResNode\r
816 )\r
817/*++\r
818\r
819Routine Description:\r
820 \r
821 Determine whethter a PCI device can be rejected\r
822\r
823Arguments:\r
824\r
825Returns:\r
826\r
827 None\r
828\r
829--*/\r
830// TODO: PciResNode - add argument and description to function comment\r
831{\r
832 PCI_IO_DEVICE *Temp;\r
833\r
834 Temp = PciResNode->PciDev;\r
835\r
836 //\r
837 // Ensure the device is present\r
838 //\r
839 if (!Temp) {\r
840 return FALSE;\r
841 }\r
842 \r
843 //\r
844 // PPB and RB should go ahead\r
845 //\r
846 if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {\r
847 return TRUE;\r
848 }\r
849\r
850 //\r
851 // Skip device on Bus0\r
852 //\r
853 if ((Temp->Parent) && (Temp->BusNumber == 0)) {\r
854 return FALSE;\r
855 }\r
856 \r
857 //\r
858 // Skip VGA\r
859 //\r
860 if (IS_PCI_VGA (&Temp->Pci)) {\r
861 return FALSE;\r
862 }\r
863\r
864 return TRUE;\r
865}\r
866\r
867PCI_RESOURCE_NODE *\r
868GetLargerConsumerDevice (\r
869 IN PCI_RESOURCE_NODE *PciResNode1,\r
870 IN PCI_RESOURCE_NODE *PciResNode2\r
871 )\r
872/*++\r
873\r
874Routine Description:\r
875 \r
876 Get the larger resource consumer\r
877\r
878Arguments:\r
879\r
880Returns:\r
881\r
882 None\r
883\r
884--*/\r
885// TODO: PciResNode1 - add argument and description to function comment\r
886// TODO: PciResNode2 - add argument and description to function comment\r
887{\r
888 if (!PciResNode2) {\r
889 return PciResNode1;\r
890 }\r
891\r
892 if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \\r
893 && (PciResNode2->ResourceUsage != PciResUsagePadding) )\r
894 {\r
895 return PciResNode1;\r
896 }\r
897\r
898 if (!PciResNode1) {\r
899 return PciResNode2;\r
900 }\r
901\r
902 if ((PciResNode1->Length) > (PciResNode2->Length)) {\r
903 return PciResNode1;\r
904 }\r
905\r
906 return PciResNode2;\r
907\r
908}\r
909\r
910PCI_RESOURCE_NODE *\r
911GetMaxResourceConsumerDevice (\r
912 IN PCI_RESOURCE_NODE *ResPool\r
913 )\r
914/*++\r
915\r
916Routine Description:\r
917 \r
918 Get the max resource consumer in the host resource pool \r
919\r
920Arguments:\r
921\r
922Returns:\r
923\r
924 None\r
925\r
926--*/\r
927// TODO: ResPool - add argument and description to function comment\r
928{\r
929 PCI_RESOURCE_NODE *Temp;\r
930 LIST_ENTRY *CurrentLink;\r
931 PCI_RESOURCE_NODE *PciResNode;\r
932 PCI_RESOURCE_NODE *PPBResNode;\r
933\r
934 PciResNode = NULL;\r
935\r
936 CurrentLink = ResPool->ChildList.ForwardLink;\r
937 while (CurrentLink && CurrentLink != &ResPool->ChildList) {\r
938\r
939 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
940\r
941 if (!IsRejectiveDevice (Temp)) {\r
942 CurrentLink = CurrentLink->ForwardLink;\r
943 continue;\r
944 }\r
945\r
946 if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \\r
947 && (Temp->ResourceUsage != PciResUsagePadding))\r
948 {\r
949 PPBResNode = GetMaxResourceConsumerDevice (Temp);\r
950 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);\r
951 } else {\r
952 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);\r
953 }\r
954\r
955 CurrentLink = CurrentLink->ForwardLink;\r
956 }\r
957\r
958 return PciResNode;\r
959}\r
960\r
961EFI_STATUS\r
962PciHostBridgeAdjustAllocation (\r
963 IN PCI_RESOURCE_NODE *IoPool,\r
964 IN PCI_RESOURCE_NODE *Mem32Pool,\r
965 IN PCI_RESOURCE_NODE *PMem32Pool,\r
966 IN PCI_RESOURCE_NODE *Mem64Pool,\r
967 IN PCI_RESOURCE_NODE *PMem64Pool,\r
968 IN UINT64 IoResStatus,\r
969 IN UINT64 Mem32ResStatus,\r
970 IN UINT64 PMem32ResStatus,\r
971 IN UINT64 Mem64ResStatus,\r
972 IN UINT64 PMem64ResStatus\r
973 )\r
974/*++\r
975\r
976Routine Description:\r
977 \r
978 Adjust host bridge allocation so as to reduce resource requirement\r
979\r
980Arguments:\r
981\r
982Returns:\r
983\r
984 None\r
985\r
986--*/\r
987// TODO: IoPool - add argument and description to function comment\r
988// TODO: Mem32Pool - add argument and description to function comment\r
989// TODO: PMem32Pool - add argument and description to function comment\r
990// TODO: Mem64Pool - add argument and description to function comment\r
991// TODO: PMem64Pool - add argument and description to function comment\r
992// TODO: IoResStatus - add argument and description to function comment\r
993// TODO: Mem32ResStatus - add argument and description to function comment\r
994// TODO: PMem32ResStatus - add argument and description to function comment\r
995// TODO: Mem64ResStatus - add argument and description to function comment\r
996// TODO: PMem64ResStatus - add argument and description to function comment\r
997// TODO: EFI_ABORTED - add return value to function comment\r
998// TODO: EFI_SUCCESS - add return value to function comment\r
999// TODO: EFI_ABORTED - add return value to function comment\r
1000{\r
1001 BOOLEAN AllocationAjusted;\r
1002 PCI_RESOURCE_NODE *PciResNode;\r
1003 PCI_RESOURCE_NODE *ResPool[5];\r
1004 PCI_IO_DEVICE *RemovedPciDev[5];\r
1005 UINT64 ResStatus[5];\r
1006 UINTN RemovedPciDevNum;\r
1007 UINTN DevIndex;\r
1008 UINTN ResType;\r
1009 EFI_STATUS Status;\r
1010 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;\r
1011\r
1012 PciResNode = NULL;\r
1013 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));\r
1014 RemovedPciDevNum = 0;\r
1015\r
1016 ResPool[0] = IoPool;\r
1017 ResPool[1] = Mem32Pool;\r
1018 ResPool[2] = PMem32Pool;\r
1019 ResPool[3] = Mem64Pool;\r
1020 ResPool[4] = PMem64Pool;\r
1021\r
1022 ResStatus[0] = IoResStatus;\r
1023 ResStatus[1] = Mem32ResStatus;\r
1024 ResStatus[2] = PMem32ResStatus;\r
1025 ResStatus[3] = Mem64ResStatus;\r
1026 ResStatus[4] = PMem64ResStatus;\r
1027\r
1028 AllocationAjusted = FALSE;\r
1029\r
1030 for (ResType = 0; ResType < 5; ResType++) {\r
1031\r
1032 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {\r
1033 continue;\r
1034 }\r
1035\r
1036 if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {\r
1037 //\r
1038 // Hostbridge hasn't this resource type\r
1039 //\r
1040 return EFI_ABORTED;\r
1041 }\r
1042 \r
1043 //\r
1044 // Hostbridge hasn't enough resource\r
1045 //\r
1046 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);\r
1047 if (!PciResNode) {\r
1048 continue;\r
1049 }\r
1050 \r
1051 //\r
1052 // Check if the device has been removed before\r
1053 //\r
1054 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {\r
1055 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {\r
1056 continue;\r
1057 }\r
1058 }\r
1059 \r
1060 //\r
1061 // Remove the device if it isn't in the array\r
1062 //\r
1063 Status = RejectPciDevice (PciResNode->PciDev);\r
1064 if (Status == EFI_SUCCESS) {\r
1065 \r
1066 //\r
1067 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
1068 //\r
1069 //\r
1070 // Have no way to get ReqRes, AllocRes & Bar here\r
1071 //\r
1072 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
1073 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
1074 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;\r
1075 AllocFailExtendedData.Bar = PciResNode->Bar;\r
1076\r
1077 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1078 EFI_PROGRESS_CODE,\r
1079 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
1080 (VOID *) &AllocFailExtendedData,\r
1081 sizeof (AllocFailExtendedData)\r
1082 );\r
1083\r
1084 //\r
1085 // Add it to the array and indicate at least a device has been rejected\r
1086 //\r
1087 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
1088 AllocationAjusted = TRUE;\r
1089 }\r
1090 }\r
1091 //\r
1092 // End for\r
1093 //\r
1094\r
1095 if (AllocationAjusted) {\r
1096 return EFI_SUCCESS;\r
1097 } else {\r
1098 return EFI_ABORTED;\r
1099 }\r
1100}\r
1101\r
1102EFI_STATUS\r
1103ConstructAcpiResourceRequestor (\r
1104 IN PCI_IO_DEVICE *Bridge,\r
1105 IN PCI_RESOURCE_NODE *IoNode,\r
1106 IN PCI_RESOURCE_NODE *Mem32Node,\r
1107 IN PCI_RESOURCE_NODE *PMem32Node,\r
1108 IN PCI_RESOURCE_NODE *Mem64Node,\r
1109 IN PCI_RESOURCE_NODE *PMem64Node,\r
1110 OUT VOID **pConfig\r
1111 )\r
1112/*++\r
1113\r
1114Routine Description:\r
1115\r
1116Arguments:\r
1117\r
1118Returns:\r
1119\r
1120 None\r
1121\r
1122--*/\r
1123// TODO: Bridge - add argument and description to function comment\r
1124// TODO: IoNode - add argument and description to function comment\r
1125// TODO: Mem32Node - add argument and description to function comment\r
1126// TODO: PMem32Node - add argument and description to function comment\r
1127// TODO: Mem64Node - add argument and description to function comment\r
1128// TODO: PMem64Node - add argument and description to function comment\r
1129// TODO: pConfig - add argument and description to function comment\r
1130// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1131// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1132// TODO: EFI_SUCCESS - add return value to function comment\r
1133{\r
1134 UINT8 NumConfig;\r
1135 UINT8 Aperture;\r
1136 UINT8 *Configuration;\r
1137 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1138 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
1139\r
1140 NumConfig = 0;\r
1141 Aperture = 0;\r
1142\r
1143 *pConfig = NULL;\r
1144\r
1145 //\r
1146 // if there is io request, add to the io aperture\r
1147 //\r
1148 if (ResourceRequestExisted (IoNode)) {\r
1149 NumConfig++;\r
1150 Aperture |= 0x01;\r
1151 }\r
1152\r
1153 //\r
1154 // if there is mem32 request, add to the mem32 aperture\r
1155 //\r
1156 if (ResourceRequestExisted (Mem32Node)) {\r
1157 NumConfig++;\r
1158 Aperture |= 0x02;\r
1159 }\r
1160\r
1161 //\r
1162 // if there is pmem32 request, add to the pmem32 aperture\r
1163 //\r
1164 if (ResourceRequestExisted (PMem32Node)) {\r
1165 NumConfig++;\r
1166 Aperture |= 0x04;\r
1167 }\r
1168\r
1169 //\r
1170 // if there is mem64 request, add to the mem64 aperture\r
1171 //\r
1172 if (ResourceRequestExisted (Mem64Node)) {\r
1173 NumConfig++;\r
1174 Aperture |= 0x08;\r
1175 }\r
1176\r
1177 //\r
1178 // if there is pmem64 request, add to the pmem64 aperture\r
1179 //\r
1180 if (ResourceRequestExisted (PMem64Node)) {\r
1181 NumConfig++;\r
1182 Aperture |= 0x10;\r
1183 }\r
1184\r
1185 if (NumConfig != 0) {\r
1186\r
1187 //\r
1188 // If there is at least one type of resource request,\r
1189 // allocate a acpi resource node\r
1190 //\r
1191 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1192 if (Configuration == NULL) {\r
1193 return EFI_OUT_OF_RESOURCES;\r
1194 }\r
1195\r
1196 ZeroMem (\r
1197 Configuration,\r
1198 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1199 );\r
1200\r
1201 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1202\r
1203 //\r
1204 // Deal with io aperture\r
1205 //\r
1206 if (Aperture & 0x01) {\r
1207 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1208 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1209 //\r
1210 // Io\r
1211 //\r
1212 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1213 //\r
1214 // non ISA range\r
1215 //\r
1216 Ptr->SpecificFlag = 1;\r
1217 Ptr->AddrLen = IoNode->Length;\r
1218 Ptr->AddrRangeMax = IoNode->Alignment;\r
1219\r
1220 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1221 }\r
1222 //\r
1223 // Deal with mem32 aperture\r
1224 //\r
1225 if (Aperture & 0x02) {\r
1226 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1227 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1228 //\r
1229 // Mem\r
1230 //\r
1231 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1232 //\r
1233 // Nonprefechable\r
1234 //\r
1235 Ptr->SpecificFlag = 0;\r
1236 //\r
1237 // 32 bit\r
1238 //\r
1239 Ptr->AddrSpaceGranularity = 32;\r
1240 Ptr->AddrLen = Mem32Node->Length;\r
1241 Ptr->AddrRangeMax = Mem32Node->Alignment;\r
1242\r
1243 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1244 }\r
1245\r
1246 //\r
1247 // Deal with Pmem32 aperture\r
1248 //\r
1249 if (Aperture & 0x04) {\r
1250 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1251 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1252 //\r
1253 // Mem\r
1254 //\r
1255 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1256 //\r
1257 // prefechable\r
1258 //\r
1259 Ptr->SpecificFlag = 0x6;\r
1260 //\r
1261 // 32 bit\r
1262 //\r
1263 Ptr->AddrSpaceGranularity = 32;\r
1264 Ptr->AddrLen = PMem32Node->Length;\r
1265 Ptr->AddrRangeMax = PMem32Node->Alignment;\r
1266\r
1267 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1268 }\r
1269 //\r
1270 // Deal with mem64 aperture\r
1271 //\r
1272 if (Aperture & 0x08) {\r
1273 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1274 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1275 //\r
1276 // Mem\r
1277 //\r
1278 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1279 //\r
1280 // nonprefechable\r
1281 //\r
1282 Ptr->SpecificFlag = 0;\r
1283 //\r
1284 // 64 bit\r
1285 //\r
1286 Ptr->AddrSpaceGranularity = 64;\r
1287 Ptr->AddrLen = Mem64Node->Length;\r
1288 Ptr->AddrRangeMax = Mem64Node->Alignment;\r
1289\r
1290 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1291 }\r
1292 //\r
1293 // Deal with Pmem64 aperture\r
1294 //\r
1295 if (Aperture & 0x10) {\r
1296 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1297 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1298 //\r
1299 // Mem\r
1300 //\r
1301 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1302 //\r
1303 // prefechable\r
1304 //\r
1305 Ptr->SpecificFlag = 0x06;\r
1306 //\r
1307 // 64 bit\r
1308 //\r
1309 Ptr->AddrSpaceGranularity = 64;\r
1310 Ptr->AddrLen = PMem64Node->Length;\r
1311 Ptr->AddrRangeMax = PMem64Node->Alignment;\r
1312\r
1313 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1314 }\r
1315\r
1316 //\r
1317 // put the checksum\r
1318 //\r
1319 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
1320\r
1321 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1322 PtrEnd->Checksum = 0;\r
1323\r
1324 } else {\r
1325\r
1326 //\r
1327 // If there is no resource request\r
1328 //\r
1329 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1330 if (Configuration == NULL) {\r
1331 return EFI_OUT_OF_RESOURCES;\r
1332 }\r
1333\r
1334 ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1335\r
1336 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
1337 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1338\r
1339 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1340 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1341 PtrEnd->Checksum = 0;\r
1342 }\r
1343\r
1344 *pConfig = Configuration;\r
1345\r
1346 return EFI_SUCCESS;\r
1347}\r
1348\r
1349EFI_STATUS\r
1350GetResourceBase (\r
1351 IN VOID *pConfig,\r
1352 OUT UINT64 *IoBase,\r
1353 OUT UINT64 *Mem32Base,\r
1354 OUT UINT64 *PMem32Base,\r
1355 OUT UINT64 *Mem64Base,\r
1356 OUT UINT64 *PMem64Base\r
1357 )\r
1358/*++\r
1359\r
1360Routine Description:\r
1361\r
1362Arguments:\r
1363\r
1364Returns:\r
1365\r
1366 None\r
1367\r
1368--*/\r
1369// TODO: pConfig - add argument and description to function comment\r
1370// TODO: IoBase - add argument and description to function comment\r
1371// TODO: Mem32Base - add argument and description to function comment\r
1372// TODO: PMem32Base - add argument and description to function comment\r
1373// TODO: Mem64Base - add argument and description to function comment\r
1374// TODO: PMem64Base - add argument and description to function comment\r
1375// TODO: EFI_SUCCESS - add return value to function comment\r
1376{\r
1377 UINT8 *Temp;\r
1378 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1379 UINT64 ResStatus;\r
1380\r
1381 *IoBase = 0xFFFFFFFFFFFFFFFFULL;\r
1382 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1383 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1384 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1385 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1386\r
1387 Temp = (UINT8 *) pConfig;\r
1388\r
1389 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1390\r
1391 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1392 ResStatus = Ptr->AddrTranslationOffset;\r
1393\r
1394 if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
1395\r
1396 switch (Ptr->ResType) {\r
1397\r
1398 //\r
1399 // Memory type aperture\r
1400 //\r
1401 case 0:\r
1402 \r
1403 //\r
1404 // Check to see the granularity\r
1405 //\r
1406 if (Ptr->AddrSpaceGranularity == 32) {\r
1407 if (Ptr->SpecificFlag & 0x06) {\r
1408 *PMem32Base = Ptr->AddrRangeMin;\r
1409 } else {\r
1410 *Mem32Base = Ptr->AddrRangeMin;\r
1411 }\r
1412 }\r
1413\r
1414 if (Ptr->AddrSpaceGranularity == 64) {\r
1415 if (Ptr->SpecificFlag & 0x06) {\r
1416 *PMem64Base = Ptr->AddrRangeMin;\r
1417 } else {\r
1418 *Mem64Base = Ptr->AddrRangeMin;\r
1419 }\r
1420 }\r
1421 break;\r
1422\r
1423 case 1:\r
1424\r
1425 //\r
1426 // Io type aperture\r
1427 //\r
1428 *IoBase = Ptr->AddrRangeMin;\r
1429 break;\r
1430\r
1431 default:\r
1432 break;\r
1433\r
1434 }\r
1435 //\r
1436 // End switch\r
1437 //\r
1438 }\r
1439 //\r
1440 // End for\r
1441 //\r
1442 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1443 }\r
1444\r
1445 return EFI_SUCCESS;\r
1446}\r
1447\r
1448EFI_STATUS\r
1449PciBridgeEnumerator (\r
1450 IN PCI_IO_DEVICE *BridgeDev\r
1451 )\r
1452/*++\r
1453\r
1454Routine Description:\r
1455\r
1456Arguments:\r
1457\r
1458Returns:\r
1459\r
1460 None\r
1461\r
1462--*/\r
1463// TODO: BridgeDev - add argument and description to function comment\r
1464// TODO: EFI_SUCCESS - add return value to function comment\r
1465{\r
1466 UINT8 SubBusNumber;\r
1467 UINT8 StartBusNumber;\r
1468 EFI_PCI_IO_PROTOCOL *PciIo;\r
1469 EFI_STATUS Status;\r
1470\r
1471 SubBusNumber = 0;\r
1472 StartBusNumber = 0;\r
1473 PciIo = &(BridgeDev->PciIo);\r
1474 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
1475\r
1476 if (EFI_ERROR (Status)) {\r
1477 return Status;\r
1478 }\r
1479\r
1480 Status = PciAssignBusNumber (\r
1481 BridgeDev,\r
1482 StartBusNumber,\r
1483 &SubBusNumber\r
1484 );\r
1485\r
1486 if (EFI_ERROR (Status)) {\r
1487 return Status;\r
1488 }\r
1489\r
1490 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
1491\r
1492 if (EFI_ERROR (Status)) {\r
1493 return Status;\r
1494 }\r
1495\r
1496 Status = PciBridgeResourceAllocator (BridgeDev);\r
1497\r
1498 if (EFI_ERROR (Status)) {\r
1499 return Status;\r
1500 }\r
1501\r
1502 Status = DetermineDeviceAttribute (BridgeDev);\r
1503\r
1504 if (EFI_ERROR (Status)) {\r
1505 return Status;\r
1506 }\r
1507\r
1508 return EFI_SUCCESS;\r
1509\r
1510}\r
1511\r
1512EFI_STATUS\r
1513PciBridgeResourceAllocator (\r
1514 IN PCI_IO_DEVICE *Bridge\r
1515 )\r
1516/*++\r
1517\r
1518Routine Description:\r
1519\r
1520Arguments:\r
1521\r
1522Returns:\r
1523\r
1524 None\r
1525\r
1526--*/\r
1527// TODO: Bridge - add argument and description to function comment\r
1528// TODO: EFI_SUCCESS - add return value to function comment\r
1529{\r
1530 PCI_RESOURCE_NODE *IoBridge;\r
1531 PCI_RESOURCE_NODE *Mem32Bridge;\r
1532 PCI_RESOURCE_NODE *PMem32Bridge;\r
1533 PCI_RESOURCE_NODE *Mem64Bridge;\r
1534 PCI_RESOURCE_NODE *PMem64Bridge;\r
1535 UINT64 IoBase;\r
1536 UINT64 Mem32Base;\r
1537 UINT64 PMem32Base;\r
1538 UINT64 Mem64Base;\r
1539 UINT64 PMem64Base;\r
1540 EFI_STATUS Status;\r
1541\r
1542 IoBridge = CreateResourceNode (\r
1543 Bridge,\r
1544 0,\r
1545 0xFFF,\r
1546 0,\r
1547 PciBarTypeIo16,\r
1548 PciResUsageTypical\r
1549 );\r
1550\r
1551 Mem32Bridge = CreateResourceNode (\r
1552 Bridge,\r
1553 0,\r
1554 0xFFFFF,\r
1555 0,\r
1556 PciBarTypeMem32,\r
1557 PciResUsageTypical\r
1558 );\r
1559\r
1560 PMem32Bridge = CreateResourceNode (\r
1561 Bridge,\r
1562 0,\r
1563 0xFFFFF,\r
1564 0,\r
1565 PciBarTypePMem32,\r
1566 PciResUsageTypical\r
1567 );\r
1568\r
1569 Mem64Bridge = CreateResourceNode (\r
1570 Bridge,\r
1571 0,\r
1572 0xFFFFF,\r
1573 0,\r
1574 PciBarTypeMem64,\r
1575 PciResUsageTypical\r
1576 );\r
1577\r
1578 PMem64Bridge = CreateResourceNode (\r
1579 Bridge,\r
1580 0,\r
1581 0xFFFFF,\r
1582 0,\r
1583 PciBarTypePMem64,\r
1584 PciResUsageTypical\r
1585 );\r
1586\r
1587 //\r
1588 // Create resourcemap by going through all the devices subject to this root bridge\r
1589 //\r
1590 Status = CreateResourceMap (\r
1591 Bridge,\r
1592 IoBridge,\r
1593 Mem32Bridge,\r
1594 PMem32Bridge,\r
1595 Mem64Bridge,\r
1596 PMem64Bridge\r
1597 );\r
1598\r
1599 if (EFI_ERROR (Status)) {\r
1600 return Status;\r
1601 }\r
1602\r
1603 Status = GetResourceBaseFromBridge (\r
1604 Bridge,\r
1605 &IoBase,\r
1606 &Mem32Base,\r
1607 &PMem32Base,\r
1608 &Mem64Base,\r
1609 &PMem64Base\r
1610 );\r
1611\r
1612 if (EFI_ERROR (Status)) {\r
1613 return Status;\r
1614 }\r
1615\r
1616 //\r
1617 // Program IO resources\r
1618 //\r
1619 ProgramResource (\r
1620 IoBase,\r
1621 IoBridge\r
1622 );\r
1623\r
1624 //\r
1625 // Program Mem32 resources\r
1626 //\r
1627 ProgramResource (\r
1628 Mem32Base,\r
1629 Mem32Bridge\r
1630 );\r
1631\r
1632 //\r
1633 // Program PMem32 resources\r
1634 //\r
1635 ProgramResource (\r
1636 PMem32Base,\r
1637 PMem32Bridge\r
1638 );\r
1639\r
1640 //\r
1641 // Program Mem64 resources\r
1642 //\r
1643 ProgramResource (\r
1644 Mem64Base,\r
1645 Mem64Bridge\r
1646 );\r
1647\r
1648 //\r
1649 // Program PMem64 resources\r
1650 //\r
1651 ProgramResource (\r
1652 PMem64Base,\r
1653 PMem64Bridge\r
1654 );\r
1655\r
1656 DestroyResourceTree (IoBridge);\r
1657 DestroyResourceTree (Mem32Bridge);\r
1658 DestroyResourceTree (PMem32Bridge);\r
1659 DestroyResourceTree (PMem64Bridge);\r
1660 DestroyResourceTree (Mem64Bridge);\r
1661\r
1662 gBS->FreePool (IoBridge);\r
1663 gBS->FreePool (Mem32Bridge);\r
1664 gBS->FreePool (PMem32Bridge);\r
1665 gBS->FreePool (PMem64Bridge);\r
1666 gBS->FreePool (Mem64Bridge);\r
1667\r
1668 return EFI_SUCCESS;\r
1669}\r
1670\r
1671EFI_STATUS\r
1672GetResourceBaseFromBridge (\r
1673 IN PCI_IO_DEVICE *Bridge,\r
1674 OUT UINT64 *IoBase,\r
1675 OUT UINT64 *Mem32Base,\r
1676 OUT UINT64 *PMem32Base,\r
1677 OUT UINT64 *Mem64Base,\r
1678 OUT UINT64 *PMem64Base\r
1679 )\r
1680/*++\r
1681\r
1682Routine Description:\r
1683\r
1684Arguments:\r
1685\r
1686Returns:\r
1687\r
1688 None\r
1689\r
1690--*/\r
1691// TODO: Bridge - add argument and description to function comment\r
1692// TODO: IoBase - add argument and description to function comment\r
1693// TODO: Mem32Base - add argument and description to function comment\r
1694// TODO: PMem32Base - add argument and description to function comment\r
1695// TODO: Mem64Base - add argument and description to function comment\r
1696// TODO: PMem64Base - add argument and description to function comment\r
1697// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1698// TODO: EFI_SUCCESS - add return value to function comment\r
1699{\r
1700 if (!Bridge->Allocated) {\r
1701 return EFI_OUT_OF_RESOURCES;\r
1702 }\r
1703\r
1704 *IoBase = gAllOne;\r
1705 *Mem32Base = gAllOne;\r
1706 *PMem32Base = gAllOne;\r
1707 *Mem64Base = gAllOne;\r
1708 *PMem64Base = gAllOne;\r
1709\r
1710 if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
1711\r
1712 if (Bridge->PciBar[PPB_IO_RANGE].Length) {\r
1713 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
1714 }\r
1715\r
1716 if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {\r
1717 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
1718 }\r
1719\r
1720 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {\r
1721 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
1722 }\r
1723\r
1724 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {\r
1725 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
1726 } else {\r
1727 *PMem64Base = gAllOne;\r
1728 }\r
1729\r
1730 }\r
1731\r
1732 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
1733 if (Bridge->PciBar[P2C_IO_1].Length) {\r
1734 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
1735 } else {\r
1736 if (Bridge->PciBar[P2C_IO_2].Length) {\r
1737 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
1738 }\r
1739 }\r
1740\r
1741 if (Bridge->PciBar[P2C_MEM_1].Length) {\r
1742 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
1743 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1744 }\r
1745\r
1746 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
1747 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1748 }\r
1749 }\r
1750\r
1751 if (Bridge->PciBar[P2C_MEM_2].Length) {\r
1752 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
1753 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1754 }\r
1755\r
1756 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
1757 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1758 }\r
1759 }\r
1760 }\r
1761\r
1762 return EFI_SUCCESS;\r
1763}\r
1764\r
1765EFI_STATUS\r
1766NotifyPhase (\r
1767 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
1768 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
1769 )\r
1770/*++\r
1771\r
1772Routine Description:\r
1773\r
1774Arguments:\r
1775\r
1776Returns:\r
1777\r
1778 None\r
1779\r
1780--*/\r
1781// TODO: PciResAlloc - add argument and description to function comment\r
1782// TODO: Phase - add argument and description to function comment\r
1783// TODO: EFI_NOT_FOUND - add return value to function comment\r
1784// TODO: EFI_SUCCESS - add return value to function comment\r
1785{\r
1786 EFI_HANDLE HostBridgeHandle;\r
1787 EFI_HANDLE RootBridgeHandle;\r
1788 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1789 EFI_STATUS Status;\r
1790\r
1791 HostBridgeHandle = NULL;\r
1792 RootBridgeHandle = NULL;\r
1793 if (gPciPlatformProtocol != NULL) {\r
1794 //\r
1795 // Get Host Bridge Handle.\r
1796 //\r
1797 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
1798\r
1799 //\r
1800 // Get the rootbridge Io protocol to find the host bridge handle\r
1801 //\r
1802 Status = gBS->HandleProtocol (\r
1803 RootBridgeHandle,\r
1804 &gEfiPciRootBridgeIoProtocolGuid,\r
1805 (VOID **) &PciRootBridgeIo\r
1806 );\r
1807\r
1808 if (EFI_ERROR (Status)) {\r
1809 return EFI_NOT_FOUND;\r
1810 }\r
1811\r
1812 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
1813\r
1814 //\r
1815 // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1816 //\r
1817 gPciPlatformProtocol->PhaseNotify (\r
1818 gPciPlatformProtocol,\r
1819 HostBridgeHandle,\r
1820 Phase,\r
1821 ChipsetEntry\r
1822 );\r
1823 }\r
1824\r
1825 Status = PciResAlloc->NotifyPhase (\r
1826 PciResAlloc,\r
1827 Phase\r
1828 );\r
1829\r
1830 if (gPciPlatformProtocol != NULL) {\r
1831 //\r
1832 // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1833 //\r
1834 gPciPlatformProtocol->PhaseNotify (\r
1835 gPciPlatformProtocol,\r
1836 HostBridgeHandle,\r
1837 Phase,\r
1838 ChipsetExit\r
1839 );\r
1840\r
1841 }\r
1842\r
1843 return EFI_SUCCESS;\r
1844}\r
1845\r
1846EFI_STATUS\r
1847PreprocessController (\r
1848 IN PCI_IO_DEVICE *Bridge,\r
1849 IN UINT8 Bus,\r
1850 IN UINT8 Device,\r
1851 IN UINT8 Func,\r
1852 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1853 )\r
1854/*++\r
1855\r
1856Routine Description:\r
1857\r
1858Arguments:\r
1859\r
1860Returns:\r
1861\r
1862 None\r
1863\r
1864--*/\r
1865// TODO: Bridge - add argument and description to function comment\r
1866// TODO: Bus - add argument and description to function comment\r
1867// TODO: Device - add argument and description to function comment\r
1868// TODO: Func - add argument and description to function comment\r
1869// TODO: Phase - add argument and description to function comment\r
1870// TODO: EFI_UNSUPPORTED - add return value to function comment\r
1871// TODO: EFI_SUCCESS - add return value to function comment\r
1872{\r
1873 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;\r
1874 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
1875 EFI_HANDLE RootBridgeHandle;\r
1876 EFI_HANDLE HostBridgeHandle;\r
1877 EFI_STATUS Status;\r
1878\r
1879 //\r
1880 // Get the host bridge handle\r
1881 //\r
1882 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
1883\r
1884 //\r
1885 // Get the pci host bridge resource allocation protocol\r
1886 //\r
1887 Status = gBS->OpenProtocol (\r
1888 HostBridgeHandle,\r
1889 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
1890 (VOID **) &PciResAlloc,\r
1891 NULL,\r
1892 NULL,\r
1893 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1894 );\r
1895\r
1896 if (EFI_ERROR (Status)) {\r
1897 return EFI_UNSUPPORTED;\r
1898 }\r
1899 \r
1900 //\r
1901 // Get Root Brige Handle\r
1902 //\r
1903 while (Bridge->Parent) {\r
1904 Bridge = Bridge->Parent;\r
1905 }\r
1906\r
1907 RootBridgeHandle = Bridge->Handle;\r
1908\r
1909 RootBridgePciAddress.Register = 0;\r
1910 RootBridgePciAddress.Function = Func;\r
1911 RootBridgePciAddress.Device = Device;\r
1912 RootBridgePciAddress.Bus = Bus;\r
1913 RootBridgePciAddress.ExtendedRegister = 0;\r
1914\r
1915 if (gPciPlatformProtocol != NULL) {\r
1916 //\r
1917 // Call PlatformPci::PrepController() if the protocol is present.\r
1918 //\r
1919 gPciPlatformProtocol->PlatformPrepController (\r
1920 gPciPlatformProtocol,\r
1921 HostBridgeHandle,\r
1922 RootBridgeHandle,\r
1923 RootBridgePciAddress,\r
1924 Phase,\r
1925 ChipsetEntry\r
1926 );\r
1927 }\r
1928\r
1929 Status = PciResAlloc->PreprocessController (\r
1930 PciResAlloc,\r
1931 RootBridgeHandle,\r
1932 RootBridgePciAddress,\r
1933 Phase\r
1934 );\r
1935\r
1936 if (gPciPlatformProtocol != NULL) {\r
1937 //\r
1938 // Call PlatformPci::PrepController() if the protocol is present.\r
1939 //\r
1940 gPciPlatformProtocol->PlatformPrepController (\r
1941 gPciPlatformProtocol,\r
1942 HostBridgeHandle,\r
1943 RootBridgeHandle,\r
1944 RootBridgePciAddress,\r
1945 Phase,\r
1946 ChipsetExit\r
1947 );\r
1948 }\r
1949\r
1950 return EFI_SUCCESS;\r
1951}\r
1952\r
1953EFI_STATUS\r
1954EFIAPI\r
1955PciHotPlugRequestNotify (\r
1956 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
1957 IN EFI_PCI_HOTPLUG_OPERATION Operation,\r
1958 IN EFI_HANDLE Controller,\r
1959 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,\r
1960 IN OUT UINT8 *NumberOfChildren,\r
1961 IN OUT EFI_HANDLE * ChildHandleBuffer\r
1962 )\r
1963/*++\r
1964\r
1965Routine Description:\r
1966\r
1967 Hot plug request notify.\r
1968 \r
1969Arguments:\r
1970\r
1971 This - A pointer to the hot plug request protocol.\r
1972 Operation - The operation.\r
1973 Controller - A pointer to the controller.\r
1974 RemainningDevicePath - A pointer to the device path.\r
1975 NumberOfChildren - A the number of child handle in the ChildHandleBuffer.\r
1976 ChildHandleBuffer - A pointer to the array contain the child handle.\r
1977\r
1978Returns:\r
1979\r
1980 Status code.\r
1981\r
1982--*/\r
1983// TODO: RemainingDevicePath - add argument and description to function comment\r
1984// TODO: EFI_NOT_FOUND - add return value to function comment\r
1985// TODO: EFI_SUCCESS - add return value to function comment\r
1986// TODO: EFI_SUCCESS - add return value to function comment\r
1987// TODO: EFI_SUCCESS - add return value to function comment\r
1988{\r
1989 PCI_IO_DEVICE *Bridge;\r
1990 PCI_IO_DEVICE *Temp;\r
1991 EFI_PCI_IO_PROTOCOL *PciIo;\r
1992 UINTN Index;\r
1993 EFI_HANDLE RootBridgeHandle;\r
1994 EFI_STATUS Status;\r
1995\r
1996 Status = gBS->OpenProtocol (\r
1997 Controller,\r
1998 &gEfiPciIoProtocolGuid,\r
1999 (VOID **) &PciIo,\r
2000 gPciBusDriverBinding.DriverBindingHandle,\r
2001 Controller,\r
2002 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2003 );\r
2004\r
2005 if (EFI_ERROR (Status)) {\r
2006 return EFI_NOT_FOUND;\r
2007 }\r
2008\r
2009 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2010\r
2011 //\r
2012 // Get root bridge handle\r
2013 //\r
2014 Temp = Bridge;\r
2015 while (Temp->Parent) {\r
2016 Temp = Temp->Parent;\r
2017 }\r
2018\r
2019 RootBridgeHandle = Temp->Handle;\r
2020\r
2021 if (Operation == EfiPciHotPlugRequestAdd) {\r
2022\r
2023 if (NumberOfChildren != NULL) {\r
2024 *NumberOfChildren = 0;\r
2025 }\r
2026\r
2027 if (IsListEmpty (&Bridge->ChildList)) {\r
2028\r
2029 Status = PciBridgeEnumerator (Bridge);\r
2030\r
2031 if (EFI_ERROR (Status)) {\r
2032 return Status;\r
2033 }\r
2034 }\r
2035\r
2036 Status = StartPciDevicesOnBridge (\r
2037 RootBridgeHandle,\r
2038 Bridge,\r
2039 RemainingDevicePath,\r
2040 NumberOfChildren,\r
2041 ChildHandleBuffer\r
2042 );\r
2043\r
2044 return EFI_SUCCESS;\r
2045 }\r
2046\r
2047 if (Operation == EfiPciHotplugRequestRemove) {\r
2048\r
2049 if (*NumberOfChildren == 0) {\r
2050 //\r
2051 // Remove all devices on the bridge\r
2052 //\r
2053 Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);\r
2054 return Status;\r
2055\r
2056 }\r
2057\r
2058 for (Index = 0; Index < *NumberOfChildren; Index++) {\r
2059 //\r
2060 // De register all the pci device\r
2061 //\r
2062 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);\r
2063\r
2064 if (EFI_ERROR (Status)) {\r
2065 return Status;\r
2066 }\r
2067\r
2068 }\r
2069 //\r
2070 // End for\r
2071 //\r
2072 return EFI_SUCCESS;\r
2073 }\r
2074\r
2075 return EFI_SUCCESS;\r
2076}\r
2077\r
2078BOOLEAN\r
2079SearchHostBridgeHandle (\r
2080 IN EFI_HANDLE RootBridgeHandle\r
2081 )\r
2082/*++\r
2083\r
2084Routine Description:\r
2085 \r
2086Arguments:\r
2087\r
2088Returns:\r
2089\r
2090 None\r
2091\r
2092--*/\r
2093// TODO: RootBridgeHandle - add argument and description to function comment\r
2094{\r
2095 EFI_HANDLE HostBridgeHandle;\r
2096 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2097 UINTN Index;\r
2098 EFI_STATUS Status;\r
2099\r
2100 //\r
2101 // Get the rootbridge Io protocol to find the host bridge handle\r
2102 //\r
2103 Status = gBS->OpenProtocol (\r
2104 RootBridgeHandle,\r
2105 &gEfiPciRootBridgeIoProtocolGuid,\r
2106 (VOID **) &PciRootBridgeIo,\r
2107 gPciBusDriverBinding.DriverBindingHandle,\r
2108 RootBridgeHandle,\r
2109 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2110 );\r
2111\r
2112 if (EFI_ERROR (Status)) {\r
2113 return FALSE;\r
2114 }\r
2115\r
2116 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
2117 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2118 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2119 return TRUE;\r
2120 }\r
2121 }\r
2122\r
2123 return FALSE;\r
2124}\r
2125\r
2126EFI_STATUS\r
2127AddHostBridgeEnumerator (\r
2128 IN EFI_HANDLE HostBridgeHandle\r
2129 )\r
2130/*++\r
2131\r
2132Routine Description:\r
2133 \r
2134Arguments:\r
2135\r
2136Returns:\r
2137\r
2138 None\r
2139\r
2140--*/\r
2141// TODO: HostBridgeHandle - add argument and description to function comment\r
2142// TODO: EFI_ABORTED - add return value to function comment\r
2143// TODO: EFI_ABORTED - add return value to function comment\r
2144// TODO: EFI_SUCCESS - add return value to function comment\r
2145{\r
2146 UINTN Index;\r
2147\r
2148 if (!HostBridgeHandle) {\r
2149 return EFI_ABORTED;\r
2150 }\r
2151\r
2152 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2153 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2154 return EFI_ABORTED;\r
2155 }\r
2156 }\r
2157\r
2158 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {\r
2159 gPciHostBrigeHandles[Index] = HostBridgeHandle;\r
2160 gPciHostBridgeNumber++;\r
2161 }\r
2162\r
2163 return EFI_SUCCESS;\r
2164}\r