]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
3ef1daf69ec089585e368d48b0c2e9b4d726ff26
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciHotPlugSupport.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 PciHotPlugSupport.c
15
16 Abstract:
17
18
19
20 Revision History
21
22 --*/
23
24 #include "Pcibus.h"
25 #include "PciHotPlugSupport.h"
26
27 EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
28 EFI_HPC_LOCATION *gPciRootHpcPool;
29 UINTN gPciRootHpcCount;
30 ROOT_HPC_DATA *gPciRootHpcData;
31
32 VOID
33 EFIAPI
34 PciHPCInitialized (
35 IN EFI_EVENT Event,
36 IN VOID *Context
37 )
38 /*++
39
40 Routine Description:
41
42 Arguments:
43
44 Returns:
45
46 None
47
48 --*/
49 // TODO: Event - add argument and description to function comment
50 // TODO: Context - add argument and description to function comment
51 {
52 ROOT_HPC_DATA *HpcData;
53
54 HpcData = (ROOT_HPC_DATA *) Context;
55 HpcData->Initialized = TRUE;
56
57 }
58
59 BOOLEAN
60 EfiCompareDevicePath (
61 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
62 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
63 )
64 /*++
65
66 Routine Description:
67
68 Arguments:
69
70 Returns:
71
72 None
73
74 --*/
75 // TODO: DevicePath1 - add argument and description to function comment
76 // TODO: DevicePath2 - add argument and description to function comment
77 {
78 UINTN Size1;
79 UINTN Size2;
80
81 Size1 = GetDevicePathSize (DevicePath1);
82 Size2 = GetDevicePathSize (DevicePath2);
83
84 if (Size1 != Size2) {
85 return FALSE;
86 }
87
88 if (CompareMem (DevicePath1, DevicePath2, Size1)) {
89 return FALSE;
90 }
91
92 return TRUE;
93 }
94
95 EFI_STATUS
96 InitializeHotPlugSupport (
97 VOID
98 )
99 /*++
100
101 Routine Description:
102
103 Arguments:
104
105 Returns:
106
107 None
108
109 --*/
110 // TODO: EFI_UNSUPPORTED - add return value to function comment
111 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
112 // TODO: EFI_SUCCESS - add return value to function comment
113 {
114 EFI_STATUS Status;
115 EFI_HPC_LOCATION *HpcList;
116 UINTN HpcCount;
117
118 //
119 // Locate the PciHotPlugInit Protocol
120 // If it doesn't exist, that means there is no
121 // hot plug controller supported on the platform
122 // the PCI Bus driver is running on. HotPlug Support
123 // is an optional feature, so absence of the protocol
124 // won't incur the penalty
125 //
126 gPciHotPlugInit = NULL;
127 gPciRootHpcPool = NULL;
128 gPciRootHpcCount = 0;
129 gPciRootHpcData = NULL;
130
131 Status = gBS->LocateProtocol (
132 &gEfiPciHotPlugInitProtocolGuid,
133 NULL,
134 (VOID **) &gPciHotPlugInit
135 );
136
137 if (EFI_ERROR (Status)) {
138 return EFI_UNSUPPORTED;
139 }
140
141 Status = gPciHotPlugInit->GetRootHpcList (
142 gPciHotPlugInit,
143 &HpcCount,
144 &HpcList
145 );
146
147 if (!EFI_ERROR (Status)) {
148
149 gPciRootHpcPool = HpcList;
150 gPciRootHpcCount = HpcCount;
151 gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);
152 if (gPciRootHpcData == NULL) {
153 return EFI_OUT_OF_RESOURCES;
154 }
155 }
156
157 return EFI_SUCCESS;
158 }
159
160 BOOLEAN
161 IsRootPciHotPlugBus (
162 IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
163 OUT UINTN *HpIndex
164 )
165 /*++
166
167 Routine Description:
168
169 Arguments:
170
171 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
172 HpIndex - A pointer to the Index.
173
174 Returns:
175
176 None
177
178 --*/
179 // TODO: HpbDevicePath - add argument and description to function comment
180 {
181 UINTN Index;
182
183 for (Index = 0; Index < gPciRootHpcCount; Index++) {
184
185 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {
186
187 if (HpIndex != NULL) {
188 *HpIndex = Index;
189 }
190
191 return TRUE;
192 }
193 }
194
195 return FALSE;
196 }
197
198 BOOLEAN
199 IsRootPciHotPlugController (
200 IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
201 OUT UINTN *HpIndex
202 )
203 /*++
204
205 Routine Description:
206
207 Arguments:
208
209 HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
210 HpIndex - A pointer to the Index.
211
212 Returns:
213
214 None
215
216 --*/
217 {
218 UINTN Index;
219
220 for (Index = 0; Index < gPciRootHpcCount; Index++) {
221
222 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {
223
224 if (HpIndex != NULL) {
225 *HpIndex = Index;
226 }
227
228 return TRUE;
229 }
230 }
231
232 return FALSE;
233 }
234
235 EFI_STATUS
236 CreateEventForHpc (
237 IN UINTN HpIndex,
238 OUT EFI_EVENT *Event
239 )
240 /*++
241
242 Routine Description:
243
244 Arguments:
245
246 Returns:
247
248 None
249
250 --*/
251 // TODO: HpIndex - add argument and description to function comment
252 // TODO: Event - add argument and description to function comment
253 {
254 EFI_STATUS Status;
255
256 Status = gBS->CreateEvent (
257 EVT_NOTIFY_SIGNAL,
258 TPL_CALLBACK,
259 PciHPCInitialized,
260 gPciRootHpcData + HpIndex,
261 &((gPciRootHpcData + HpIndex)->Event)
262 );
263
264 if (!EFI_ERROR (Status)) {
265 *Event = (gPciRootHpcData + HpIndex)->Event;
266 }
267
268 return Status;
269 }
270
271 EFI_STATUS
272 AllRootHPCInitialized (
273 IN UINTN TimeoutInMicroSeconds
274 )
275 /*++
276
277 Routine Description:
278
279 Arguments:
280 TimeoutInMicroSeconds - microseconds to wait for all root hpc's initialization
281
282 Returns:
283 EFI_SUCCESS - All root hpc's initialization is finished before the timeout
284 EFI_TIMEOUT - Time out
285
286 --*/
287 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
288 // TODO: EFI_SUCCESS - add return value to function comment
289 // TODO: EFI_TIMEOUT - add return value to function comment
290 {
291 UINT32 Delay;
292 UINTN Index;
293
294 Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);
295 do {
296
297 for (Index = 0; Index < gPciRootHpcCount; Index++) {
298
299 if (!gPciRootHpcData[Index].Initialized) {
300 break;
301 }
302 }
303
304 if (Index == gPciRootHpcCount) {
305 return EFI_SUCCESS;
306 }
307
308 //
309 // Stall for 30 us
310 //
311 gBS->Stall (30);
312
313 Delay--;
314
315 } while (Delay);
316
317 return EFI_TIMEOUT;
318 }
319
320 EFI_STATUS
321 IsSHPC (
322 PCI_IO_DEVICE *PciIoDevice
323 )
324 /*++
325
326 Routine Description:
327
328 Arguments:
329
330 Returns:
331
332 None
333
334 --*/
335 // TODO: PciIoDevice - add argument and description to function comment
336 // TODO: EFI_NOT_FOUND - add return value to function comment
337 // TODO: EFI_SUCCESS - add return value to function comment
338 // TODO: EFI_NOT_FOUND - add return value to function comment
339 {
340
341 EFI_STATUS Status;
342 UINT8 Offset;
343
344 if (!PciIoDevice) {
345 return EFI_NOT_FOUND;
346 }
347
348 Offset = 0;
349 Status = LocateCapabilityRegBlock (
350 PciIoDevice,
351 EFI_PCI_CAPABILITY_ID_HOTPLUG,
352 &Offset,
353 NULL
354 );
355
356 //
357 // If the PPB has the hot plug controller build-in,
358 // then return TRUE;
359 //
360 if (!EFI_ERROR (Status)) {
361 return EFI_SUCCESS;
362 }
363
364 return EFI_NOT_FOUND;
365 }
366
367 EFI_STATUS
368 GetResourcePaddingForHpb (
369 IN PCI_IO_DEVICE *PciIoDevice
370 )
371 /*++
372
373 Routine Description:
374
375 Arguments:
376
377 Returns:
378
379 None
380
381 --*/
382 // TODO: PciIoDevice - add argument and description to function comment
383 // TODO: EFI_SUCCESS - add return value to function comment
384 // TODO: EFI_NOT_FOUND - add return value to function comment
385 {
386 EFI_STATUS Status;
387 EFI_HPC_STATE State;
388 UINT64 PciAddress;
389 EFI_HPC_PADDING_ATTRIBUTES Attributes;
390 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
391
392 Status = IsPciHotPlugBus (PciIoDevice);
393
394 if (!EFI_ERROR (Status)) {
395 PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
396 Status = gPciHotPlugInit->GetResourcePadding (
397 gPciHotPlugInit,
398 PciIoDevice->DevicePath,
399 PciAddress,
400 &State,
401 (VOID **) &Descriptors,
402 &Attributes
403 );
404
405 if (EFI_ERROR (Status)) {
406 return Status;
407 }
408
409 if ((State & EFI_HPC_STATE_ENABLED) && (State & EFI_HPC_STATE_INITIALIZED)) {
410 PciIoDevice->ResourcePaddingDescriptors = Descriptors;
411 PciIoDevice->PaddingAttributes = Attributes;
412 }
413
414 return EFI_SUCCESS;
415 }
416
417 return EFI_NOT_FOUND;
418 }
419
420 EFI_STATUS
421 IsPciHotPlugBus (
422 PCI_IO_DEVICE *PciIoDevice
423 )
424 /*++
425
426 Routine Description:
427
428 Arguments:
429
430 Returns:
431
432 None
433
434 --*/
435 // TODO: PciIoDevice - add argument and description to function comment
436 // TODO: EFI_SUCCESS - add return value to function comment
437 // TODO: EFI_SUCCESS - add return value to function comment
438 // TODO: EFI_NOT_FOUND - add return value to function comment
439 {
440 BOOLEAN Result;
441 EFI_STATUS Status;
442
443 Status = IsSHPC (PciIoDevice);
444
445 //
446 // If the PPB has the hot plug controller build-in,
447 // then return TRUE;
448 //
449 if (!EFI_ERROR (Status)) {
450 return EFI_SUCCESS;
451 }
452
453 //
454 // Otherwise, see if it is a Root HPC
455 //
456 Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL);
457
458 if (Result) {
459 return EFI_SUCCESS;
460 }
461
462 return EFI_NOT_FOUND;
463 }