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