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