1 /** @file
2 * Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex
3 *
4 * Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
5 *
6 * This program and the accompanying materials
7 * are licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
10 *
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15
16 #include "PciHostBridge.h"
17
18 EFI_STATUS
PciHbRaNotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)19 PciHbRaNotifyPhase (
20 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
21 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
22 )
23 {
24 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
25 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
26 EFI_STATUS Status;
27 EFI_PHYSICAL_ADDRESS BaseAddress;
28 UINT64 AddrLen;
29 UINTN BitsOfAlignment;
30
31 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
32
33 PCI_TRACE ("PciHbRaNotifyPhase()");
34
35 // Check RootBridge Signature
36 ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
37
38 // The enumeration cannot be restarted after the process has been further than the first phase
39 if (Phase == EfiPciHostBridgeBeginEnumeration) {
40 if (!HostBridgeInstance->CanRestarted) {
41 return EFI_NOT_READY;
42 }
43 } else {
44 HostBridgeInstance->CanRestarted = FALSE;
45 }
46
47 switch (Phase) {
48 case EfiPciHostBridgeBeginEnumeration:
49 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)");
50 // Resets the host bridge PCI apertures and internal data structures
51 Status = HWPciRbInit (HostBridgeInstance->CpuIo);
52 if (EFI_ERROR (Status)) {
53 return Status;
54 }
55 break;
56
57 case EfiPciHostBridgeBeginBusAllocation:
58 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)");
59 // The bus allocation phase is about to begin
60 break;
61
62 case EfiPciHostBridgeEndBusAllocation:
63 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)");
64 // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
65 // a bus number range into their configuration
66 break;
67
68 case EfiPciHostBridgeBeginResourceAllocation:
69 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)");
70 // The resource allocation phase is about to begin.
71 break;
72
73 case EfiPciHostBridgeAllocateResources:
74 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)");
75 // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
76 // PciHbRaSubmitResources() before.
77
78 RootBridgeInstance = HostBridgeInstance->RootBridge;
79 if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
80 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1; // Get the number of '1' in Alignment
81 AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
82
83 Status = gDS->AllocateIoSpace (
84 EfiGcdAllocateAnySearchBottomUp,
85 EfiGcdIoTypeIo,
86 BitsOfAlignment,
87 AddrLen,
88 &BaseAddress,
89 HostBridgeInstance->ImageHandle,
90 NULL
91 );
92 // If error then ResAlloc[n].Base ==0
93 if (!EFI_ERROR (Status)) {
94 RootBridgeInstance->ResAlloc[ResTypeIo].Base = (UINTN)BaseAddress;
95 }
96 }
97
98 if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
99 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1; // Get the number of '1' in Alignment
100 AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
101
102 // Top of the 32bit PCI Memory space
103 BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
104
105 Status = gDS->AllocateMemorySpace (
106 EfiGcdAllocateMaxAddressSearchTopDown,
107 EfiGcdMemoryTypeMemoryMappedIo,
108 BitsOfAlignment,
109 AddrLen,
110 &BaseAddress,
111 HostBridgeInstance->ImageHandle,
112 NULL
113 );
114
115 // Ensure the allocation is in the 32bit PCI memory space
116 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
117 RootBridgeInstance->ResAlloc[ResTypeMem32].Base = (UINTN)BaseAddress;
118 }
119 }
120 if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
121 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1; // Get the number of '1' in Alignment
122 AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
123
124 // Top of the 32bit PCI Memory space
125 BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
126
127 Status = gDS->AllocateMemorySpace (
128 EfiGcdAllocateMaxAddressSearchTopDown,
129 EfiGcdMemoryTypeMemoryMappedIo,
130 BitsOfAlignment,
131 AddrLen,
132 &BaseAddress,
133 HostBridgeInstance->ImageHandle,
134 NULL
135 );
136
137 // Ensure the allocation is in the 32bit PCI memory space
138 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
139 RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress;
140 }
141 }
142 if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
143 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1; // Get the number of '1' in Alignment
144 AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
145
146 // Top of the 64bit PCI Memory space
147 BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
148
149 Status = gDS->AllocateMemorySpace (
150 EfiGcdAllocateMaxAddressSearchTopDown,
151 EfiGcdMemoryTypeMemoryMappedIo,
152 BitsOfAlignment,
153 AddrLen,
154 &BaseAddress,
155 HostBridgeInstance->ImageHandle,
156 NULL
157 );
158
159 // Ensure the allocation is in the 64bit PCI memory space
160 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
161 RootBridgeInstance->ResAlloc[ResTypeMem64].Base = (UINTN)BaseAddress;
162 }
163 }
164 if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
165 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1; //Get the number of '1' in Alignment
166 AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
167
168 // Top of the 64bit PCI Memory space
169 BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
170
171 Status = gDS->AllocateMemorySpace (
172 EfiGcdAllocateMaxAddressSearchTopDown,
173 EfiGcdMemoryTypeMemoryMappedIo,
174 BitsOfAlignment,
175 AddrLen,
176 &BaseAddress,
177 HostBridgeInstance->ImageHandle,
178 NULL
179 );
180
181 // Ensure the allocation is in the 64bit PCI memory space
182 if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
183 RootBridgeInstance->ResAlloc[ResTypePMem64].Base = (UINTN)BaseAddress;
184 }
185 }
186
187 break;
188
189 case EfiPciHostBridgeSetResources:
190 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)");
191 // Programs the host bridge hardware to decode previously allocated resources (proposed resources)
192 // for all the PCI root bridges. The PCI bus driver will now program the resources
193 break;
194
195 case EfiPciHostBridgeFreeResources:
196 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)");
197 // Deallocates resources that were previously allocated for all the PCI root bridges and resets the
198 // I/O and memory apertures to their initial state.*/
199 break;
200
201 case EfiPciHostBridgeEndResourceAllocation:
202 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)");
203 break;
204
205 case EfiPciHostBridgeEndEnumeration:
206 PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)");
207 break;
208
209 default:
210 DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase));
211 ASSERT (0);
212 }
213
214 return EFI_SUCCESS;
215 }
216
217 /**
218 * PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge.
219 * As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge
220 * if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND
221 **/
222 EFI_STATUS
PciHbRaGetNextRootBridge(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN OUT EFI_HANDLE * RootBridgeHandle)223 PciHbRaGetNextRootBridge (
224 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
225 IN OUT EFI_HANDLE *RootBridgeHandle
226 )
227 {
228 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
229
230 PCI_TRACE ("PciHbRaGetNextRootBridge()");
231
232 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
233 ASSERT (HostBridgeInstance->RootBridge != NULL);
234
235 //Check RootBridge Signature
236 ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
237
238 if (*RootBridgeHandle == NULL) {
239 *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
240 return EFI_SUCCESS;
241 } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
242 return EFI_NOT_FOUND;
243 } else {
244 return EFI_INVALID_PARAMETER;
245 }
246 }
247
248 /** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge.
249 * A PCI Root bridge could support these types :
250 * - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory.
251 * - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
252 **/
253 EFI_STATUS
PciHbRaGetAllocAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT UINT64 * Attributes)254 PciHbRaGetAllocAttributes (
255 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
256 IN EFI_HANDLE RootBridgeHandle,
257 OUT UINT64 *Attributes
258 )
259 {
260 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
261
262 PCI_TRACE ("PciHbRaGetAllocAttributes()");
263
264 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
265
266 // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
267 ASSERT (HostBridgeInstance->RootBridge != NULL);
268 if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 *Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes;
273 return EFI_SUCCESS;
274 }
275
276 EFI_STATUS
PciHbRaStartBusEnumeration(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)277 PciHbRaStartBusEnumeration (
278 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
279 IN EFI_HANDLE RootBridgeHandle,
280 OUT VOID **Configuration
281 )
282 {
283 VOID *Buffer;
284 UINT8 *Ptr;
285 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
286
287 // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
288 // to set bus numbers to PCI-to-PCI bridge.
289 PCI_TRACE ("PciHbRaStartBusEnumeration()");
290
291 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
292
293 Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
294 if (Buffer == NULL) {
295 return EFI_OUT_OF_RESOURCES;
296 }
297
298 Ptr = (UINT8 *)Buffer;
299
300 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; // QWORD Address space Descriptor
301 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len = 0x2B; // Length of this descriptor in bytes not including the first two fields
302 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; // Resource Type Bus Number Range
303 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
304 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
305 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
306 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart; // Bus Start
307 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0; // Bus Max
308 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
309 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
310
311 Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
312 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
313 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
314
315 *Configuration = Buffer;
316 return EFI_SUCCESS;
317 }
318
319 EFI_STATUS
PciHbRaSetBusNumbers(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)320 PciHbRaSetBusNumbers (
321 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
322 IN EFI_HANDLE RootBridgeHandle,
323 IN VOID *Configuration
324 )
325 {
326 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
327 UINT8 *Ptr;
328 UINTN BusStart;
329 UINTN BusEnd;
330 UINTN BusLen;
331
332 PCI_TRACE ("PciHbRaSetBusNumbers()");
333
334 Ptr = Configuration;
335 if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
336 return EFI_INVALID_PARAMETER;
337 }
338
339 // Check if the passed ACPI descriptor table define a Bus Number Range
340 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
341 return EFI_INVALID_PARAMETER;
342 }
343
344 // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
345 if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
346 return EFI_INVALID_PARAMETER;
347 }
348
349 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
350 ASSERT (HostBridgeInstance->RootBridge != NULL);
351 if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
352 return EFI_INVALID_PARAMETER;
353 }
354
355 BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
356 BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
357 BusEnd = BusStart + BusLen - 1;
358
359 ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
360 ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
361
362 HostBridgeInstance->RootBridge->BusStart = BusStart;
363 HostBridgeInstance->RootBridge->BusLength = BusLen;
364
365 return EFI_SUCCESS;
366 }
367
368 /**
369 * This function is used to submit all the I/O and memory resources that are required by the specified
370 * PCI root bridge.
371 **/
372 EFI_STATUS
PciHbRaSubmitResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)373 PciHbRaSubmitResources (
374 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
375 IN EFI_HANDLE RootBridgeHandle,
376 IN VOID *Configuration
377 )
378 {
379 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
380 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
381 UINT8 *Ptr;
382 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
383 PCI_RESOURCE_TYPE ResType;
384
385 PCI_TRACE ("PciHbRaSubmitResources()");
386
387 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
388
389 if (Configuration == NULL) {
390 return EFI_INVALID_PARAMETER;
391 }
392
393 // Check if the ACPI Descriptor tables is conformed
394 Ptr = (UINT8 *)Configuration;
395 while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
396 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
397 }
398 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
399 return EFI_INVALID_PARAMETER;
400 }
401
402 // Check the RootBridgeHandle
403 RootBridgeInstance = HostBridgeInstance->RootBridge;
404 ASSERT (RootBridgeInstance != NULL);
405 if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
406 return EFI_INVALID_PARAMETER;
407 }
408
409 Ptr = (UINT8 *)Configuration;
410 while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
411 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
412
413 // Check if the description is valid
414 if (Desc->AddrLen > 0xffffffff) {
415 return EFI_INVALID_PARAMETER;
416 }
417
418 if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 switch (Desc->ResType) {
423 case ACPI_ADDRESS_SPACE_TYPE_MEM:
424 // Check invalid Address Space Granularity
425 if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
426 return EFI_INVALID_PARAMETER;
427 }
428
429 // check the memory resource request is supported by PCI root bridge
430 if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
431 return EFI_INVALID_PARAMETER;
432 }
433
434 if (Desc->AddrSpaceGranularity == 32) {
435 if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
436 ResType = ResTypePMem32;
437 } else {
438 ResType = ResTypeMem32;
439 }
440 } else {
441 if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
442 ResType = ResTypePMem64;
443 } else {
444 ResType = ResTypeMem64;
445 }
446 }
447 RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
448 RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
449 RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
450 break;
451 case ACPI_ADDRESS_SPACE_TYPE_IO:
452 RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
453 RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
454 RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
455 break;
456 default:
457 ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
458 break;
459 }
460 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
461 }
462
463 return EFI_SUCCESS;
464 }
465
466 /** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by
467 * PciHbRaSubmitResources() before
468 **/
469 EFI_STATUS
PciHbRaGetProposedResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)470 PciHbRaGetProposedResources (
471 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
472 IN EFI_HANDLE RootBridgeHandle,
473 OUT VOID **Configuration
474 )
475 {
476 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
477 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
478 UINT32 i;
479 UINT32 ResAllocCount;
480 VOID *Buffer;
481 UINT8 *Ptr;
482 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
483
484 PCI_TRACE ("PciHbRaGetProposedResources()");
485
486 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
487
488 // Check the RootBridgeHandle
489 RootBridgeInstance = HostBridgeInstance->RootBridge;
490 ASSERT (RootBridgeInstance != NULL);
491 if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
492 return EFI_INVALID_PARAMETER;
493 }
494
495 // Count the number of Resource Allocated for this Root Bridge
496 ResAllocCount = 0;
497 for (i = 0; i < ResTypeMax; i++) {
498 if (RootBridgeInstance->ResAlloc[i].Length != 0) ResAllocCount++;
499 }
500
501 if (ResAllocCount == 0) {
502 return EFI_INVALID_PARAMETER;
503 }
504
505 Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
506 if (Buffer == NULL) {
507 return EFI_OUT_OF_RESOURCES;
508 }
509
510 Ptr = Buffer;
511 for (i = 0; i < ResTypeMax; i++) {
512 if (RootBridgeInstance->ResAlloc[i].Length != 0) { // Base != 0 if the resource has been allocated
513 Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
514
515 Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
516 Desc->Len = 0x2B;
517 Desc->GenFlag = 0;
518 Desc->AddrRangeMax = 0;
519
520 switch (i) {
521 case ResTypeIo:
522 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
523 Desc->SpecificFlag = 0;
524 Desc->AddrSpaceGranularity = 0;
525 break;
526 case ResTypeMem32:
527 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
528 Desc->SpecificFlag = 0;
529 Desc->AddrSpaceGranularity = 32;
530 break;
531 case ResTypePMem32:
532 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
533 Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
534 Desc->AddrSpaceGranularity = 32;
535 break;
536 case ResTypeMem64:
537 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
538 Desc->SpecificFlag = 0;
539 Desc->AddrSpaceGranularity = 64;
540 break;
541 case ResTypePMem64:
542 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
543 Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
544 Desc->AddrSpaceGranularity = 64;
545 break;
546 }
547 Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
548 Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
549 Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
550 Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
551 }
552 }
553
554 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
555 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
556
557 *Configuration = Buffer;
558 return EFI_SUCCESS;
559 }
560
561 EFI_STATUS
PciHbRaPreprocessController(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)562 PciHbRaPreprocessController (
563 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
564 IN EFI_HANDLE RootBridgeHandle,
565 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
566 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
567 )
568 {
569 PCI_HOST_BRIDGE_INSTANCE* HostBridge;
570 PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
571 UINT32 CapabilityPtr;
572 UINT32 CapabilityEntry;
573 UINT16 CapabilityID;
574 UINT32 DeviceCapability;
575
576 PCI_TRACE ("PciHbRaPreprocessController()");
577
578 if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
579 // Do Max payload fixup for every devices
580 if (Phase == EfiPciBeforeResourceCollection) {
581 // Get RootBridge Instance from Host Bridge Instance
582 HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
583 RootBridge = HostBridge->RootBridge;
584
585 // Get the first PCI Capability
586 CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
587 RootBridge->Io.Pci.Read (
588 &RootBridge->Io,
589 EfiPciWidthUint8,
590 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
591 1,
592 &CapabilityPtr
593 );
594 CapabilityPtr &= 0x1FF;
595
596 // Get Pci Express Capability
597 while (CapabilityPtr != 0) {
598 RootBridge->Io.Pci.Read (
599 &RootBridge->Io,
600 EfiPciWidthUint16,
601 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
602 1,
603 &CapabilityEntry
604 );
605
606 CapabilityID = (UINT8)CapabilityEntry;
607
608 // Is PCIe capability ?
609 if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
610 // Get PCIe Device Capabilities
611 RootBridge->Io.Pci.Read (
612 &RootBridge->Io,
613 EfiPciWidthUint32,
614 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
615 1,
616 &DeviceCapability
617 );
618
619 // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
620 DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
621 // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
622 DeviceCapability &= ~ ((UINT32)(0x7 << 12));
623 // Enable all error reporting
624 DeviceCapability |= 0xF;
625
626 RootBridge->Io.Pci.Write (
627 &RootBridge->Io,
628 EfiPciWidthUint32,
629 EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
630 1,
631 &DeviceCapability
632 );
633
634 return EFI_SUCCESS;
635 }
636 CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
637 }
638 }
639 }
640
641 return EFI_SUCCESS;
642 }
643