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