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