]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c
4ebf9a7afcb7e0eb07d96bd7c102b115fe3941df
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciHotPlugSupport.c
1 /*++
2
3 Copyright (c) 2006, 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 EFI_EVENT_NOTIFY_SIGNAL,
258 EFI_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 TimeoutInMilliSeconds
274 )
275 /*++
276
277 Routine Description:
278
279 Arguments:
280
281 Returns:
282
283 None
284
285 --*/
286 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
287 // TODO: EFI_SUCCESS - add return value to function comment
288 // TODO: EFI_TIMEOUT - add return value to function comment
289 {
290 UINT32 Delay;
291 UINTN Index;
292
293 Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
294 do {
295
296 for (Index = 0; Index < gPciRootHpcCount; Index++) {
297
298 if (!gPciRootHpcData[Index].Initialized) {
299 break;
300 }
301 }
302
303 if (Index == gPciRootHpcCount) {
304 return EFI_SUCCESS;
305 }
306
307 //
308 // Stall for 30 us
309 //
310 gBS->Stall (30);
311
312 Delay--;
313
314 } while (Delay);
315
316 return EFI_TIMEOUT;
317 }
318
319 EFI_STATUS
320 IsSHPC (
321 PCI_IO_DEVICE *PciIoDevice
322 )
323 /*++
324
325 Routine Description:
326
327 Arguments:
328
329 Returns:
330
331 None
332
333 --*/
334 // TODO: PciIoDevice - add argument and description to function comment
335 // TODO: EFI_NOT_FOUND - add return value to function comment
336 // TODO: EFI_SUCCESS - add return value to function comment
337 // TODO: EFI_NOT_FOUND - add return value to function comment
338 {
339
340 EFI_STATUS Status;
341 UINT8 Offset;
342
343 if (!PciIoDevice) {
344 return EFI_NOT_FOUND;
345 }
346
347 Offset = 0;
348 Status = LocateCapabilityRegBlock (
349 PciIoDevice,
350 EFI_PCI_CAPABILITY_ID_HOTPLUG,
351 &Offset,
352 NULL
353 );
354
355 //
356 // If the PPB has the hot plug controller build-in,
357 // then return TRUE;
358 //
359 if (!EFI_ERROR (Status)) {
360 return EFI_SUCCESS;
361 }
362
363 return EFI_NOT_FOUND;
364 }
365
366 EFI_STATUS
367 GetResourcePaddingForHpb (
368 IN PCI_IO_DEVICE *PciIoDevice
369 )
370 /*++
371
372 Routine Description:
373
374 Arguments:
375
376 Returns:
377
378 None
379
380 --*/
381 // TODO: PciIoDevice - add argument and description to function comment
382 // TODO: EFI_SUCCESS - add return value to function comment
383 // TODO: EFI_NOT_FOUND - add return value to function comment
384 {
385 EFI_STATUS Status;
386 EFI_HPC_STATE State;
387 UINT64 PciAddress;
388 EFI_HPC_PADDING_ATTRIBUTES Attributes;
389 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
390
391 Status = IsPciHotPlugBus (PciIoDevice);
392
393 if (!EFI_ERROR (Status)) {
394 PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
395 Status = gPciHotPlugInit->GetResourcePadding (
396 gPciHotPlugInit,
397 PciIoDevice->DevicePath,
398 PciAddress,
399 &State,
400 (VOID **) &Descriptors,
401 &Attributes
402 );
403
404 if (EFI_ERROR (Status)) {
405 return Status;
406 }
407
408 if ((State & EFI_HPC_STATE_ENABLED) && (State & EFI_HPC_STATE_INITIALIZED)) {
409 PciIoDevice->ResourcePaddingDescriptors = Descriptors;
410 PciIoDevice->PaddingAttributes = Attributes;
411 }
412
413 return EFI_SUCCESS;
414 }
415
416 return EFI_NOT_FOUND;
417 }
418
419 EFI_STATUS
420 IsPciHotPlugBus (
421 PCI_IO_DEVICE *PciIoDevice
422 )
423 /*++
424
425 Routine Description:
426
427 Arguments:
428
429 Returns:
430
431 None
432
433 --*/
434 // TODO: PciIoDevice - add argument and description to function comment
435 // TODO: EFI_SUCCESS - add return value to function comment
436 // TODO: EFI_SUCCESS - add return value to function comment
437 // TODO: EFI_NOT_FOUND - add return value to function comment
438 {
439 BOOLEAN Result;
440 EFI_STATUS Status;
441
442 Status = IsSHPC (PciIoDevice);
443
444 //
445 // If the PPB has the hot plug controller build-in,
446 // then return TRUE;
447 //
448 if (!EFI_ERROR (Status)) {
449 return EFI_SUCCESS;
450 }
451
452 //
453 // Otherwise, see if it is a Root HPC
454 //
455 Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL);
456
457 if (Result) {
458 return EFI_SUCCESS;
459 }
460
461 return EFI_NOT_FOUND;
462 }