]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PciHostBridgeDxe/PciHostBridge.c
FatBinPkg: Update EBC/IA32/X64/IPF binaries
[mirror_edk2.git] / OvmfPkg / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2 Provides the basic interfaces to abstract a PCI Host Bridge Resource
3 Allocation
4
5 Copyright (C) 2015, Red Hat, Inc.
6 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include <Library/QemuFwCfgLib.h>
19
20 #include "PciHostBridge.h"
21
22 STATIC
23 CONST
24 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
25 {
26 {
27 ACPI_DEVICE_PATH,
28 ACPI_DP,
29 {
30 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
31 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
32 }
33 },
34 EISA_PNP_ID(0x0A03), // HID
35 0 // UID
36 },
37
38 {
39 END_DEVICE_PATH_TYPE,
40 END_ENTIRE_DEVICE_PATH_SUBTYPE,
41 {
42 END_DEVICE_PATH_LENGTH,
43 0
44 }
45 }
46 };
47
48 EFI_HANDLE mDriverImageHandle;
49
50 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
51 PCI_HOST_BRIDGE_SIGNATURE, // Signature
52 NULL, // HostBridgeHandle
53 {NULL, NULL}, // Head
54 FALSE, // ResourceSubiteed
55 TRUE, // CanRestarted
56 {
57 NotifyPhase,
58 GetNextRootBridge,
59 GetAttributes,
60 StartBusEnumeration,
61 SetBusNumbers,
62 SubmitResources,
63 GetProposedResources,
64 PreprocessController
65 }
66 };
67
68 //
69 // Implementation
70 //
71
72 /**
73 Allocate and initialize a root bridge.
74
75 param[in] RootBusNumber The bus number of the root bus (root bridge) to
76 create.
77
78 param[in] MaxSubBusNumber The inclusive maximum bus number that can be
79 assigned to any subordinate bus found behind any
80 PCI bridge hanging off this root bus.
81
82 The caller is repsonsible for ensuring that
83 RootBusNumber <= MaxSubBusNumber. If
84 RootBusNumber equals MaxSubBusNumber, then the
85 root bus has no room for subordinate buses.
86
87 param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge
88 that is the parent of the root bridge to create.
89 HostBridgeHandle is expected to have
90 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
91 installed on it.
92
93 param[out] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has
94 been created as the result of the function call.
95
96 @retval EFI_SUCCESS Initialization successful. A new
97 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL has been
98 created as the child of HostBridgeHandle. A
99 device path consisting of an ACPI device path
100 node, with UID = RootBusNumber, has been
101 installed on the same new handle.
102
103 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
104
105 @return Error codes from
106 gBS->InstallMultipleProtocolInterfaces().
107 **/
108 STATIC
109 EFI_STATUS
110 InitRootBridge (
111 IN UINT8 RootBusNumber,
112 IN UINT8 MaxSubBusNumber,
113 IN EFI_HANDLE HostBridgeHandle,
114 OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
115 )
116 {
117 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
118 PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
119 EFI_STATUS Status;
120
121 ASSERT (RootBusNumber <= MaxSubBusNumber);
122
123 PrivateData = AllocateZeroPool (sizeof *PrivateData);
124 if (PrivateData == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
129
130 CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
131 sizeof mRootBridgeDevicePathTemplate);
132 PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
133
134 ResAperture.BusBase = RootBusNumber;
135 ResAperture.BusLimit = MaxSubBusNumber;
136 ResAperture.MemBase = BASE_2GB;
137 ResAperture.MemLimit = BASE_4GB - 1;
138 ResAperture.IoBase = 0;
139 ResAperture.IoLimit = MAX_UINT16;
140 //
141 // The function call below allocates no resources and performs no actions
142 // that have to be rolled back on later failure. It always succeeds.
143 //
144 Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
145 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
146 ASSERT_EFI_ERROR (Status);
147
148 Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
149 &gEfiDevicePathProtocolGuid, &PrivateData->DevicePath,
150 &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
151 NULL);
152 if (EFI_ERROR (Status)) {
153 goto FreePrivateData;
154 }
155
156 DEBUG ((EFI_D_INFO,
157 "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
158 __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
159 *RootBus = PrivateData;
160 return EFI_SUCCESS;
161
162 FreePrivateData:
163 FreePool (PrivateData);
164 return Status;
165 }
166
167
168 /**
169 Uninitialize and free a root bridge set up with InitRootBridge().
170
171 On return, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance and the device path
172 will have been released, freeing RootBus->Handle as well.
173
174 param[in] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has been created
175 with InitRootBridge(), and should be released.
176 **/
177 STATIC
178 VOID
179 UninitRootBridge (
180 IN PCI_ROOT_BRIDGE_INSTANCE *RootBus
181 )
182 {
183 EFI_STATUS Status;
184
185 Status = gBS->UninstallMultipleProtocolInterfaces (RootBus->Handle,
186 &gEfiDevicePathProtocolGuid, &RootBus->DevicePath,
187 &gEfiPciRootBridgeIoProtocolGuid, &RootBus->Io,
188 NULL);
189 ASSERT_EFI_ERROR (Status);
190 FreePool (RootBus);
191 }
192
193
194 /**
195 Entry point of this driver
196
197 @param ImageHandle Handle of driver image
198 @param SystemTable Point to EFI_SYSTEM_TABLE
199
200 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
201 @retval EFI_DEVICE_ERROR Can not install the protocol instance
202 @retval EFI_SUCCESS Success to initialize the Pci host bridge.
203 **/
204 EFI_STATUS
205 EFIAPI
206 InitializePciHostBridge (
207 IN EFI_HANDLE ImageHandle,
208 IN EFI_SYSTEM_TABLE *SystemTable
209 )
210 {
211 EFI_STATUS Status;
212 FIRMWARE_CONFIG_ITEM FwCfgItem;
213 UINTN FwCfgSize;
214 UINT64 ExtraRootBridgesLeft;
215 UINTN LastRootBridgeNumber;
216 UINTN RootBridgeNumber;
217 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
218 PCI_ROOT_BRIDGE_INSTANCE *RootBus;
219 EFI_STATUS UninstallStatus;
220
221 mDriverImageHandle = ImageHandle;
222
223 //
224 // Create Host Bridge Device Handle
225 //
226 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
227 &mPciHostBridgeInstanceTemplate);
228 if (HostBridge == NULL) {
229 return EFI_OUT_OF_RESOURCES;
230 }
231
232 InitializeListHead (&HostBridge->Head);
233
234 Status = gBS->InstallMultipleProtocolInterfaces (
235 &HostBridge->HostBridgeHandle,
236 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
237 &HostBridge->ResAlloc,
238 NULL
239 );
240 if (EFI_ERROR (Status)) {
241 goto FreeHostBridge;
242 }
243
244 //
245 // QEMU provides the number of extra root buses, shortening the exhaustive
246 // search below. If there is no hint, the feature is missing.
247 //
248 Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
249 if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
250 ExtraRootBridgesLeft = 0;
251 } else {
252 QemuFwCfgSelectItem (FwCfgItem);
253 QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
254 DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
255 __FUNCTION__, ExtraRootBridgesLeft));
256 }
257
258 //
259 // The "main" root bus is always there.
260 //
261 LastRootBridgeNumber = 0;
262
263 //
264 // Scan all other root buses. If function 0 of any device on a bus returns a
265 // VendorId register value different from all-bits-one, then that bus is
266 // alive.
267 //
268 for (RootBridgeNumber = 1;
269 RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
270 ++RootBridgeNumber) {
271 UINTN Device;
272
273 for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
274 if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
275 PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
276 break;
277 }
278 }
279 if (Device <= MAX_PCI_DEVICE_NUMBER) {
280 //
281 // Found the next root bus. We can now install the *previous* one,
282 // because now we know how big a bus number range *that* one has, for any
283 // subordinate buses that might exist behind PCI bridges hanging off it.
284 //
285 Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
286 (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
287 &RootBus);
288 if (EFI_ERROR (Status)) {
289 goto RollbackProtocols;
290 }
291 InsertTailList (&HostBridge->Head, &RootBus->Link);
292 LastRootBridgeNumber = RootBridgeNumber;
293 --ExtraRootBridgesLeft;
294 }
295 }
296
297 //
298 // Install the last root bus (which might be the only, ie. main, root bus, if
299 // we've found no extra root buses).
300 //
301 Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
302 HostBridge->HostBridgeHandle, &RootBus);
303 if (EFI_ERROR (Status)) {
304 goto RollbackProtocols;
305 }
306 InsertTailList (&HostBridge->Head, &RootBus->Link);
307
308 return EFI_SUCCESS;
309
310 RollbackProtocols:
311 while (!IsListEmpty (&HostBridge->Head)) {
312 LIST_ENTRY *Entry;
313
314 Entry = GetFirstNode (&HostBridge->Head);
315 RemoveEntryList (Entry);
316 RootBus = DRIVER_INSTANCE_FROM_LIST_ENTRY (Entry);
317 UninitRootBridge (RootBus);
318 }
319 UninstallStatus = gBS->UninstallMultipleProtocolInterfaces (
320 HostBridge->HostBridgeHandle,
321 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
322 &HostBridge->ResAlloc,
323 NULL
324 );
325 ASSERT_EFI_ERROR (UninstallStatus);
326
327 FreeHostBridge:
328 FreePool (HostBridge);
329
330 return Status;
331 }
332
333
334 /**
335 These are the notifications from the PCI bus driver that it is about to enter
336 a certain phase of the PCI enumeration process.
337
338 This member function can be used to notify the host bridge driver to perform
339 specific actions, including any chipset-specific initialization, so that the
340 chipset is ready to enter the next phase. Eight notification points are
341 defined at this time. See belows:
342
343 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures
344 and internal data structures. The PCI
345 enumerator should issue this
346 notification before starting a fresh
347 enumeration process. Enumeration
348 cannot be restarted after sending any
349 other notification such as
350 EfiPciHostBridgeBeginBusAllocation.
351
352 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to
353 begin. No specific action is required
354 here. This notification can be used to
355 perform any chipset-specific
356 programming.
357
358 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming
359 phase is complete. No specific action
360 is required here. This notification
361 can be used to perform any
362 chipset-specific programming.
363
364 EfiPciHostBridgeBeginResourceAllocation
365 The resource allocation phase is about
366 to begin. No specific action is
367 required here. This notification can
368 be used to perform any
369 chipset-specific programming.
370
371 EfiPciHostBridgeAllocateResources Allocates resources per previously
372 submitted requests for all the PCI
373 root bridges. These resource settings
374 are returned on the next call to
375 GetProposedResources(). Before calling
376 NotifyPhase() with a Phase of
377 EfiPciHostBridgeAllocateResource, the
378 PCI bus enumerator is responsible for
379 gathering I/O and memory requests for
380 all the PCI root bridges and
381 submitting these requests using
382 SubmitResources(). This function pads
383 the resource amount to suit the root
384 bridge hardware, takes care of
385 dependencies between the PCI root
386 bridges, and calls the Global
387 Coherency Domain (GCD) with the
388 allocation request. In the case of
389 padding, the allocated range could be
390 bigger than what was requested.
391
392 EfiPciHostBridgeSetResources Programs the host bridge hardware to
393 decode previously allocated resources
394 (proposed resources) for all the PCI
395 root bridges. After the hardware is
396 programmed, reassigning resources will
397 not be supported. The bus settings are
398 not affected.
399
400 EfiPciHostBridgeFreeResources Deallocates resources that were
401 previously allocated for all the PCI
402 root bridges and resets the I/O and
403 memory apertures to their initial
404 state. The bus settings are not
405 affected. If the request to allocate
406 resources fails, the PCI enumerator
407 can use this notification to
408 deallocate previous resources, adjust
409 the requests, and retry allocation.
410
411 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is
412 completed. No specific action is
413 required here. This notification can
414 be used to perform any chipsetspecific
415 programming.
416
417 @param[in] This The instance pointer of
418 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
419
420 @param[in] Phase The phase during enumeration
421
422 @retval EFI_NOT_READY This phase cannot be entered at this time. For
423 example, this error is valid for a Phase of
424 EfiPciHostBridgeAllocateResources if
425 SubmitResources() has not been called for one
426 or more PCI root bridges before this call
427
428 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
429 This error is valid for a Phase of
430 EfiPciHostBridgeSetResources.
431
432 @retval EFI_INVALID_PARAMETER Invalid phase parameter
433
434 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
435 lack of resources. This error is valid for a
436 Phase of EfiPciHostBridgeAllocateResources if
437 the previously submitted resource requests
438 cannot be fulfilled or were only partially
439 fulfilled.
440
441 @retval EFI_SUCCESS The notification was accepted without any
442 errors.
443 **/
444 EFI_STATUS
445 EFIAPI
446 NotifyPhase(
447 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
448 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
449 )
450 {
451 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
452 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
453 PCI_RESOURCE_TYPE Index;
454 LIST_ENTRY *List;
455 EFI_PHYSICAL_ADDRESS BaseAddress;
456 UINT64 AddrLen;
457 UINTN BitsOfAlignment;
458 EFI_STATUS Status;
459 EFI_STATUS ReturnStatus;
460
461 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
462
463 switch (Phase) {
464
465 case EfiPciHostBridgeBeginEnumeration:
466 if (HostBridgeInstance->CanRestarted) {
467 //
468 // Reset the Each Root Bridge
469 //
470 List = HostBridgeInstance->Head.ForwardLink;
471
472 while (List != &HostBridgeInstance->Head) {
473 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
474 for (Index = TypeIo; Index < TypeMax; Index++) {
475 RootBridgeInstance->ResAllocNode[Index].Type = Index;
476 RootBridgeInstance->ResAllocNode[Index].Base = 0;
477 RootBridgeInstance->ResAllocNode[Index].Length = 0;
478 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
479 }
480
481 List = List->ForwardLink;
482 }
483
484 HostBridgeInstance->ResourceSubmited = FALSE;
485 HostBridgeInstance->CanRestarted = TRUE;
486 } else {
487 //
488 // Can not restart
489 //
490 return EFI_NOT_READY;
491 }
492 break;
493
494 case EfiPciHostBridgeEndEnumeration:
495 break;
496
497 case EfiPciHostBridgeBeginBusAllocation:
498 //
499 // No specific action is required here, can perform any chipset specific
500 // programing
501 //
502 HostBridgeInstance->CanRestarted = FALSE;
503 break;
504
505 case EfiPciHostBridgeEndBusAllocation:
506 //
507 // No specific action is required here, can perform any chipset specific
508 // programing
509 //
510 //HostBridgeInstance->CanRestarted = FALSE;
511 break;
512
513 case EfiPciHostBridgeBeginResourceAllocation:
514 //
515 // No specific action is required here, can perform any chipset specific
516 // programing
517 //
518 //HostBridgeInstance->CanRestarted = FALSE;
519 break;
520
521 case EfiPciHostBridgeAllocateResources:
522 ReturnStatus = EFI_SUCCESS;
523 if (HostBridgeInstance->ResourceSubmited) {
524 //
525 // Take care of the resource dependencies between the root bridges
526 //
527 List = HostBridgeInstance->Head.ForwardLink;
528
529 while (List != &HostBridgeInstance->Head) {
530 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
531 for (Index = TypeIo; Index < TypeBus; Index++) {
532 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
533
534 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
535
536 //
537 // Get the number of '1' in Alignment.
538 //
539 BitsOfAlignment =
540 (UINTN)(HighBitSet64 (
541 RootBridgeInstance->ResAllocNode[Index].Alignment
542 ) + 1);
543
544 switch (Index) {
545
546 case TypeIo:
547 //
548 // It is impossible for this chipset to align 0xFFFF for IO16
549 // So clear it
550 //
551 if (BitsOfAlignment >= 16) {
552 BitsOfAlignment = 0;
553 }
554
555 Status = gDS->AllocateIoSpace (
556 EfiGcdAllocateAnySearchBottomUp,
557 EfiGcdIoTypeIo,
558 BitsOfAlignment,
559 AddrLen,
560 &BaseAddress,
561 mDriverImageHandle,
562 NULL
563 );
564
565 if (!EFI_ERROR (Status)) {
566 RootBridgeInstance->ResAllocNode[Index].Base =
567 (UINTN)BaseAddress;
568 RootBridgeInstance->ResAllocNode[Index].Status =
569 ResAllocated;
570 } else {
571 ReturnStatus = Status;
572 if (Status != EFI_OUT_OF_RESOURCES) {
573 RootBridgeInstance->ResAllocNode[Index].Length = 0;
574 }
575 }
576
577 break;
578
579
580 case TypeMem32:
581 //
582 // It is impossible for this chipset to align 0xFFFFFFFF for
583 // Mem32
584 // So clear it
585 //
586
587 if (BitsOfAlignment >= 32) {
588 BitsOfAlignment = 0;
589 }
590
591 Status = gDS->AllocateMemorySpace (
592 EfiGcdAllocateAnySearchBottomUp,
593 EfiGcdMemoryTypeMemoryMappedIo,
594 BitsOfAlignment,
595 AddrLen,
596 &BaseAddress,
597 mDriverImageHandle,
598 NULL
599 );
600
601 if (!EFI_ERROR (Status)) {
602 // We were able to allocate the PCI memory
603 RootBridgeInstance->ResAllocNode[Index].Base =
604 (UINTN)BaseAddress;
605 RootBridgeInstance->ResAllocNode[Index].Status =
606 ResAllocated;
607
608 } else {
609 // Not able to allocate enough PCI memory
610 ReturnStatus = Status;
611
612 if (Status != EFI_OUT_OF_RESOURCES) {
613 RootBridgeInstance->ResAllocNode[Index].Length = 0;
614 }
615 ASSERT (FALSE);
616 }
617 break;
618
619 case TypePMem32:
620 case TypeMem64:
621 case TypePMem64:
622 ReturnStatus = EFI_ABORTED;
623 break;
624 default:
625 ASSERT (FALSE);
626 break;
627 }; //end switch
628 }
629 }
630
631 List = List->ForwardLink;
632 }
633
634 return ReturnStatus;
635
636 } else {
637 return EFI_NOT_READY;
638 }
639 break;
640
641 case EfiPciHostBridgeSetResources:
642 break;
643
644 case EfiPciHostBridgeFreeResources:
645 ReturnStatus = EFI_SUCCESS;
646 List = HostBridgeInstance->Head.ForwardLink;
647 while (List != &HostBridgeInstance->Head) {
648 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
649 for (Index = TypeIo; Index < TypeBus; Index++) {
650 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
651 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
652 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
653 switch (Index) {
654
655 case TypeIo:
656 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
657 if (EFI_ERROR (Status)) {
658 ReturnStatus = Status;
659 }
660 break;
661
662 case TypeMem32:
663 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
664 if (EFI_ERROR (Status)) {
665 ReturnStatus = Status;
666 }
667 break;
668
669 case TypePMem32:
670 break;
671
672 case TypeMem64:
673 break;
674
675 case TypePMem64:
676 break;
677
678 default:
679 ASSERT (FALSE);
680 break;
681
682 }; //end switch
683 RootBridgeInstance->ResAllocNode[Index].Type = Index;
684 RootBridgeInstance->ResAllocNode[Index].Base = 0;
685 RootBridgeInstance->ResAllocNode[Index].Length = 0;
686 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
687 }
688 }
689
690 List = List->ForwardLink;
691 }
692
693 HostBridgeInstance->ResourceSubmited = FALSE;
694 HostBridgeInstance->CanRestarted = TRUE;
695 return ReturnStatus;
696
697 case EfiPciHostBridgeEndResourceAllocation:
698 HostBridgeInstance->CanRestarted = FALSE;
699 break;
700
701 default:
702 return EFI_INVALID_PARAMETER;
703 }
704
705 return EFI_SUCCESS;
706 }
707
708 /**
709 Return the device handle of the next PCI root bridge that is associated with
710 this Host Bridge.
711
712 This function is called multiple times to retrieve the device handles of all
713 the PCI root bridges that are associated with this PCI host bridge. Each PCI
714 host bridge is associated with one or more PCI root bridges. On each call,
715 the handle that was returned by the previous call is passed into the
716 interface, and on output the interface returns the device handle of the next
717 PCI root bridge. The caller can use the handle to obtain the instance of the
718 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
719 PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
720 enumerator must enumerate the PCI root bridges in the order that they are
721 returned by this function.
722
723 For D945 implementation, there is only one root bridge in PCI host bridge.
724
725 @param[in] This The instance pointer of
726 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
727
728 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI
729 root bridge.
730
731 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then
732 return the first Rootbridge handle of the
733 specific Host bridge and return EFI_SUCCESS.
734
735 @retval EFI_NOT_FOUND Can not find the any more root bridge in
736 specific host bridge.
737
738 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
739 returned on a previous call to
740 GetNextRootBridge().
741 **/
742 EFI_STATUS
743 EFIAPI
744 GetNextRootBridge(
745 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
746 IN OUT EFI_HANDLE *RootBridgeHandle
747 )
748 {
749 BOOLEAN NoRootBridge;
750 LIST_ENTRY *List;
751 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
752 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
753
754 NoRootBridge = TRUE;
755 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
756 List = HostBridgeInstance->Head.ForwardLink;
757
758
759 while (List != &HostBridgeInstance->Head) {
760 NoRootBridge = FALSE;
761 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
762 if (*RootBridgeHandle == NULL) {
763 //
764 // Return the first Root Bridge Handle of the Host Bridge
765 //
766 *RootBridgeHandle = RootBridgeInstance->Handle;
767 return EFI_SUCCESS;
768 } else {
769 if (*RootBridgeHandle == RootBridgeInstance->Handle) {
770 //
771 // Get next if have
772 //
773 List = List->ForwardLink;
774 if (List!=&HostBridgeInstance->Head) {
775 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
776 *RootBridgeHandle = RootBridgeInstance->Handle;
777 return EFI_SUCCESS;
778 } else {
779 return EFI_NOT_FOUND;
780 }
781 }
782 }
783
784 List = List->ForwardLink;
785 } //end while
786
787 if (NoRootBridge) {
788 return EFI_NOT_FOUND;
789 } else {
790 return EFI_INVALID_PARAMETER;
791 }
792 }
793
794 /**
795 Returns the allocation attributes of a PCI root bridge.
796
797 The function returns the allocation attributes of a specific PCI root bridge.
798 The attributes can vary from one PCI root bridge to another. These attributes
799 are different from the decode-related attributes that are returned by the
800 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
801 RootBridgeHandle parameter is used to specify the instance of the PCI root
802 bridge. The device handles of all the root bridges that are associated with
803 this host bridge must be obtained by calling GetNextRootBridge(). The
804 attributes are static in the sense that they do not change during or after
805 the enumeration process. The hardware may provide mechanisms to change the
806 attributes on the fly, but such changes must be completed before
807 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
808 values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
809 "Related Definitions" below. The caller uses these attributes to combine
810 multiple resource requests.
811
812 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
813 bus enumerator needs to include requests for the prefetchable memory in the
814 nonprefetchable memory pool and not request any prefetchable memory.
815
816 Attribute Description
817 ------------------------------------ ---------------------------------------
818 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root
819 bridge does not support separate
820 windows for nonprefetchable and
821 prefetchable memory. A PCI bus driver
822 needs to include requests for
823 prefetchable memory in the
824 nonprefetchable memory pool.
825
826 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root
827 bridge supports 64-bit memory windows.
828 If this bit is not set, the PCI bus
829 driver needs to include requests for a
830 64-bit memory address in the
831 corresponding 32-bit memory pool.
832
833 @param[in] This The instance pointer of
834 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
835
836 @param[in] RootBridgeHandle The device handle of the PCI root bridge in
837 which the caller is interested. Type
838 EFI_HANDLE is defined in
839 InstallProtocolInterface() in the UEFI 2.0
840 Specification.
841
842 @param[out] Attributes The pointer to attribte of root bridge, it is
843 output parameter
844
845 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
846
847 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
848
849 @retval EFI_SUCCESS Success to get attribute of interested root
850 bridge.
851 **/
852 EFI_STATUS
853 EFIAPI
854 GetAttributes(
855 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
856 IN EFI_HANDLE RootBridgeHandle,
857 OUT UINT64 *Attributes
858 )
859 {
860 LIST_ENTRY *List;
861 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
862 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
863
864 if (Attributes == NULL) {
865 return EFI_INVALID_PARAMETER;
866 }
867
868 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
869 List = HostBridgeInstance->Head.ForwardLink;
870
871 while (List != &HostBridgeInstance->Head) {
872 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
873 if (RootBridgeHandle == RootBridgeInstance->Handle) {
874 *Attributes = RootBridgeInstance->RootBridgeAttrib;
875 return EFI_SUCCESS;
876 }
877 List = List->ForwardLink;
878 }
879
880 //
881 // RootBridgeHandle is not an EFI_HANDLE
882 // that was returned on a previous call to GetNextRootBridge()
883 //
884 return EFI_INVALID_PARAMETER;
885 }
886
887 /**
888 Sets up the specified PCI root bridge for the bus enumeration process.
889
890 This member function sets up the root bridge for bus enumeration and returns
891 the PCI bus range over which the search should be performed in ACPI 2.0
892 resource descriptor format.
893
894 @param[in] This The
895 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
896 instance.
897
898 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
899
900 @param[out] Configuration Pointer to the pointer to the PCI bus resource
901 descriptor.
902
903 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
904
905 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
906
907 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
908 **/
909 EFI_STATUS
910 EFIAPI
911 StartBusEnumeration(
912 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
913 IN EFI_HANDLE RootBridgeHandle,
914 OUT VOID **Configuration
915 )
916 {
917 LIST_ENTRY *List;
918 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
919 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
920 VOID *Buffer;
921 UINT8 *Temp;
922 UINT64 BusStart;
923 UINT64 BusEnd;
924
925 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
926 List = HostBridgeInstance->Head.ForwardLink;
927
928 while (List != &HostBridgeInstance->Head) {
929 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
930 if (RootBridgeHandle == RootBridgeInstance->Handle) {
931 //
932 // Set up the Root Bridge for Bus Enumeration
933 //
934 BusStart = RootBridgeInstance->BusBase;
935 BusEnd = RootBridgeInstance->BusLimit;
936 //
937 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
938 //
939
940 Buffer = AllocatePool (
941 sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
942 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
943 );
944 if (Buffer == NULL) {
945 return EFI_OUT_OF_RESOURCES;
946 }
947
948 Temp = (UINT8 *)Buffer;
949
950 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
951 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
952 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
953 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
954 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
955 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
956 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
957 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
958 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
959 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
960 BusEnd - BusStart + 1;
961
962 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
963 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
964 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
965
966 *Configuration = Buffer;
967 return EFI_SUCCESS;
968 }
969 List = List->ForwardLink;
970 }
971
972 return EFI_INVALID_PARAMETER;
973 }
974
975 /**
976 Programs the PCI root bridge hardware so that it decodes the specified PCI
977 bus range.
978
979 This member function programs the specified PCI root bridge to decode the bus
980 range that is specified by the input parameter Configuration.
981 The bus range information is specified in terms of the ACPI 2.0 resource
982 descriptor format.
983
984 @param[in] This The
985 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
986 instance
987
988 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be
989 programmed
990
991 @param[in] Configuration The pointer to the PCI bus resource descriptor
992
993 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
994 handle.
995
996 @retval EFI_INVALID_PARAMETER Configuration is NULL.
997
998 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
999 2.0 resource descriptor.
1000
1001 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI
1002 2.0 bus resource descriptor.
1003
1004 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource
1005 descriptors other than bus descriptors.
1006
1007 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid
1008 ACPI resource descriptors.
1009
1010 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this
1011 root bridge.
1012
1013 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this
1014 root bridge.
1015
1016 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1017
1018 @retval EFI_SUCCESS The bus range for the PCI root bridge was
1019 programmed.
1020 **/
1021 EFI_STATUS
1022 EFIAPI
1023 SetBusNumbers(
1024 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1025 IN EFI_HANDLE RootBridgeHandle,
1026 IN VOID *Configuration
1027 )
1028 {
1029 LIST_ENTRY *List;
1030 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1031 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1032 UINT8 *Ptr;
1033 UINTN BusStart;
1034 UINTN BusEnd;
1035 UINTN BusLen;
1036
1037 if (Configuration == NULL) {
1038 return EFI_INVALID_PARAMETER;
1039 }
1040
1041 Ptr = Configuration;
1042
1043 //
1044 // Check the Configuration is valid
1045 //
1046 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1050 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
1051 return EFI_INVALID_PARAMETER;
1052 }
1053
1054 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1055 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058
1059 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1060 List = HostBridgeInstance->Head.ForwardLink;
1061
1062 Ptr = Configuration;
1063
1064 while (List != &HostBridgeInstance->Head) {
1065 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1066 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1067 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
1068
1069 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
1070 BusStart = (UINTN)Desc->AddrRangeMin;
1071 BusLen = (UINTN)Desc->AddrLen;
1072 BusEnd = BusStart + BusLen - 1;
1073
1074 if (BusStart > BusEnd) {
1075 return EFI_INVALID_PARAMETER;
1076 }
1077
1078 if ((BusStart < RootBridgeInstance->BusBase) ||
1079 (BusEnd > RootBridgeInstance->BusLimit)) {
1080 return EFI_INVALID_PARAMETER;
1081 }
1082
1083 //
1084 // Update the Bus Range
1085 //
1086 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
1087 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
1088 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
1089
1090 //
1091 // Program the Root Bridge Hardware
1092 //
1093
1094 return EFI_SUCCESS;
1095 }
1096
1097 List = List->ForwardLink;
1098 }
1099
1100 return EFI_INVALID_PARAMETER;
1101 }
1102
1103
1104 /**
1105 Submits the I/O and memory resource requirements for the specified PCI root
1106 bridge.
1107
1108 This function is used to submit all the I/O and memory resources that are
1109 required by the specified PCI root bridge. The input parameter Configuration
1110 is used to specify the following:
1111 - The various types of resources that are required
1112 - The associated lengths in terms of ACPI 2.0 resource descriptor format
1113
1114 @param[in] This Pointer to the
1115 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1116 instance.
1117
1118 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory
1119 resource requirements are being submitted.
1120
1121 @param[in] Configuration The pointer to the PCI I/O and PCI memory
1122 resource descriptor.
1123
1124 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI
1125 root bridge were accepted.
1126
1127 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1128 handle.
1129
1130 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1131
1132 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI
1133 2.0 resource descriptor.
1134
1135 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or
1136 more resource types that are not supported by
1137 this PCI root bridge. This error will happen
1138 if the caller did not combine resources
1139 according to Attributes that were returned by
1140 GetAllocAttributes().
1141
1142 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
1143
1144 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI
1145 root bridge.
1146
1147 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for
1148 this PCI root bridge.
1149 **/
1150 EFI_STATUS
1151 EFIAPI
1152 SubmitResources(
1153 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1154 IN EFI_HANDLE RootBridgeHandle,
1155 IN VOID *Configuration
1156 )
1157 {
1158 LIST_ENTRY *List;
1159 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1160 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1161 UINT8 *Temp;
1162 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1163 UINT64 AddrLen;
1164 UINT64 Alignment;
1165
1166 //
1167 // Check the input parameter: Configuration
1168 //
1169 if (Configuration == NULL) {
1170 return EFI_INVALID_PARAMETER;
1171 }
1172
1173 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1174 List = HostBridgeInstance->Head.ForwardLink;
1175
1176 Temp = (UINT8 *)Configuration;
1177 while ( *Temp == 0x8A) {
1178 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1179 }
1180 if (*Temp != 0x79) {
1181 return EFI_INVALID_PARAMETER;
1182 }
1183
1184 Temp = (UINT8 *)Configuration;
1185 while (List != &HostBridgeInstance->Head) {
1186 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1187 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1188 while ( *Temp == 0x8A) {
1189 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1190
1191 //
1192 // Check Address Length
1193 //
1194 if (Ptr->AddrLen > 0xffffffff) {
1195 return EFI_INVALID_PARAMETER;
1196 }
1197
1198 //
1199 // Check address range alignment
1200 //
1201 if (Ptr->AddrRangeMax >= 0xffffffff ||
1202 Ptr->AddrRangeMax != (GetPowerOfTwo64 (
1203 Ptr->AddrRangeMax + 1) - 1)) {
1204 return EFI_INVALID_PARAMETER;
1205 }
1206
1207 switch (Ptr->ResType) {
1208
1209 case 0:
1210
1211 //
1212 // Check invalid Address Sapce Granularity
1213 //
1214 if (Ptr->AddrSpaceGranularity != 32) {
1215 return EFI_INVALID_PARAMETER;
1216 }
1217
1218 //
1219 // check the memory resource request is supported by PCI root bridge
1220 //
1221 if (RootBridgeInstance->RootBridgeAttrib ==
1222 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
1223 Ptr->SpecificFlag == 0x06) {
1224 return EFI_INVALID_PARAMETER;
1225 }
1226
1227 AddrLen = Ptr->AddrLen;
1228 Alignment = Ptr->AddrRangeMax;
1229 if (Ptr->AddrSpaceGranularity == 32) {
1230 if (Ptr->SpecificFlag == 0x06) {
1231 //
1232 // Apply from GCD
1233 //
1234 RootBridgeInstance->ResAllocNode[TypePMem32].Status =
1235 ResSubmitted;
1236 } else {
1237 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
1238 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
1239 Alignment;
1240 RootBridgeInstance->ResAllocNode[TypeMem32].Status =
1241 ResRequested;
1242 HostBridgeInstance->ResourceSubmited = TRUE;
1243 }
1244 }
1245
1246 if (Ptr->AddrSpaceGranularity == 64) {
1247 if (Ptr->SpecificFlag == 0x06) {
1248 RootBridgeInstance->ResAllocNode[TypePMem64].Status =
1249 ResSubmitted;
1250 } else {
1251 RootBridgeInstance->ResAllocNode[TypeMem64].Status =
1252 ResSubmitted;
1253 }
1254 }
1255 break;
1256
1257 case 1:
1258 AddrLen = (UINTN) Ptr->AddrLen;
1259 Alignment = (UINTN) Ptr->AddrRangeMax;
1260 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
1261 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
1262 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
1263 HostBridgeInstance->ResourceSubmited = TRUE;
1264 break;
1265
1266 default:
1267 break;
1268 };
1269
1270 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1271 }
1272
1273 return EFI_SUCCESS;
1274 }
1275
1276 List = List->ForwardLink;
1277 }
1278
1279 return EFI_INVALID_PARAMETER;
1280 }
1281
1282 /**
1283 Returns the proposed resource settings for the specified PCI root bridge.
1284
1285 This member function returns the proposed resource settings for the
1286 specified PCI root bridge. The proposed resource settings are prepared when
1287 NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
1288 The output parameter Configuration specifies the following:
1289 - The various types of resources, excluding bus resources, that are
1290 allocated
1291 - The associated lengths in terms of ACPI 2.0 resource descriptor format
1292
1293 @param[in] This Pointer to the
1294 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1295 instance.
1296
1297 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is
1298 defined in InstallProtocolInterface() in the
1299 UEFI 2.0 Specification.
1300
1301 @param[out] Configuration The pointer to the pointer to the PCI I/O and
1302 memory resource descriptor.
1303
1304 @retval EFI_SUCCESS The requested parameters were returned.
1305
1306 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1307 handle.
1308
1309 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1310
1311 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
1312 lack of resources.
1313 **/
1314 EFI_STATUS
1315 EFIAPI
1316 GetProposedResources(
1317 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1318 IN EFI_HANDLE RootBridgeHandle,
1319 OUT VOID **Configuration
1320 )
1321 {
1322 LIST_ENTRY *List;
1323 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1324 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1325 UINTN Index;
1326 UINTN Number;
1327 VOID *Buffer;
1328 UINT8 *Temp;
1329 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1330 UINT64 ResStatus;
1331
1332 Buffer = NULL;
1333 Number = 0;
1334 //
1335 // Get the Host Bridge Instance from the resource allocation protocol
1336 //
1337 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1338 List = HostBridgeInstance->Head.ForwardLink;
1339
1340 //
1341 // Enumerate the root bridges in this host bridge
1342 //
1343 while (List != &HostBridgeInstance->Head) {
1344 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1345 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1346 for (Index = 0; Index < TypeBus; Index ++) {
1347 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1348 Number ++;
1349 }
1350 }
1351
1352 if (Number == 0) {
1353 return EFI_INVALID_PARAMETER;
1354 }
1355
1356 Buffer = AllocateZeroPool (
1357 Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
1358 sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
1359 );
1360 if (Buffer == NULL) {
1361 return EFI_OUT_OF_RESOURCES;
1362 }
1363
1364 Temp = Buffer;
1365 for (Index = 0; Index < TypeBus; Index ++) {
1366 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1367 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1368 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
1369
1370 switch (Index) {
1371
1372 case TypeIo:
1373 //
1374 // Io
1375 //
1376 Ptr->Desc = 0x8A;
1377 Ptr->Len = 0x2B;
1378 Ptr->ResType = 1;
1379 Ptr->GenFlag = 0;
1380 Ptr->SpecificFlag = 0;
1381 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1382 Ptr->AddrRangeMax = 0;
1383 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1384 EFI_RESOURCE_SATISFIED :
1385 EFI_RESOURCE_LESS;
1386 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1387 break;
1388
1389 case TypeMem32:
1390 //
1391 // Memory 32
1392 //
1393 Ptr->Desc = 0x8A;
1394 Ptr->Len = 0x2B;
1395 Ptr->ResType = 0;
1396 Ptr->GenFlag = 0;
1397 Ptr->SpecificFlag = 0;
1398 Ptr->AddrSpaceGranularity = 32;
1399 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1400 Ptr->AddrRangeMax = 0;
1401 Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1402 EFI_RESOURCE_SATISFIED :
1403 EFI_RESOURCE_LESS;
1404 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1405 break;
1406
1407 case TypePMem32:
1408 //
1409 // Prefetch memory 32
1410 //
1411 Ptr->Desc = 0x8A;
1412 Ptr->Len = 0x2B;
1413 Ptr->ResType = 0;
1414 Ptr->GenFlag = 0;
1415 Ptr->SpecificFlag = 6;
1416 Ptr->AddrSpaceGranularity = 32;
1417 Ptr->AddrRangeMin = 0;
1418 Ptr->AddrRangeMax = 0;
1419 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1420 Ptr->AddrLen = 0;
1421 break;
1422
1423 case TypeMem64:
1424 //
1425 // Memory 64
1426 //
1427 Ptr->Desc = 0x8A;
1428 Ptr->Len = 0x2B;
1429 Ptr->ResType = 0;
1430 Ptr->GenFlag = 0;
1431 Ptr->SpecificFlag = 0;
1432 Ptr->AddrSpaceGranularity = 64;
1433 Ptr->AddrRangeMin = 0;
1434 Ptr->AddrRangeMax = 0;
1435 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1436 Ptr->AddrLen = 0;
1437 break;
1438
1439 case TypePMem64:
1440 //
1441 // Prefetch memory 64
1442 //
1443 Ptr->Desc = 0x8A;
1444 Ptr->Len = 0x2B;
1445 Ptr->ResType = 0;
1446 Ptr->GenFlag = 0;
1447 Ptr->SpecificFlag = 6;
1448 Ptr->AddrSpaceGranularity = 64;
1449 Ptr->AddrRangeMin = 0;
1450 Ptr->AddrRangeMax = 0;
1451 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1452 Ptr->AddrLen = 0;
1453 break;
1454 };
1455
1456 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1457 }
1458 }
1459
1460 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
1461 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
1462
1463 *Configuration = Buffer;
1464
1465 return EFI_SUCCESS;
1466 }
1467
1468 List = List->ForwardLink;
1469 }
1470
1471 return EFI_INVALID_PARAMETER;
1472 }
1473
1474 /**
1475 Provides the hooks from the PCI bus driver to every PCI controller
1476 (device/function) at various stages of the PCI enumeration process that allow
1477 the host bridge driver to preinitialize individual PCI controllers before
1478 enumeration.
1479
1480 This function is called during the PCI enumeration process. No specific
1481 action is expected from this member function. It allows the host bridge
1482 driver to preinitialize individual PCI controllers before enumeration.
1483
1484 @param This Pointer to the
1485 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1486 instance.
1487
1488 @param RootBridgeHandle The associated PCI root bridge handle. Type
1489 EFI_HANDLE is defined in InstallProtocolInterface()
1490 in the UEFI 2.0 Specification.
1491
1492 @param PciAddress The address of the PCI device on the PCI bus. This
1493 address can be passed to the
1494 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
1495 access the PCI configuration space of the device.
1496 See Table 12-1 in the UEFI 2.0 Specification for the
1497 definition of
1498 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1499
1500 @param Phase The phase of the PCI device enumeration.
1501
1502 @retval EFI_SUCCESS The requested parameters were returned.
1503
1504 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge
1505 handle.
1506
1507 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined
1508 in
1509 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1510
1511 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
1512 The PCI enumerator should not enumerate this
1513 device, including its child devices if it is
1514 a PCI-to-PCI bridge.
1515 **/
1516 EFI_STATUS
1517 EFIAPI
1518 PreprocessController (
1519 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1520 IN EFI_HANDLE RootBridgeHandle,
1521 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1522 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1523 )
1524 {
1525 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1526 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1527 LIST_ENTRY *List;
1528
1529 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1530 List = HostBridgeInstance->Head.ForwardLink;
1531
1532 //
1533 // Enumerate the root bridges in this host bridge
1534 //
1535 while (List != &HostBridgeInstance->Head) {
1536 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1537 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1538 break;
1539 }
1540 List = List->ForwardLink;
1541 }
1542 if (List == &HostBridgeInstance->Head) {
1543 return EFI_INVALID_PARAMETER;
1544 }
1545
1546 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
1547 return EFI_INVALID_PARAMETER;
1548 }
1549
1550 return EFI_SUCCESS;
1551 }