[Description]:
[people/mcb30/edk2.git] / edk2 / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
1 /**@file\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 **/\r
13 \r
14 \r
15 #include "pcibus.h"\r
16 #include "PciEnumerator.h"\r
17 #include "PciResourceSupport.h"\r
18 #include "PciOptionRomSupport.h"\r
19 \r
20 EFI_STATUS\r
21 PciEnumerator (\r
22   IN EFI_HANDLE                    Controller\r
23   )\r
24 /*++\r
25 \r
26 Routine Description:\r
27 \r
28   This routine is used to enumerate entire pci bus system\r
29   in a given platform\r
30 \r
31 Arguments:\r
32 \r
33 Returns:\r
34 \r
35   None\r
36 \r
37 --*/\r
38 // TODO:    Controller - add argument and description to function comment\r
39 // TODO:    EFI_SUCCESS - add return value to function comment\r
40 // TODO:    EFI_SUCCESS - add return value to function comment\r
41 {\r
42 \r
43   EFI_HANDLE                                        HostBridgeHandle;\r
44   EFI_STATUS                                        Status;\r
45   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;\r
46   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   *PciRootBridgeIo;\r
47 \r
48   //\r
49   // If PCI bus has already done the full enumeration, never do it again\r
50   //\r
51   if (!gFullEnumeration) {\r
52     return PciEnumeratorLight (Controller);\r
53   }\r
54 \r
55   //\r
56   // Get the rootbridge Io protocol to find the host bridge handle\r
57   //\r
58   Status = gBS->OpenProtocol (\r
59                   Controller,\r
60                   &gEfiPciRootBridgeIoProtocolGuid,\r
61                   (VOID **) &PciRootBridgeIo,\r
62                   gPciBusDriverBinding.DriverBindingHandle,\r
63                   Controller,\r
64                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
65                   );\r
66 \r
67   if (EFI_ERROR (Status)) {\r
68     return Status;\r
69   }\r
70 \r
71   //\r
72   // Get the host bridge handle\r
73   //\r
74   HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
75 \r
76   //\r
77   // Get the pci host bridge resource allocation protocol\r
78   //\r
79   Status = gBS->OpenProtocol (\r
80                   HostBridgeHandle,\r
81                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
82                   (VOID **) &PciResAlloc,\r
83                   gPciBusDriverBinding.DriverBindingHandle,\r
84                   Controller,\r
85                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
86                   );\r
87 \r
88   if (EFI_ERROR (Status)) {\r
89     return Status;\r
90   }\r
91 \r
92   //\r
93   // Notify the pci bus enumeration is about to begin\r
94   //\r
95   NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
96 \r
97   //\r
98   // Start the bus allocation phase\r
99   //\r
100   Status = PciHostBridgeEnumerator (PciResAlloc);\r
101 \r
102   if (EFI_ERROR (Status)) {\r
103     return Status;\r
104   }\r
105 \r
106   //\r
107   // Submit the resource request\r
108   //\r
109   Status = PciHostBridgeResourceAllocator (PciResAlloc);\r
110 \r
111   if (EFI_ERROR (Status)) {\r
112     return Status;\r
113   }\r
114 \r
115   //\r
116   // Process P2C\r
117   //\r
118   Status = PciHostBridgeP2CProcess (PciResAlloc);\r
119 \r
120   if (EFI_ERROR (Status)) {\r
121     return Status;\r
122   }\r
123 \r
124   //\r
125   // Process attributes for devices on this host bridge\r
126   //\r
127   Status = PciHostBridgeDeviceAttribute (PciResAlloc);\r
128   if (EFI_ERROR (Status)) {\r
129     return Status;\r
130   }\r
131 \r
132   gFullEnumeration = FALSE;\r
133 \r
134   return EFI_SUCCESS;\r
135 }\r
136 \r
137 EFI_STATUS\r
138 PciRootBridgeEnumerator (\r
139   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,\r
140   IN PCI_IO_DEVICE                                     *RootBridgeDev\r
141   )\r
142 /*++\r
143 \r
144 Routine Description:\r
145 \r
146 Arguments:\r
147 \r
148 Returns:\r
149 \r
150   None\r
151 \r
152 --*/\r
153 // TODO:    PciResAlloc - add argument and description to function comment\r
154 // TODO:    RootBridgeDev - add argument and description to function comment\r
155 // TODO:    EFI_SUCCESS - add return value to function comment\r
156 {\r
157   EFI_STATUS                        Status;\r
158   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;\r
159   UINT8                             SubBusNumber;\r
160   UINT8                             StartBusNumber;\r
161   UINT8                             PaddedBusRange;\r
162   EFI_HANDLE                        RootBridgeHandle;\r
163 \r
164   SubBusNumber    = 0;\r
165   StartBusNumber  = 0;\r
166   PaddedBusRange  = 0;\r
167 \r
168   //\r
169   // Get the root bridge handle\r
170   //\r
171   RootBridgeHandle = RootBridgeDev->Handle;\r
172 \r
173   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
174     EFI_PROGRESS_CODE,\r
175     EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
176     RootBridgeDev->DevicePath\r
177     );\r
178 \r
179   //\r
180   // Get the Bus information\r
181   //\r
182   Status = PciResAlloc->StartBusEnumeration (\r
183                           PciResAlloc,\r
184                           RootBridgeHandle,\r
185                           (VOID **) &pConfiguration\r
186                           );\r
187 \r
188   if (EFI_ERROR (Status)) {\r
189     return Status;\r
190   }\r
191 \r
192   //\r
193   // Get the bus number to start with\r
194   //\r
195   StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);\r
196   PaddedBusRange  = (UINT8) (pConfiguration->AddrRangeMax);\r
197 \r
198   //\r
199   // Initialize the subordinate bus number\r
200   //\r
201   SubBusNumber = StartBusNumber;\r
202 \r
203   //\r
204   // Reset all assigned PCI bus number\r
205   //\r
206   ResetAllPpbBusNumber (\r
207     RootBridgeDev, \r
208     StartBusNumber\r
209   );\r
210 \r
211   //\r
212   // Assign bus number\r
213   //\r
214   Status = PciScanBus (\r
215             RootBridgeDev,\r
216             (UINT8) (pConfiguration->AddrRangeMin),\r
217             &SubBusNumber,\r
218             &PaddedBusRange\r
219             );\r
220 \r
221   if (EFI_ERROR (Status)) {\r
222     return Status;\r
223   }\r
224 \r
225 \r
226   //\r
227   // Assign max bus number scanned\r
228   //\r
229   pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
230 \r
231   //\r
232   // Set bus number\r
233   //\r
234   Status = PciResAlloc->SetBusNumbers (\r
235                           PciResAlloc,\r
236                           RootBridgeHandle,\r
237                           pConfiguration\r
238                           );\r
239   \r
240   gBS->FreePool (pConfiguration);\r
241   \r
242   if (EFI_ERROR (Status)) {\r
243     return Status;\r
244   }\r
245 \r
246   return EFI_SUCCESS;\r
247 }\r
248 \r
249 EFI_STATUS\r
250 ProcessOptionRom (\r
251   IN PCI_IO_DEVICE *Bridge,\r
252   IN UINT64        RomBase,\r
253   IN UINT64        MaxLength\r
254   )\r
255 /*++\r
256 \r
257 Routine Description:\r
258 \r
259   This routine is used to process option rom on a certain root bridge\r
260 \r
261 Arguments:\r
262 \r
263 Returns:\r
264 \r
265   None\r
266 \r
267 --*/\r
268 // TODO:    Bridge - add argument and description to function comment\r
269 // TODO:    RomBase - add argument and description to function comment\r
270 // TODO:    MaxLength - add argument and description to function comment\r
271 // TODO:    EFI_SUCCESS - add return value to function comment\r
272 {\r
273   LIST_ENTRY      *CurrentLink;\r
274   PCI_IO_DEVICE   *Temp;\r
275 \r
276   //\r
277   // Go through bridges to reach all devices\r
278   //\r
279   CurrentLink = Bridge->ChildList.ForwardLink;\r
280   while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
281     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
282     if (!IsListEmpty (&Temp->ChildList)) {\r
283 \r
284       //\r
285       // Go further to process the option rom under this bridge\r
286       //\r
287       ProcessOptionRom (Temp, RomBase, MaxLength);\r
288     }\r
289 \r
290     if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {\r
291 \r
292       //\r
293       // Load and process the option rom\r
294       //\r
295       LoadOpRomImage (Temp, RomBase);\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         break;\r
1052       }\r
1053     }\r
1054 \r
1055     if (DevIndex != RemovedPciDevNum) {\r
1056       continue;\r
1057     }\r
1058 \r
1059     //\r
1060     // Remove the device if it isn't in the array\r
1061     //\r
1062     Status = RejectPciDevice (PciResNode->PciDev);\r
1063     if (Status == EFI_SUCCESS) {\r
1064 \r
1065       //\r
1066       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
1067       //\r
1068       //\r
1069       // Have no way to get ReqRes, AllocRes & Bar here\r
1070       //\r
1071       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
1072       AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
1073       AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;\r
1074       AllocFailExtendedData.Bar            = PciResNode->Bar;\r
1075 \r
1076       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1077             EFI_PROGRESS_CODE,\r
1078             EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
1079             (VOID *) &AllocFailExtendedData,\r
1080             sizeof (AllocFailExtendedData)\r
1081             );\r
1082 \r
1083       //\r
1084       // Add it to the array and indicate at least a device has been rejected\r
1085       //\r
1086       RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
1087       AllocationAjusted                 = TRUE;\r
1088     }\r
1089   }\r
1090   //\r
1091   // End for\r
1092   //\r
1093 \r
1094   if (AllocationAjusted) {\r
1095     return EFI_SUCCESS;\r
1096   } else {\r
1097     return EFI_ABORTED;\r
1098   }\r
1099 }\r
1100 \r
1101 EFI_STATUS\r
1102 ConstructAcpiResourceRequestor (\r
1103   IN PCI_IO_DEVICE      *Bridge,\r
1104   IN PCI_RESOURCE_NODE  *IoNode,\r
1105   IN PCI_RESOURCE_NODE  *Mem32Node,\r
1106   IN PCI_RESOURCE_NODE  *PMem32Node,\r
1107   IN PCI_RESOURCE_NODE  *Mem64Node,\r
1108   IN PCI_RESOURCE_NODE  *PMem64Node,\r
1109   OUT VOID              **pConfig\r
1110   )\r
1111 /*++\r
1112 \r
1113 Routine Description:\r
1114 \r
1115 Arguments:\r
1116 \r
1117 Returns:\r
1118 \r
1119   None\r
1120 \r
1121 --*/\r
1122 // TODO:    Bridge - add argument and description to function comment\r
1123 // TODO:    IoNode - add argument and description to function comment\r
1124 // TODO:    Mem32Node - add argument and description to function comment\r
1125 // TODO:    PMem32Node - add argument and description to function comment\r
1126 // TODO:    Mem64Node - add argument and description to function comment\r
1127 // TODO:    PMem64Node - add argument and description to function comment\r
1128 // TODO:    pConfig - add argument and description to function comment\r
1129 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
1130 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
1131 // TODO:    EFI_SUCCESS - add return value to function comment\r
1132 {\r
1133   UINT8                             NumConfig;\r
1134   UINT8                             Aperture;\r
1135   UINT8                             *Configuration;\r
1136   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1137   EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
1138 \r
1139   NumConfig = 0;\r
1140   Aperture  = 0;\r
1141 \r
1142   *pConfig  = NULL;\r
1143 \r
1144   //\r
1145   // if there is io request, add to the io aperture\r
1146   //\r
1147   if (ResourceRequestExisted (IoNode)) {\r
1148     NumConfig++;\r
1149     Aperture |= 0x01;\r
1150   }\r
1151 \r
1152   //\r
1153   // if there is mem32 request, add to the mem32 aperture\r
1154   //\r
1155   if (ResourceRequestExisted (Mem32Node)) {\r
1156     NumConfig++;\r
1157     Aperture |= 0x02;\r
1158   }\r
1159 \r
1160   //\r
1161   // if there is pmem32 request, add to the pmem32 aperture\r
1162   //\r
1163   if (ResourceRequestExisted (PMem32Node)) {\r
1164     NumConfig++;\r
1165     Aperture |= 0x04;\r
1166   }\r
1167 \r
1168   //\r
1169   // if there is mem64 request, add to the mem64 aperture\r
1170   //\r
1171   if (ResourceRequestExisted (Mem64Node)) {\r
1172     NumConfig++;\r
1173     Aperture |= 0x08;\r
1174   }\r
1175 \r
1176   //\r
1177   // if there is pmem64 request, add to the pmem64 aperture\r
1178   //\r
1179   if (ResourceRequestExisted (PMem64Node)) {\r
1180     NumConfig++;\r
1181     Aperture |= 0x10;\r
1182   }\r
1183 \r
1184   if (NumConfig != 0) {\r
1185 \r
1186     //\r
1187     // If there is at least one type of resource request,\r
1188     // allocate a acpi resource node\r
1189     //\r
1190     Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1191     if (Configuration == NULL) {\r
1192       return EFI_OUT_OF_RESOURCES;\r
1193     }\r
1194 \r
1195     ZeroMem (\r
1196       Configuration,\r
1197       sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
1198       );\r
1199 \r
1200     Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1201 \r
1202     //\r
1203     // Deal with io aperture\r
1204     //\r
1205     if (Aperture & 0x01) {\r
1206       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1207       Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1208       //\r
1209       // Io\r
1210       //\r
1211       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1212       //\r
1213       // non ISA range\r
1214       //\r
1215       Ptr->SpecificFlag = 1;\r
1216       Ptr->AddrLen      = IoNode->Length;\r
1217       Ptr->AddrRangeMax = IoNode->Alignment;\r
1218 \r
1219       Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1220     }\r
1221     //\r
1222     // Deal with mem32 aperture\r
1223     //\r
1224     if (Aperture & 0x02) {\r
1225       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1226       Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1227       //\r
1228       // Mem\r
1229       //\r
1230       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1231       //\r
1232       // Nonprefechable\r
1233       //\r
1234       Ptr->SpecificFlag = 0;\r
1235       //\r
1236       // 32 bit\r
1237       //\r
1238       Ptr->AddrSpaceGranularity = 32;\r
1239       Ptr->AddrLen      = Mem32Node->Length;\r
1240       Ptr->AddrRangeMax = Mem32Node->Alignment;\r
1241 \r
1242       Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1243     }\r
1244 \r
1245     //\r
1246     // Deal with Pmem32 aperture\r
1247     //\r
1248     if (Aperture & 0x04) {\r
1249       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1250       Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1251       //\r
1252       // Mem\r
1253       //\r
1254       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1255       //\r
1256       // prefechable\r
1257       //\r
1258       Ptr->SpecificFlag = 0x6;\r
1259       //\r
1260       // 32 bit\r
1261       //\r
1262       Ptr->AddrSpaceGranularity = 32;\r
1263       Ptr->AddrLen      = PMem32Node->Length;\r
1264       Ptr->AddrRangeMax = PMem32Node->Alignment;\r
1265 \r
1266       Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1267     }\r
1268     //\r
1269     // Deal with mem64 aperture\r
1270     //\r
1271     if (Aperture & 0x08) {\r
1272       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1273       Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1274       //\r
1275       // Mem\r
1276       //\r
1277       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1278       //\r
1279       // nonprefechable\r
1280       //\r
1281       Ptr->SpecificFlag = 0;\r
1282       //\r
1283       // 64 bit\r
1284       //\r
1285       Ptr->AddrSpaceGranularity = 64;\r
1286       Ptr->AddrLen      = Mem64Node->Length;\r
1287       Ptr->AddrRangeMax = Mem64Node->Alignment;\r
1288 \r
1289       Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1290     }\r
1291     //\r
1292     // Deal with Pmem64 aperture\r
1293     //\r
1294     if (Aperture & 0x10) {\r
1295       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1296       Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1297       //\r
1298       // Mem\r
1299       //\r
1300       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1301       //\r
1302       // prefechable\r
1303       //\r
1304       Ptr->SpecificFlag = 0x06;\r
1305       //\r
1306       // 64 bit\r
1307       //\r
1308       Ptr->AddrSpaceGranularity = 64;\r
1309       Ptr->AddrLen      = PMem64Node->Length;\r
1310       Ptr->AddrRangeMax = PMem64Node->Alignment;\r
1311 \r
1312       Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1313     }\r
1314 \r
1315     //\r
1316     // put the checksum\r
1317     //\r
1318     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
1319 \r
1320     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
1321     PtrEnd->Checksum  = 0;\r
1322 \r
1323   } else {\r
1324 \r
1325     //\r
1326     // If there is no resource request\r
1327     //\r
1328     Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1329     if (Configuration == NULL) {\r
1330       return EFI_OUT_OF_RESOURCES;\r
1331     }\r
1332 \r
1333     ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1334 \r
1335     Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
1336     Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1337 \r
1338     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1339     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
1340     PtrEnd->Checksum  = 0;\r
1341   }\r
1342 \r
1343   *pConfig = Configuration;\r
1344 \r
1345   return EFI_SUCCESS;\r
1346 }\r
1347 \r
1348 EFI_STATUS\r
1349 GetResourceBase (\r
1350   IN VOID     *pConfig,\r
1351   OUT UINT64  *IoBase,\r
1352   OUT UINT64  *Mem32Base,\r
1353   OUT UINT64  *PMem32Base,\r
1354   OUT UINT64  *Mem64Base,\r
1355   OUT UINT64  *PMem64Base\r
1356   )\r
1357 /*++\r
1358 \r
1359 Routine Description:\r
1360 \r
1361 Arguments:\r
1362 \r
1363 Returns:\r
1364 \r
1365   None\r
1366 \r
1367 --*/\r
1368 // TODO:    pConfig - add argument and description to function comment\r
1369 // TODO:    IoBase - add argument and description to function comment\r
1370 // TODO:    Mem32Base - add argument and description to function comment\r
1371 // TODO:    PMem32Base - add argument and description to function comment\r
1372 // TODO:    Mem64Base - add argument and description to function comment\r
1373 // TODO:    PMem64Base - add argument and description to function comment\r
1374 // TODO:    EFI_SUCCESS - add return value to function comment\r
1375 {\r
1376   UINT8                             *Temp;\r
1377   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1378   UINT64                            ResStatus;\r
1379 \r
1380   *IoBase     = 0xFFFFFFFFFFFFFFFFULL;\r
1381   *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;\r
1382   *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
1383   *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;\r
1384   *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
1385 \r
1386   Temp        = (UINT8 *) pConfig;\r
1387 \r
1388   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1389 \r
1390     Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
1391     ResStatus = Ptr->AddrTranslationOffset;\r
1392 \r
1393     if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
1394 \r
1395       switch (Ptr->ResType) {\r
1396 \r
1397       //\r
1398       // Memory type aperture\r
1399       //\r
1400       case 0:\r
1401 \r
1402         //\r
1403         // Check to see the granularity\r
1404         //\r
1405         if (Ptr->AddrSpaceGranularity == 32) {\r
1406           if (Ptr->SpecificFlag & 0x06) {\r
1407             *PMem32Base = Ptr->AddrRangeMin;\r
1408           } else {\r
1409             *Mem32Base = Ptr->AddrRangeMin;\r
1410           }\r
1411         }\r
1412 \r
1413         if (Ptr->AddrSpaceGranularity == 64) {\r
1414           if (Ptr->SpecificFlag & 0x06) {\r
1415             *PMem64Base = Ptr->AddrRangeMin;\r
1416           } else {\r
1417             *Mem64Base = Ptr->AddrRangeMin;\r
1418           }\r
1419         }\r
1420         break;\r
1421 \r
1422       case 1:\r
1423 \r
1424         //\r
1425         // Io type aperture\r
1426         //\r
1427         *IoBase = Ptr->AddrRangeMin;\r
1428         break;\r
1429 \r
1430       default:\r
1431         break;\r
1432 \r
1433       }\r
1434       //\r
1435       // End switch\r
1436       //\r
1437     }\r
1438     //\r
1439     // End for\r
1440     //\r
1441     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1442   }\r
1443 \r
1444   return EFI_SUCCESS;\r
1445 }\r
1446 \r
1447 EFI_STATUS\r
1448 PciBridgeEnumerator (\r
1449   IN PCI_IO_DEVICE                                     *BridgeDev\r
1450   )\r
1451 /*++\r
1452 \r
1453 Routine Description:\r
1454 \r
1455 Arguments:\r
1456 \r
1457 Returns:\r
1458 \r
1459   None\r
1460 \r
1461 --*/\r
1462 // TODO:    BridgeDev - add argument and description to function comment\r
1463 // TODO:    EFI_SUCCESS - add return value to function comment\r
1464 {\r
1465   UINT8               SubBusNumber;\r
1466   UINT8               StartBusNumber;\r
1467   EFI_PCI_IO_PROTOCOL *PciIo;\r
1468   EFI_STATUS          Status;\r
1469 \r
1470   SubBusNumber    = 0;\r
1471   StartBusNumber  = 0;\r
1472   PciIo           = &(BridgeDev->PciIo);\r
1473   Status          = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
1474 \r
1475   if (EFI_ERROR (Status)) {\r
1476     return Status;\r
1477   }\r
1478 \r
1479   Status = PciAssignBusNumber (\r
1480             BridgeDev,\r
1481             StartBusNumber,\r
1482             &SubBusNumber\r
1483             );\r
1484 \r
1485   if (EFI_ERROR (Status)) {\r
1486     return Status;\r
1487   }\r
1488 \r
1489   Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
1490 \r
1491   if (EFI_ERROR (Status)) {\r
1492     return Status;\r
1493   }\r
1494 \r
1495   Status = PciBridgeResourceAllocator (BridgeDev);\r
1496 \r
1497   if (EFI_ERROR (Status)) {\r
1498     return Status;\r
1499   }\r
1500 \r
1501   Status = DetermineDeviceAttribute (BridgeDev);\r
1502 \r
1503   if (EFI_ERROR (Status)) {\r
1504     return Status;\r
1505   }\r
1506 \r
1507   return EFI_SUCCESS;\r
1508 \r
1509 }\r
1510 \r
1511 EFI_STATUS\r
1512 PciBridgeResourceAllocator (\r
1513   IN PCI_IO_DEVICE  *Bridge\r
1514   )\r
1515 /*++\r
1516 \r
1517 Routine Description:\r
1518 \r
1519 Arguments:\r
1520 \r
1521 Returns:\r
1522 \r
1523   None\r
1524 \r
1525 --*/\r
1526 // TODO:    Bridge - add argument and description to function comment\r
1527 // TODO:    EFI_SUCCESS - add return value to function comment\r
1528 {\r
1529   PCI_RESOURCE_NODE *IoBridge;\r
1530   PCI_RESOURCE_NODE *Mem32Bridge;\r
1531   PCI_RESOURCE_NODE *PMem32Bridge;\r
1532   PCI_RESOURCE_NODE *Mem64Bridge;\r
1533   PCI_RESOURCE_NODE *PMem64Bridge;\r
1534   UINT64            IoBase;\r
1535   UINT64            Mem32Base;\r
1536   UINT64            PMem32Base;\r
1537   UINT64            Mem64Base;\r
1538   UINT64            PMem64Base;\r
1539   EFI_STATUS        Status;\r
1540 \r
1541   IoBridge = CreateResourceNode (\r
1542               Bridge,\r
1543               0,\r
1544               0xFFF,\r
1545               0,\r
1546               PciBarTypeIo16,\r
1547               PciResUsageTypical\r
1548               );\r
1549 \r
1550   Mem32Bridge = CreateResourceNode (\r
1551                   Bridge,\r
1552                   0,\r
1553                   0xFFFFF,\r
1554                   0,\r
1555                   PciBarTypeMem32,\r
1556                   PciResUsageTypical\r
1557                   );\r
1558 \r
1559   PMem32Bridge = CreateResourceNode (\r
1560                   Bridge,\r
1561                   0,\r
1562                   0xFFFFF,\r
1563                   0,\r
1564                   PciBarTypePMem32,\r
1565                   PciResUsageTypical\r
1566                   );\r
1567 \r
1568   Mem64Bridge = CreateResourceNode (\r
1569                   Bridge,\r
1570                   0,\r
1571                   0xFFFFF,\r
1572                   0,\r
1573                   PciBarTypeMem64,\r
1574                   PciResUsageTypical\r
1575                   );\r
1576 \r
1577   PMem64Bridge = CreateResourceNode (\r
1578                   Bridge,\r
1579                   0,\r
1580                   0xFFFFF,\r
1581                   0,\r
1582                   PciBarTypePMem64,\r
1583                   PciResUsageTypical\r
1584                   );\r
1585 \r
1586   //\r
1587   // Create resourcemap by going through all the devices subject to this root bridge\r
1588   //\r
1589   Status = CreateResourceMap (\r
1590             Bridge,\r
1591             IoBridge,\r
1592             Mem32Bridge,\r
1593             PMem32Bridge,\r
1594             Mem64Bridge,\r
1595             PMem64Bridge\r
1596             );\r
1597 \r
1598   if (EFI_ERROR (Status)) {\r
1599     return Status;\r
1600   }\r
1601 \r
1602   Status = GetResourceBaseFromBridge (\r
1603             Bridge,\r
1604             &IoBase,\r
1605             &Mem32Base,\r
1606             &PMem32Base,\r
1607             &Mem64Base,\r
1608             &PMem64Base\r
1609             );\r
1610 \r
1611   if (EFI_ERROR (Status)) {\r
1612     return Status;\r
1613   }\r
1614 \r
1615   //\r
1616   // Program IO resources\r
1617   //\r
1618   ProgramResource (\r
1619     IoBase,\r
1620     IoBridge\r
1621     );\r
1622 \r
1623   //\r
1624   // Program Mem32 resources\r
1625   //\r
1626   ProgramResource (\r
1627     Mem32Base,\r
1628     Mem32Bridge\r
1629     );\r
1630 \r
1631   //\r
1632   // Program PMem32 resources\r
1633   //\r
1634   ProgramResource (\r
1635     PMem32Base,\r
1636     PMem32Bridge\r
1637     );\r
1638 \r
1639   //\r
1640   // Program Mem64 resources\r
1641   //\r
1642   ProgramResource (\r
1643     Mem64Base,\r
1644     Mem64Bridge\r
1645     );\r
1646 \r
1647   //\r
1648   // Program PMem64 resources\r
1649   //\r
1650   ProgramResource (\r
1651     PMem64Base,\r
1652     PMem64Bridge\r
1653     );\r
1654 \r
1655   DestroyResourceTree (IoBridge);\r
1656   DestroyResourceTree (Mem32Bridge);\r
1657   DestroyResourceTree (PMem32Bridge);\r
1658   DestroyResourceTree (PMem64Bridge);\r
1659   DestroyResourceTree (Mem64Bridge);\r
1660 \r
1661   gBS->FreePool (IoBridge);\r
1662   gBS->FreePool (Mem32Bridge);\r
1663   gBS->FreePool (PMem32Bridge);\r
1664   gBS->FreePool (PMem64Bridge);\r
1665   gBS->FreePool (Mem64Bridge);\r
1666 \r
1667   return EFI_SUCCESS;\r
1668 }\r
1669 \r
1670 EFI_STATUS\r
1671 GetResourceBaseFromBridge (\r
1672   IN  PCI_IO_DEVICE *Bridge,\r
1673   OUT UINT64        *IoBase,\r
1674   OUT UINT64        *Mem32Base,\r
1675   OUT UINT64        *PMem32Base,\r
1676   OUT UINT64        *Mem64Base,\r
1677   OUT UINT64        *PMem64Base\r
1678   )\r
1679 /*++\r
1680 \r
1681 Routine Description:\r
1682 \r
1683 Arguments:\r
1684 \r
1685 Returns:\r
1686 \r
1687   None\r
1688 \r
1689 --*/\r
1690 // TODO:    Bridge - add argument and description to function comment\r
1691 // TODO:    IoBase - add argument and description to function comment\r
1692 // TODO:    Mem32Base - add argument and description to function comment\r
1693 // TODO:    PMem32Base - add argument and description to function comment\r
1694 // TODO:    Mem64Base - add argument and description to function comment\r
1695 // TODO:    PMem64Base - add argument and description to function comment\r
1696 // TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
1697 // TODO:    EFI_SUCCESS - add return value to function comment\r
1698 {\r
1699   if (!Bridge->Allocated) {\r
1700     return EFI_OUT_OF_RESOURCES;\r
1701   }\r
1702 \r
1703   *IoBase     = gAllOne;\r
1704   *Mem32Base  = gAllOne;\r
1705   *PMem32Base = gAllOne;\r
1706   *Mem64Base  = gAllOne;\r
1707   *PMem64Base = gAllOne;\r
1708 \r
1709   if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
1710 \r
1711     if (Bridge->PciBar[PPB_IO_RANGE].Length) {\r
1712       *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
1713     }\r
1714 \r
1715     if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {\r
1716       *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
1717     }\r
1718 \r
1719     if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {\r
1720       *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
1721     }\r
1722 \r
1723     if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {\r
1724       *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
1725     } else {\r
1726       *PMem64Base = gAllOne;\r
1727     }\r
1728 \r
1729   }\r
1730 \r
1731   if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
1732     if (Bridge->PciBar[P2C_IO_1].Length) {\r
1733       *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
1734     } else {\r
1735       if (Bridge->PciBar[P2C_IO_2].Length) {\r
1736         *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
1737       }\r
1738     }\r
1739 \r
1740     if (Bridge->PciBar[P2C_MEM_1].Length) {\r
1741       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
1742         *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1743       }\r
1744 \r
1745       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
1746         *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
1747       }\r
1748     }\r
1749 \r
1750     if (Bridge->PciBar[P2C_MEM_2].Length) {\r
1751       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
1752         *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1753       }\r
1754 \r
1755       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
1756         *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
1757       }\r
1758     }\r
1759   }\r
1760 \r
1761   return EFI_SUCCESS;\r
1762 }\r
1763 \r
1764 EFI_STATUS\r
1765 NotifyPhase (\r
1766   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
1767   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase\r
1768   )\r
1769 /*++\r
1770 \r
1771 Routine Description:\r
1772 \r
1773 Arguments:\r
1774 \r
1775 Returns:\r
1776 \r
1777   None\r
1778 \r
1779 --*/\r
1780 // TODO:    PciResAlloc - add argument and description to function comment\r
1781 // TODO:    Phase - add argument and description to function comment\r
1782 // TODO:    EFI_NOT_FOUND - add return value to function comment\r
1783 // TODO:    EFI_SUCCESS - add return value to function comment\r
1784 {\r
1785   EFI_HANDLE                      HostBridgeHandle;\r
1786   EFI_HANDLE                      RootBridgeHandle;\r
1787   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1788   EFI_STATUS                      Status;\r
1789 \r
1790   HostBridgeHandle  = NULL;\r
1791   RootBridgeHandle  = NULL;\r
1792   if (gPciPlatformProtocol != NULL) {\r
1793     //\r
1794     // Get Host Bridge Handle.\r
1795     //\r
1796     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
1797 \r
1798     //\r
1799     // Get the rootbridge Io protocol to find the host bridge handle\r
1800     //\r
1801     Status = gBS->HandleProtocol (\r
1802                     RootBridgeHandle,\r
1803                     &gEfiPciRootBridgeIoProtocolGuid,\r
1804                     (VOID **) &PciRootBridgeIo\r
1805                     );\r
1806 \r
1807     if (EFI_ERROR (Status)) {\r
1808       return EFI_NOT_FOUND;\r
1809     }\r
1810 \r
1811     HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
1812 \r
1813     //\r
1814     // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1815     //\r
1816     gPciPlatformProtocol->PhaseNotify (\r
1817                             gPciPlatformProtocol,\r
1818                             HostBridgeHandle,\r
1819                             Phase,\r
1820                             ChipsetEntry\r
1821                             );\r
1822   }\r
1823 \r
1824   Status = PciResAlloc->NotifyPhase (\r
1825                           PciResAlloc,\r
1826                           Phase\r
1827                           );\r
1828 \r
1829   if (gPciPlatformProtocol != NULL) {\r
1830     //\r
1831     // Call PlatformPci::PhaseNotify() if the protocol is present.\r
1832     //\r
1833     gPciPlatformProtocol->PhaseNotify (\r
1834                             gPciPlatformProtocol,\r
1835                             HostBridgeHandle,\r
1836                             Phase,\r
1837                             ChipsetExit\r
1838                             );\r
1839 \r
1840   }\r
1841 \r
1842   return EFI_SUCCESS;\r
1843 }\r
1844 \r
1845 EFI_STATUS\r
1846 PreprocessController (\r
1847   IN PCI_IO_DEVICE                                    *Bridge,\r
1848   IN UINT8                                            Bus,\r
1849   IN UINT8                                            Device,\r
1850   IN UINT8                                            Func,\r
1851   IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase\r
1852   )\r
1853 /*++\r
1854 \r
1855 Routine Description:\r
1856 \r
1857 Arguments:\r
1858 \r
1859 Returns:\r
1860 \r
1861   None\r
1862 \r
1863 --*/\r
1864 // TODO:    Bridge - add argument and description to function comment\r
1865 // TODO:    Bus - add argument and description to function comment\r
1866 // TODO:    Device - add argument and description to function comment\r
1867 // TODO:    Func - add argument and description to function comment\r
1868 // TODO:    Phase - add argument and description to function comment\r
1869 // TODO:    EFI_UNSUPPORTED - add return value to function comment\r
1870 // TODO:    EFI_SUCCESS - add return value to function comment\r
1871 {\r
1872   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;\r
1873   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;\r
1874   EFI_HANDLE                                        RootBridgeHandle;\r
1875   EFI_HANDLE                                        HostBridgeHandle;\r
1876   EFI_STATUS                                        Status;\r
1877 \r
1878   //\r
1879   // Get the host bridge handle\r
1880   //\r
1881   HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
1882 \r
1883   //\r
1884   // Get the pci host bridge resource allocation protocol\r
1885   //\r
1886   Status = gBS->OpenProtocol (\r
1887                   HostBridgeHandle,\r
1888                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
1889                   (VOID **) &PciResAlloc,\r
1890                   NULL,\r
1891                   NULL,\r
1892                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1893                   );\r
1894 \r
1895   if (EFI_ERROR (Status)) {\r
1896     return EFI_UNSUPPORTED;\r
1897   }\r
1898 \r
1899   //\r
1900   // Get Root Brige Handle\r
1901   //\r
1902   while (Bridge->Parent) {\r
1903     Bridge = Bridge->Parent;\r
1904   }\r
1905 \r
1906   RootBridgeHandle                      = Bridge->Handle;\r
1907 \r
1908   RootBridgePciAddress.Register         = 0;\r
1909   RootBridgePciAddress.Function         = Func;\r
1910   RootBridgePciAddress.Device           = Device;\r
1911   RootBridgePciAddress.Bus              = Bus;\r
1912   RootBridgePciAddress.ExtendedRegister = 0;\r
1913 \r
1914   if (gPciPlatformProtocol != NULL) {\r
1915     //\r
1916     // Call PlatformPci::PrepController() if the protocol is present.\r
1917     //\r
1918     gPciPlatformProtocol->PlatformPrepController (\r
1919                             gPciPlatformProtocol,\r
1920                             HostBridgeHandle,\r
1921                             RootBridgeHandle,\r
1922                             RootBridgePciAddress,\r
1923                             Phase,\r
1924                             ChipsetEntry\r
1925                             );\r
1926   }\r
1927 \r
1928   Status = PciResAlloc->PreprocessController (\r
1929                           PciResAlloc,\r
1930                           RootBridgeHandle,\r
1931                           RootBridgePciAddress,\r
1932                           Phase\r
1933                           );\r
1934 \r
1935   if (gPciPlatformProtocol != NULL) {\r
1936     //\r
1937     // Call PlatformPci::PrepController() if the protocol is present.\r
1938     //\r
1939     gPciPlatformProtocol->PlatformPrepController (\r
1940                             gPciPlatformProtocol,\r
1941                             HostBridgeHandle,\r
1942                             RootBridgeHandle,\r
1943                             RootBridgePciAddress,\r
1944                             Phase,\r
1945                             ChipsetExit\r
1946                             );\r
1947   }\r
1948 \r
1949   return EFI_SUCCESS;\r
1950 }\r
1951 \r
1952 EFI_STATUS\r
1953 EFIAPI\r
1954 PciHotPlugRequestNotify (\r
1955   IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
1956   IN EFI_PCI_HOTPLUG_OPERATION        Operation,\r
1957   IN EFI_HANDLE                       Controller,\r
1958   IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,\r
1959   IN OUT UINT8                        *NumberOfChildren,\r
1960   IN OUT EFI_HANDLE                   * ChildHandleBuffer\r
1961   )\r
1962 /*++\r
1963 \r
1964 Routine Description:\r
1965 \r
1966   Hot plug request notify.\r
1967 \r
1968 Arguments:\r
1969 \r
1970   This                 - A pointer to the hot plug request protocol.\r
1971   Operation            - The operation.\r
1972   Controller           - A pointer to the controller.\r
1973   RemainningDevicePath - A pointer to the device path.\r
1974   NumberOfChildren     - A the number of child handle in the ChildHandleBuffer.\r
1975   ChildHandleBuffer    - A pointer to the array contain the child handle.\r
1976 \r
1977 Returns:\r
1978 \r
1979   Status code.\r
1980 \r
1981 --*/\r
1982 // TODO:    RemainingDevicePath - add argument and description to function comment\r
1983 // TODO:    EFI_NOT_FOUND - add return value to function comment\r
1984 // TODO:    EFI_SUCCESS - add return value to function comment\r
1985 // TODO:    EFI_SUCCESS - add return value to function comment\r
1986 // TODO:    EFI_SUCCESS - add return value to function comment\r
1987 {\r
1988   PCI_IO_DEVICE       *Bridge;\r
1989   PCI_IO_DEVICE       *Temp;\r
1990   EFI_PCI_IO_PROTOCOL *PciIo;\r
1991   UINTN               Index;\r
1992   EFI_HANDLE          RootBridgeHandle;\r
1993   EFI_STATUS          Status;\r
1994 \r
1995   Status = gBS->OpenProtocol (\r
1996                   Controller,\r
1997                   &gEfiPciIoProtocolGuid,\r
1998                   (VOID **) &PciIo,\r
1999                   gPciBusDriverBinding.DriverBindingHandle,\r
2000                   Controller,\r
2001                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2002                   );\r
2003 \r
2004   if (EFI_ERROR (Status)) {\r
2005     return EFI_NOT_FOUND;\r
2006   }\r
2007 \r
2008   Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
2009 \r
2010   //\r
2011   // Get root bridge handle\r
2012   //\r
2013   Temp = Bridge;\r
2014   while (Temp->Parent) {\r
2015     Temp = Temp->Parent;\r
2016   }\r
2017 \r
2018   RootBridgeHandle = Temp->Handle;\r
2019 \r
2020   if (Operation == EfiPciHotPlugRequestAdd) {\r
2021 \r
2022     if (NumberOfChildren != NULL) {\r
2023       *NumberOfChildren = 0;\r
2024     }\r
2025 \r
2026     if (IsListEmpty (&Bridge->ChildList)) {\r
2027 \r
2028       Status = PciBridgeEnumerator (Bridge);\r
2029 \r
2030       if (EFI_ERROR (Status)) {\r
2031         return Status;\r
2032       }\r
2033     }\r
2034 \r
2035     Status = StartPciDevicesOnBridge (\r
2036               RootBridgeHandle,\r
2037               Bridge,\r
2038               RemainingDevicePath,\r
2039               NumberOfChildren,\r
2040               ChildHandleBuffer\r
2041               );\r
2042 \r
2043     return EFI_SUCCESS;\r
2044   }\r
2045 \r
2046   if (Operation == EfiPciHotplugRequestRemove) {\r
2047 \r
2048     if (*NumberOfChildren == 0) {\r
2049       //\r
2050       // Remove all devices on the bridge\r
2051       //\r
2052       Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);\r
2053       return Status;\r
2054 \r
2055     }\r
2056 \r
2057     for (Index = 0; Index < *NumberOfChildren; Index++) {\r
2058       //\r
2059       // De register all the pci device\r
2060       //\r
2061       Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);\r
2062 \r
2063       if (EFI_ERROR (Status)) {\r
2064         return Status;\r
2065       }\r
2066 \r
2067     }\r
2068     //\r
2069     // End for\r
2070     //\r
2071     return EFI_SUCCESS;\r
2072   }\r
2073 \r
2074   return EFI_SUCCESS;\r
2075 }\r
2076 \r
2077 BOOLEAN\r
2078 SearchHostBridgeHandle (\r
2079   IN EFI_HANDLE RootBridgeHandle\r
2080   )\r
2081 /*++\r
2082 \r
2083 Routine Description:\r
2084 \r
2085 Arguments:\r
2086 \r
2087 Returns:\r
2088 \r
2089   None\r
2090 \r
2091 --*/\r
2092 // TODO:    RootBridgeHandle - add argument and description to function comment\r
2093 {\r
2094   EFI_HANDLE                      HostBridgeHandle;\r
2095   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
2096   UINTN                           Index;\r
2097   EFI_STATUS                      Status;\r
2098 \r
2099   //\r
2100   // Get the rootbridge Io protocol to find the host bridge handle\r
2101   //\r
2102   Status = gBS->OpenProtocol (\r
2103                   RootBridgeHandle,\r
2104                   &gEfiPciRootBridgeIoProtocolGuid,\r
2105                   (VOID **) &PciRootBridgeIo,\r
2106                   gPciBusDriverBinding.DriverBindingHandle,\r
2107                   RootBridgeHandle,\r
2108                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2109                   );\r
2110 \r
2111   if (EFI_ERROR (Status)) {\r
2112     return FALSE;\r
2113   }\r
2114 \r
2115   HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
2116   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2117     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2118       return TRUE;\r
2119     }\r
2120   }\r
2121 \r
2122   return FALSE;\r
2123 }\r
2124 \r
2125 EFI_STATUS\r
2126 AddHostBridgeEnumerator (\r
2127   IN EFI_HANDLE HostBridgeHandle\r
2128   )\r
2129 /*++\r
2130 \r
2131 Routine Description:\r
2132 \r
2133 Arguments:\r
2134 \r
2135 Returns:\r
2136 \r
2137   None\r
2138 \r
2139 --*/\r
2140 // TODO:    HostBridgeHandle - add argument and description to function comment\r
2141 // TODO:    EFI_ABORTED - add return value to function comment\r
2142 // TODO:    EFI_ABORTED - add return value to function comment\r
2143 // TODO:    EFI_SUCCESS - add return value to function comment\r
2144 {\r
2145   UINTN Index;\r
2146 \r
2147   if (!HostBridgeHandle) {\r
2148     return EFI_ABORTED;\r
2149   }\r
2150 \r
2151   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
2152     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
2153       return EFI_ABORTED;\r
2154     }\r
2155   }\r
2156 \r
2157   if (Index < PCI_MAX_HOST_BRIDGE_NUM) {\r
2158     gPciHostBrigeHandles[Index] = HostBridgeHandle;\r
2159     gPciHostBridgeNumber++;\r
2160   }\r
2161 \r
2162   return EFI_SUCCESS;\r
2163 }\r