]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
Add general Tiano Compress tool path.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciHotPlugSupport.c
CommitLineData
97404058 1/**@ file\r
57076f45 2 This module provide support function for hot plug device.\r
3 \r
3db51098 4Copyright (c) 2006, Intel Corporation \r
5All rights reserved. This program and the accompanying materials \r
6are licensed 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
ead42efc 12\r
3db51098 13**/\r
ead42efc 14\r
ead42efc 15\r
03417d8d 16#include "PciBus.h"\r
ead42efc 17#include "PciHotPlugSupport.h"\r
18\r
19EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;\r
20EFI_HPC_LOCATION *gPciRootHpcPool;\r
21UINTN gPciRootHpcCount;\r
22ROOT_HPC_DATA *gPciRootHpcData;\r
23\r
57076f45 24/**\r
25 Init HPC private data.\r
26 \r
27 @param Event event object\r
28 @param Context HPC private data.\r
29**/\r
ead42efc 30VOID\r
31EFIAPI\r
32PciHPCInitialized (\r
33 IN EFI_EVENT Event,\r
34 IN VOID *Context\r
35 )\r
ead42efc 36{\r
37 ROOT_HPC_DATA *HpcData;\r
38\r
39 HpcData = (ROOT_HPC_DATA *) Context;\r
40 HpcData->Initialized = TRUE;\r
41\r
42}\r
43\r
57076f45 44/**\r
45 Compare two device path\r
46 \r
97404058 47 @param DevicePath1 the first device path want to be compared.\r
48 @param DevicePath2 the first device path want to be compared.\r
57076f45 49 \r
97404058 50 @retval TRUE equal.\r
51 @retval FALSE different.\r
57076f45 52**/\r
ead42efc 53BOOLEAN\r
54EfiCompareDevicePath (\r
55 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
56 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
57 )\r
ead42efc 58{\r
59 UINTN Size1;\r
60 UINTN Size2;\r
61\r
62 Size1 = GetDevicePathSize (DevicePath1);\r
63 Size2 = GetDevicePathSize (DevicePath2);\r
64\r
65 if (Size1 != Size2) {\r
66 return FALSE;\r
67 }\r
68\r
69 if (CompareMem (DevicePath1, DevicePath2, Size1)) {\r
70 return FALSE;\r
71 }\r
72\r
73 return TRUE;\r
74}\r
75\r
57076f45 76/**\r
77 Init hot plug support and root hot plug private data.\r
78 \r
79**/\r
ead42efc 80EFI_STATUS\r
81InitializeHotPlugSupport (\r
82 VOID\r
83 )\r
ead42efc 84{\r
85 EFI_STATUS Status;\r
86 EFI_HPC_LOCATION *HpcList;\r
87 UINTN HpcCount;\r
88\r
89 //\r
90 // Locate the PciHotPlugInit Protocol\r
91 // If it doesn't exist, that means there is no\r
92 // hot plug controller supported on the platform\r
93 // the PCI Bus driver is running on. HotPlug Support\r
94 // is an optional feature, so absence of the protocol\r
95 // won't incur the penalty\r
96 //\r
97 gPciHotPlugInit = NULL;\r
98 gPciRootHpcPool = NULL;\r
99 gPciRootHpcCount = 0;\r
100 gPciRootHpcData = NULL;\r
101\r
102 Status = gBS->LocateProtocol (\r
103 &gEfiPciHotPlugInitProtocolGuid,\r
104 NULL,\r
105 (VOID **) &gPciHotPlugInit\r
106 );\r
107\r
108 if (EFI_ERROR (Status)) {\r
109 return EFI_UNSUPPORTED;\r
110 }\r
111\r
112 Status = gPciHotPlugInit->GetRootHpcList (\r
113 gPciHotPlugInit,\r
114 &HpcCount,\r
115 &HpcList\r
116 );\r
117\r
118 if (!EFI_ERROR (Status)) {\r
119\r
120 gPciRootHpcPool = HpcList;\r
121 gPciRootHpcCount = HpcCount;\r
122 gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);\r
123 if (gPciRootHpcData == NULL) {\r
124 return EFI_OUT_OF_RESOURCES;\r
125 }\r
126 }\r
127\r
128 return EFI_SUCCESS;\r
129}\r
130\r
57076f45 131/**\r
132 Test whether device path is for root pci hot plug bus\r
133 \r
97404058 134 @param HpbdevicePath tested device path.\r
57076f45 135 @param HpIndex Return the index of root hot plug in global array.\r
136 \r
97404058 137 @retval TRUE device path is for root pci hot plug.\r
138 @retval FALSE device path is not for root pci hot plug.\r
57076f45 139**/\r
ead42efc 140BOOLEAN\r
141IsRootPciHotPlugBus (\r
142 IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,\r
143 OUT UINTN *HpIndex\r
144 )\r
ead42efc 145{\r
146 UINTN Index;\r
147\r
148 for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
149\r
150 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {\r
151\r
152 if (HpIndex != NULL) {\r
153 *HpIndex = Index;\r
154 }\r
155\r
156 return TRUE;\r
157 }\r
158 }\r
159\r
160 return FALSE;\r
161}\r
162\r
57076f45 163/**\r
164 Test whether device path is for root pci hot plug controller\r
165 \r
97404058 166 @param HpbdevicePath tested device path.\r
57076f45 167 @param HpIndex Return the index of root hot plug in global array.\r
168 \r
97404058 169 @retval TRUE device path is for root pci hot plug controller.\r
170 @retval FALSE device path is not for root pci hot plug controller.\r
57076f45 171**/\r
ead42efc 172BOOLEAN\r
173IsRootPciHotPlugController (\r
174 IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,\r
175 OUT UINTN *HpIndex\r
176 )\r
ead42efc 177{\r
178 UINTN Index;\r
179\r
180 for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
181\r
182 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {\r
183\r
184 if (HpIndex != NULL) {\r
185 *HpIndex = Index;\r
186 }\r
187\r
188 return TRUE;\r
189 }\r
190 }\r
191\r
192 return FALSE;\r
193}\r
194\r
57076f45 195/**\r
196 Wrapper for creating event object for HPC \r
197 \r
97404058 198 @param HpIndex index of hot plug device in global array.\r
199 @param Event event object.\r
57076f45 200 \r
97404058 201 @return status of create event invoken.\r
57076f45 202**/\r
ead42efc 203EFI_STATUS\r
204CreateEventForHpc (\r
205 IN UINTN HpIndex,\r
206 OUT EFI_EVENT *Event\r
207 )\r
ead42efc 208{\r
209 EFI_STATUS Status;\r
210\r
211 Status = gBS->CreateEvent (\r
212 EVT_NOTIFY_SIGNAL,\r
213 TPL_CALLBACK,\r
214 PciHPCInitialized,\r
215 gPciRootHpcData + HpIndex,\r
216 &((gPciRootHpcData + HpIndex)->Event)\r
217 );\r
218\r
219 if (!EFI_ERROR (Status)) {\r
220 *Event = (gPciRootHpcData + HpIndex)->Event;\r
221 }\r
222\r
223 return Status;\r
224}\r
225\r
57076f45 226/**\r
227 Wait for all root HPC initialized.\r
228 \r
97404058 229 @param TimeoutInMicroSeconds microseconds to wait for all root hpc's initialization.\r
57076f45 230**/\r
ead42efc 231EFI_STATUS\r
232AllRootHPCInitialized (\r
233 IN UINTN TimeoutInMicroSeconds\r
234 )\r
ead42efc 235{\r
236 UINT32 Delay;\r
237 UINTN Index;\r
238\r
239 Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);\r
240 do {\r
241\r
242 for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
243\r
244 if (!gPciRootHpcData[Index].Initialized) {\r
245 break;\r
246 }\r
247 }\r
248\r
249 if (Index == gPciRootHpcCount) {\r
250 return EFI_SUCCESS;\r
251 }\r
252\r
253 //\r
254 // Stall for 30 us\r
255 //\r
256 gBS->Stall (30);\r
257\r
258 Delay--;\r
259\r
97404058 260 } while (Delay > 0);\r
ead42efc 261\r
262 return EFI_TIMEOUT;\r
263}\r
264\r
57076f45 265/**\r
266 Check HPC capability register block\r
267 \r
97404058 268 @param PciIoDevice PCI device instance.\r
57076f45 269 \r
97404058 270 @retval EFI_SUCCESS PCI device is HPC.\r
271 @retval EFI_NOT_FOUND PCI device is not HPC.\r
57076f45 272**/\r
ead42efc 273EFI_STATUS\r
274IsSHPC (\r
275 PCI_IO_DEVICE *PciIoDevice\r
276 )\r
ead42efc 277{\r
278\r
279 EFI_STATUS Status;\r
280 UINT8 Offset;\r
281\r
97404058 282 if (PciIoDevice == NULL) {\r
ead42efc 283 return EFI_NOT_FOUND;\r
284 }\r
285\r
286 Offset = 0;\r
287 Status = LocateCapabilityRegBlock (\r
288 PciIoDevice,\r
289 EFI_PCI_CAPABILITY_ID_HOTPLUG,\r
290 &Offset,\r
291 NULL\r
292 );\r
293\r
294 //\r
295 // If the PPB has the hot plug controller build-in,\r
296 // then return TRUE;\r
297 //\r
298 if (!EFI_ERROR (Status)) {\r
299 return EFI_SUCCESS;\r
300 }\r
301\r
302 return EFI_NOT_FOUND;\r
303}\r
304\r
57076f45 305/**\r
306 Get resource padding for hot plug bus\r
307 \r
308 @param PciIoDevice PCI device instance\r
309 \r
310 @retval EFI_SUCCESS success get padding and set it into PCI device instance\r
311 @retval EFI_NOT_FOUND PCI device is not a hot plug bus.\r
312**/\r
ead42efc 313EFI_STATUS\r
314GetResourcePaddingForHpb (\r
315 IN PCI_IO_DEVICE *PciIoDevice\r
316 )\r
bcd70414 317/**\r
ead42efc 318\r
319Routine Description:\r
320\r
321Arguments:\r
322\r
323Returns:\r
324\r
325 None\r
326\r
bcd70414 327**/\r
ead42efc 328// TODO: PciIoDevice - add argument and description to function comment\r
329// TODO: EFI_SUCCESS - add return value to function comment\r
330// TODO: EFI_NOT_FOUND - add return value to function comment\r
331{\r
332 EFI_STATUS Status;\r
333 EFI_HPC_STATE State;\r
334 UINT64 PciAddress;\r
335 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
336 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
337\r
338 Status = IsPciHotPlugBus (PciIoDevice);\r
339\r
340 if (!EFI_ERROR (Status)) {\r
341 PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
342 Status = gPciHotPlugInit->GetResourcePadding (\r
343 gPciHotPlugInit,\r
344 PciIoDevice->DevicePath,\r
345 PciAddress,\r
346 &State,\r
347 (VOID **) &Descriptors,\r
348 &Attributes\r
349 );\r
350\r
351 if (EFI_ERROR (Status)) {\r
352 return Status;\r
353 }\r
354\r
97404058 355 if ((State & EFI_HPC_STATE_ENABLED) != 0 && (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
ead42efc 356 PciIoDevice->ResourcePaddingDescriptors = Descriptors;\r
357 PciIoDevice->PaddingAttributes = Attributes;\r
358 }\r
359\r
360 return EFI_SUCCESS;\r
361 }\r
362\r
363 return EFI_NOT_FOUND;\r
364}\r
365\r
57076f45 366/**\r
367 Test whether PCI device is hot plug bus.\r
368 \r
97404058 369 @param PciIoDevice PCI device instance.\r
57076f45 370 \r
97404058 371 @retval EFI_SUCCESS PCI device is hot plug bus.\r
372 @retval EFI_NOT_FOUND PCI device is not hot plug bus.\r
57076f45 373**/\r
ead42efc 374EFI_STATUS\r
375IsPciHotPlugBus (\r
376 PCI_IO_DEVICE *PciIoDevice\r
377 )\r
ead42efc 378{\r
379 BOOLEAN Result;\r
380 EFI_STATUS Status;\r
381\r
382 Status = IsSHPC (PciIoDevice);\r
383\r
384 //\r
385 // If the PPB has the hot plug controller build-in,\r
386 // then return TRUE;\r
387 //\r
388 if (!EFI_ERROR (Status)) {\r
389 return EFI_SUCCESS;\r
390 }\r
391\r
392 //\r
393 // Otherwise, see if it is a Root HPC\r
394 //\r
395 Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL);\r
396\r
397 if (Result) {\r
398 return EFI_SUCCESS;\r
399 }\r
400\r
401 return EFI_NOT_FOUND;\r
402}\r
57076f45 403\r