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