]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
[Description]:
[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
a1d887b7 1049 break;\r
ead42efc 1050 }\r
1051 }\r
a1d887b7 1052\r
1053 if (DevIndex != RemovedPciDevNum) {\r
1054 continue;\r
1055 }\r
ead42efc 1056\r
1057 //\r
1058 // Remove the device if it isn't in the array\r
1059 //\r
1060 Status = RejectPciDevice (PciResNode->PciDev);\r
1061 if (Status == EFI_SUCCESS) {\r
1062\r
1063 //\r
1064 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
1065 //\r
1066 //\r
1067 // Have no way to get ReqRes, AllocRes & Bar here\r
1068 //\r
1069 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
1070 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
1071 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;\r
1072 AllocFailExtendedData.Bar = PciResNode->Bar;\r
1073\r
1074 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1075 EFI_PROGRESS_CODE,\r
1076 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
1077 (VOID *) &AllocFailExtendedData,\r
1078 sizeof (AllocFailExtendedData)\r
1079 );\r
1080\r
1081 //\r
1082 // Add it to the array and indicate at least a device has been rejected\r
1083 //\r
1084 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
1085 AllocationAjusted = TRUE;\r
1086 }\r
1087 }\r
1088 //\r
1089 // End for\r
1090 //\r
1091\r
1092 if (AllocationAjusted) {\r
1093 return EFI_SUCCESS;\r
1094 } else {\r
1095 return EFI_ABORTED;\r
1096 }\r
1097}\r
1098\r
1099EFI_STATUS\r
1100ConstructAcpiResourceRequestor (\r
1101 IN PCI_IO_DEVICE *Bridge,\r
1102 IN PCI_RESOURCE_NODE *IoNode,\r
1103 IN PCI_RESOURCE_NODE *Mem32Node,\r
1104 IN PCI_RESOURCE_NODE *PMem32Node,\r
1105 IN PCI_RESOURCE_NODE *Mem64Node,\r
1106 IN PCI_RESOURCE_NODE *PMem64Node,\r
1107 OUT VOID **pConfig\r
1108 )\r
1109/*++\r
1110\r
1111Routine Description:\r
1112\r
1113Arguments:\r
1114\r
1115Returns:\r
1116\r
1117 None\r
1118\r
1119--*/\r
1120// TODO: Bridge - add argument and description to function comment\r
1121// TODO: IoNode - add argument and description to function comment\r
1122// TODO: Mem32Node - add argument and description to function comment\r
1123// TODO: PMem32Node - add argument and description to function comment\r
1124// TODO: Mem64Node - add argument and description to function comment\r
1125// TODO: PMem64Node - add argument and description to function comment\r
1126// TODO: pConfig - add argument and description to function comment\r
1127// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1128// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1129// TODO: EFI_SUCCESS - add return value to function comment\r
1130{\r
1131 UINT8 NumConfig;\r
1132 UINT8 Aperture;\r
1133 UINT8 *Configuration;\r
1134 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1135 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
1136\r
1137 NumConfig = 0;\r
1138 Aperture = 0;\r
1139\r
1140 *pConfig = NULL;\r
1141\r
1142 //\r
1143 // if there is io request, add to the io aperture\r
1144 //\r
1145 if (ResourceRequestExisted (IoNode)) {\r
1146 NumConfig++;\r
1147 Aperture |= 0x01;\r
1148 }\r
1149\r
1150 //\r
1151 // if there is mem32 request, add to the mem32 aperture\r
1152 //\r
1153 if (ResourceRequestExisted (Mem32Node)) {\r
1154 NumConfig++;\r
1155 Aperture |= 0x02;\r
1156 }\r
1157\r
1158 //\r
1159 // if there is pmem32 request, add to the pmem32 aperture\r
1160 //\r
1161 if (ResourceRequestExisted (PMem32Node)) {\r
1162 NumConfig++;\r
1163 Aperture |= 0x04;\r
1164 }\r
1165\r
1166 //\r
1167 // if there is mem64 request, add to the mem64 aperture\r
1168 //\r
1169 if (ResourceRequestExisted (Mem64Node)) {\r
1170 NumConfig++;\r
1171 Aperture |= 0x08;\r
1172 }\r
1173\r
1174 //\r
1175 // if there is pmem64 request, add to the pmem64 aperture\r
1176 //\r
1177 if (ResourceRequestExisted (PMem64Node)) {\r
1178 NumConfig++;\r
1179 Aperture |= 0x10;\r
1180 }\r
1181\r
1182 if (NumConfig != 0) {\r
1183\r
1184 //\r
1185 // If there is at least one type of resource request,\r
1186 // allocate a acpi resource node\r
1187 //\r
1188 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1189 if (Configuration == NULL) {\r
1190 return EFI_OUT_OF_RESOURCES;\r
1191 }\r
1192\r
1193 ZeroMem (\r
1194 Configuration,\r
1195 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1196 );\r
1197\r
1198 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1199\r
1200 //\r
1201 // Deal with io aperture\r
1202 //\r
1203 if (Aperture & 0x01) {\r
1204 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1205 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1206 //\r
1207 // Io\r
1208 //\r
1209 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1210 //\r
1211 // non ISA range\r
1212 //\r
1213 Ptr->SpecificFlag = 1;\r
1214 Ptr->AddrLen = IoNode->Length;\r
1215 Ptr->AddrRangeMax = IoNode->Alignment;\r
1216\r
1217 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1218 }\r
1219 //\r
1220 // Deal with mem32 aperture\r
1221 //\r
1222 if (Aperture & 0x02) {\r
1223 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1224 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1225 //\r
1226 // Mem\r
1227 //\r
1228 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1229 //\r
1230 // Nonprefechable\r
1231 //\r
1232 Ptr->SpecificFlag = 0;\r
1233 //\r
1234 // 32 bit\r
1235 //\r
1236 Ptr->AddrSpaceGranularity = 32;\r
1237 Ptr->AddrLen = Mem32Node->Length;\r
1238 Ptr->AddrRangeMax = Mem32Node->Alignment;\r
1239\r
1240 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1241 }\r
1242\r
1243 //\r
1244 // Deal with Pmem32 aperture\r
1245 //\r
1246 if (Aperture & 0x04) {\r
1247 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1248 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1249 //\r
1250 // Mem\r
1251 //\r
1252 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1253 //\r
1254 // prefechable\r
1255 //\r
1256 Ptr->SpecificFlag = 0x6;\r
1257 //\r
1258 // 32 bit\r
1259 //\r
1260 Ptr->AddrSpaceGranularity = 32;\r
1261 Ptr->AddrLen = PMem32Node->Length;\r
1262 Ptr->AddrRangeMax = PMem32Node->Alignment;\r
1263\r
1264 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1265 }\r
1266 //\r
1267 // Deal with mem64 aperture\r
1268 //\r
1269 if (Aperture & 0x08) {\r
1270 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1271 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1272 //\r
1273 // Mem\r
1274 //\r
1275 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1276 //\r
1277 // nonprefechable\r
1278 //\r
1279 Ptr->SpecificFlag = 0;\r
1280 //\r
1281 // 64 bit\r
1282 //\r
1283 Ptr->AddrSpaceGranularity = 64;\r
1284 Ptr->AddrLen = Mem64Node->Length;\r
1285 Ptr->AddrRangeMax = Mem64Node->Alignment;\r
1286\r
1287 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1288 }\r
1289 //\r
1290 // Deal with Pmem64 aperture\r
1291 //\r
1292 if (Aperture & 0x10) {\r
1293 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1294 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1295 //\r
1296 // Mem\r
1297 //\r
1298 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1299 //\r
1300 // prefechable\r
1301 //\r
1302 Ptr->SpecificFlag = 0x06;\r
1303 //\r
1304 // 64 bit\r
1305 //\r
1306 Ptr->AddrSpaceGranularity = 64;\r
1307 Ptr->AddrLen = PMem64Node->Length;\r
1308 Ptr->AddrRangeMax = PMem64Node->Alignment;\r
1309\r
1310 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1311 }\r
1312\r
1313 //\r
1314 // put the checksum\r
1315 //\r
1316 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
1317\r
1318 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1319 PtrEnd->Checksum = 0;\r
1320\r
1321 } else {\r
1322\r
1323 //\r
1324 // If there is no resource request\r
1325 //\r
1326 Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1327 if (Configuration == NULL) {\r
1328 return EFI_OUT_OF_RESOURCES;\r
1329 }\r
1330\r
1331 ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1332\r
1333 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
1334 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1335\r
1336 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1337 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1338 PtrEnd->Checksum = 0;\r
1339 }\r
1340\r
1341 *pConfig = Configuration;\r
1342\r
1343 return EFI_SUCCESS;\r
1344}\r
1345\r
1346EFI_STATUS\r
1347GetResourceBase (\r
1348 IN VOID *pConfig,\r
1349 OUT UINT64 *IoBase,\r
1350 OUT UINT64 *Mem32Base,\r
1351 OUT UINT64 *PMem32Base,\r
1352 OUT UINT64 *Mem64Base,\r
1353 OUT UINT64 *PMem64Base\r
1354 )\r
1355/*++\r
1356\r
1357Routine Description:\r
1358\r
1359Arguments:\r
1360\r
1361Returns:\r
1362\r
1363 None\r
1364\r
1365--*/\r
1366// TODO: pConfig - add argument and description to function comment\r
1367// TODO: IoBase - add argument and description to function comment\r
1368// TODO: Mem32Base - add argument and description to function comment\r
1369// TODO: PMem32Base - add argument and description to function comment\r
1370// TODO: Mem64Base - add argument and description to function comment\r
1371// TODO: PMem64Base - add argument and description to function comment\r
1372// TODO: EFI_SUCCESS - add return value to function comment\r
1373{\r
1374 UINT8 *Temp;\r
1375 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1376 UINT64 ResStatus;\r
1377\r
1378 *IoBase = 0xFFFFFFFFFFFFFFFFULL;\r
1379 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1380 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1381 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1382 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1383\r
1384 Temp = (UINT8 *) pConfig;\r
1385\r
1386 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1387\r
1388 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1389 ResStatus = Ptr->AddrTranslationOffset;\r
1390\r
1391 if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
1392\r
1393 switch (Ptr->ResType) {\r
1394\r
1395 //\r
1396 // Memory type aperture\r
1397 //\r
1398 case 0:\r
1399\r
1400 //\r
1401 // Check to see the granularity\r
1402 //\r
1403 if (Ptr->AddrSpaceGranularity == 32) {\r
1404 if (Ptr->SpecificFlag & 0x06) {\r
1405 *PMem32Base = Ptr->AddrRangeMin;\r
1406 } else {\r
1407 *Mem32Base = Ptr->AddrRangeMin;\r
1408 }\r
1409 }\r
1410\r
1411 if (Ptr->AddrSpaceGranularity == 64) {\r
1412 if (Ptr->SpecificFlag & 0x06) {\r
1413 *PMem64Base = Ptr->AddrRangeMin;\r
1414 } else {\r
1415 *Mem64Base = Ptr->AddrRangeMin;\r
1416 }\r
1417 }\r
1418 break;\r
1419\r
1420 case 1:\r
1421\r
1422 //\r
1423 // Io type aperture\r
1424 //\r
1425 *IoBase = Ptr->AddrRangeMin;\r
1426 break;\r
1427\r
1428 default:\r
1429 break;\r
1430\r
1431 }\r
1432 //\r
1433 // End switch\r
1434 //\r
1435 }\r
1436 //\r
1437 // End for\r
1438 //\r
1439 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1440 }\r
1441\r
1442 return EFI_SUCCESS;\r
1443}\r
1444\r
1445EFI_STATUS\r
1446PciBridgeEnumerator (\r
1447 IN PCI_IO_DEVICE *BridgeDev\r
1448 )\r
1449/*++\r
1450\r
1451Routine Description:\r
1452\r
1453Arguments:\r
1454\r
1455Returns:\r
1456\r
1457 None\r
1458\r
1459--*/\r
1460// TODO: BridgeDev - add argument and description to function comment\r
1461// TODO: EFI_SUCCESS - add return value to function comment\r
1462{\r
1463 UINT8 SubBusNumber;\r
1464 UINT8 StartBusNumber;\r
1465 EFI_PCI_IO_PROTOCOL *PciIo;\r
1466 EFI_STATUS Status;\r
1467\r
1468 SubBusNumber = 0;\r
1469 StartBusNumber = 0;\r
1470 PciIo = &(BridgeDev->PciIo);\r
1471 Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
1472\r
1473 if (EFI_ERROR (Status)) {\r
1474 return Status;\r
1475 }\r
1476\r
1477 Status = PciAssignBusNumber (\r
1478 BridgeDev,\r
1479 StartBusNumber,\r
1480 &SubBusNumber\r
1481 );\r
1482\r
1483 if (EFI_ERROR (Status)) {\r
1484 return Status;\r
1485 }\r
1486\r
1487 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
1488\r
1489 if (EFI_ERROR (Status)) {\r
1490 return Status;\r
1491 }\r
1492\r
1493 Status = PciBridgeResourceAllocator (BridgeDev);\r
1494\r
1495 if (EFI_ERROR (Status)) {\r
1496 return Status;\r
1497 }\r
1498\r
1499 Status = DetermineDeviceAttribute (BridgeDev);\r
1500\r
1501 if (EFI_ERROR (Status)) {\r
1502 return Status;\r
1503 }\r
1504\r
1505 return EFI_SUCCESS;\r
1506\r
1507}\r
1508\r
1509EFI_STATUS\r
1510PciBridgeResourceAllocator (\r
1511 IN PCI_IO_DEVICE *Bridge\r
1512 )\r
1513/*++\r
1514\r
1515Routine Description:\r
1516\r
1517Arguments:\r
1518\r
1519Returns:\r
1520\r
1521 None\r
1522\r
1523--*/\r
1524// TODO: Bridge - add argument and description to function comment\r
1525// TODO: EFI_SUCCESS - add return value to function comment\r
1526{\r
1527 PCI_RESOURCE_NODE *IoBridge;\r
1528 PCI_RESOURCE_NODE *Mem32Bridge;\r
1529 PCI_RESOURCE_NODE *PMem32Bridge;\r
1530 PCI_RESOURCE_NODE *Mem64Bridge;\r
1531 PCI_RESOURCE_NODE *PMem64Bridge;\r
1532 UINT64 IoBase;\r
1533 UINT64 Mem32Base;\r
1534 UINT64 PMem32Base;\r
1535 UINT64 Mem64Base;\r
1536 UINT64 PMem64Base;\r
1537 EFI_STATUS Status;\r
1538\r
1539 IoBridge = CreateResourceNode (\r
1540 Bridge,\r
1541 0,\r
1542 0xFFF,\r
1543 0,\r
1544 PciBarTypeIo16,\r
1545 PciResUsageTypical\r
1546 );\r
1547\r
1548 Mem32Bridge = CreateResourceNode (\r
1549 Bridge,\r
1550 0,\r
1551 0xFFFFF,\r
1552 0,\r
1553 PciBarTypeMem32,\r
1554 PciResUsageTypical\r
1555 );\r
1556\r
1557 PMem32Bridge = CreateResourceNode (\r
1558 Bridge,\r
1559 0,\r
1560 0xFFFFF,\r
1561 0,\r
1562 PciBarTypePMem32,\r
1563 PciResUsageTypical\r
1564 );\r
1565\r
1566 Mem64Bridge = CreateResourceNode (\r
1567 Bridge,\r
1568 0,\r
1569 0xFFFFF,\r
1570 0,\r
1571 PciBarTypeMem64,\r
1572 PciResUsageTypical\r
1573 );\r
1574\r
1575 PMem64Bridge = CreateResourceNode (\r
1576 Bridge,\r
1577 0,\r
1578 0xFFFFF,\r
1579 0,\r
1580 PciBarTypePMem64,\r
1581 PciResUsageTypical\r
1582 );\r
1583\r
1584 //\r
1585 // Create resourcemap by going through all the devices subject to this root bridge\r
1586 //\r
1587 Status = CreateResourceMap (\r
1588 Bridge,\r
1589 IoBridge,\r
1590 Mem32Bridge,\r
1591 PMem32Bridge,\r
1592 Mem64Bridge,\r
1593 PMem64Bridge\r
1594 );\r
1595\r
1596 if (EFI_ERROR (Status)) {\r
1597 return Status;\r
1598 }\r
1599\r
1600 Status = GetResourceBaseFromBridge (\r
1601 Bridge,\r
1602 &IoBase,\r
1603 &Mem32Base,\r
1604 &PMem32Base,\r
1605 &Mem64Base,\r
1606 &PMem64Base\r
1607 );\r
1608\r
1609 if (EFI_ERROR (Status)) {\r
1610 return Status;\r
1611 }\r
1612\r
1613 //\r
1614 // Program IO resources\r
1615 //\r
1616 ProgramResource (\r
1617 IoBase,\r
1618 IoBridge\r
1619 );\r
1620\r
1621 //\r
1622 // Program Mem32 resources\r
1623 //\r
1624 ProgramResource (\r
1625 Mem32Base,\r
1626 Mem32Bridge\r
1627 );\r
1628\r
1629 //\r
1630 // Program PMem32 resources\r
1631 //\r
1632 ProgramResource (\r
1633 PMem32Base,\r
1634 PMem32Bridge\r
1635 );\r
1636\r
1637 //\r
1638 // Program Mem64 resources\r
1639 //\r
1640 ProgramResource (\r
1641 Mem64Base,\r
1642 Mem64Bridge\r
1643 );\r
1644\r
1645 //\r
1646 // Program PMem64 resources\r
1647 //\r
1648 ProgramResource (\r
1649 PMem64Base,\r
1650 PMem64Bridge\r
1651 );\r
1652\r
1653 DestroyResourceTree (IoBridge);\r
1654 DestroyResourceTree (Mem32Bridge);\r
1655 DestroyResourceTree (PMem32Bridge);\r
1656 DestroyResourceTree (PMem64Bridge);\r
1657 DestroyResourceTree (Mem64Bridge);\r
1658\r
1659 gBS->FreePool (IoBridge);\r
1660 gBS->FreePool (Mem32Bridge);\r
1661 gBS->FreePool (PMem32Bridge);\r
1662 gBS->FreePool (PMem64Bridge);\r
1663 gBS->FreePool (Mem64Bridge);\r
1664\r
1665 return EFI_SUCCESS;\r
1666}\r
1667\r
1668EFI_STATUS\r
1669GetResourceBaseFromBridge (\r
1670 IN PCI_IO_DEVICE *Bridge,\r
1671 OUT UINT64 *IoBase,\r
1672 OUT UINT64 *Mem32Base,\r
1673 OUT UINT64 *PMem32Base,\r
1674 OUT UINT64 *Mem64Base,\r
1675 OUT UINT64 *PMem64Base\r
1676 )\r
1677/*++\r
1678\r
1679Routine Description:\r
1680\r
1681Arguments:\r
1682\r
1683Returns:\r
1684\r
1685 None\r
1686\r
1687--*/\r
1688// TODO: Bridge - add argument and description to function comment\r
1689// TODO: IoBase - add argument and description to function comment\r
1690// TODO: Mem32Base - add argument and description to function comment\r
1691// TODO: PMem32Base - add argument and description to function comment\r
1692// TODO: Mem64Base - add argument and description to function comment\r
1693// TODO: PMem64Base - add argument and description to function comment\r
1694// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1695// TODO: EFI_SUCCESS - add return value to function comment\r
1696{\r
1697 if (!Bridge->Allocated) {\r
1698 return EFI_OUT_OF_RESOURCES;\r
1699 }\r
1700\r
1701 *IoBase = gAllOne;\r
1702 *Mem32Base = gAllOne;\r
1703 *PMem32Base = gAllOne;\r
1704 *Mem64Base = gAllOne;\r
1705 *PMem64Base = gAllOne;\r
1706\r
1707 if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
1708\r
1709 if (Bridge->PciBar[PPB_IO_RANGE].Length) {\r
1710 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
1711 }\r
1712\r
1713 if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {\r
1714 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
1715 }\r
1716\r
1717 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {\r
1718 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
1719 }\r
1720\r
1721 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {\r
1722 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
1723 } else {\r
1724 *PMem64Base = gAllOne;\r
1725 }\r
1726\r
1727 }\r
1728\r
1729 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
1730 if (Bridge->PciBar[P2C_IO_1].Length) {\r
1731 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
1732 } else {\r
1733 if (Bridge->PciBar[P2C_IO_2].Length) {\r
1734 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
1735 }\r
1736 }\r
1737\r
1738 if (Bridge->PciBar[P2C_MEM_1].Length) {\r
1739 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
1740 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1741 }\r
1742\r
1743 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
1744 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1745 }\r
1746 }\r
1747\r
1748 if (Bridge->PciBar[P2C_MEM_2].Length) {\r
1749 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
1750 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1751 }\r
1752\r
1753 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
1754 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1755 }\r
1756 }\r
1757 }\r
1758\r
1759 return EFI_SUCCESS;\r
1760}\r
1761\r
1762EFI_STATUS\r
1763NotifyPhase (\r
1764 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
1765 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
1766 )\r
1767/*++\r
1768\r
1769Routine Description:\r
1770\r
1771Arguments:\r
1772\r
1773Returns:\r
1774\r
1775 None\r
1776\r
1777--*/\r
1778// TODO: PciResAlloc - add argument and description to function comment\r
1779// TODO: Phase - add argument and description to function comment\r
1780// TODO: EFI_NOT_FOUND - add return value to function comment\r
1781// TODO: EFI_SUCCESS - add return value to function comment\r
1782{\r
1783 EFI_HANDLE HostBridgeHandle;\r
1784 EFI_HANDLE RootBridgeHandle;\r
1785 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1786 EFI_STATUS Status;\r
1787\r
1788 HostBridgeHandle = NULL;\r
1789 RootBridgeHandle = NULL;\r
1790 if (gPciPlatformProtocol != NULL) {\r
1791 //\r
1792 // Get Host Bridge Handle.\r
1793 //\r
1794 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
1795\r
1796 //\r
1797 // Get the rootbridge Io protocol to find the host bridge handle\r
1798 //\r
1799 Status = gBS->HandleProtocol (\r
1800 RootBridgeHandle,\r
1801 &gEfiPciRootBridgeIoProtocolGuid,\r
1802 (VOID **) &PciRootBridgeIo\r
1803 );\r
1804\r
1805 if (EFI_ERROR (Status)) {\r
1806 return EFI_NOT_FOUND;\r
1807 }\r
1808\r
1809 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
1810\r
1811 //\r
1812 // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1813 //\r
1814 gPciPlatformProtocol->PhaseNotify (\r
1815 gPciPlatformProtocol,\r
1816 HostBridgeHandle,\r
1817 Phase,\r
1818 ChipsetEntry\r
1819 );\r
1820 }\r
1821\r
1822 Status = PciResAlloc->NotifyPhase (\r
1823 PciResAlloc,\r
1824 Phase\r
1825 );\r
1826\r
1827 if (gPciPlatformProtocol != NULL) {\r
1828 //\r
1829 // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1830 //\r
1831 gPciPlatformProtocol->PhaseNotify (\r
1832 gPciPlatformProtocol,\r
1833 HostBridgeHandle,\r
1834 Phase,\r
1835 ChipsetExit\r
1836 );\r
1837\r
1838 }\r
1839\r
1840 return EFI_SUCCESS;\r
1841}\r
1842\r
1843EFI_STATUS\r
1844PreprocessController (\r
1845 IN PCI_IO_DEVICE *Bridge,\r
1846 IN UINT8 Bus,\r
1847 IN UINT8 Device,\r
1848 IN UINT8 Func,\r
1849 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1850 )\r
1851/*++\r
1852\r
1853Routine Description:\r
1854\r
1855Arguments:\r
1856\r
1857Returns:\r
1858\r
1859 None\r
1860\r
1861--*/\r
1862// TODO: Bridge - add argument and description to function comment\r
1863// TODO: Bus - add argument and description to function comment\r
1864// TODO: Device - add argument and description to function comment\r
1865// TODO: Func - add argument and description to function comment\r
1866// TODO: Phase - add argument and description to function comment\r
1867// TODO: EFI_UNSUPPORTED - add return value to function comment\r
1868// TODO: EFI_SUCCESS - add return value to function comment\r
1869{\r
1870 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;\r
1871 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;\r
1872 EFI_HANDLE RootBridgeHandle;\r
1873 EFI_HANDLE HostBridgeHandle;\r
1874 EFI_STATUS Status;\r
1875\r
1876 //\r
1877 // Get the host bridge handle\r
1878 //\r
1879 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
1880\r
1881 //\r
1882 // Get the pci host bridge resource allocation protocol\r
1883 //\r
1884 Status = gBS->OpenProtocol (\r
1885 HostBridgeHandle,\r
1886 &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
1887 (VOID **) &PciResAlloc,\r
1888 NULL,\r
1889 NULL,\r
1890 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1891 );\r
1892\r
1893 if (EFI_ERROR (Status)) {\r
1894 return EFI_UNSUPPORTED;\r
1895 }\r
1896\r
1897 //\r
1898 // Get Root Brige Handle\r
1899 //\r
1900 while (Bridge->Parent) {\r
1901 Bridge = Bridge->Parent;\r
1902 }\r
1903\r
1904 RootBridgeHandle = Bridge->Handle;\r
1905\r
1906 RootBridgePciAddress.Register = 0;\r
1907 RootBridgePciAddress.Function = Func;\r
1908 RootBridgePciAddress.Device = Device;\r
1909 RootBridgePciAddress.Bus = Bus;\r
1910 RootBridgePciAddress.ExtendedRegister = 0;\r
1911\r
1912 if (gPciPlatformProtocol != NULL) {\r
1913 //\r
1914 // Call PlatformPci::PrepController() if the protocol is present.\r
1915 //\r
1916 gPciPlatformProtocol->PlatformPrepController (\r
1917 gPciPlatformProtocol,\r
1918 HostBridgeHandle,\r
1919 RootBridgeHandle,\r
1920 RootBridgePciAddress,\r
1921 Phase,\r
1922 ChipsetEntry\r
1923 );\r
1924 }\r
1925\r
1926 Status = PciResAlloc->PreprocessController (\r
1927 PciResAlloc,\r
1928 RootBridgeHandle,\r
1929 RootBridgePciAddress,\r
1930 Phase\r
1931 );\r
1932\r
1933 if (gPciPlatformProtocol != NULL) {\r
1934 //\r
1935 // Call PlatformPci::PrepController() if the protocol is present.\r
1936 //\r
1937 gPciPlatformProtocol->PlatformPrepController (\r
1938 gPciPlatformProtocol,\r
1939 HostBridgeHandle,\r
1940 RootBridgeHandle,\r
1941 RootBridgePciAddress,\r
1942 Phase,\r
1943 ChipsetExit\r
1944 );\r
1945 }\r
1946\r
1947 return EFI_SUCCESS;\r
1948}\r
1949\r
1950EFI_STATUS\r
1951EFIAPI\r
1952PciHotPlugRequestNotify (\r
1953 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
1954 IN EFI_PCI_HOTPLUG_OPERATION Operation,\r
1955 IN EFI_HANDLE Controller,\r
1956 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,\r
1957 IN OUT UINT8 *NumberOfChildren,\r
1958 IN OUT EFI_HANDLE * ChildHandleBuffer\r
1959 )\r
1960/*++\r
1961\r
1962Routine Description:\r
1963\r
1964 Hot plug request notify.\r
1965\r
1966Arguments:\r
1967\r
1968 This - A pointer to the hot plug request protocol.\r
1969 Operation - The operation.\r
1970 Controller - A pointer to the controller.\r
1971 RemainningDevicePath - A pointer to the device path.\r
1972 NumberOfChildren - A the number of child handle in the ChildHandleBuffer.\r
1973 ChildHandleBuffer - A pointer to the array contain the child handle.\r
1974\r
1975Returns:\r
1976\r
1977 Status code.\r
1978\r
1979--*/\r
1980// TODO: RemainingDevicePath - add argument and description to function comment\r
1981// TODO: EFI_NOT_FOUND - add return value to function comment\r
1982// TODO: EFI_SUCCESS - add return value to function comment\r
1983// TODO: EFI_SUCCESS - add return value to function comment\r
1984// TODO: EFI_SUCCESS - add return value to function comment\r
1985{\r
1986 PCI_IO_DEVICE *Bridge;\r
1987 PCI_IO_DEVICE *Temp;\r
1988 EFI_PCI_IO_PROTOCOL *PciIo;\r
1989 UINTN Index;\r
1990 EFI_HANDLE RootBridgeHandle;\r
1991 EFI_STATUS Status;\r
1992\r
1993 Status = gBS->OpenProtocol (\r
1994 Controller,\r
1995 &gEfiPciIoProtocolGuid,\r
1996 (VOID **) &PciIo,\r
1997 gPciBusDriverBinding.DriverBindingHandle,\r
1998 Controller,\r
1999 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2000 );\r
2001\r
2002 if (EFI_ERROR (Status)) {\r
2003 return EFI_NOT_FOUND;\r
2004 }\r
2005\r
2006 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2007\r
2008 //\r
2009 // Get root bridge handle\r
2010 //\r
2011 Temp = Bridge;\r
2012 while (Temp->Parent) {\r
2013 Temp = Temp->Parent;\r
2014 }\r
2015\r
2016 RootBridgeHandle = Temp->Handle;\r
2017\r
2018 if (Operation == EfiPciHotPlugRequestAdd) {\r
2019\r
2020 if (NumberOfChildren != NULL) {\r
2021 *NumberOfChildren = 0;\r
2022 }\r
2023\r
2024 if (IsListEmpty (&Bridge->ChildList)) {\r
2025\r
2026 Status = PciBridgeEnumerator (Bridge);\r
2027\r
2028 if (EFI_ERROR (Status)) {\r
2029 return Status;\r
2030 }\r
2031 }\r
2032\r
2033 Status = StartPciDevicesOnBridge (\r
2034 RootBridgeHandle,\r
2035 Bridge,\r
2036 RemainingDevicePath,\r
2037 NumberOfChildren,\r
2038 ChildHandleBuffer\r
2039 );\r
2040\r
2041 return EFI_SUCCESS;\r
2042 }\r
2043\r
2044 if (Operation == EfiPciHotplugRequestRemove) {\r
2045\r
2046 if (*NumberOfChildren == 0) {\r
2047 //\r
2048 // Remove all devices on the bridge\r
2049 //\r
2050 Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);\r
2051 return Status;\r
2052\r
2053 }\r
2054\r
2055 for (Index = 0; Index < *NumberOfChildren; Index++) {\r
2056 //\r
2057 // De register all the pci device\r
2058 //\r
2059 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);\r
2060\r
2061 if (EFI_ERROR (Status)) {\r
2062 return Status;\r
2063 }\r
2064\r
2065 }\r
2066 //\r
2067 // End for\r
2068 //\r
2069 return EFI_SUCCESS;\r
2070 }\r
2071\r
2072 return EFI_SUCCESS;\r
2073}\r
2074\r
2075BOOLEAN\r
2076SearchHostBridgeHandle (\r
2077 IN EFI_HANDLE RootBridgeHandle\r
2078 )\r
2079/*++\r
2080\r
2081Routine Description:\r
2082\r
2083Arguments:\r
2084\r
2085Returns:\r
2086\r
2087 None\r
2088\r
2089--*/\r
2090// TODO: RootBridgeHandle - add argument and description to function comment\r
2091{\r
2092 EFI_HANDLE HostBridgeHandle;\r
2093 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2094 UINTN Index;\r
2095 EFI_STATUS Status;\r
2096\r
2097 //\r
2098 // Get the rootbridge Io protocol to find the host bridge handle\r
2099 //\r
2100 Status = gBS->OpenProtocol (\r
2101 RootBridgeHandle,\r
2102 &gEfiPciRootBridgeIoProtocolGuid,\r
2103 (VOID **) &PciRootBridgeIo,\r
2104 gPciBusDriverBinding.DriverBindingHandle,\r
2105 RootBridgeHandle,\r
2106 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2107 );\r
2108\r
2109 if (EFI_ERROR (Status)) {\r
2110 return FALSE;\r
2111 }\r
2112\r
2113 HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
2114 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2115 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2116 return TRUE;\r
2117 }\r
2118 }\r
2119\r
2120 return FALSE;\r
2121}\r
2122\r
2123EFI_STATUS\r
2124AddHostBridgeEnumerator (\r
2125 IN EFI_HANDLE HostBridgeHandle\r
2126 )\r
2127/*++\r
2128\r
2129Routine Description:\r
2130\r
2131Arguments:\r
2132\r
2133Returns:\r
2134\r
2135 None\r
2136\r
2137--*/\r
2138// TODO: HostBridgeHandle - add argument and description to function comment\r
2139// TODO: EFI_ABORTED - add return value to function comment\r
2140// TODO: EFI_ABORTED - add return value to function comment\r
2141// TODO: EFI_SUCCESS - add return value to function comment\r
2142{\r
2143 UINTN Index;\r
2144\r
2145 if (!HostBridgeHandle) {\r
2146 return EFI_ABORTED;\r
2147 }\r
2148\r
2149 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2150 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2151 return EFI_ABORTED;\r
2152 }\r
2153 }\r
2154\r
2155 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {\r
2156 gPciHostBrigeHandles[Index] = HostBridgeHandle;\r
2157 gPciHostBridgeNumber++;\r
2158 }\r
2159\r
2160 return EFI_SUCCESS;\r
2161}\r