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