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