]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c
• BaseMemoryLib:
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciLib.c
CommitLineData
878ddf1f 1/*++\r
2\r
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
11\r
12Module Name:\r
13\r
14 PciLib.c \r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver Lib file\r
19 It abstracts some functions that can be different \r
20 between light PCI bus driver and full PCI bus driver\r
21\r
22Revision History\r
23\r
24--*/\r
25\r
26#include "pcibus.h"\r
27\r
28EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {\r
29 PciHotPlugRequestNotify\r
30};\r
31\r
32\r
33VOID\r
34InstallHotPlugRequestProtocol (\r
35 IN EFI_STATUS *Status\r
36 )\r
37/*++\r
38\r
39Routine Description:\r
40\r
41Arguments:\r
42 Status - A pointer to the status.\r
43\r
44Returns:\r
45\r
46 None\r
47\r
48--*/\r
49{\r
50 EFI_HANDLE Handle;\r
51\r
52 Handle = NULL;\r
53 *Status = gBS->InstallProtocolInterface (\r
54 &Handle,\r
55 &gEfiPciHotPlugRequestProtocolGuid,\r
56 EFI_NATIVE_INTERFACE,\r
57 &gPciHotPlugRequest\r
58 );\r
59}\r
60\r
61VOID\r
62InstallPciHotplugGuid (\r
63 IN PCI_IO_DEVICE *PciIoDevice\r
64 )\r
65/*++\r
66\r
67Routine Description:\r
68\r
69Arguments:\r
70\r
71 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
72\r
73Returns:\r
74\r
75 None\r
76\r
77--*/\r
78{\r
79 EFI_STATUS Status;\r
80\r
81 if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {\r
82\r
83 Status = gBS->InstallProtocolInterface (\r
84 &PciIoDevice->Handle,\r
85 &gEfiPciHotplugDeviceGuid,\r
86 EFI_NATIVE_INTERFACE,\r
87 NULL\r
88 );\r
89 }\r
90}\r
91\r
92VOID\r
93UninstallPciHotplugGuid (\r
94 IN PCI_IO_DEVICE *PciIoDevice\r
95 )\r
96/*++\r
97\r
98Routine Description:\r
99\r
100Arguments:\r
101\r
102 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
103\r
104Returns:\r
105\r
106 None\r
107\r
108--*/\r
109{\r
110 EFI_STATUS Status;\r
111\r
112 Status = gBS->OpenProtocol (\r
113 PciIoDevice->Handle,\r
114 &gEfiPciHotplugDeviceGuid,\r
115 NULL,\r
116 NULL,\r
117 NULL,\r
118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
119 );\r
120\r
121 if (Status == EFI_SUCCESS) {\r
122 //\r
123 // This may triger CardBus driver to stop for\r
124 // Pccard devices opened the GUID via BY_DRIVER\r
125 //\r
126 Status = gBS->UninstallProtocolInterface (\r
127 PciIoDevice->Handle,\r
128 &gEfiPciHotplugDeviceGuid,\r
129 NULL\r
130 );\r
131 }\r
132}\r
133\r
134VOID\r
135GetBackPcCardBar (\r
136 IN PCI_IO_DEVICE *PciIoDevice\r
137 )\r
138/*++\r
139\r
140Routine Description:\r
141\r
142\r
143Arguments:\r
144\r
145 PciIoDevice - A pointer to the PCI_IO_DEVICE.\r
146\r
147Returns:\r
148\r
149 None\r
150\r
151--*/\r
152{\r
153 UINT32 Address;\r
154\r
155 //\r
156 // Read PciBar information from the bar register\r
157 //\r
158 if (!gFullEnumeration) {\r
159\r
160 Address = 0;\r
161 PciIoDevice->PciIo.Pci.Read (\r
162 &(PciIoDevice->PciIo),\r
163 EfiPciIoWidthUint32,\r
164 0x1c,\r
165 1,\r
166 &Address\r
167 );\r
168\r
169 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);\r
170 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
171 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
172\r
173 Address = 0;\r
174 PciIoDevice->PciIo.Pci.Read (\r
175 &(PciIoDevice->PciIo),\r
176 EfiPciIoWidthUint32,\r
177 0x20,\r
178 1,\r
179 &Address\r
180 );\r
181 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);\r
182 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
183 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
184\r
185 Address = 0;\r
186 PciIoDevice->PciIo.Pci.Read (\r
187 &(PciIoDevice->PciIo),\r
188 EfiPciIoWidthUint32,\r
189 0x2c,\r
190 1,\r
191 &Address\r
192 );\r
193 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
194 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
195 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
196\r
197 Address = 0;\r
198 PciIoDevice->PciIo.Pci.Read (\r
199 &(PciIoDevice->PciIo),\r
200 EfiPciIoWidthUint32,\r
201 0x34,\r
202 1,\r
203 &Address\r
204 );\r
205 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
206 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
207 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
208\r
209 }\r
210\r
211 if (gPciHotPlugInit != NULL) {\r
212 GetResourcePaddingForHpb (PciIoDevice);\r
213 }\r
214}\r
215\r
216EFI_STATUS\r
217RemoveRejectedPciDevices (\r
218 EFI_HANDLE RootBridgeHandle,\r
219 IN PCI_IO_DEVICE *Bridge\r
220 )\r
221/*++\r
222\r
223Routine Description:\r
224\r
225\r
226Arguments:\r
227\r
228 RootBridgeHandle - An efi handle.\r
229 Bridge - An pointer to the PCI_IO_DEVICE.\r
230\r
231Returns:\r
232\r
233 None\r
234\r
235--*/\r
236// TODO: EFI_SUCCESS - add return value to function comment\r
237{\r
238 PCI_IO_DEVICE *Temp;\r
239 LIST_ENTRY *CurrentLink;\r
240 LIST_ENTRY *LastLink;\r
241\r
242 CurrentLink = Bridge->ChildList.ForwardLink;\r
243\r
244 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
245\r
246 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
247\r
248 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
249 //\r
250 // Remove rejected devices recusively\r
251 //\r
252 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
253 } else {\r
254 //\r
255 // Skip rejection for all PPBs, while detect rejection for others\r
256 //\r
257 if (IsPciDeviceRejected (Temp)) {\r
258 \r
259 //\r
260 // For P2C, remove all devices on it\r
261 //\r
262 \r
263 if (!IsListEmpty (&Temp->ChildList)) {\r
264 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
265 }\r
266 \r
267 //\r
268 // Finally remove itself\r
269 //\r
270 \r
271 LastLink = CurrentLink->BackLink;\r
272 RemoveEntryList (CurrentLink);\r
273 FreePciDevice (Temp);\r
274\r
275 CurrentLink = LastLink;\r
276 }\r
277 }\r
278\r
279 CurrentLink = CurrentLink->ForwardLink;\r
280 }\r
281\r
282 return EFI_SUCCESS;\r
283}\r
284\r
285EFI_STATUS\r
286PciHostBridgeResourceAllocator (\r
287 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
288 )\r
289/*++\r
290\r
291Routine Description:\r
292\r
293 Host brige resource allocator.\r
294\r
295Arguments:\r
296\r
297 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
298\r
299Returns:\r
300\r
301 EFI Status.\r
302\r
303--*/\r
304// TODO: EFI_NOT_FOUND - add return value to function comment\r
305// TODO: EFI_NOT_FOUND - add return value to function comment\r
306// TODO: EFI_NOT_FOUND - add return value to function comment\r
307// TODO: EFI_SUCCESS - add return value to function comment\r
308{\r
309 PCI_IO_DEVICE *RootBridgeDev;\r
310 EFI_HANDLE RootBridgeHandle;\r
311 VOID *AcpiConfig;\r
312 EFI_STATUS Status;\r
313 UINT64 IoBase;\r
314 UINT64 Mem32Base;\r
315 UINT64 PMem32Base;\r
316 UINT64 Mem64Base;\r
317 UINT64 PMem64Base;\r
318 UINT64 IoResStatus;\r
319 UINT64 Mem32ResStatus;\r
320 UINT64 PMem32ResStatus;\r
321 UINT64 Mem64ResStatus;\r
322 UINT64 PMem64ResStatus;\r
323 UINT64 MaxOptionRomSize;\r
324 PCI_RESOURCE_NODE *IoBridge;\r
325 PCI_RESOURCE_NODE *Mem32Bridge;\r
326 PCI_RESOURCE_NODE *PMem32Bridge;\r
327 PCI_RESOURCE_NODE *Mem64Bridge;\r
328 PCI_RESOURCE_NODE *PMem64Bridge;\r
329 PCI_RESOURCE_NODE IoPool;\r
330 PCI_RESOURCE_NODE Mem32Pool;\r
331 PCI_RESOURCE_NODE PMem32Pool;\r
332 PCI_RESOURCE_NODE Mem64Pool;\r
333 PCI_RESOURCE_NODE PMem64Pool;\r
334 BOOLEAN ReAllocate;\r
335 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;\r
336 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;\r
337\r
338 //\r
339 // Reallocate flag\r
340 //\r
341 ReAllocate = FALSE;\r
342\r
343 //\r
344 // It will try several times if the resource allocation fails\r
345 //\r
346 while (TRUE) {\r
347\r
348 //\r
349 // Initialize resource pool\r
350 // \r
351 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
352 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
353 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
354 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
355 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
356\r
357 RootBridgeDev = NULL;\r
358 RootBridgeHandle = 0;\r
359\r
360 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
361\r
362 //\r
363 // Get RootBridg Device by handle\r
364 //\r
365 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
366\r
367 if (RootBridgeDev == NULL) {\r
368 return EFI_NOT_FOUND;\r
369 }\r
370\r
371 //\r
372 // Create the entire system resource map from the information collected by\r
373 // enumerator. Several resource tree was created\r
374 //\r
375\r
376 IoBridge = CreateResourceNode (\r
377 RootBridgeDev,\r
378 0,\r
379 0xFFF,\r
380 0,\r
381 PciBarTypeIo16,\r
382 PciResUsageTypical\r
383 );\r
384\r
385 Mem32Bridge = CreateResourceNode (\r
386 RootBridgeDev,\r
387 0,\r
388 0xFFFFF,\r
389 0,\r
390 PciBarTypeMem32,\r
391 PciResUsageTypical\r
392 );\r
393\r
394 PMem32Bridge = CreateResourceNode (\r
395 RootBridgeDev,\r
396 0,\r
397 0xFFFFF,\r
398 0,\r
399 PciBarTypePMem32,\r
400 PciResUsageTypical\r
401 );\r
402\r
403 Mem64Bridge = CreateResourceNode (\r
404 RootBridgeDev,\r
405 0,\r
406 0xFFFFF,\r
407 0,\r
408 PciBarTypeMem64,\r
409 PciResUsageTypical\r
410 );\r
411\r
412 PMem64Bridge = CreateResourceNode (\r
413 RootBridgeDev,\r
414 0,\r
415 0xFFFFF,\r
416 0,\r
417 PciBarTypePMem64,\r
418 PciResUsageTypical\r
419 );\r
420\r
421 //\r
422 // Create resourcemap by going through all the devices subject to this root bridge\r
423 //\r
424 Status = CreateResourceMap (\r
425 RootBridgeDev,\r
426 IoBridge,\r
427 Mem32Bridge,\r
428 PMem32Bridge,\r
429 Mem64Bridge,\r
430 PMem64Bridge\r
431 );\r
432\r
433 //\r
434 // Get the max ROM size that the root bridge can process\r
435 //\r
436 RootBridgeDev->RomSize = Mem32Bridge->Length;\r
437\r
438 //\r
439 // Skip to enlarge the resource request during realloction\r
440 //\r
441 if (!ReAllocate) {\r
442 //\r
443 // Get Max Option Rom size for current root bridge\r
444 //\r
445 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
446\r
447 //\r
448 // Enlarger the mem32 resource to accomdate the option rom\r
449 // if the mem32 resource is not enough to hold the rom\r
450 //\r
451 if (MaxOptionRomSize > Mem32Bridge->Length) {\r
452\r
453 Mem32Bridge->Length = MaxOptionRomSize;\r
454 RootBridgeDev->RomSize = MaxOptionRomSize;\r
455\r
456 //\r
457 // Alignment should be adjusted as well\r
458 //\r
459 if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
460 Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
461 }\r
462 }\r
463 } \r
464 \r
465 //\r
466 // Based on the all the resource tree, contruct ACPI resource node to\r
467 // submit the resource aperture to pci host bridge protocol\r
468 //\r
469 Status = ConstructAcpiResourceRequestor (\r
470 RootBridgeDev,\r
471 IoBridge,\r
472 Mem32Bridge,\r
473 PMem32Bridge,\r
474 Mem64Bridge,\r
475 PMem64Bridge,\r
476 &AcpiConfig\r
477 );\r
478\r
479 //\r
480 // Insert these resource nodes into the database\r
481 //\r
482 InsertResourceNode (&IoPool, IoBridge);\r
483 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
484 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
485 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
486 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
487\r
488 if (Status == EFI_SUCCESS) {\r
489 //\r
490 // Submit the resource requirement\r
491 //\r
492 Status = PciResAlloc->SubmitResources (\r
493 PciResAlloc,\r
494 RootBridgeDev->Handle,\r
495 AcpiConfig\r
496 );\r
497 }\r
498\r
499 //\r
500 // Free acpi resource node\r
501 //\r
502 if (AcpiConfig != NULL) {\r
503 gBS->FreePool (AcpiConfig);\r
504 }\r
505\r
506 if (EFI_ERROR (Status)) {\r
507 //\r
508 // Destroy all the resource tree\r
509 //\r
510 DestroyResourceTree (&IoPool);\r
511 DestroyResourceTree (&Mem32Pool);\r
512 DestroyResourceTree (&PMem32Pool);\r
513 DestroyResourceTree (&Mem64Pool);\r
514 DestroyResourceTree (&PMem64Pool);\r
515 return Status;\r
516 }\r
517 }\r
518\r
519 //\r
520 // Notify pci bus driver starts to program the resource\r
521 //\r
522 \r
523 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
524\r
525 if (!EFI_ERROR (Status)) {\r
526 //\r
527 // Allocation succeed, then continue the following\r
528 //\r
529 break;\r
530 }\r
531 \r
532 //\r
533 // If the resource allocation is unsuccessful, free resources on bridge\r
534 //\r
535 \r
536 RootBridgeDev = NULL;\r
537 RootBridgeHandle = 0;\r
538\r
539 IoResStatus = EFI_RESOURCE_SATISFIED;\r
540 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
541 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
542 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
543 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
544\r
545 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
546 //\r
547 // Get RootBridg Device by handle\r
548 //\r
549 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
550 if (RootBridgeDev == NULL) {\r
551 return EFI_NOT_FOUND;\r
552 }\r
553 \r
554 //\r
555 // Get host bridge handle for status report\r
556 //\r
557 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
558\r
559 //\r
560 // Get acpi resource node for all the resource types\r
561 //\r
562 AcpiConfig = NULL;\r
563\r
564 Status = PciResAlloc->GetProposedResources (\r
565 PciResAlloc,\r
566 RootBridgeDev->Handle,\r
567 &AcpiConfig\r
568 );\r
569\r
570 if (EFI_ERROR (Status)) {\r
571 return Status;\r
572 }\r
573\r
574 if (AcpiConfig != NULL) {\r
575 //\r
576 // Adjust resource allocation policy for each RB\r
577 //\r
578 GetResourceAllocationStatus (\r
579 AcpiConfig,\r
580 &IoResStatus,\r
581 &Mem32ResStatus,\r
582 &PMem32ResStatus,\r
583 &Mem64ResStatus,\r
584 &PMem64ResStatus\r
585 );\r
586 gBS->FreePool (AcpiConfig);\r
587 }\r
588 }\r
589 //\r
590 // End while\r
591 //\r
592\r
593 //\r
594 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
595 //\r
596 //\r
597 // It is very difficult to follow the spec here\r
598 // Device path , Bar index can not be get here\r
599 //\r
600 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
601\r
602 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
603 EFI_PROGRESS_CODE,\r
604 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
605 (VOID *) &AllocFailExtendedData,\r
606 sizeof (AllocFailExtendedData)\r
607 );\r
608\r
609 Status = PciHostBridgeAdjustAllocation (\r
610 &IoPool,\r
611 &Mem32Pool,\r
612 &PMem32Pool,\r
613 &Mem64Pool,\r
614 &PMem64Pool,\r
615 IoResStatus,\r
616 Mem32ResStatus,\r
617 PMem32ResStatus,\r
618 Mem64ResStatus,\r
619 PMem64ResStatus\r
620 );\r
621\r
622 //\r
623 // Destroy all the resource tree\r
624 //\r
625 DestroyResourceTree (&IoPool);\r
626 DestroyResourceTree (&Mem32Pool);\r
627 DestroyResourceTree (&PMem32Pool);\r
628 DestroyResourceTree (&Mem64Pool);\r
629 DestroyResourceTree (&PMem64Pool);\r
630\r
631 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
632\r
633 if (EFI_ERROR (Status)) {\r
634 return Status;\r
635 }\r
636\r
637 ReAllocate = TRUE;\r
638\r
639 }\r
640 //\r
641 // End main while\r
642 //\r
643\r
644 //\r
645 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
646 //\r
647 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
648 EFI_PROGRESS_CODE,\r
649 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
650 (VOID *) &HandleExtendedData,\r
651 sizeof (HandleExtendedData)\r
652 );\r
653\r
654 //\r
655 // Notify pci bus driver starts to program the resource\r
656 //\r
657 NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
658\r
659 RootBridgeDev = NULL;\r
660\r
661 RootBridgeHandle = 0;\r
662\r
663 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
664\r
665 //\r
666 // Get RootBridg Device by handle\r
667 //\r
668 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
669\r
670 if (RootBridgeDev == NULL) {\r
671 return EFI_NOT_FOUND;\r
672 }\r
673 \r
674 //\r
675 // Get acpi resource node for all the resource types\r
676 //\r
677 AcpiConfig = NULL;\r
678 Status = PciResAlloc->GetProposedResources (\r
679 PciResAlloc,\r
680 RootBridgeDev->Handle,\r
681 &AcpiConfig\r
682 );\r
683\r
684 if (EFI_ERROR (Status)) {\r
685 return Status;\r
686 }\r
687\r
688 //\r
689 // Get the resource base by interpreting acpi resource node\r
690 //\r
691 //\r
692 GetResourceBase (\r
693 AcpiConfig,\r
694 &IoBase,\r
695 &Mem32Base,\r
696 &PMem32Base,\r
697 &Mem64Base,\r
698 &PMem64Base\r
699 );\r
700\r
701 //\r
702 // Process option rom for this root bridge\r
703 //\r
704 Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
705\r
706 //\r
707 // Create the entire system resource map from the information collected by\r
708 // enumerator. Several resource tree was created\r
709 //\r
710 Status = GetResourceMap (\r
711 RootBridgeDev,\r
712 &IoBridge,\r
713 &Mem32Bridge,\r
714 &PMem32Bridge,\r
715 &Mem64Bridge,\r
716 &PMem64Bridge,\r
717 &IoPool,\r
718 &Mem32Pool,\r
719 &PMem32Pool,\r
720 &Mem64Pool,\r
721 &PMem64Pool\r
722 );\r
723\r
724 if (EFI_ERROR (Status)) {\r
725 return Status;\r
726 }\r
727\r
728 //\r
729 // Program IO resources\r
730 //\r
731 ProgramResource (\r
732 IoBase,\r
733 IoBridge\r
734 );\r
735\r
736 //\r
737 // Program Mem32 resources\r
738 //\r
739 ProgramResource (\r
740 Mem32Base,\r
741 Mem32Bridge\r
742 );\r
743\r
744 //\r
745 // Program PMem32 resources\r
746 //\r
747 ProgramResource (\r
748 PMem32Base,\r
749 PMem32Bridge\r
750 );\r
751\r
752 //\r
753 // Program Mem64 resources\r
754 //\r
755 ProgramResource (\r
756 Mem64Base,\r
757 Mem64Bridge\r
758 );\r
759\r
760 //\r
761 // Program PMem64 resources\r
762 //\r
763 ProgramResource (\r
764 PMem64Base,\r
765 PMem64Bridge\r
766 );\r
767\r
768 if (AcpiConfig != NULL) {\r
769 gBS->FreePool (AcpiConfig);\r
770 }\r
771 }\r
772\r
773 //\r
774 // Destroy all the resource tree\r
775 //\r
776 DestroyResourceTree (&IoPool);\r
777 DestroyResourceTree (&Mem32Pool);\r
778 DestroyResourceTree (&PMem32Pool);\r
779 DestroyResourceTree (&Mem64Pool);\r
780 DestroyResourceTree (&PMem64Pool);\r
781\r
782 //\r
783 // Notify the resource allocation phase is to end\r
784 //\r
785 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
786\r
787 return EFI_SUCCESS;\r
788}\r
789\r
790EFI_STATUS\r
791PciScanBus (\r
792 IN PCI_IO_DEVICE *Bridge,\r
793 IN UINT8 StartBusNumber,\r
794 OUT UINT8 *SubBusNumber,\r
795 OUT UINT8 *PaddedBusRange\r
796 )\r
797/*++\r
798\r
799Routine Description:\r
800\r
801 This routine is used to assign bus number to the given PCI bus system\r
802\r
803Arguments:\r
804\r
805 Bridge - A pointer to the PCI_IO_DEVICE structure.\r
806 StartBusNumber - The start bus number.\r
807 SubBusNumber - A pointer to the sub bus number.\r
808 PaddedBusRange - A pointer to the padded bus range.\r
809\r
810Returns:\r
811\r
812 None\r
813\r
814--*/\r
815// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
816// TODO: EFI_SUCCESS - add return value to function comment\r
817{\r
818 EFI_STATUS Status;\r
819 PCI_TYPE00 Pci;\r
820 UINT8 Device;\r
821 UINT8 Func;\r
822 UINT64 Address;\r
823 UINTN SecondBus;\r
824 UINT16 Register;\r
825 UINTN HpIndex;\r
826 PCI_IO_DEVICE *PciDevice;\r
827 EFI_EVENT Event;\r
828 EFI_HPC_STATE State;\r
829 UINT64 PciAddress;\r
830 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
831 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
832 UINT16 BusRange;\r
833 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
834 BOOLEAN BusPadding;\r
835\r
836 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
837 SecondBus = 0;\r
838 Register = 0;\r
839 State = 0;\r
840 Attributes = 0;\r
841 BusRange = 0;\r
842\r
843 ResetAllPpbBusReg (Bridge, StartBusNumber);\r
844\r
845 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
846 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
847\r
848 //\r
849 // Check to see whether a pci device is present\r
850 //\r
851 Status = PciDevicePresent (\r
852 PciRootBridgeIo,\r
853 &Pci,\r
854 StartBusNumber,\r
855 Device,\r
856 Func\r
857 );\r
858\r
859 if (EFI_ERROR (Status)) {\r
860 if (Func == 0) {\r
861 //\r
862 // Skip sub functions, this is not a multi function device\r
863 //\r
864 Func = PCI_MAX_FUNC;\r
865 }\r
866\r
867 continue;\r
868 }\r
869 \r
870 //\r
871 // Get the PCI device information\r
872 //\r
873 Status = PciSearchDevice (\r
874 Bridge,\r
875 &Pci,\r
876 StartBusNumber,\r
877 Device,\r
878 Func,\r
879 &PciDevice\r
880 );\r
881\r
882 ASSERT (!EFI_ERROR (Status));\r
883\r
884 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
885\r
886 if (!IS_PCI_BRIDGE (&Pci)) {\r
887 //\r
888 // PCI bridges will be called later\r
889 // Here just need for PCI device or PCI to cardbus controller\r
890 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
891 //\r
892 PreprocessController (\r
893 PciDevice,\r
894 PciDevice->BusNumber,\r
895 PciDevice->DeviceNumber,\r
896 PciDevice->FunctionNumber,\r
897 EfiPciBeforeChildBusEnumeration\r
898 );\r
899 }\r
900 \r
901 //\r
902 // For Pci Hotplug controller devcie only\r
903 //\r
904 if (gPciHotPlugInit != NULL) {\r
905 //\r
906 // Check if it is a Hotplug PCI controller\r
907 //\r
908 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
909\r
910 if (!gPciRootHpcData[HpIndex].Initialized) {\r
911\r
912 Status = CreateEventForHpc (HpIndex, &Event);\r
913\r
914 ASSERT (!EFI_ERROR (Status));\r
915\r
916 Status = gPciHotPlugInit->InitializeRootHpc (\r
917 gPciHotPlugInit,\r
918 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
919 PciAddress,\r
920 Event,\r
921 &State\r
922 );\r
923 \r
924 PreprocessController (\r
925 PciDevice,\r
926 PciDevice->BusNumber,\r
927 PciDevice->DeviceNumber,\r
928 PciDevice->FunctionNumber,\r
929 EfiPciBeforeChildBusEnumeration\r
930 ); \r
931 continue;\r
932 }\r
933 }\r
934 }\r
935\r
936 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
937 //\r
938 // For PPB\r
939 // Get the bridge information\r
940 //\r
941 BusPadding = FALSE;\r
942 if (gPciHotPlugInit != NULL) {\r
943\r
944 if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
945 \r
946 //\r
947 // If it is initialized, get the padded bus range\r
948 //\r
949 Status = gPciHotPlugInit->GetResourcePadding (\r
950 gPciHotPlugInit,\r
951 gPciRootHpcPool[HpIndex].HpbDevicePath,\r
952 PciAddress,\r
953 &State,\r
954 (VOID **) &Descriptors,\r
955 &Attributes\r
956 );\r
957\r
958 if (EFI_ERROR (Status)) {\r
959 return Status;\r
960 }\r
961\r
962 BusRange = 0;\r
963 Status = PciGetBusRange (\r
964 &Descriptors,\r
965 NULL,\r
966 NULL,\r
967 &BusRange\r
968 );\r
969\r
970 gBS->FreePool (Descriptors);\r
971\r
972 if (EFI_ERROR (Status)) {\r
973 return Status;\r
974 }\r
975\r
976 BusPadding = TRUE;\r
977 }\r
978 }\r
979\r
980 (*SubBusNumber)++;\r
981 SecondBus = *SubBusNumber;\r
982\r
983 Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
984 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
985\r
986 Status = PciRootBridgeIo->Pci.Write (\r
987 PciRootBridgeIo,\r
988 EfiPciWidthUint16,\r
989 Address,\r
990 1,\r
991 &Register\r
992 );\r
993\r
994\r
995 //\r
996 // If it is PPB, resursively search down this bridge\r
997 //\r
998 if (IS_PCI_BRIDGE (&Pci)) {\r
999 \r
1000 //\r
1001 // Initialize SubBusNumber to Maximum bus number\r
1002 //\r
1003 Register = 0xFF;\r
1004 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1005 Status = PciRootBridgeIo->Pci.Write (\r
1006 PciRootBridgeIo,\r
1007 EfiPciWidthUint8,\r
1008 Address,\r
1009 1,\r
1010 &Register\r
1011 );\r
1012\r
1013 //\r
1014 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1015 //\r
1016 PreprocessController (\r
1017 PciDevice,\r
1018 PciDevice->BusNumber,\r
1019 PciDevice->DeviceNumber,\r
1020 PciDevice->FunctionNumber,\r
1021 EfiPciBeforeChildBusEnumeration\r
1022 );\r
1023\r
1024 Status = PciScanBus (\r
1025 PciDevice,\r
1026 (UINT8) (SecondBus),\r
1027 SubBusNumber,\r
1028 PaddedBusRange\r
1029 );\r
1030\r
1031 if (EFI_ERROR (Status)) {\r
1032 return EFI_DEVICE_ERROR;\r
1033 }\r
1034 }\r
1035\r
1036 if (BusPadding) {\r
1037 //\r
1038 // Ensure the device is enabled and initialized\r
1039 //\r
1040 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1041 (State & EFI_HPC_STATE_ENABLED) &&\r
1042 (State & EFI_HPC_STATE_INITIALIZED) ) {\r
1043 *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
1044 } else {\r
1045 *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
1046 }\r
1047 }\r
1048\r
1049 //\r
1050 // Set the current maximum bus number under the PPB\r
1051 //\r
1052 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
1053\r
1054 Status = PciRootBridgeIo->Pci.Write (\r
1055 PciRootBridgeIo,\r
1056 EfiPciWidthUint8,\r
1057 Address,\r
1058 1,\r
1059 SubBusNumber\r
1060 );\r
1061 }\r
1062\r
1063 if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
1064\r
1065 //\r
1066 // Skip sub functions, this is not a multi function device\r
1067 //\r
1068 Func = PCI_MAX_FUNC;\r
1069 }\r
1070\r
1071 }\r
1072 }\r
1073\r
1074 return EFI_SUCCESS;\r
1075}\r
1076\r
1077EFI_STATUS\r
1078PciRootBridgeP2CProcess (\r
1079 IN PCI_IO_DEVICE *Bridge\r
1080 )\r
1081/*++\r
1082\r
1083Routine Description:\r
1084 \r
1085 Process Option Rom on this host bridge\r
1086\r
1087Arguments:\r
1088\r
1089Returns:\r
1090\r
1091 None\r
1092\r
1093--*/\r
1094// TODO: Bridge - add argument and description to function comment\r
1095// TODO: EFI_SUCCESS - add return value to function comment\r
1096{\r
1097 LIST_ENTRY *CurrentLink;\r
1098 PCI_IO_DEVICE *Temp;\r
1099 EFI_HPC_STATE State;\r
1100 UINT64 PciAddress;\r
1101 EFI_STATUS Status;\r
1102\r
1103 CurrentLink = Bridge->ChildList.ForwardLink;\r
1104\r
1105 while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
1106\r
1107 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1108\r
1109 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1110\r
1111 if (gPciHotPlugInit && Temp->Allocated) {\r
1112 \r
1113 //\r
1114 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1115 //\r
1116 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1117 EFI_PROGRESS_CODE,\r
1118 EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
1119 Temp->DevicePath\r
1120 );\r
1121\r
1122 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1123 Status = gPciHotPlugInit->InitializeRootHpc (\r
1124 gPciHotPlugInit,\r
1125 Temp->DevicePath,\r
1126 PciAddress,\r
1127 NULL,\r
1128 &State\r
1129 );\r
1130\r
1131 if (!EFI_ERROR (Status)) {\r
1132 Status = PciBridgeEnumerator (Temp);\r
1133\r
1134 if (EFI_ERROR (Status)) {\r
1135 return Status;\r
1136 }\r
1137 }\r
1138\r
1139 CurrentLink = CurrentLink->ForwardLink;\r
1140 continue;\r
1141\r
1142 }\r
1143 }\r
1144\r
1145 if (!IsListEmpty (&Temp->ChildList)) {\r
1146 Status = PciRootBridgeP2CProcess (Temp);\r
1147 }\r
1148\r
1149 CurrentLink = CurrentLink->ForwardLink;\r
1150 }\r
1151\r
1152 return EFI_SUCCESS;\r
1153}\r
1154\r
1155EFI_STATUS\r
1156PciHostBridgeP2CProcess (\r
1157 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1158 )\r
1159/*++\r
1160\r
1161Routine Description:\r
1162 \r
1163Arguments:\r
1164\r
1165Returns:\r
1166\r
1167 None\r
1168\r
1169--*/\r
1170// TODO: PciResAlloc - add argument and description to function comment\r
1171// TODO: EFI_NOT_FOUND - add return value to function comment\r
1172// TODO: EFI_SUCCESS - add return value to function comment\r
1173{\r
1174 EFI_HANDLE RootBridgeHandle;\r
1175 PCI_IO_DEVICE *RootBridgeDev;\r
1176 EFI_STATUS Status;\r
1177\r
1178 RootBridgeHandle = NULL;\r
1179\r
1180 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1181\r
1182 //\r
1183 // Get RootBridg Device by handle\r
1184 //\r
1185 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1186\r
1187 if (RootBridgeDev == NULL) {\r
1188 return EFI_NOT_FOUND;\r
1189 }\r
1190\r
1191 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1192\r
1193 if (EFI_ERROR (Status)) {\r
1194 return Status;\r
1195 }\r
1196\r
1197 }\r
1198\r
1199 return EFI_SUCCESS;\r
1200}\r
1201\r
1202EFI_STATUS\r
1203PciHostBridgeEnumerator (\r
1204 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1205 )\r
1206/*++\r
1207\r
1208Routine Description:\r
1209\r
1210 This function is used to enumerate the entire host bridge \r
1211 in a given platform\r
1212\r
1213Arguments:\r
1214\r
1215 PciResAlloc - A pointer to the resource allocate protocol.\r
1216\r
1217Returns:\r
1218\r
1219 None\r
1220\r
1221--*/\r
1222// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1223// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1224// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
1225// TODO: EFI_SUCCESS - add return value to function comment\r
1226{\r
1227 EFI_HANDLE RootBridgeHandle;\r
1228 PCI_IO_DEVICE *RootBridgeDev;\r
1229 EFI_STATUS Status;\r
1230 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1231 UINT16 MinBus;\r
1232 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1233\r
1234 InitializeHotPlugSupport ();\r
1235\r
1236 //\r
1237 // Notify the bus allocation phase is about to start\r
1238 //\r
1239 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1240\r
1241 RootBridgeHandle = NULL;\r
1242 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1243\r
1244 //\r
1245 // if a root bridge instance is found, create root bridge device for it\r
1246 //\r
1247\r
1248 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1249\r
1250 if (RootBridgeDev == NULL) {\r
1251 return EFI_OUT_OF_RESOURCES;\r
1252 }\r
1253\r
1254 //\r
1255 // Enumerate all the buses under this root bridge\r
1256 //\r
1257\r
1258 Status = PciRootBridgeEnumerator (\r
1259 PciResAlloc,\r
1260 RootBridgeDev\r
1261 );\r
1262\r
1263 if (EFI_ERROR (Status)) {\r
1264 return Status;\r
1265 }\r
1266\r
1267 DestroyRootBridge (RootBridgeDev);\r
1268\r
1269 //\r
1270 // Error proccess here\r
1271 //\r
1272 }\r
1273\r
1274 // \r
1275 // Notify the bus allocation phase is finished for the first time\r
1276 // \r
1277 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1278 \r
1279 \r
1280 if (gPciHotPlugInit != NULL) {\r
1281 //\r
1282 // Wait for all HPC initialized\r
1283 //\r
1284 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1285\r
1286 if (EFI_ERROR (Status)) {\r
1287 return Status;\r
1288 }\r
1289\r
1290 //\r
1291 // Notify the bus allocation phase is about to start for the 2nd time\r
1292 //\r
1293 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1294 \r
1295 RootBridgeHandle = NULL;\r
1296 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1297\r
1298 //\r
1299 // if a root bridge instance is found, create root bridge device for it\r
1300 //\r
1301\r
1302 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1303\r
1304 if (RootBridgeDev == NULL) {\r
1305 return EFI_OUT_OF_RESOURCES;\r
1306 }\r
1307\r
1308 //\r
1309 // Enumerate all the buses under this root bridge\r
1310 //\r
1311\r
1312 Status = PciRootBridgeEnumerator (\r
1313 PciResAlloc,\r
1314 RootBridgeDev\r
1315 );\r
1316\r
1317 DestroyRootBridge (RootBridgeDev);\r
1318 if (EFI_ERROR (Status)) {\r
1319 return Status;\r
1320 }\r
1321 }\r
1322 \r
1323 //\r
1324 // Notify the bus allocation phase is to end\r
1325 //\r
1326 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1327 }\r
1328\r
1329 //\r
1330 // Notify the resource allocation phase is to start\r
1331 //\r
1332 NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1333\r
1334 RootBridgeHandle = NULL;\r
1335 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
1336\r
1337 //\r
1338 // if a root bridge instance is found, create root bridge device for it\r
1339 //\r
1340\r
1341 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1342\r
1343 if (RootBridgeDev == NULL) {\r
1344 return EFI_OUT_OF_RESOURCES;\r
1345 }\r
1346\r
1347 Status = StartManagingRootBridge (RootBridgeDev);\r
1348\r
1349 if (EFI_ERROR (Status)) {\r
1350 return Status;\r
1351 }\r
1352\r
1353 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1354 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
1355\r
1356 if (EFI_ERROR (Status)) {\r
1357 return Status;\r
1358 }\r
1359\r
1360 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1361\r
1362 if (EFI_ERROR (Status)) {\r
1363 return Status;\r
1364 }\r
1365\r
1366 //\r
1367 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1368 // protocol\r
1369 //\r
1370 DetermineRootBridgeAttributes (\r
1371 PciResAlloc,\r
1372 RootBridgeDev\r
1373 );\r
1374\r
1375 //\r
1376 // Collect all the resource information under this root bridge\r
1377 // A database that records all the information about pci device subject to this\r
1378 // root bridge will then be created\r
1379 //\r
1380 Status = PciPciDeviceInfoCollector (\r
1381 RootBridgeDev,\r
1382 (UINT8) MinBus\r
1383 );\r
1384\r
1385 if (EFI_ERROR (Status)) {\r
1386 return Status;\r
1387 }\r
1388\r
1389 InsertRootBridge (RootBridgeDev);\r
1390\r
1391 //\r
1392 // Record the hostbridge handle\r
1393 //\r
1394 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1395 }\r
1396\r
1397 return EFI_SUCCESS;\r
1398}\r