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