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