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