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