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