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