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