12. Hot Plug PCI

12.1. HOT PLUG PCI Overview

This specification defines the core code and services that are required for an implementation of the Hot-Plug PCI Initialization Protocol. A PCI bus driver, running in the EFI Boot Services environment, uses this protocol to initialize the hot-plug subsystem. The same protocol may be used by other buses such as CardBus that support hot plugging. This specification does the following:

  • Describes the basic components of the hot-plug PCI subsystem and the Hot-Plug PCI Initialization Protocol

  • Provides code definitions for the Hot-Plug PCI Initialization Protocol and the hot-plug-PCI-related type definitions that are architecturally required.

12.2. Hot Plug PCI Initialization Protocol Introduction

This chapter describes the Hot-Plug PCI Initialization Protocol. A PCI bus driver, running in the EFI Boot Services environment, uses this protocol to initialize the hot-plug subsystem. This protocol is generic enough to include PCI-to-CardBus bridges and PCI Express* systems. This protocol abstracts the hot-plug controller initialization and resource padding. This protocol is required on platforms that support PCI Hot Plug* or PCI Express slots. For the purposes of initialization, a CardBus PC Card bus is treated in the same way. This protocol is not required on all other platforms. This protocol is not intended to support hot plugging of PCI cards during the preboot stage. Separate components can be developed if such support is desired. See Hot-Plug PCI Initialization Protocol in Code Definitions for the definition of EFI_PCI_HOT_PLUG_INIT_PROTOCOL .

12.3. Hot Plug PCI Initialization Protocol RelatedInformation

The following resources are referenced throughout this specification or may be useful to you:

12.4. Requirements

PI Architecture firmware must support platforms with PCI Hot Plug* slots and PCI Express* Hot Plug slots, as well as CardBus PC Card sockets. In both cases, the user is allowed to plug in new devices or remove existing devices during runtime. PCI Hot Plug slots are controlled by a PCI Hot Plug controller whereas CardBus sockets are controlled by a PCI-to-CardBus bridge. PCI Express Hot Plug slots are controlled by a PCI Express root port or a downstream port in a switch. The term “Hot Plug Controller” (HPC) in this document refers to all of these types of controllers. From the standpoint of initialization, all three are identical and have the same general requirements, as follows:

  • The root HPCs may come up uninitialized after system reset. These HPCs must be initialized by the system firmware.

  • Every HPC may require resource padding. The padding must be taken into account during PCI enumeration. This scenario is true for conventional PCI, PCI Express, and CardBus PC Cards because they all consume shared system resources (I/O, memory, and bus). These resources are produced by the root PCI bridge.

These general requirements place the following specific requirements on an implementation of the PI Architechture PCI hot plug support:

  • PI Architecture firmware must handle root HPCs differently than other regular PCI devices. When a root HPC is initialized, the hot-plug slots or CardBus sockets are enabled and this process may uncover more PCI buses and devices. In that respect, root HPCs are somewhat like PCI bridges. The root HPC initialization process may involve detecting bus type and optimum bus speed. The initialization process may also detect faults and voltage mismatches. The initialization process may be specific to the controller and the platform. At the time of the root HPC initialization, the PCI bus may not be fully initialized and the standard PCI bus-specific protocols are not available. PI Architecture firmware must provide an alternate infrastructure for the initialization code. In other words, the HPC initialization code should not be required to understand the bus numbering scheme and other chipset details.

  • PI Architecture firmware must support an unlimited number of HPCs in the system. PI Architecture firmware must support various types of HPCs as long as they follow industry standards or conventions. A mix of various types of HPCs is allowed.

  • PI Architecture firmware must support legacy PCI Hot Plug Controllers (PHPCs; class code 0x6, subclass code 0x4) as well as Standard (PCI) Hot Plug Controllers (SHPCs). Other conventional PCI Hot Plug controllers are not supported.

  • PI Architecture firmware must be capable of supporting a PHPC that is a child of another PHPC. In that case, the PCI Standard Hot-Plug Controller and Subsystem Specification requires that the child PHPC must be initialized without firmware assistance because it is not a root PHPC.

  • PI Architecture firmware must be capable of supporting SHPCs on an add-in card. In that case, the PCI Standard Hot-Plug Controller and Subsystem Specification requires that such an SHPC must be initialized without firmware assistance because it is not a root PHPC. PI Architecture firmware must also support plug-in CardBus bridges that follow the CardBus Specification, which is part of the PC Card Standard .

  • As stated above, root HPCs may require firmware initialization. PI Architecture firmware must be capable of supporting root HPCs that are initialized by hardware and do not require any firmware initialization.

  • A PI Architecture PCI bus enumerator must overallocate resources for PCI Hot Plug buses and CardBus sockets. The amount of overallocation may be platform specific.

  • The root HPC initialization process may be time consuming. An SHPC can take as long as 15 seconds to enable power to a hot-plug bus without violating the PCI Special Interest Group (PCI-SIG*) requirements. PI Architecture firmware should be able to initialize multiple HPCs in parallel to reduce boot time. In contrast, CardBus initialization is quick.

  • PI Architecture firmware should be able to handle when an HPC fails. PI Architecture firmware should be able to handle an HPC that has been disabled.

  • The PCI bus driver in PI Architecture firmware is not required to assume anything that is not in one of the PCI-SIG specifications.

  • It must be possible to produce legacy Hot Plug Resource Tables (HPRTs) if necessary. HPRTs are described in the PCI Standard Hot-Plug Controller and Subsystem Specification.

12.5. Sample Implementation for a Platform Containing PCIHot Plug* Slots

Typically, the PCI bus driver will enumerate and allocate resources to all devices for a PCI host bridge. A sample algorithm for PCI bus enumeration is described below to clarify some of the finer points of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL . Actual implementations may vary although the relative ordering of events is critical. The activities related to PCI Hot Plug* are underlined. Please note that multiple passes of bus enumeration are required in a system containing PCI Hot Plug slots.

See PCI Host Bridge Resource Allocation Protocol for definitions of the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL and its member functions.

If the platform supports PCI Hot Plug, an instance of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL is installed.

The PCI enumeration process begins.

Look for instances of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL . If it is not found, all the hot-plug subsystem initialization steps can be skipped. If one exists, create a list of root Hot Plug Controllers (HPCs) by calling EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetRootHpcList() .

Notify the host bridge driver that bus enumeration is about to begin by calling EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.NotifyPhase (EfiPciHostBridgeBeginBusAllocation).

For every PCI root bridge handle, do the following:

  1. Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.StartBusEnumeration (This,RootBridgeHandle).

  2. Make sure each PCI root bridge handle supports the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL . See the UE FI 2.1 Specification for the definition of the PCI Root Bridge I/O Protocol.

  3. Allocate memory to hold resource requirements. These can be two resource descriptors, one to hold bus requirements and another to hold the I/O and memory requirements.

  4. Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.GetAllocAttributes() to get the attributes of this PCI root bridge. This information is used to combine different types of memory resources in the next step.

Scan all the devices in the specified bus range and the specified segment, one bus at a time. If the device is a PCI-to-PCI bridge, update the bus numbers and program the bus number registers in the PCI-to-PCI bridge hardware. If the device path of a device matches that of a root HPC and it is not a PCI-to-CardBus bridge, it must be initialized by calling

EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc() before the bus it controls can be fully enumerated. The PCI bus enumerator determines the PCI address of the PCI Hot Plug Controller (PHPC) and passes it as an input to InitializeRootHpc() .

  1. Continue to scan devices on that root bridge and start the initialization of all root HPCs.

  2. Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SetBusNumbers() so that the HPCs under initialization are still accessible. SetBusNumbers() cannot affect the PCI addresses of the HPCs.

Wait until all the HPCs that were found on various root bridges in step 5 to complete initialization.

Go back to step 5 for another pass and rescan the PCI buses. For all the root HPCs and the nonroot HPCs, call EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding() to obtain the amount of overallocation and add that amount to the requests from the physical devices. Reprogram the bus numbers by taking into account the bus resource padding information. This action will require calling EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SetBusNumbers() . The rescan is not required if there is only one root bridge in the system.

Once the memory resources are allocated and a PCI-to-CardBus bridge is part of the HpcList, it will be initialized.

12.6. PCI Hot Plug PCI Initialization Protocol

12.6.1. EFI_PCI_HOT_PLUG_INIT_PROTOCOL

Summary

This protocol provides the necessary functionality to initialize the Hot Plug Controllers (HPCs) and the buses that they control. This protocol also provides information regarding resource padding.

Note

This protocol is required only on platforms that support one or more PCI Hot Plug* slots or CardBus sockets.

GUID

#define EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID \\
  { 0xaa0e8bc1, 0xdabc, 0x46b0, 0xa8, 0x44, 0x37, 0xb8, 0x16,\\
  0x9b, 0x2b, 0xea }

Protocol Interface Structure

typedef struct \_EFI_PCI_HOT_PLUG_INIT_PROTOCOL {
  EFI_GET_ROOT_HPC_LIST      GetRootHpcList;
  EFI_INITIALIZE_ROOT_HPC    InitializeRootHpc;
  EFI_GET_HOT_PLUG_PADDING   GetResourcePadding;
} EFI_PCI_HOT_PLUG_INIT_PROTOCOL;

Parameters

GetRootHpcList

Returns a list of root HPCs and the buses that they control. See the GetRootHpcList() function description.

InitializeRootHpc

Initializes the specified root HPC. See the InitializeRootHpc() function description.

GetResourcePadding

Returns the resource padding that is required by the HPC. See the GetResourcePadding() function description.

Description

The EFI_PCI_HOT_PLUG_INIT_PROTOCOL provides a mechanism for the PCI bus enumerator to properly initialize the HPCs and CardBus sockets that require initialization. The HPC initialization takes place before the PCI enumeration process is complete. There cannot be more than one instance of this protocol in a system. This protocol is installed on its own separate handle.

Because the system may include multiple HPCs, one instance of this protocol should represent all of them. The protocol functions use the device path of the HPC to identify the HPC. When the PCI bus enumerator finds a root HPC, it will call EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc() . If InitializeRootHpc() is unable to initialize a root HPC, the PCI enumerator will ignore that root HPC and continue the enumeration process. If the HPC is not initialized, the devices that it controls may not be initialized, and no resource padding will be provided.

From the standpoint of the PCI bus enumerator, HPCs are divided into the following two classes:

Root HPC

These HPCs must be initialized by calling InitializeRootHpc() during the enumeration process. These HPCs will also require resource padding. The platform code must have a priori knowledge of these devices and must know how to initialize them. There may not be any way to access their PCI configuration space before the PCI enumerator programs all the upstream bridges and thus enables the path to these devices. The PCI bus enumerator is responsible for determining the PCI bus address of the HPC before it calls InitializeRootHpc().

Nonroot HPC

These HPCs will not need explicit initialization during enumeration process. These HPCs will require resource padding. The platform code does not have to have a priori knowledge of these devices.

12.6.2. EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetRootHpcList()

Summary

Returns a list of root Hot Plug Controllers (HPCs) that require initialization during the boot process.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_GET_ROOT_HPC_LIST) (
  IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL    *This,
  OUT UINTN                            *HpcCount,
  OUT EFI_HPC_LOCATION                 **HpcList
  );

Parameters

This

Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance.

HpcCount

The number of root HPCs that were returned.

HpcList

The list of root HPCs. HpcCount defines the number of elements in this list. Type EFI_HPC_LOCATION is defined in “Related Definitions” below.

Description

This procedure returns a list of root HPCs. The PCI bus driver must initialize these controllers during the boot process. The PCI bus driver may or may not be able to detect these HPCs. If the platform includes a PCI-to-CardBus bridge, it can be included in this list if it requires initialization. The HpcList must be self consistent. An HPC cannot control any of its parent buses. Only one HPC can control a PCI bus. Because this list includes only root HPCs, no HPC in the list can be a child of another HPC. This policy must be enforced by the EFI_PCI_HOT_PLUG_INIT_PROTOCOL . The PCI bus driver may not check for such invalid conditions.

The callee allocates the buffer HpcList.

//****************************************************\*
// EFI_HPC_LOCATION
//****************************************************\*
typedef struct {
  EFI_DEVICE_PATH_PROTOCOL \* *HpcDevicePath* ;
  EFI_DEVICE_PATH_PROTOCOL \* *HpbDevicePath* ;
} EFI_HPC_LOCATION;
HpcDevicePath

The device path to the root HPC. An HPC cannot control its parent buses. The PCI bus driver requires this information so that it can pass the correct HpcPciAddress to the InitializeRootHpc() and GetResourcePadding() functions. Type EFI_DEVICE_PATH_PROTOCOL is defined in LocateDevicePath() in PCI Platform Overview of the UEFI 2.1 Specification.

HpbDevicePath

The device path to the Hot Plug Bus (HPB) that is controlled by the root HPC. The PCI bus driver uses this information to check if a particular PCI bus has hot-plug slots. The device path of a PCI bus is the same as the device path of its parent. For Standard (PCI) Hot Plug Controllers (SHPCs) and PCI Express*, HpbDevicePath is the same as HpcDevicePath.

Status Codes Returned

EFI_SUCCESS

HpcList was returned

EFI_OUT_OF_RESOURCES

HpcList was not returned due to insufficient resources

EFI_INVALID_PARAMETER

HpcCount is NULL

EFI_INVALID_PARAMETER

HpcList is NULL

12.6.3. EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc()

Summary

Initializes one root Hot Plug Controller (HPC). This process may causes initialization of its subordinate buses.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_INITIALIZE_ROOT_HPC) (
  IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL  *This,
  IN EFI_DEVICE_PATH_PROTOCOL        *HpcDevicePath,
  IN UINT64                          HpcPciAddress,
  IN EFI_EVENT                       Event, OPTIONAL
  OUT EFI_HPC_STATE                  *HpcState
  );

Parameters

This

Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance.

HpcDevicePath

The device path to the HPC that is being initialized. Type EFI_DEVICE_PATH_PROTOCOL is defined in LocateDevicePath() in PCI Platform Overview of the UEFI 2.1 Specification.

HpcPciAddress

The address of the HPC function on the PCI bus.

Event

The event that should be signaled when the HPC initialization is complete. Set to NULL if the caller wants to wait until the entire initialization process is complete. The event must be of type EFI_EVENT_NOTIFY_SIGNAL . Type EFI_EVENT is defined in CreateEvent() in the UEFI Specification .

HpcState

The state of the HPC hardware. The type EFI_HPC_STATE is defined in “Related Definitions” below.

Description

This function initializes the specified HPC. At the end of initialization, the hot-plug slots or sockets (controlled by this HPC) are powered and are connected to the bus. All the necessary registers in the HPC are set up. For a Standard (PCI) Hot Plug Controller (SHPC), the registers that must be set up are defined in the PCI Standard Hot Plug Controller and Subsystem Specification . For others HPCs, they are specific to the HPC hardware. The initialization process may choose not to enable certain PCI Hot Plug* slots or sockets for any reason. The PCI Hot Plug slots or CardBus sockets that are left disabled at this stage are not available to the system. A PCI slot may be disabled due to a power fault, PCI bus type mismatch, or power budget constraints. The HPC initialization process can be time consuming. Powering up the slots that are controlled by SHPCs can take up to 15 seconds. In a system with multiple HPCs, it is desirable to perform these activities in parallel. Therefore, this procedure supports nonblocking execution mode.

If InitializeRootHpc() is called with a non-NULL event, HPC initialization is considered complete after the event is signaled. If InitializeRootHpc() is called with a non-NULL event, a return from InitializeRootHpc() with EFI_SUCCESS marks the completion of the HPC initialization.

The PCI bus enumerator will call this function for every root HPC that is returned by GetRootHpcList() .

The PCI bus enumerator must make sure that the registers that are required during HPC initialization are accessible before calling InitializeRootHpc() . The determination of whether the registers are accessible is based on the following rules:

  • For HPCs (legacy HPCs, SHPCs inside a PCI-to-PCI bridge, and PCI Express* HPCs), the PCI configuration space of the HPC device must be accessible. In other words, all the upstream bridges including root bridges and special-purpose PCI-to-PCI bridges are programmed to forward PCI configuration cycles to the HPC.

  • SHPCs inside a root bridge are accessible without any initialization of the PCI bus.

  • PCI-to-CardBus bridges have their registers mapped into the memory space using a memory Base Address Register (BAR).

This function takes the device path of the HPC as an input. At the time of HPC initialization, the PCI bus enumeration is not complete. The PCI bus enumerator may not have created a handle for the HPC and the hot-plug initialization code cannot use the EFI_PCI_IO_PROTOCOL or EFI_DEVICE_PATH_PROTOCOL like other PCI device drivers. The device path uniquely identifies the HPC and also the PCI bus that it controls.

If the HPC is a PCI device, the hot-plug initialization code may need its address on the PCI bus to access its registers. The PCI address of a regular PCI device is dynamic but is known to the PCI bus driver. Therefore, the PCI bus driver provides it through the input parameter HpcPciAddress to this function. Passing this address eliminates the need for InitializeRootHpc() to convert the device path into the PCI address. If the HPC is a function in a multifunction device, this address is the PCI address of that function. The HPC’s configuration space must be accessible at the specified HpcPciAddress until the HPC initialization is complete. In other words, the PCI bus driver cannot renumber PCI buses that are upstream to the HPC while it is being initialized.

This member function can use the LocateDevicePath() function to locate the appropriate instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL .

If the Event is not NULL, this function will return control to the caller without completing the entire initialization. This function must perform some basic checks to make sure that it knows how to initialize the specified HPC before returning control. The Event is signaled when the initialization process completes, regardless of whether it results in a failure. The caller must check HpcState to get the initialization status after the event is signaled.

If Event is not NULL, it is possible that the Event may be signaled before this function returns. There are at least two cases where that may happen:

  • A simple implementation of EFI_PCI_HOT_PLUG_INIT_PROTOCOL may force the caller to wait until the initialization is complete. In that case, the InitializeRootHpc() function may signal the event before it returns control back to the caller.

  • The HPC may already have been initialized by the time InitializeRootHpc() is called. In that case, InitializeRootHpc() will signal Event and return control back to the caller.

HpcState returns the state of the HPC at the time when control returns. If Event is NULL, HpcState must indicate that the HPC has completed initialization. If Event is not NULL, HpcState can indicate that the HPC has not completed initialization when this function returns, but HpcState must be updated before Event is signaled.

The firmware may not wait until InitializeRootHpc() to start HPC initialization. The firmware may start the initialization earlier in the boot process and the initialization may be completely done by the time the PCI bus enumerator calls InitializeRootHpc(). An HPC can be initialized by hardware alone, and no firmware initialization may be needed. For such HPCs, this member function does not have to do any real work. In such cases, InitializeRootHpc() merely acts as a synchronization point.

//****************************************************\*
// EFI_HPC_STATE
//****************************************************\*
// Describes current state of an HPC

typedef UINT16 EFI_HPC_STATE;

#define EFI_HPC_STATE_INITIALIZED 0x01
#define EFI_HPC_STATE_ENABLED 0x02

Following is a description of the possible states for EFI_HPC_STATE .

Table 12.19 Description of possible states for EFI_HPC_STATE

0

Not initialized

EFI_HPC_STATE_INITIALIZED

The HPC initialization function was called and the HPC completed initialization but it was not enabled for some reason The HPC may be disabled in hardware or it may be disabled due to user preferences hardware failure or other reasons No resource padding is required

EFI_HPC_STATE_INITIALIZED EFI_HPC_ENABLED

The HPC initialization function was called the HPC completed initialization and it was enabled Resource padding is required

Status Codes Returned

EFI_SUCCESS

If Event is NULL, the specific HPC wassuccessfully initialized. If Event i snot NULL, Event will be signaled at a latertime when initialization is complete.

EFI_UNSUPPORTED

This instance of*EFI_PCI_HOT_PLUG_INIT_PROTOCOL* does notsupport the specified HPC. If Event isnot NULL, it will not be signaled.

EFI_OUT_OF_RESOURCES

Initialization failed due to insufficientresources. If Event is not NULL, it willnot be signaled.

EFI_INVALID_PARAMETER

HpcState is NULL.

12.6.4. EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding()

Summary

Returns the resource padding that is required by the PCI bus that is controlled by the specified Hot Plug Controller (HPC).

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_GET_HOT_PLUG_PADDING) (
  IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL   *This,
  IN EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,
  IN UINT64                           HpcPciAddress,
  OUT EFI_HPC_STATE                   *HpcState,
  OUT VOID                            **Padding,
  OUT EFI_HPC_PADDING_ATTRIBUTES      *Attributes
  );

Parameters

This

Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance.

HpcDevicePath

The device path to the HPC. Type EFI_DEVICE_PATH_PROTOCOL is defined in LocateDevicePath() in PCI Platform Overview of the UEFI 2.1 Specification.

HpcPciAddress

The address of the HPC function on the PCI bus.

HpcState

The state of the HPC hardware. Type EFI_HPC_STATE is defined in EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc() .

Padding

The amount of resource padding that is required by the PCI bus under the control of the specified HPC. Because the caller does not know the size of this buffer, this buffer is allocated by the callee and freed by the caller.

Attributes

Describes how padding is accounted for. The padding is returned in the form of ACPI (2.0 & 3.0) resource descriptors. The exact definition of each of the fields is the same as in PCI Host Bridge Resource Allocation Protocol in Section 10.8.2 . Type EFI_HPC_PADDING_ATTRIBUTES is defined in “Related Definitions” below.

Description

This function returns the resource padding that is required by the PCI bus that is controlled by the specified HPC. This member function is called for all the root HPCs and nonroot HPCs that are detected by the PCI bus enumerator. This function will be called before PCI resource allocation is completed. This function must be called after all the root HPCs, with the possible exception of a PCI-to-CardBus bridge, have completed initialization. Waiting until initialization is completed allows the HPC driver to optimize the padding requirement. The calculation may take into account the number of empty and/or populated PCI Hot Plug* slots, the number of PCI-to-PCI bridges among the populated slots, and other factors. This information is available only after initialization is complete. PCI-to-CardBus bridges require memory resources before the initialization is started and therefore are considered an exception. The padding requirements are relatively constant for PCI-to-CardBus bridges and an estimated value must be returned.

If InitializeRootHpc() is called with a non-NULL event, HPC initialization is considered complete after the event is signaled. If InitializeRootHpc() is called with a non-NULL event, a return from InitializeRootHpc() with EFI_SUCCESS marks the completion of HPC initialization.

The input parameters HpcDevicePath , HpcPciAddress , and HpcState are described in EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc() . The value of HpcPciAddress for the same root HPC may be different from what was passed to I nitializeRootHpc() . The HPC’s configuration space must be accessible at the specified HpcPciAddress until this function returns control.

The padding is returned in the form of ACPI (2.0 & 3.0) resource descriptors. The exact definition of each of the fields is the same as in the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SubmitResources() function. See the PCI HostBridge Code Definitions for the definition of this function.

The PCI bus driver is responsible for adding this resource request to the resource requests by the physical PCI devices. If Attributes is EfiPaddingPciBus, the padding takes effect at the PCI bus level. If Attributes is EfiPaddingPciRootBridge, the required padding takes effect at the root bridge level. For details, see the definition of EFI_HPC_PADDING_ATTRIBUTES in “Related Definitions” below.

Note that the padding request cannot ask for specific legacy resources such as COM port addresses. Legacy PC Card devices may require such resources. Supporting these resource requirements is outside the scope of this specification.

//****************************************************\*
// EFI_HPC_PADDING_ATTRIBUTES
//****************************************************\*
// Describes how resource padding should be applied

typedef enum {
  EfiPaddingPciBus,
  EfiPaddingPciRootBridge
} EFI_HPC_PADDING_ATTRIBUTES;

Following is a description of the fields in the above definition.

Table 12.20 EFI_HPC_PADDING_ATTRIBUTES field descriptions

EfiPaddingPciBus

Apply the padding at a PCI bus level In other words the resources that are allocated to the bus containing hot plug slots are padded by the specified amount If the hot plug bus is behind a PCI to PCI bridge the PCI to PCI bridge apertures will indicate the padding

EfiPaddingPciRootBridge

Apply the padding at a PCI root bridge level If a PCI root bridge includes more than one hot plug bus the resource padding requests for these buses are added together and the resources that are allocated to the root bridge are padded by the specified amount This strategy may reduce the total amount of padding but requires reprogramming of PCI to PCI bridges in a hot add event If the hot plug bus is behind a PCI to PCI bridge the PCI to PCI bridge apertures do not indicate the padding for that bus

Status Codes Returned

EFI_SUCCESS

The resource padding was successfullyreturned.

EFI_UNSUPPORTED

This instance of the*EFI_PCI_HOT_PLUG_INIT_PROTOCOL* does not support the specified HPC.

EFI_NOT_READY

This function was called before HPCinitialization is complete.

EFI_INVALID_PARAMETER

HpcState is NULL.

EFI_INVALID_PARAMETER

Padding is NULL.

EFI_INVALID_PARAMETER

Attributes is NULL.

EFI_OUT_OF_RESOURCES

ACPI (2.0 & 3.0) resource descriptors for Padding cannot be allocated due to insufficient resources.

12.7. PCI Hot Plug Request Protocol

A hot-plug capable PCI bus driver should produce the EFI PCI Hot Plug Request protocol. When a PCI device or a PCI-like device (for example, 32-bit PC Card) is installed after PCI bus does the enumeration, the PCI bus driver can be notified through this protocol. For example, when a 32-bit PC Card is inserted into the PC Card socket, the PC Card bus driver can call interface of this protocol to notify PCI bus driver to allocate resource and create handles for this PC Card.

Summary

Provides services to notify PCI bus driver that some events have happened in a hot-plug controller (for example, PC Card socket, or PHPC), and ask PCI bus driver to create or destroy handles for the PCI-like devices.

GUID

#define EFI_PCI_HOTPLUG_REQUEST_PROTOCOL_GUID \
  {0x19cb87ab,0x2cb9,0x4665,0x83,0x60,0xdd,0xcf,0x60,0x54,\
  0xf7,0x9d}

Protocol Interface Structure

typedef struct \_EFI_PCI_HOTPLUG_REQUEST_PROTOCOL {
  EFI_PCI_HOTPLUG_REQUEST_NOTIFY Notify;
} EFI_PCI_HOTPLUG_REQUEST_PROTOCOL;

Parameters

Notify

Notify the PCI bus driver that some events have happened in a hot-plug controller (for example, PC Card socket, or PHPC), and ask PCI bus driver to create or destroy handles for the PCI-like devices. See Section 0 for a detailed description.

Description

The EFI_PCI_HOTPLUG_REQUEST_PROTOCOL is installed by the PCI bus driver on a separate handle when PCI bus driver starts up. There is only one instance in the system. Any driver that wants to use this protocol must locate it globally.

The EFI_PCI_HOTPLUG_REQUEST_PROTOCOL allows the driver of hot-plug controller, for example, PC Card Bus driver, to notify PCI bus driver that an event has happened in the hot-plug controller, and the PCI bus driver is requested to create (add) or destroy (remove) handles for the specified PCI-like devices. For example, when a 32-bit PC Card is inserted, this protocol interface will be called with an add operation, and the PCI bus driver will enumerate and start the devices inserted; when a 32-bit PC Card is removed, this protocol interface will be called with a remove operation, and the PCI bus driver will stop the devices and destroy their handles.

The existence of this protocol represents the capability of the PCI bus driver. If this protocol exists in system, it means PCI bus driver is hot-plug capable, thus together with the effort of PC Card bus driver, hot-plug of PC Card can be supported. Otherwise, the hot-plug capability is not provided.

12.7.1. EFI_PCI_HOTPLUG_REQUEST_PROTOCOL.Notify()

Summary

This function is used to notify PCI bus driver that some events happened in a hot-plug controller, and the PCI bus driver is requested to start or stop specified PCI-like devices.

Prototype

typedef
EFI_STATUS
(EFIAPI *EFI_PCI_HOTPLUG_REQUEST_NOTIFY) (
  IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL  *This,
  IN EFI_PCI_HOTPLUG_OPERATION         Operation,
  IN EFI_HANDLE                        Controller,
  IN EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath OPTIONAL,
  IN OUT UINT8                         NumberOfChildren,
  IN OUT EFI_HANDLE                    *ChildHandleBuffer
  );

Parameters

This

A pointer to the EFI_PCI_HOTPLUG_REQUEST_PROTOCOL instance. Type EFI_PCI_HOTPLUG_REQUEST_PROTOCOL is defined in Section 0.

Operation

The operation the PCI bus driver is requested to make. See “Related Definitions” for the list of legal values.

Controller

The handle of the hot-plug controller.

RemainingDevicePath

The remaining device path for the PCI-like hot-plug device. It only contains device path nodes behind the hot-plug controller. It is an optional parameter and only valid when the Operation is a add operation. If it is NULL, all devices behind the PC Card socket are started.

NumberOfChildren

The number of child handles. For a add operation, it is an output parameter. For a remove operation, it’s an input parameter. When it contains a non-zero value, children handles specified in ChildHandleBuffer are destroyed. Otherwise, PCI bus driver is notified to stop managing the controller handle.

ChildHandleBuffer

The buffer which contains the child handles. For a add operation, it is an output parameter and contains all newly created child handles. For a remove operation, it contains child handles to be destroyed when NumberOfChildren contains a non-zero value. It can be NULL when NumberOfChildren is 0. It’s the caller’s responsibility to allocate and free memory for this buffer.

Description

This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has happened on the hot-plug controller. Currently, the operations include add operation and remove operation.

If it is a add operation, the PCI bus driver will enumerate, allocate resources for devices behind the hot-plug controller, and create handle for the device specified by RemainingDevicePath. The RemainingDevicePath is an optional parameter. If it is not NULL, only the specified device is started; if it is NULL, all devices behind the hot-plug controller are started. The newly created handles of PC Card functions are returned in the ChildHandleBuffer , together with the number of child handle in NumberOfChildren .

If it is a remove operation, when NumberOfChildren contains a non-zero value, child handles specified in ChildHandleBuffer are stopped and destroyed; otherwise, PCI bus driver is notified to stop managing the controller handle.

//******************************************************\*
// EFI PCI HOTPLUG NOTIFY OPERATION
//******************************************************\*
typedef enum {
  EfiPciHotPlugRequestAdd,
  EfiPciHotplugRequestRemove
} EFI_PCI_HOTPLUG_OPERATION;
EfiPciHotplugRequestAdd

The PCI bus driver is requested to create handles for the specified devices. An array of EFI_HANDLE is returned, a NULL element marks the end of the array.

EfiPciHotplugRequestRemove

The PCI bus driver is requested to destroy handles for the specified devices.

Status Codes Returned

EFI_SUCCESS

The handles for the specified device have been created or destroyed as requested and for an add operation the new handles are returned in ChildHandleBuffer

EFI_INVALID_PARAMETER

Operation is not a legal value

EFI_INVALID_PARAMETER

Controller is NULL or not a valid handle

EFI_INVALID_PARAMETER

NumberOfChildren is NULL

EFI_INVALID_PARAMETER

ChildHandleBuffer is NULL while Operation is ìremoveî and NumberOfChildren contains a non zero value

EFI_INVALID_PARAMETER

ChildHandleBuffer is NULL while Operation is ìaddî

EFI_OUT_OF_RESOURCES

There are no enough resources to start the devices

12.8. Sample Implementation for a Platform Containing PCIHot Plug* Slots

Typically, the PCI bus driver will enumerate and allocate resources to all devices for a PCI host bridge. A sample algorithm for PCI bus enumeration is described below to clarify some of the finer points of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL . Actual implementations may vary although the relative ordering of events is critical. The activities related to PCI Hot Plug* are underlined. Please note that hot plug PCI devices may require that multiple passes of bus enumeration are required.

There are several phases during the PCI bus enumeration process when PCI hot plug slots are present. At each phase, the PlatformNotify function of the EFI_PCI_PLATFORM_PROTOCOL and EFI_PCI_OVERRIDE_PROTOCOL will be called with the execution phase BeforePciHostBridge. Then the PCI host bridge driver function NotifyPhase is called. Finally, the PlatformNotify functions are called again, but with the execution phase AfterPciHostBridge .

  1. If the platform supports PCI Hot Plug, an instance of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL is installed.

  2. The PCI enumeration process begins.

  3. Look for instances of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL . If it is not found, all the hot-plug subsystem initialization steps can be skipped. If one exists, create a list of root Hot Plug Controllers (HPCs) by calling EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetRootHpcList() .

  4. Notify the drivers using EfiPciHostBridgeBeginBusAllocation .

  5. For every PCI root bridge handle, do the following:

  • Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.StartBusEnumeration ( This, RootBridgeHandle ).

  • Make sure each PCI root bridge handle supports the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL . See the UEFI 2.1`Specification for the definition of the PCI Root Bridge I/O Protocol.

  • Allocate memory to hold resource requirements.

  • Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.GetAllocAttributes() to get the attributes of this PCI root bridge. This information is used to combine different types of memory resources in the next step.

Scan all the devices in the specified bus range and the specified segment, one bus at a time. If the device is a PCI-to-PCI bridge, update the bus numbers and program the bus number registers in the PCI-to-PCI bridge hardware. If the device path of a device matches that of a root HPC and it is not a PCI-to-CardBus bridge, it must be initialized by calling EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc() before the bus it controls can be fully enumerated. The PCI bus enumerator determines the PCI address of the PCI Hot Plug Controller (PHPC) and passes it as an input to InitializeRootHpc() .

  • Continue to scan devices on that root bridge and start the initialization of all root HPCs.

  • Call EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SetBusNumbers() so that the HPCs under initialization are still accessible. SetBusNumbers() cannot affect the PCI addresses of the HPCs.

  1. Wait until all the HPCs that were found on various root bridges in step 5 to complete initialization.

  2. Go back to step 5 for another pass and rescan the PCI buses. For all the root HPCs and the nonroot HPCs, call EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding() to obtain the amount of overallocation and add that amount to the requests from the physical devices. Reprogram the bus numbers by taking into account the bus resource padding information. This action requires calling EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.SetBusNumbers() . The rescan is not required if there is only one root bridge in the system.

Once the memory resources are allocated and a PCI-to-CardBus bridge is part of the HpcList, it will be initialized.