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