TianoCore EDK2 master
Loading...
Searching...
No Matches
PciHotPlugSupport.c
Go to the documentation of this file.
1
9#include "PciBus.h"
10
11EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit = NULL;
12EFI_HPC_LOCATION *gPciRootHpcPool = NULL;
13UINTN gPciRootHpcCount = 0;
14ROOT_HPC_DATA *gPciRootHpcData = NULL;
15
23VOID
24EFIAPI
26 IN EFI_EVENT Event,
27 IN VOID *Context
28 )
29{
30 ROOT_HPC_DATA *HpcData;
31
32 HpcData = (ROOT_HPC_DATA *)Context;
33 HpcData->Initialized = TRUE;
34}
35
46BOOLEAN
48 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
49 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
50 )
51{
52 UINTN Size1;
53 UINTN Size2;
54
55 Size1 = GetDevicePathSize (DevicePath1);
56 Size2 = GetDevicePathSize (DevicePath2);
57
58 if (Size1 != Size2) {
59 return FALSE;
60 }
61
62 if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {
63 return FALSE;
64 }
65
66 return TRUE;
67}
68
84 VOID
85 )
86{
87 EFI_STATUS Status;
88 EFI_HPC_LOCATION *HpcList;
89 UINTN HpcCount;
90
91 //
92 // Locate the PciHotPlugInit Protocol
93 // If it doesn't exist, that means there is no
94 // hot plug controller supported on the platform
95 // the PCI Bus driver is running on. HotPlug Support
96 // is an optional feature, so absence of the protocol
97 // won't incur the penalty.
98 //
99 Status = gBS->LocateProtocol (
100 &gEfiPciHotPlugInitProtocolGuid,
101 NULL,
102 (VOID **)&gPciHotPlugInit
103 );
104
105 if (EFI_ERROR (Status)) {
106 return EFI_UNSUPPORTED;
107 }
108
109 Status = gPciHotPlugInit->GetRootHpcList (
110 gPciHotPlugInit,
111 &HpcCount,
112 &HpcList
113 );
114
115 if (!EFI_ERROR (Status)) {
116 gPciRootHpcPool = HpcList;
117 gPciRootHpcCount = HpcCount;
118 gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);
119 if (gPciRootHpcData == NULL) {
120 return EFI_OUT_OF_RESOURCES;
121 }
122 }
123
124 return EFI_SUCCESS;
125}
126
138BOOLEAN
140 IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
141 OUT UINTN *HpIndex OPTIONAL
142 )
143{
144 UINTN Index;
145
146 for (Index = 0; Index < gPciRootHpcCount; Index++) {
147 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {
148 if (HpIndex != NULL) {
149 *HpIndex = Index;
150 }
151
152 return TRUE;
153 }
154 }
155
156 return FALSE;
157}
158
170BOOLEAN
172 IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
173 OUT UINTN *HpIndex
174 )
175{
176 UINTN Index;
177
178 for (Index = 0; Index < gPciRootHpcCount; Index++) {
179 if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {
180 if (HpIndex != NULL) {
181 *HpIndex = Index;
182 }
183
184 return TRUE;
185 }
186 }
187
188 return FALSE;
189}
190
202 IN UINTN HpIndex,
203 OUT EFI_EVENT *Event
204 )
205{
206 EFI_STATUS Status;
207
208 Status = gBS->CreateEvent (
209 EVT_NOTIFY_SIGNAL,
210 TPL_CALLBACK,
212 gPciRootHpcData + HpIndex,
213 &((gPciRootHpcData + HpIndex)->Event)
214 );
215
216 if (!EFI_ERROR (Status)) {
217 *Event = (gPciRootHpcData + HpIndex)->Event;
218 }
219
220 return Status;
221}
222
234 IN UINTN TimeoutInMicroSeconds
235 )
236{
237 UINT32 Delay;
238 UINTN Index;
239
240 Delay = (UINT32)((TimeoutInMicroSeconds / 30) + 1);
241
242 do {
243 for (Index = 0; Index < gPciRootHpcCount; Index++) {
244 if (gPciRootHpcData[Index].Found && !gPciRootHpcData[Index].Initialized) {
245 break;
246 }
247 }
248
249 if (Index == gPciRootHpcCount) {
250 return EFI_SUCCESS;
251 }
252
253 //
254 // Stall for 30 microseconds..
255 //
256 gBS->Stall (30);
257
258 Delay--;
259 } while (Delay > 0);
260
261 return EFI_TIMEOUT;
262}
263
273BOOLEAN
275 IN PCI_IO_DEVICE *PciIoDevice
276 )
277{
278 EFI_STATUS Status;
279 UINT8 Offset;
280
281 if (PciIoDevice == NULL) {
282 return FALSE;
283 }
284
285 Offset = 0;
286 Status = LocateCapabilityRegBlock (
287 PciIoDevice,
288 EFI_PCI_CAPABILITY_ID_SHPC,
289 &Offset,
290 NULL
291 );
292
293 //
294 // If the PCI-PCI bridge has the hot plug controller build-in,
295 // then return TRUE;
296 //
297 if (!EFI_ERROR (Status)) {
298 return TRUE;
299 }
300
301 return FALSE;
302}
303
320BOOLEAN
322 IN PCI_IO_DEVICE *PciIoDevice
323 )
324{
325 UINT32 Offset;
326 EFI_STATUS Status;
327 PCI_REG_PCIE_CAPABILITY Capability;
328 PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability;
329
330 if (PciIoDevice == NULL) {
331 return FALSE;
332 }
333
334 //
335 // Read the PCI Express Capabilities Register
336 //
337 if (!PciIoDevice->IsPciExp) {
338 return FALSE;
339 }
340
341 Offset = PciIoDevice->PciExpressCapabilityOffset +
342 OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability);
343 Status = PciIoDevice->PciIo.Pci.Read (
344 &PciIoDevice->PciIo,
345 EfiPciIoWidthUint16,
346 Offset,
347 1,
348 &Capability
349 );
350 if (EFI_ERROR (Status)) {
351 return FALSE;
352 }
353
354 //
355 // Check the contents of the register
356 //
357 switch (Capability.Bits.DevicePortType) {
358 case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
359 case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
360 break;
361 default:
362 return FALSE;
363 }
364
365 if (!Capability.Bits.SlotImplemented) {
366 return FALSE;
367 }
368
369 //
370 // Read the Slot Capabilities Register
371 //
372 Offset = PciIoDevice->PciExpressCapabilityOffset +
373 OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability);
374 Status = PciIoDevice->PciIo.Pci.Read (
375 &PciIoDevice->PciIo,
376 EfiPciIoWidthUint32,
377 Offset,
378 1,
379 &SlotCapability
380 );
381 if (EFI_ERROR (Status)) {
382 return FALSE;
383 }
384
385 //
386 // Check the contents of the register
387 //
388 if (SlotCapability.Bits.HotPlugCapable) {
389 return TRUE;
390 }
391
392 return FALSE;
393}
394
401VOID
403 IN PCI_IO_DEVICE *PciIoDevice
404 )
405{
406 EFI_STATUS Status;
407 EFI_HPC_STATE State;
408 UINT64 PciAddress;
411
412 if (IsPciHotPlugBus (PciIoDevice)) {
413 //
414 // If PCI-PCI bridge device is PCI Hot Plug bus.
415 //
416 PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
417 Status = gPciHotPlugInit->GetResourcePadding (
418 gPciHotPlugInit,
419 PciIoDevice->DevicePath,
420 PciAddress,
421 &State,
422 (VOID **)&Descriptors,
423 &Attributes
424 );
425
426 if (EFI_ERROR (Status)) {
427 return;
428 }
429
430 if (((State & EFI_HPC_STATE_ENABLED) != 0) && ((State & EFI_HPC_STATE_INITIALIZED) != 0)) {
431 PciIoDevice->ResourcePaddingDescriptors = Descriptors;
432 PciIoDevice->PaddingAttributes = Attributes;
433 }
434
435 return;
436 }
437}
438
448BOOLEAN
450 PCI_IO_DEVICE *PciIoDevice
451 )
452{
453 if (IsSHPC (PciIoDevice)) {
454 //
455 // If the PPB has the hot plug controller build-in,
456 // then return TRUE;
457 //
458 return TRUE;
459 }
460
461 if (SupportsPcieHotplug (PciIoDevice)) {
462 //
463 // If the PPB is a PCIe root complex port or a switch downstream port, and
464 // implements a hot-plug capable slot, then also return TRUE.
465 //
466 return TRUE;
467 }
468
469 //
470 // Otherwise, see if it is a Root HPC
471 //
472 if (IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL)) {
473 return TRUE;
474 }
475
476 return FALSE;
477}
UINT64 UINTN
PACKED struct @89 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
EFI_STATUS LocateCapabilityRegBlock(IN PCI_IO_DEVICE *PciIoDevice, IN UINT8 CapId, IN OUT UINT8 *Offset, OUT UINT8 *NextRegBlock OPTIONAL)
Definition: PciCommand.c:106
#define EFI_HPC_STATE_ENABLED
EFI_HPC_PADDING_ATTRIBUTES
UINT16 EFI_HPC_STATE
#define EFI_HPC_STATE_INITIALIZED
EFI_STATUS CreateEventForHpc(IN UINTN HpIndex, OUT EFI_EVENT *Event)
BOOLEAN SupportsPcieHotplug(IN PCI_IO_DEVICE *PciIoDevice)
BOOLEAN IsRootPciHotPlugController(IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, OUT UINTN *HpIndex)
BOOLEAN IsRootPciHotPlugBus(IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath, OUT UINTN *HpIndex OPTIONAL)
VOID GetResourcePaddingForHpb(IN PCI_IO_DEVICE *PciIoDevice)
BOOLEAN EfiCompareDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2)
BOOLEAN IsSHPC(IN PCI_IO_DEVICE *PciIoDevice)
BOOLEAN IsPciHotPlugBus(PCI_IO_DEVICE *PciIoDevice)
VOID EFIAPI PciHPCInitialized(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS AllRootHPCInitialized(IN UINTN TimeoutInMicroSeconds)
EFI_STATUS InitializeHotPlugSupport(VOID)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_GET_ROOT_HPC_LIST GetRootHpcList
EFI_GET_HOT_PLUG_PADDING GetResourcePadding