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