]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Pci/Dxe/PciHostBridge/PciHostBridge.c
ArmPkg/CompilerIntrinsicsLib: Add uread, uwrite GCC assembly sources
[mirror_edk2.git] / QuarkPlatformPkg / Pci / Dxe / PciHostBridge / PciHostBridge.c
1 /** @file
2 Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system.
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9
10 **/
11
12 #include "PciHostBridge.h"
13 #include <IntelQNCRegs.h>
14
15 //
16 // We can hardcode the following for a Simple IIO -
17 // Root Bridge Count within the host bridge
18 // Root Bridge's device path
19 // Root Bridge's resource appeture
20 //
21 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = {
22 {
23 {
24 {
25 ACPI_DEVICE_PATH,
26 ACPI_DP,
27 {
28 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
29 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
30 }
31 },
32 EISA_PNP_ID (0x0A03),
33 0
34 },
35 {
36 END_DEVICE_PATH_TYPE,
37 END_ENTIRE_DEVICE_PATH_SUBTYPE,
38 {
39 END_DEVICE_PATH_LENGTH,
40 0
41 }
42 }
43 }
44 };
45
46 EFI_HANDLE mDriverImageHandle;
47 PCI_ROOT_BRIDGE_RESOURCE_APERTURE *mResAperture;
48
49 //
50 // Implementation
51 //
52 EFI_STATUS
53 EFIAPI
54 InitializePciHostBridge (
55 IN EFI_HANDLE ImageHandle,
56 IN EFI_SYSTEM_TABLE *SystemTable
57 )
58 /*++
59
60 Routine Description:
61
62 Entry point of this driver.
63
64 Arguments:
65
66 ImageHandle - Image handle of this driver.
67 SystemTable - Pointer to standard EFI system table.
68
69 Returns:
70
71 EFI_SUCCESS - Succeed.
72 EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol.
73
74 --*/
75 {
76 EFI_STATUS Status;
77 UINTN TotalRootBridgeFound;
78 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
79 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
80 UINT64 AllocAttributes;
81 EFI_PHYSICAL_ADDRESS BaseAddress;
82
83 PrivateData = NULL;
84
85 mDriverImageHandle = ImageHandle;
86
87 //
88 // Most systems in the world including complex servers
89 // have only one Host Bridge. Create Host Bridge Device Handle
90 //
91 Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge);
92 ASSERT_EFI_ERROR (Status);
93 ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE));
94
95 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
96 HostBridge->RootBridgeCount = 1;
97 HostBridge->ResourceSubmited = FALSE;
98 HostBridge->CanRestarted = TRUE;
99 //
100 // InitializeListHead (&HostBridge->Head);
101 //
102 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
103 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
104 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
105 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
106 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
107 HostBridge->ResAlloc.SubmitResources = SubmitResources;
108 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
109 HostBridge->ResAlloc.PreprocessController = PreprocessController;
110
111 Status = gBS->InstallProtocolInterface (
112 &HostBridge->HostBridgeHandle,
113 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
114 EFI_NATIVE_INTERFACE,
115 &HostBridge->ResAlloc
116 );
117 if (EFI_ERROR (Status)) {
118 gBS->FreePool (HostBridge);
119 return EFI_DEVICE_ERROR;
120 }
121
122 Status = gBS->AllocatePool (EfiBootServicesData,
123 HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE),
124 (VOID **) &mResAperture);
125 ASSERT_EFI_ERROR (Status);
126 ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE));
127
128 DEBUG ((EFI_D_INFO, "Address of resource Aperture: %x\n", mResAperture));
129
130 //
131 // Create Root Bridge Device Handle in this Host Bridge
132 //
133 InitializeListHead (&HostBridge->Head);
134
135 TotalRootBridgeFound = 0;
136
137 Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData);
138 ASSERT_EFI_ERROR (Status);
139 ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE));
140
141 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
142 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound];
143 AllocAttributes = GetAllocAttributes (TotalRootBridgeFound);
144
145 SimpleIioRootBridgeConstructor (
146 &PrivateData->Io,
147 HostBridge->HostBridgeHandle,
148 &(mResAperture[TotalRootBridgeFound]),
149 AllocAttributes
150 );
151 //
152 // Update Root Bridge with UDS resource information
153 //
154 PrivateData->Aperture.BusBase = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE;
155 PrivateData->Aperture.BusLimit = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT;
156 PrivateData->Aperture.Mem32Base = PcdGet32 (PcdPciHostBridgeMemory32Base);
157 PrivateData->Aperture.Mem32Limit = PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1);
158 PrivateData->Aperture.IoBase = PcdGet16 (PcdPciHostBridgeIoBase);
159 PrivateData->Aperture.IoLimit = PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1);
160
161 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusBase: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE));
162 DEBUG ((EFI_D_INFO, "PCI Host Bridge BusLimit: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT));
163 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Base: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base)));
164 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Limit: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1)));
165 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Base: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base)));
166 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Limit: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base) + (PcdGet64 (PcdPciHostBridgeMemory64Size) - 1)));
167 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoBase: %x\n", PcdGet16 (PcdPciHostBridgeIoBase)));
168 DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoLimit: %x\n", PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1)));
169
170 PrivateData->Handle = NULL;
171 Status = gBS->InstallMultipleProtocolInterfaces (
172 &PrivateData->Handle,
173 &gEfiDevicePathProtocolGuid,
174 PrivateData->DevicePath,
175 &gEfiPciRootBridgeIoProtocolGuid,
176 &PrivateData->Io,
177 NULL
178 );
179 ASSERT_EFI_ERROR (Status);
180
181 InsertTailList (&HostBridge->Head, &PrivateData->Link);
182 TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found
183
184 //
185 // Add PCIE base into Runtime memory so that it can be reported in E820 table
186 //
187 Status = gDS->AddMemorySpace (
188 EfiGcdMemoryTypeMemoryMappedIo,
189 PcdGet64 (PcdPciExpressBaseAddress),
190 PcdGet64 (PcdPciExpressSize),
191 EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
192 );
193 ASSERT_EFI_ERROR(Status);
194
195 BaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
196
197 Status = gDS->AllocateMemorySpace (
198 EfiGcdAllocateAddress,
199 EfiGcdMemoryTypeMemoryMappedIo,
200 0,
201 PcdGet64 (PcdPciExpressSize),
202 &BaseAddress,
203 ImageHandle,
204 NULL
205 );
206 ASSERT_EFI_ERROR(Status);
207
208 Status = gDS->SetMemorySpaceAttributes (
209 PcdGet64 (PcdPciExpressBaseAddress),
210 PcdGet64 (PcdPciExpressSize),
211 EFI_MEMORY_RUNTIME
212 );
213 ASSERT_EFI_ERROR (Status);
214
215 if (PcdGet16 (PcdPciHostBridgeIoSize) > 0) {
216 //
217 // At present, we use up the first 4k for fixed ranges like
218 // ICH GPIO, ACPI and ISA devices. The first 4k is not
219 // tracked through GCD. It should be.
220 //
221 Status = gDS->AddIoSpace (
222 EfiGcdIoTypeIo,
223 PcdGet16(PcdPciHostBridgeIoBase),
224 PcdGet16(PcdPciHostBridgeIoSize)
225 );
226 ASSERT_EFI_ERROR (Status);
227 }
228
229 if (PcdGet32(PcdPciHostBridgeMemory32Size) > 0) {
230 //
231 // Shouldn't the capabilities be UC?
232 //
233 Status = gDS->AddMemorySpace (
234 EfiGcdMemoryTypeMemoryMappedIo,
235 PcdGet32(PcdPciHostBridgeMemory32Base),
236 PcdGet32(PcdPciHostBridgeMemory32Size),
237 0
238 );
239 ASSERT_EFI_ERROR (Status);
240 }
241
242 return Status;
243 }
244
245 EFI_STATUS
246 EFIAPI
247 NotifyPhase (
248 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
249 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
250 )
251 /*++
252
253 Routine Description:
254
255 Enter a certain phase of the PCI enumeration process.
256
257 Arguments:
258
259 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
260 Phase - The phase during enumeration.
261
262 Returns:
263
264 EFI_SUCCESS - Succeed.
265 EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
266 EFI_NOT_READY - Resources have not been submitted yet.
267
268 --*/
269 {
270 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
271 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
272 PCI_RESOURCE_TYPE Index;
273 EFI_LIST_ENTRY *List;
274 EFI_PHYSICAL_ADDRESS BaseAddress;
275 UINT64 AddrLen;
276 UINTN BitsOfAlignment;
277 UINT64 Alignment;
278 EFI_STATUS Status;
279 EFI_STATUS ReturnStatus;
280 PCI_RESOURCE_TYPE Index1;
281 PCI_RESOURCE_TYPE Index2;
282 BOOLEAN ResNodeHandled[TypeMax];
283 UINT64 MaxAlignment;
284
285 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
286
287 switch (Phase) {
288 case EfiPciHostBridgeBeginEnumeration:
289 if (HostBridgeInstance->CanRestarted) {
290 //
291 // Reset Root Bridge
292 //
293 List = HostBridgeInstance->Head.ForwardLink;
294
295 while (List != &HostBridgeInstance->Head) {
296 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
297 for (Index = TypeIo; Index < TypeMax; Index++) {
298 RootBridgeInstance->ResAllocNode[Index].Type = Index;
299 RootBridgeInstance->ResAllocNode[Index].Base = 0;
300 RootBridgeInstance->ResAllocNode[Index].Length = 0;
301 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
302 } // for
303
304 List = List->ForwardLink;
305 } // while
306
307 HostBridgeInstance->ResourceSubmited = FALSE;
308 HostBridgeInstance->CanRestarted = TRUE;
309 } else {
310 //
311 // Can not restart
312 //
313 return EFI_NOT_READY;
314 } // if
315 break;
316
317 case EfiPciHostBridgeEndEnumeration:
318 return EFI_SUCCESS;
319 break;
320
321 case EfiPciHostBridgeBeginBusAllocation:
322 //
323 // No specific action is required here, can perform any chipset specific programing
324 //
325 HostBridgeInstance->CanRestarted = FALSE;
326 return EFI_SUCCESS;
327 break;
328
329 case EfiPciHostBridgeEndBusAllocation:
330 //
331 // No specific action is required here, can perform any chipset specific programing
332 //
333 // HostBridgeInstance->CanRestarted = FALSE;
334 //
335 return EFI_SUCCESS;
336 break;
337
338 case EfiPciHostBridgeBeginResourceAllocation:
339 //
340 // No specific action is required here, can perform any chipset specific programing
341 //
342 // HostBridgeInstance->CanRestarted = FALSE;
343 //
344 return EFI_SUCCESS;
345 break;
346
347 case EfiPciHostBridgeAllocateResources:
348 ReturnStatus = EFI_SUCCESS;
349 if (HostBridgeInstance->ResourceSubmited) {
350 List = HostBridgeInstance->Head.ForwardLink;
351 while (List != &HostBridgeInstance->Head) {
352 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
353 ResNodeHandled[Index1] = FALSE;
354 }
355
356 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
357 DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance: %x)\n", RootBridgeInstance));
358 DEBUG ((EFI_D_INFO, " Signature: %x\n", RootBridgeInstance->Signature));
359 DEBUG ((EFI_D_INFO, " Bus Number Assigned: %x\n", RootBridgeInstance->BusNumberAssigned));
360 DEBUG ((EFI_D_INFO, " Bus Scan Count: %x\n", RootBridgeInstance->BusScanCount));
361
362 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
363 if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) {
364 ResNodeHandled[Index1] = TRUE;
365 } else {
366 //
367 // Allocate the resource node with max alignment at first
368 //
369 MaxAlignment = 0;
370 Index = TypeMax;
371 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
372 if (ResNodeHandled[Index2]) {
373 continue;
374 }
375 if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) {
376 MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment;
377 Index = Index2;
378 }
379 } // for
380
381 if (Index < TypeMax) {
382 ResNodeHandled[Index] = TRUE;
383 } else {
384 ASSERT (FALSE);
385 }
386
387 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
388
389 //
390 // Get the number of '1' in Alignment.
391 //
392 for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
393 Alignment = RShiftU64 (Alignment, 1);
394 }
395
396 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
397 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
398
399 DEBUG ((EFI_D_INFO, "\n\nResource Type to assign : %x\n", Index));
400 DEBUG ((EFI_D_INFO, " Length to allocate: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
401 DEBUG ((EFI_D_INFO, " Aligment: %x\n", Alignment));
402
403 switch (Index) {
404 case TypeIo:
405 if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) {
406 //
407 // It is impossible for 0xFFFF Alignment for IO16
408 //
409 if (BitsOfAlignment >= 16)
410 Alignment = 0;
411
412 BaseAddress = RootBridgeInstance->Aperture.IoBase;
413
414 //
415 // Have to make sure Aligment is handled seeing we are doing direct address allocation
416 //
417 if ((BaseAddress & ~(Alignment)) != BaseAddress)
418 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
419
420 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) {
421
422 Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment,
423 AddrLen, &BaseAddress, mDriverImageHandle, NULL );
424
425 if (!EFI_ERROR (Status)) {
426 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
427 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
428 goto TypeIoFound;
429 }
430
431 BaseAddress += (Alignment + 1);
432 } // while
433
434 } // if
435
436 TypeIoFound:
437 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
438 //
439 // No Room at the Inn for this resources request
440 //
441 ReturnStatus = EFI_OUT_OF_RESOURCES;
442 } // if
443
444 break;
445
446 case TypeMem32:
447 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
448
449 BaseAddress = RootBridgeInstance->Aperture.Mem32Base;
450 //
451 // Have to make sure Aligment is handled seeing we are doing direct address allocation
452 //
453 if ((BaseAddress & ~(Alignment)) != BaseAddress)
454 BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
455
456 while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) {
457
458 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
459 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
460
461 if (!EFI_ERROR (Status)) {
462 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
463 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
464 goto TypeMem32Found;
465 } // if
466
467 BaseAddress += (Alignment + 1);
468 } // while
469 } // if
470
471 TypeMem32Found:
472 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
473 //
474 // No Room at the Inn for this resources request
475 //
476 ReturnStatus = EFI_OUT_OF_RESOURCES;
477 }
478
479 break;
480
481 case TypePMem32:
482 StartTypePMem32:
483 if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
484
485 BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1;
486 BaseAddress -= AddrLen;
487
488 //
489 // Have to make sure Aligment is handled seeing we are doing direct address allocation
490 //
491 if ((BaseAddress & ~(Alignment)) != BaseAddress)
492 BaseAddress = ((BaseAddress) & ~(Alignment));
493
494 while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) {
495
496 DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%lx .....", Index, BaseAddress));
497 Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
498 BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
499
500 if (!EFI_ERROR (Status)) {
501 RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress;
502 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
503 DEBUG ((EFI_D_INFO, "... Passed!!\n"));
504 goto TypePMem32Found;
505 }
506 DEBUG ((EFI_D_INFO, "... Failed!!\n"));
507 BaseAddress -= (Alignment + 1);
508 } // while
509 } // if
510
511 TypePMem32Found:
512 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
513 //
514 // No Room at the Inn for this resources request
515 //
516 ReturnStatus = EFI_OUT_OF_RESOURCES;
517 }
518
519 break;
520
521 case TypeMem64:
522 case TypePMem64:
523 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
524 //
525 // If 64-bit resourcing is not available, then try as PMem32
526 //
527 goto StartTypePMem32;
528 }
529
530 break;
531
532 default:
533 break;
534 } // End switch (Index)
535
536 DEBUG ((EFI_D_INFO, "Resource Type Assigned: %x\n", Index));
537 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
538 DEBUG ((EFI_D_INFO, " Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base));
539 DEBUG ((EFI_D_INFO, " Length Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
540 } else {
541 DEBUG ((DEBUG_ERROR, " Resource Allocation failed! There was no room at the inn\n"));
542 }
543
544 }
545 }
546
547 List = List->ForwardLink;
548 }
549
550 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
551 DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n"));
552 }
553
554 //
555 // Set resource to zero for nodes where allocation fails
556 //
557 List = HostBridgeInstance->Head.ForwardLink;
558 while (List != &HostBridgeInstance->Head) {
559 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
560 for (Index = TypeIo; Index < TypeBus; Index++) {
561 if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
562 RootBridgeInstance->ResAllocNode[Index].Length = 0;
563 }
564 }
565 List = List->ForwardLink;
566 }
567 return ReturnStatus;
568 } else {
569 return EFI_NOT_READY;
570 }
571 //
572 // HostBridgeInstance->CanRestarted = FALSE;
573 //
574 break;
575
576 case EfiPciHostBridgeSetResources:
577 //
578 // HostBridgeInstance->CanRestarted = FALSE;
579 //
580 break;
581
582 case EfiPciHostBridgeFreeResources:
583 //
584 // HostBridgeInstance->CanRestarted = FALSE;
585 //
586 ReturnStatus = EFI_SUCCESS;
587 List = HostBridgeInstance->Head.ForwardLink;
588 while (List != &HostBridgeInstance->Head) {
589 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
590 for (Index = TypeIo; Index < TypeBus; Index++) {
591 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
592 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
593 BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridgeInstance->ResAllocNode[Index].Base;
594 switch (Index) {
595 case TypeIo:
596 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
597 if (EFI_ERROR (Status)) {
598 ReturnStatus = Status;
599 }
600 break;
601
602 case TypeMem32:
603 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
604 if (EFI_ERROR (Status)) {
605 ReturnStatus = Status;
606 }
607 break;
608
609 case TypePMem32:
610 break;
611
612 case TypeMem64:
613 break;
614
615 case TypePMem64:
616 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
617 if (EFI_ERROR (Status)) {
618 ReturnStatus = Status;
619 }
620 break;
621
622 default:
623 break;
624 } // end switch (Index)
625
626 RootBridgeInstance->ResAllocNode[Index].Type = Index;
627 RootBridgeInstance->ResAllocNode[Index].Base = 0;
628 RootBridgeInstance->ResAllocNode[Index].Length = 0;
629 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
630 }
631 }
632
633 List = List->ForwardLink;
634 }
635
636 HostBridgeInstance->ResourceSubmited = FALSE;
637 HostBridgeInstance->CanRestarted = TRUE;
638 return ReturnStatus;
639 break;
640
641 case EfiPciHostBridgeEndResourceAllocation:
642 //
643 // Resource enumeration is done. Perform any activities that
644 // must wait until that time.
645 //
646 break;
647
648 default:
649 return EFI_INVALID_PARAMETER;
650 } // End switch (Phase)
651
652 return EFI_SUCCESS;
653 }
654
655 EFI_STATUS
656 EFIAPI
657 GetNextRootBridge (
658 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
659 IN OUT EFI_HANDLE *RootBridgeHandle
660 )
661 /*++
662
663 Routine Description:
664 Return the device handle of the next PCI root bridge that is associated with
665 this Host Bridge.
666
667 Arguments:
668
669 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
670 RootBridgeHandle - Returns the device handle of the next PCI Root Bridge.
671 On input, it holds the RootBridgeHandle returned by the most
672 recent call to GetNextRootBridge().The handle for the first
673 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
674
675 Returns:
676
677 EFI_SUCCESS - Succeed.
678 EFI_NOT_FOUND - Next PCI root bridge not found.
679 EFI_INVALID_PARAMETER - Wrong parameter passed in.
680
681 --*/
682 {
683 BOOLEAN NoRootBridge;
684 EFI_LIST_ENTRY *List;
685 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
686 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
687
688 NoRootBridge = TRUE;
689 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
690 List = HostBridgeInstance->Head.ForwardLink;
691
692 while (List != &HostBridgeInstance->Head) {
693 NoRootBridge = FALSE;
694 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
695 if (*RootBridgeHandle == NULL) {
696 //
697 // Return the first Root Bridge Handle of the Host Bridge
698 //
699 *RootBridgeHandle = RootBridgeInstance->Handle;
700 return EFI_SUCCESS;
701 } else {
702 if (*RootBridgeHandle == RootBridgeInstance->Handle) {
703 //
704 // Get next if have
705 //
706 List = List->ForwardLink;
707 if (List != &HostBridgeInstance->Head) {
708 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
709 *RootBridgeHandle = RootBridgeInstance->Handle;
710 return EFI_SUCCESS;
711 } else {
712 return EFI_NOT_FOUND;
713 }
714 }
715 }
716
717 List = List->ForwardLink;
718 //
719 // end while
720 //
721 }
722
723 if (NoRootBridge) {
724 return EFI_NOT_FOUND;
725 } else {
726 return EFI_INVALID_PARAMETER;
727 }
728 }
729
730 EFI_STATUS
731 EFIAPI
732 GetAttributes (
733 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
734 IN EFI_HANDLE RootBridgeHandle,
735 OUT UINT64 *Attributes
736 )
737 /*++
738
739 Routine Description:
740 Returns the attributes of a PCI Root Bridge.
741
742 Arguments:
743
744 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
745 RootBridgeHandle - The device handle of the PCI Root Bridge
746 that the caller is interested in.
747 Attributes - The pointer to attributes of the PCI Root Bridge.
748
749 Returns:
750
751 EFI_SUCCESS - Succeed.
752 EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or
753 RootBridgeHandle is not an EFI_HANDLE
754 that was returned on a previous call to
755 GetNextRootBridge().
756
757 --*/
758 {
759 EFI_LIST_ENTRY *List;
760 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
761 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
762
763 if (Attributes == NULL) {
764 return EFI_INVALID_PARAMETER;
765 }
766
767 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
768 List = HostBridgeInstance->Head.ForwardLink;
769
770 while (List != &HostBridgeInstance->Head) {
771 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
772 if (RootBridgeHandle == RootBridgeInstance->Handle) {
773 *Attributes = RootBridgeInstance->RootBridgeAllocAttrib;
774 return EFI_SUCCESS;
775 }
776
777 List = List->ForwardLink;
778 }
779 //
780 // RootBridgeHandle is not an EFI_HANDLE
781 // that was returned on a previous call to GetNextRootBridge()
782 //
783 return EFI_INVALID_PARAMETER;
784 }
785
786 EFI_STATUS
787 EFIAPI
788 StartBusEnumeration (
789 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
790 IN EFI_HANDLE RootBridgeHandle,
791 OUT VOID **Configuration
792 )
793 /*++
794
795 Routine Description:
796 This is the request from the PCI enumerator to set up
797 the specified PCI Root Bridge for bus enumeration process.
798
799 Arguments:
800
801 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
802 RootBridgeHandle - The PCI Root Bridge to be set up.
803 Configuration - Pointer to the pointer to the PCI bus resource descriptor.
804
805 Returns:
806
807 EFI_SUCCESS - Succeed.
808 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
809 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
810
811 --*/
812 {
813 EFI_LIST_ENTRY *List;
814 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
815 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
816 VOID *Buffer;
817 UINT8 *Temp;
818 EFI_STATUS Status;
819 UINTN BusStart;
820 UINTN BusEnd;
821 UINT64 BusReserve;
822
823 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
824 List = HostBridgeInstance->Head.ForwardLink;
825
826 while (List != &HostBridgeInstance->Head) {
827 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
828 if (RootBridgeHandle == RootBridgeInstance->Handle) {
829 //
830 // Set up the Root Bridge for Bus Enumeration
831 //
832 BusStart = RootBridgeInstance->Aperture.BusBase;
833 BusEnd = RootBridgeInstance->Aperture.BusLimit;
834 BusReserve = RootBridgeInstance->Aperture.BusReserve;
835 //
836 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
837 //
838 Status = gBS->AllocatePool (
839 EfiBootServicesData,
840 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
841 &Buffer
842 );
843 if (EFI_ERROR (Status)) {
844 return EFI_OUT_OF_RESOURCES;
845 }
846
847 Temp = (UINT8 *) Buffer;
848
849 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
850 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B;
851 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
852 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag = 0;
853 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag = 0;
854 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity = 0;
855 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin = BusStart;
856 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax = BusReserve;
857 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;
858 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen = BusEnd - BusStart + 1;
859
860 Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
861 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;
862 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
863
864 *Configuration = Buffer;
865 return EFI_SUCCESS;
866 }
867
868 List = List->ForwardLink;
869 }
870
871 return EFI_INVALID_PARAMETER;
872 }
873
874 EFI_STATUS
875 EFIAPI
876 SetBusNumbers (
877 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
878 IN EFI_HANDLE RootBridgeHandle,
879 IN VOID *Configuration
880 )
881 /*++
882
883 Routine Description:
884 This function programs the PCI Root Bridge hardware so that
885 it decodes the specified PCI bus range.
886
887 Arguments:
888
889 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
890 RootBridgeHandle - The PCI Root Bridge whose bus range is to be programmed.
891 Configuration - The pointer to the PCI bus resource descriptor.
892
893 Returns:
894
895 EFI_SUCCESS - Succeed.
896 EFI_INVALID_PARAMETER - Wrong parameters passed in.
897
898 --*/
899 {
900 EFI_LIST_ENTRY *List;
901 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
902 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
903 UINT8 *Ptr;
904 UINTN BusStart;
905 UINTN BusEnd;
906 UINTN BusLen;
907
908 if (Configuration == NULL) {
909 return EFI_INVALID_PARAMETER;
910 }
911
912 Ptr = Configuration;
913
914 //
915 // Check the Configuration is valid
916 //
917 if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
918 return EFI_INVALID_PARAMETER;
919 }
920
921 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
922 return EFI_INVALID_PARAMETER;
923 }
924
925 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
926 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
927 return EFI_INVALID_PARAMETER;
928 }
929
930 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
931 List = HostBridgeInstance->Head.ForwardLink;
932
933 Ptr = Configuration;
934
935 while (List != &HostBridgeInstance->Head) {
936 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
937 if (RootBridgeHandle == RootBridgeInstance->Handle) {
938 BusStart = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;
939 BusLen = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;
940 BusEnd = BusStart + BusLen - 1;
941
942 if (BusStart > BusEnd) {
943 return EFI_INVALID_PARAMETER;
944 }
945
946 if ((BusStart < RootBridgeInstance->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) {
947 return EFI_INVALID_PARAMETER;
948 }
949 //
950 // Update the Bus Range
951 //
952 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
953 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
954 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
955 RootBridgeInstance->BusScanCount++;
956 if (RootBridgeInstance->BusScanCount > 0) {
957 //
958 // Only care about the 2nd PCI bus scanning
959 //
960 RootBridgeInstance->BusNumberAssigned = TRUE;
961 }
962
963 return EFI_SUCCESS;
964 }
965
966 List = List->ForwardLink;
967 }
968
969 return EFI_INVALID_PARAMETER;
970 }
971
972 EFI_STATUS
973 EFIAPI
974 SubmitResources (
975 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
976 IN EFI_HANDLE RootBridgeHandle,
977 IN VOID *Configuration
978 )
979 /*++
980
981 Routine Description:
982
983 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
984
985 Arguments:
986 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
987 RootBridgeHandle - The PCI Root Bridge whose I/O and memory resource requirements.
988 are being submitted.
989 Configuration - The pointer to the PCI I/O and PCI memory resource descriptor.
990
991 Returns:
992
993 EFI_SUCCESS - Succeed.
994 EFI_INVALID_PARAMETER - Wrong parameters passed in.
995
996 --*/
997 {
998 EFI_LIST_ENTRY *List;
999 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1000 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1001 UINT8 *Temp;
1002 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
1003 UINT64 AddrLen;
1004 UINT64 Alignment;
1005 UINT64 Value;
1006
1007 //
1008 // Check the input parameter: Configuration
1009 //
1010 if (Configuration == NULL) {
1011 return EFI_INVALID_PARAMETER;
1012 }
1013
1014 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1015 List = HostBridgeInstance->Head.ForwardLink;
1016
1017 Temp = (UINT8 *) Configuration;
1018 while (List != &HostBridgeInstance->Head) {
1019 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1020 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1021 //
1022 // Check the resource descriptors.
1023 // If the Configuration includes one or more invalid resource descriptors, all the resource
1024 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1025 //
1026 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1027 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1028 DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType));
1029 DEBUG ((EFI_D_INFO, " ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax));
1030
1031 switch (ptr->ResType) {
1032 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1033 if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) {
1034 return EFI_INVALID_PARAMETER;
1035 }
1036 if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) {
1037 return EFI_INVALID_PARAMETER;
1038 }
1039 //
1040 // If the PCI root bridge does not support separate windows for nonprefetchable and
1041 // prefetchable memory, then the PCI bus driver needs to include requests for
1042 // prefetchable memory in the nonprefetchable memory pool.
1043 //
1044 if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 &&
1045 ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) {
1046 return EFI_INVALID_PARAMETER;
1047 }
1048 case ACPI_ADDRESS_SPACE_TYPE_IO:
1049 //
1050 // Check aligment, it should be of the form 2^n-1
1051 //
1052 Value = Power2MaxMemory (ptr->AddrRangeMax + 1);
1053 if (Value != (ptr->AddrRangeMax + 1)) {
1054 CpuDeadLoop();
1055 return EFI_INVALID_PARAMETER;
1056 }
1057 break;
1058 case ACPI_ADDRESS_SPACE_TYPE_BUS:
1059 default:
1060 return EFI_INVALID_PARAMETER;
1061 }
1062 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1063 }
1064 if (*Temp != ACPI_END_TAG_DESCRIPTOR) {
1065 return EFI_INVALID_PARAMETER;
1066 }
1067
1068 Temp = (UINT8 *) Configuration;
1069 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1070 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1071
1072 switch (ptr->ResType) {
1073 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1074 AddrLen = (UINT64) ptr->AddrLen;
1075 Alignment = (UINT64) ptr->AddrRangeMax;
1076 if (ptr->AddrSpaceGranularity == 32) {
1077 if (ptr->SpecificFlag == 0x06) {
1078 //
1079 // Apply from GCD
1080 //
1081 RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
1082 } else {
1083 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
1084 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
1085 RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
1086 HostBridgeInstance->ResourceSubmited = TRUE;
1087 }
1088 }
1089
1090 if (ptr->AddrSpaceGranularity == 64) {
1091 if (ptr->SpecificFlag == 0x06) {
1092 RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
1093 } else {
1094 RootBridgeInstance->ResAllocNode[TypeMem64].Length = AddrLen;
1095 RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment;
1096 RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
1097 HostBridgeInstance->ResourceSubmited = TRUE;
1098 }
1099 }
1100 break;
1101
1102 case ACPI_ADDRESS_SPACE_TYPE_IO:
1103 AddrLen = (UINT64) ptr->AddrLen;
1104 Alignment = (UINT64) ptr->AddrRangeMax;
1105 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
1106 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
1107 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
1108 HostBridgeInstance->ResourceSubmited = TRUE;
1109 break;
1110
1111 default:
1112 break;
1113 }
1114
1115 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1116 }
1117
1118 return EFI_SUCCESS;
1119 }
1120
1121 List = List->ForwardLink;
1122 }
1123
1124 return EFI_INVALID_PARAMETER;
1125 }
1126
1127 EFI_STATUS
1128 EFIAPI
1129 GetProposedResources (
1130 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1131 IN EFI_HANDLE RootBridgeHandle,
1132 OUT VOID **Configuration
1133 )
1134 /*++
1135
1136 Routine Description:
1137 This function returns the proposed resource settings for the specified
1138 PCI Root Bridge.
1139
1140 Arguments:
1141
1142 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1143 RootBridgeHandle - The PCI Root Bridge handle.
1144 Configuration - The pointer to the pointer to the PCI I/O
1145 and memory resource descriptor.
1146
1147 Returns:
1148
1149 EFI_SUCCESS - Succeed.
1150 EFI_OUT_OF_RESOURCES - Not enough pool to be allocated.
1151 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
1152
1153 --*/
1154 {
1155 EFI_LIST_ENTRY *List;
1156 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1157 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1158 UINTN Index;
1159 UINTN Number;
1160 VOID *Buffer;
1161 UINT8 *Temp;
1162 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
1163 EFI_STATUS Status;
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 Status = gBS->AllocatePool (
1188 EfiBootServicesData,
1189 Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
1190 &Buffer
1191 );
1192
1193 if (EFI_ERROR (Status)) {
1194 return EFI_OUT_OF_RESOURCES;
1195 }
1196
1197 ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1198 }
1199
1200 ASSERT (Buffer != NULL);
1201 Temp = Buffer;
1202 for (Index = 0; Index < TypeBus; Index++) {
1203 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1204 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1205 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
1206
1207 switch (Index) {
1208
1209 case TypeIo:
1210 //
1211 // Io
1212 //
1213 ptr->Desc = 0x8A;
1214 ptr->Len = 0x2B;
1215 ptr->ResType = 1;
1216 ptr->GenFlag = 0;
1217 ptr->SpecificFlag = 0;
1218 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1219 ptr->AddrRangeMax = 0;
1220 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1221 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1222 break;
1223
1224 case TypeMem32:
1225 //
1226 // Memory 32
1227 //
1228 ptr->Desc = 0x8A;
1229 ptr->Len = 0x2B;
1230 ptr->ResType = 0;
1231 ptr->GenFlag = 0;
1232 ptr->SpecificFlag = 0;
1233 ptr->AddrSpaceGranularity = 32;
1234 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1235 ptr->AddrRangeMax = 0;
1236 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1237 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1238 break;
1239
1240 case TypePMem32:
1241 //
1242 // Prefetch memory 32
1243 //
1244 ptr->Desc = 0x8A;
1245 ptr->Len = 0x2B;
1246 ptr->ResType = 0;
1247 ptr->GenFlag = 0;
1248 ptr->SpecificFlag = 6;
1249 ptr->AddrSpaceGranularity = 32;
1250 ptr->AddrRangeMin = 0;
1251 ptr->AddrRangeMax = 0;
1252 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1253 ptr->AddrLen = 0;
1254 break;
1255
1256 case TypeMem64:
1257 //
1258 // Memory 64
1259 //
1260 ptr->Desc = 0x8A;
1261 ptr->Len = 0x2B;
1262 ptr->ResType = 0;
1263 ptr->GenFlag = 0;
1264 ptr->SpecificFlag = 0;
1265 ptr->AddrSpaceGranularity = 64;
1266 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1267 ptr->AddrRangeMax = 0;
1268 ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1269 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1270 break;
1271
1272 case TypePMem64:
1273 //
1274 // Prefetch memory 64
1275 //
1276 ptr->Desc = 0x8A;
1277 ptr->Len = 0x2B;
1278 ptr->ResType = 0;
1279 ptr->GenFlag = 0;
1280 ptr->SpecificFlag = 6;
1281 ptr->AddrSpaceGranularity = 64;
1282 ptr->AddrRangeMin = 0;
1283 ptr->AddrRangeMax = 0;
1284 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1285 ptr->AddrLen = 0;
1286 break;
1287 }
1288
1289 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1290 }
1291 }
1292
1293 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = 0x79;
1294 ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
1295
1296 *Configuration = Buffer;
1297
1298 return EFI_SUCCESS;
1299 }
1300
1301 List = List->ForwardLink;
1302 }
1303
1304 return EFI_INVALID_PARAMETER;
1305 }
1306
1307 EFI_STATUS
1308 EFIAPI
1309 PreprocessController (
1310 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1311 IN EFI_HANDLE RootBridgeHandle,
1312 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1313 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1314 )
1315 /*++
1316
1317 Routine Description:
1318 This function is called for all the PCI controllers that the PCI
1319 bus driver finds. Can be used to Preprogram the controller.
1320
1321 Arguments:
1322
1323 This - The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1324 RootBridgeHandle - The PCI Root Bridge handle.
1325 PciAddress - Address of the controller on the PCI bus.
1326 Phase - The Phase during resource allocation.
1327
1328 Returns:
1329
1330 EFI_SUCCESS - Succeed.
1331 EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle.
1332
1333 --*/
1334 {
1335 BOOLEAN RootBridgeFound;
1336 EFI_LIST_ENTRY *List;
1337 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1338 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1339
1340 if (RootBridgeHandle == NULL) {
1341 return EFI_INVALID_PARAMETER;
1342 }
1343
1344 RootBridgeFound = FALSE;
1345 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1346 List = HostBridgeInstance->Head.ForwardLink;
1347
1348 while (List != &HostBridgeInstance->Head) {
1349 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1350
1351 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1352 RootBridgeFound = TRUE;
1353 break;
1354 }
1355 //
1356 // Get next if have
1357 //
1358 List = List->ForwardLink;
1359 }
1360
1361 if (RootBridgeFound == FALSE) {
1362 return EFI_INVALID_PARAMETER;
1363 }
1364
1365 return EFI_SUCCESS;
1366 }
1367
1368 UINT64
1369 Power2MaxMemory (
1370 IN UINT64 MemoryLength
1371 )
1372 /*++
1373
1374 Routine Description:
1375
1376 Calculate maximum memory length that can be fit to a mtrr.
1377
1378 Arguments:
1379
1380 MemoryLength - Input memory length.
1381
1382 Returns:
1383
1384 Returned Maximum length.
1385
1386 --*/
1387 {
1388 UINT64 Result;
1389
1390 if (RShiftU64 (MemoryLength, 32)) {
1391 Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);
1392 } else {
1393 Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);
1394 }
1395
1396 return Result;
1397 }