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