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