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