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