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