]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
Coding style modification.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
CommitLineData
3db51098 1/**@file\r
ead42efc 2\r
3db51098 3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
ead42efc 11\r
3db51098 12**/\r
ead42efc 13\r
ead42efc 14\r
15#include "pcibus.h"\r
16#include "PciEnumerator.h"\r
17#include "PciResourceSupport.h"\r
18#include "PciOptionRomSupport.h"\r
19\r
20EFI_STATUS\r
21PciEnumerator (\r
22 IN EFI_HANDLE Controller\r
23 )\r
bcd70414 24/**\r
ead42efc 25\r
26Routine Description:\r
27\r
28 This routine is used to enumerate entire pci bus system\r
29 in a given platform\r
30\r
31Arguments:\r
32\r
33Returns:\r
34\r
35 None\r
36\r
bcd70414 37**/\r
ead42efc 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
ead42efc 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
137EFI_STATUS\r
138PciRootBridgeEnumerator (\r
139 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
140 IN PCI_IO_DEVICE *RootBridgeDev\r
141 )\r
bcd70414 142/**\r
ead42efc 143\r
144Routine Description:\r
145\r
146Arguments:\r
147\r
148Returns:\r
149\r
150 None\r
151\r
bcd70414 152**/\r
ead42efc 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
ff62de37 196 PaddedBusRange = (UINT8) (pConfiguration->AddrRangeMax);\r
ead42efc 197\r
198 //\r
199 // Initialize the subordinate bus number\r
200 //\r
201 SubBusNumber = StartBusNumber;\r
202\r
ff62de37 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
ead42efc 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
4beb4afe 239 \r
240 gBS->FreePool (pConfiguration);\r
241 \r
ead42efc 242 if (EFI_ERROR (Status)) {\r
243 return Status;\r
244 }\r
245\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249EFI_STATUS\r
250ProcessOptionRom (\r
251 IN PCI_IO_DEVICE *Bridge,\r
252 IN UINT64 RomBase,\r
253 IN UINT64 MaxLength\r
254 )\r
bcd70414 255/**\r
ead42efc 256\r
257Routine Description:\r
258\r
259 This routine is used to process option rom on a certain root bridge\r
260\r
261Arguments:\r
262\r
263Returns:\r
264\r
265 None\r
266\r
bcd70414 267**/\r
ead42efc 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
ead42efc 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
eb9a9a5e 287 ProcessOptionRom (Temp, RomBase, MaxLength);\r
ead42efc 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
eb9a9a5e 295 LoadOpRomImage (Temp, RomBase);\r
ead42efc 296 }\r
297\r
298 CurrentLink = CurrentLink->ForwardLink;\r
299 }\r
300\r
301 return EFI_SUCCESS;\r
302}\r
303\r
304EFI_STATUS\r
305PciAssignBusNumber (\r
306 IN PCI_IO_DEVICE *Bridge,\r
307 IN UINT8 StartBusNumber,\r
308 OUT UINT8 *SubBusNumber\r
309 )\r
bcd70414 310/**\r
ead42efc 311\r
312Routine Description:\r
313\r
314 This routine is used to assign bus number to the given PCI bus system\r
315\r
316Arguments:\r
317\r
318Returns:\r
319\r
320 None\r
321\r
bcd70414 322**/\r
ead42efc 323// TODO: Bridge - add argument and description to function comment\r
324// TODO: StartBusNumber - add argument and description to function comment\r
325// TODO: SubBusNumber - add argument and description to function comment\r
326// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
327// TODO: EFI_SUCCESS - add return value to function comment\r
328{\r
329 EFI_STATUS Status;\r
330 PCI_TYPE00 Pci;\r
331 UINT8 Device;\r
332 UINT8 Func;\r
333 UINT64 Address;\r
334 UINTN SecondBus;\r
335 UINT16 Register;\r
336 UINT8 Register8;\r
337 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
338\r
339 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
340\r
341 SecondBus = 0;\r
342 Register = 0;\r
343\r
344 *SubBusNumber = StartBusNumber;\r
345\r
346 //\r
347 // First check to see whether the parent is ppb\r
348 //\r
349 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
350 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
351\r
352 //\r
353 // Check to see whether a pci device is present\r
354 //\r
355\r
356 Status = PciDevicePresent (\r
357 PciRootBridgeIo,\r
358 &Pci,\r
359 StartBusNumber,\r
360 Device,\r
361 Func\r
362 );\r
363\r
364 if (!EFI_ERROR (Status) &&\r
365 (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
366\r
367 //\r
368 // Reserved one bus for cardbus bridge\r
369 //\r
370 SecondBus = ++(*SubBusNumber);\r
371\r
372 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
373\r
374 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
375\r
376 Status = PciRootBridgeIoWrite (\r
377 PciRootBridgeIo,\r
378 &Pci,\r
379 EfiPciWidthUint16,\r
380 Address,\r
381 1,\r
382 &Register\r
383 );\r
384\r
385 //\r
386 // Initialize SubBusNumber to SecondBus\r
387 //\r
388 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
389 Status = PciRootBridgeIoWrite (\r
390 PciRootBridgeIo,\r
391 &Pci,\r
392 EfiPciWidthUint8,\r
393 Address,\r
394 1,\r
395 SubBusNumber\r
396 );\r
397 //\r
398 // If it is PPB, resursively search down this bridge\r
399 //\r
400 if (IS_PCI_BRIDGE (&Pci)) {\r
401\r
402 Register8 = 0xFF;\r
403 Status = PciRootBridgeIoWrite (\r
404 PciRootBridgeIo,\r
405 &Pci,\r
406 EfiPciWidthUint8,\r
407 Address,\r
408 1,\r
409 &Register8\r
410 );\r
411\r
412 Status = PciAssignBusNumber (\r
413 Bridge,\r
414 (UINT8) (SecondBus),\r
415 SubBusNumber\r
416 );\r
417\r
418 if (EFI_ERROR (Status)) {\r
419 return EFI_DEVICE_ERROR;\r
420 }\r
421 }\r
422\r
423 //\r
424 // Set the current maximum bus number under the PPB\r
425 //\r
426\r
427 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
428\r
429 Status = PciRootBridgeIoWrite (\r
430 PciRootBridgeIo,\r
431 &Pci,\r
432 EfiPciWidthUint8,\r
433 Address,\r
434 1,\r
435 SubBusNumber\r
436 );\r
437\r
438 }\r
439\r
440 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
441\r
442 //\r
443 // Skip sub functions, this is not a multi function device\r
444 //\r
445\r
446 Func = PCI_MAX_FUNC;\r
447 }\r
448 }\r
449 }\r
450\r
451 return EFI_SUCCESS;\r
452}\r
453\r
454EFI_STATUS\r
455DetermineRootBridgeAttributes (\r
456 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
457 IN PCI_IO_DEVICE *RootBridgeDev\r
458 )\r
bcd70414 459/**\r
ead42efc 460\r
461Routine Description:\r
462\r
463 This routine is used to determine the root bridge attribute by interfacing\r
464 the host bridge resource allocation protocol.\r
465\r
466Arguments:\r
467\r
468Returns:\r
469\r
470 None\r
471\r
bcd70414 472**/\r
ead42efc 473// TODO: PciResAlloc - add argument and description to function comment\r
474// TODO: RootBridgeDev - add argument and description to function comment\r
475// TODO: EFI_SUCCESS - add return value to function comment\r
476{\r
477 UINT64 Attributes;\r
478 EFI_STATUS Status;\r
479 EFI_HANDLE RootBridgeHandle;\r
480\r
481 Attributes = 0;\r
482 RootBridgeHandle = RootBridgeDev->Handle;\r
483\r
484 //\r
485 // Get root bridge attribute by calling into pci host bridge resource allocation protocol\r
486 //\r
487 Status = PciResAlloc->GetAllocAttributes (\r
488 PciResAlloc,\r
489 RootBridgeHandle,\r
490 &Attributes\r
491 );\r
492\r
493 if (EFI_ERROR (Status)) {\r
494 return Status;\r
495 }\r
496\r
497 //\r
498 // Here is the point where PCI bus driver calls HOST bridge allocation protocol\r
499 // Currently we hardcoded for ea815\r
500 //\r
501\r
502 if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {\r
503 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;\r
504 }\r
505\r
506 if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {\r
507 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
508 }\r
509\r
510 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
511 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
512 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
513\r
514 return EFI_SUCCESS;\r
515}\r
516\r
517UINT64\r
518GetMaxOptionRomSize (\r
519 IN PCI_IO_DEVICE *Bridge\r
520 )\r
bcd70414 521/**\r
ead42efc 522\r
523Routine Description:\r
524\r
525 Get Max Option Rom size on this bridge\r
526\r
527Arguments:\r
528\r
529Returns:\r
530\r
531 None\r
532\r
bcd70414 533**/\r
ead42efc 534// TODO: Bridge - add argument and description to function comment\r
535{\r
536 LIST_ENTRY *CurrentLink;\r
537 PCI_IO_DEVICE *Temp;\r
538 UINT64 MaxOptionRomSize;\r
539 UINT64 TempOptionRomSize;\r
540\r
541 MaxOptionRomSize = 0;\r
542\r
543 //\r
544 // Go through bridges to reach all devices\r
545 //\r
546 CurrentLink = Bridge->ChildList.ForwardLink;\r
547 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
548 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
549 if (!IsListEmpty (&Temp->ChildList)) {\r
550\r
551 //\r
552 // Get max option rom size under this bridge\r
553 //\r
554 TempOptionRomSize = GetMaxOptionRomSize (Temp);\r
555\r
556 //\r
557 // Compare with the option rom size of the bridge\r
558 // Get the larger one\r
559 //\r
560 if (Temp->RomSize > TempOptionRomSize) {\r
561 TempOptionRomSize = Temp->RomSize;\r
562 }\r
563\r
564 } else {\r
565\r
566 //\r
567 // For devices get the rom size directly\r
568 //\r
569 TempOptionRomSize = Temp->RomSize;\r
570 }\r
571\r
572 //\r
573 // Get the largest rom size on this bridge\r
574 //\r
575 if (TempOptionRomSize > MaxOptionRomSize) {\r
576 MaxOptionRomSize = TempOptionRomSize;\r
577 }\r
578\r
579 CurrentLink = CurrentLink->ForwardLink;\r
580 }\r
581\r
582 return MaxOptionRomSize;\r
583}\r
584\r
585EFI_STATUS\r
586PciHostBridgeDeviceAttribute (\r
587 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
588 )\r
bcd70414 589/**\r
ead42efc 590\r
591Routine Description:\r
592\r
593 Process attributes of devices on this host bridge\r
594\r
595Arguments:\r
596\r
597Returns:\r
598\r
599 None\r
600\r
bcd70414 601**/\r
ead42efc 602// TODO: PciResAlloc - add argument and description to function comment\r
603// TODO: EFI_NOT_FOUND - add return value to function comment\r
604// TODO: EFI_SUCCESS - add return value to function comment\r
605{\r
606 EFI_HANDLE RootBridgeHandle;\r
607 PCI_IO_DEVICE *RootBridgeDev;\r
608 EFI_STATUS Status;\r
609\r
610 RootBridgeHandle = NULL;\r
611\r
612 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
613\r
614 //\r
615 // Get RootBridg Device by handle\r
616 //\r
617 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
618\r
619 if (RootBridgeDev == NULL) {\r
620 return EFI_NOT_FOUND;\r
621 }\r
622\r
623 //\r
624 // Set the attributes for devcies behind the Root Bridge\r
625 //\r
626 Status = DetermineDeviceAttribute (RootBridgeDev);\r
627 if (EFI_ERROR (Status)) {\r
628 return Status;\r
629 }\r
630\r
631 }\r
632\r
633 return EFI_SUCCESS;\r
634}\r
635\r
636EFI_STATUS\r
637GetResourceAllocationStatus (\r
638 VOID *AcpiConfig,\r
639 OUT UINT64 *IoResStatus,\r
640 OUT UINT64 *Mem32ResStatus,\r
641 OUT UINT64 *PMem32ResStatus,\r
642 OUT UINT64 *Mem64ResStatus,\r
643 OUT UINT64 *PMem64ResStatus\r
644 )\r
bcd70414 645/**\r
ead42efc 646\r
647Routine Description:\r
648\r
649 Get resource allocation status from the ACPI pointer\r
650\r
651Arguments:\r
652\r
653Returns:\r
654\r
655 None\r
656\r
bcd70414 657**/\r
ead42efc 658// TODO: AcpiConfig - add argument and description to function comment\r
659// TODO: IoResStatus - add argument and description to function comment\r
660// TODO: Mem32ResStatus - add argument and description to function comment\r
661// TODO: PMem32ResStatus - add argument and description to function comment\r
662// TODO: Mem64ResStatus - add argument and description to function comment\r
663// TODO: PMem64ResStatus - add argument and description to function comment\r
664// TODO: EFI_SUCCESS - add return value to function comment\r
665{\r
666\r
667 UINT8 *Temp;\r
668 UINT64 ResStatus;\r
669 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;\r
670\r
671 Temp = (UINT8 *) AcpiConfig;\r
672\r
673 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
674\r
675 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
676 ResStatus = ptr->AddrTranslationOffset;\r
677\r
678 switch (ptr->ResType) {\r
679 case 0:\r
680 if (ptr->AddrSpaceGranularity == 32) {\r
681 if (ptr->SpecificFlag == 0x06) {\r
682 //\r
683 // Pmem32\r
684 //\r
685 *PMem32ResStatus = ResStatus;\r
686 } else {\r
687 //\r
688 // Mem32\r
689 //\r
690 *Mem32ResStatus = ResStatus;\r
691 }\r
692 }\r
693\r
694 if (ptr->AddrSpaceGranularity == 64) {\r
695 if (ptr->SpecificFlag == 0x06) {\r
696 //\r
697 // PMem64\r
698 //\r
699 *PMem64ResStatus = ResStatus;\r
700 } else {\r
701 //\r
702 // Mem64\r
703 //\r
704 *Mem64ResStatus = ResStatus;\r
705 }\r
706 }\r
707\r
708 break;\r
709\r
710 case 1:\r
711 //\r
712 // Io\r
713 //\r
714 *IoResStatus = ResStatus;\r
715 break;\r
716\r
717 default:\r
718 break;\r
719 }\r
720\r
721 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
722 }\r
723\r
724 return EFI_SUCCESS;\r
725}\r
726\r
727EFI_STATUS\r
728RejectPciDevice (\r
729 IN PCI_IO_DEVICE *PciDevice\r
730 )\r
bcd70414 731/**\r
ead42efc 732\r
733Routine Description:\r
734\r
735 Remove a PCI device from device pool and mark its bar\r
736\r
737Arguments:\r
738\r
739Returns:\r
740\r
741 None\r
742\r
bcd70414 743**/\r
ead42efc 744// TODO: PciDevice - add argument and description to function comment\r
745// TODO: EFI_SUCCESS - add return value to function comment\r
746// TODO: EFI_ABORTED - add return value to function comment\r
747// TODO: EFI_SUCCESS - add return value to function comment\r
748// TODO: EFI_ABORTED - add return value to function comment\r
749{\r
750 PCI_IO_DEVICE *Bridge;\r
751 PCI_IO_DEVICE *Temp;\r
752 LIST_ENTRY *CurrentLink;\r
753\r
754 //\r
755 // Remove the padding resource from a bridge\r
756 //\r
757 if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \\r
758 PciDevice->ResourcePaddingDescriptors ) {\r
759 gBS->FreePool (PciDevice->ResourcePaddingDescriptors);\r
760 PciDevice->ResourcePaddingDescriptors = NULL;\r
761 return EFI_SUCCESS;\r
762 }\r
763\r
764 //\r
765 // Skip RB and PPB\r
766 //\r
767 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {\r
768 return EFI_ABORTED;\r
769 }\r
770\r
771 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {\r
772 //\r
773 // Get the root bridge device\r
774 //\r
775 Bridge = PciDevice;\r
776 while (Bridge->Parent) {\r
777 Bridge = Bridge->Parent;\r
778 }\r
779\r
780 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);\r
781\r
782 //\r
783 // Mark its bar\r
784 //\r
785 InitializeP2C (PciDevice);\r
786 }\r
787\r
788 //\r
789 // Remove the device\r
790 //\r
791 Bridge = PciDevice->Parent;\r
792 CurrentLink = Bridge->ChildList.ForwardLink;\r
793 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
794 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
795 if (Temp == PciDevice) {\r
796 InitializePciDevice (Temp);\r
797 RemoveEntryList (CurrentLink);\r
798 FreePciDevice (Temp);\r
799 return EFI_SUCCESS;\r
800 }\r
801\r
802 CurrentLink = CurrentLink->ForwardLink;\r
803 }\r
804\r
805 return EFI_ABORTED;\r
806}\r
807\r
808BOOLEAN\r
809IsRejectiveDevice (\r
810 IN PCI_RESOURCE_NODE *PciResNode\r
811 )\r
bcd70414 812/**\r
ead42efc 813\r
814Routine Description:\r
815\r
816 Determine whethter a PCI device can be rejected\r
817\r
818Arguments:\r
819\r
820Returns:\r
821\r
822 None\r
823\r
bcd70414 824**/\r
ead42efc 825// TODO: PciResNode - add argument and description to function comment\r
826{\r
827 PCI_IO_DEVICE *Temp;\r
828\r
829 Temp = PciResNode->PciDev;\r
830\r
831 //\r
832 // Ensure the device is present\r
833 //\r
834 if (!Temp) {\r
835 return FALSE;\r
836 }\r
837\r
838 //\r
839 // PPB and RB should go ahead\r
840 //\r
841 if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {\r
842 return TRUE;\r
843 }\r
844\r
845 //\r
846 // Skip device on Bus0\r
847 //\r
848 if ((Temp->Parent) && (Temp->BusNumber == 0)) {\r
849 return FALSE;\r
850 }\r
851\r
852 //\r
853 // Skip VGA\r
854 //\r
855 if (IS_PCI_VGA (&Temp->Pci)) {\r
856 return FALSE;\r
857 }\r
858\r
859 return TRUE;\r
860}\r
861\r
862PCI_RESOURCE_NODE *\r
863GetLargerConsumerDevice (\r
864 IN PCI_RESOURCE_NODE *PciResNode1,\r
865 IN PCI_RESOURCE_NODE *PciResNode2\r
866 )\r
bcd70414 867/**\r
ead42efc 868\r
869Routine Description:\r
870\r
871 Get the larger resource consumer\r
872\r
873Arguments:\r
874\r
875Returns:\r
876\r
877 None\r
878\r
bcd70414 879**/\r
ead42efc 880// TODO: PciResNode1 - add argument and description to function comment\r
881// TODO: PciResNode2 - add argument and description to function comment\r
882{\r
883 if (!PciResNode2) {\r
884 return PciResNode1;\r
885 }\r
886\r
887 if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \\r
888 && (PciResNode2->ResourceUsage != PciResUsagePadding) )\r
889 {\r
890 return PciResNode1;\r
891 }\r
892\r
893 if (!PciResNode1) {\r
894 return PciResNode2;\r
895 }\r
896\r
897 if ((PciResNode1->Length) > (PciResNode2->Length)) {\r
898 return PciResNode1;\r
899 }\r
900\r
901 return PciResNode2;\r
902\r
903}\r
904\r
905PCI_RESOURCE_NODE *\r
906GetMaxResourceConsumerDevice (\r
907 IN PCI_RESOURCE_NODE *ResPool\r
908 )\r
bcd70414 909/**\r
ead42efc 910\r
911Routine Description:\r
912\r
913 Get the max resource consumer in the host resource pool\r
914\r
915Arguments:\r
916\r
917Returns:\r
918\r
919 None\r
920\r
bcd70414 921**/\r
ead42efc 922// TODO: ResPool - add argument and description to function comment\r
923{\r
924 PCI_RESOURCE_NODE *Temp;\r
925 LIST_ENTRY *CurrentLink;\r
926 PCI_RESOURCE_NODE *PciResNode;\r
927 PCI_RESOURCE_NODE *PPBResNode;\r
928\r
929 PciResNode = NULL;\r
930\r
931 CurrentLink = ResPool->ChildList.ForwardLink;\r
932 while (CurrentLink && CurrentLink != &ResPool->ChildList) {\r
933\r
934 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
935\r
936 if (!IsRejectiveDevice (Temp)) {\r
937 CurrentLink = CurrentLink->ForwardLink;\r
938 continue;\r
939 }\r
940\r
941 if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \\r
942 && (Temp->ResourceUsage != PciResUsagePadding))\r
943 {\r
944 PPBResNode = GetMaxResourceConsumerDevice (Temp);\r
945 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);\r
946 } else {\r
947 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);\r
948 }\r
949\r
950 CurrentLink = CurrentLink->ForwardLink;\r
951 }\r
952\r
953 return PciResNode;\r
954}\r
955\r
956EFI_STATUS\r
957PciHostBridgeAdjustAllocation (\r
958 IN PCI_RESOURCE_NODE *IoPool,\r
959 IN PCI_RESOURCE_NODE *Mem32Pool,\r
960 IN PCI_RESOURCE_NODE *PMem32Pool,\r
961 IN PCI_RESOURCE_NODE *Mem64Pool,\r
962 IN PCI_RESOURCE_NODE *PMem64Pool,\r
963 IN UINT64 IoResStatus,\r
964 IN UINT64 Mem32ResStatus,\r
965 IN UINT64 PMem32ResStatus,\r
966 IN UINT64 Mem64ResStatus,\r
967 IN UINT64 PMem64ResStatus\r
968 )\r
bcd70414 969/**\r
ead42efc 970\r
971Routine Description:\r
972\r
973 Adjust host bridge allocation so as to reduce resource requirement\r
974\r
975Arguments:\r
976\r
977Returns:\r
978\r
979 None\r
980\r
bcd70414 981**/\r
ead42efc 982// TODO: IoPool - add argument and description to function comment\r
983// TODO: Mem32Pool - add argument and description to function comment\r
984// TODO: PMem32Pool - add argument and description to function comment\r
985// TODO: Mem64Pool - add argument and description to function comment\r
986// TODO: PMem64Pool - add argument and description to function comment\r
987// TODO: IoResStatus - add argument and description to function comment\r
988// TODO: Mem32ResStatus - add argument and description to function comment\r
989// TODO: PMem32ResStatus - add argument and description to function comment\r
990// TODO: Mem64ResStatus - add argument and description to function comment\r
991// TODO: PMem64ResStatus - add argument and description to function comment\r
992// TODO: EFI_ABORTED - add return value to function comment\r
993// TODO: EFI_SUCCESS - add return value to function comment\r
994// TODO: EFI_ABORTED - add return value to function comment\r
995{\r
996 BOOLEAN AllocationAjusted;\r
997 PCI_RESOURCE_NODE *PciResNode;\r
998 PCI_RESOURCE_NODE *ResPool[5];\r
999 PCI_IO_DEVICE *RemovedPciDev[5];\r
1000 UINT64 ResStatus[5];\r
1001 UINTN RemovedPciDevNum;\r
1002 UINTN DevIndex;\r
1003 UINTN ResType;\r
1004 EFI_STATUS Status;\r
1d6d9e7e 1005 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
ead42efc 1006\r
1007 PciResNode = NULL;\r
1008 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));\r
1009 RemovedPciDevNum = 0;\r
1010\r
1011 ResPool[0] = IoPool;\r
1012 ResPool[1] = Mem32Pool;\r
1013 ResPool[2] = PMem32Pool;\r
1014 ResPool[3] = Mem64Pool;\r
1015 ResPool[4] = PMem64Pool;\r
1016\r
1017 ResStatus[0] = IoResStatus;\r
1018 ResStatus[1] = Mem32ResStatus;\r
1019 ResStatus[2] = PMem32ResStatus;\r
1020 ResStatus[3] = Mem64ResStatus;\r
1021 ResStatus[4] = PMem64ResStatus;\r
1022\r
1023 AllocationAjusted = FALSE;\r
1024\r
1025 for (ResType = 0; ResType < 5; ResType++) {\r
1026\r
1027 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {\r
1028 continue;\r
1029 }\r
1030\r
1031 if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {\r
1032 //\r
1033 // Hostbridge hasn't this resource type\r
1034 //\r
1035 return EFI_ABORTED;\r
1036 }\r
1037\r
1038 //\r
1039 // Hostbridge hasn't enough resource\r
1040 //\r
1041 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);\r
1042 if (!PciResNode) {\r
1043 continue;\r
1044 }\r
1045\r
1046 //\r
1047 // Check if the device has been removed before\r
1048 //\r
1049 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {\r
1050 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {\r
a1d887b7 1051 break;\r
ead42efc 1052 }\r
1053 }\r
a1d887b7 1054\r
1055 if (DevIndex != RemovedPciDevNum) {\r
1056 continue;\r
1057 }\r
ead42efc 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
1101EFI_STATUS\r
1102ConstructAcpiResourceRequestor (\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
bcd70414 1111/**\r
ead42efc 1112\r
1113Routine Description:\r
1114\r
1115Arguments:\r
1116\r
1117Returns:\r
1118\r
1119 None\r
1120\r
bcd70414 1121**/\r
ead42efc 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
1348EFI_STATUS\r
1349GetResourceBase (\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
bcd70414 1357/**\r
ead42efc 1358\r
1359Routine Description:\r
1360\r
1361Arguments:\r
1362\r
1363Returns:\r
1364\r
1365 None\r
1366\r
bcd70414 1367**/\r
ead42efc 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
1447EFI_STATUS\r
1448PciBridgeEnumerator (\r
1449 IN PCI_IO_DEVICE *BridgeDev\r
1450 )\r
bcd70414 1451/**\r
ead42efc 1452\r
1453Routine Description:\r
1454\r
1455Arguments:\r
1456\r
1457Returns:\r
1458\r
1459 None\r
1460\r
bcd70414 1461**/\r
ead42efc 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
1511EFI_STATUS\r
1512PciBridgeResourceAllocator (\r
1513 IN PCI_IO_DEVICE *Bridge\r
1514 )\r
bcd70414 1515/**\r
ead42efc 1516\r
1517Routine Description:\r
1518\r
1519Arguments:\r
1520\r
1521Returns:\r
1522\r
1523 None\r
1524\r
bcd70414 1525**/\r
ead42efc 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
1670EFI_STATUS\r
1671GetResourceBaseFromBridge (\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
bcd70414 1679/**\r
ead42efc 1680\r
1681Routine Description:\r
1682\r
1683Arguments:\r
1684\r
1685Returns:\r
1686\r
1687 None\r
1688\r
bcd70414 1689**/\r
ead42efc 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
1764EFI_STATUS\r
1765NotifyPhase (\r
1766 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
1767 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
1768 )\r
bcd70414 1769/**\r
ead42efc 1770\r
1771Routine Description:\r
1772\r
1773Arguments:\r
1774\r
1775Returns:\r
1776\r
1777 None\r
1778\r
bcd70414 1779**/\r
ead42efc 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
1845EFI_STATUS\r
1846PreprocessController (\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
bcd70414 1853/**\r
ead42efc 1854\r
1855Routine Description:\r
1856\r
1857Arguments:\r
1858\r
1859Returns:\r
1860\r
1861 None\r
1862\r
bcd70414 1863**/\r
ead42efc 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
1952EFI_STATUS\r
1953EFIAPI\r
1954PciHotPlugRequestNotify (\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
bcd70414 1962/**\r
ead42efc 1963\r
1964Routine Description:\r
1965\r
1966 Hot plug request notify.\r
1967\r
1968Arguments:\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
1977Returns:\r
1978\r
1979 Status code.\r
1980\r
bcd70414 1981**/\r
ead42efc 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
2077BOOLEAN\r
2078SearchHostBridgeHandle (\r
2079 IN EFI_HANDLE RootBridgeHandle\r
2080 )\r
bcd70414 2081/**\r
ead42efc 2082\r
2083Routine Description:\r
2084\r
2085Arguments:\r
2086\r
2087Returns:\r
2088\r
2089 None\r
2090\r
bcd70414 2091**/\r
ead42efc 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
2125EFI_STATUS\r
2126AddHostBridgeEnumerator (\r
2127 IN EFI_HANDLE HostBridgeHandle\r
2128 )\r
bcd70414 2129/**\r
ead42efc 2130\r
2131Routine Description:\r
2132\r
2133Arguments:\r
2134\r
2135Returns:\r
2136\r
2137 None\r
2138\r
bcd70414 2139**/\r
ead42efc 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