18.3.2 Start() and Stop()
The Start()
service of the Driver Binding Protocol for a PCI driver also
opens the PCI I/O Protocol with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER
.
If the PCI driver is a bus or hybrid driver, the Device Path Protocol opens
using the attribute EFI_OPEN_PROTOCOL_BY_DRIVER
. A device driver is not required to open the
Device Path Protocol. In addition, all PCI drivers are required to call the Attributes()
service of the PCI I/O Protocol to enable the I/O, memory, and bus master bits
in the Command register of the PCI configuration header. By default, the PCI
bus driver is not required to enable the Command register of the PCI
controllers. Instead, it is the responsibility of the Start()
service to
enable these bits and that of the Stop()
service to restore these bits. In
order for the Stop()
service to restore the attributes, a PCI Driver
typically stores the original attributes in a UINT64
field of the private
context data structure.
There is one additional attribute that must be specified in this call to the
Attributes()
service. If the PCI controller is a bus master and capable of
generating 64-bit DMA addresses, the EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
attribute must also be enabled. Unfortunately, there is no standard method for
detecting if a PCI controller supports 32-bit or 64-bit DMA addresses. As a
result, it is the PCI driver's responsibility to inform the PCI bus driver that
the PCI controller is capable of producing 64-bit DMA addresses.
The PCI bus driver assumes that all PCI controllers are only capable of generating 32-bit DMA addresses unless the PCI driver enables the dual address cycle attribute.
The PCI bus driver uses this information along with the services of the PCI
Root Bridge I/O Protocol to perform PCI DMA transactions. If a PCI bus master that is
capable of 32-bit DMA addresses is present in a platform supporting more than 4
GB of system memory, the DMA transactions may have to be double buffered.
Double buffering can reduce the performance of a driver. It is also possible
for some platforms to only support system memory above 4 GB. For these reasons,
a PCI driver must always accurately describe the DMA capabilities of the PCI
controller from the Start()
service of the Driver Binding Protocol.
The example below shows the code fragment from the Start()
services of a PCI
driver for a PCI controller supporting 64-bit DMA transactions. The example
opens the PCI I/O Protocol attribute of EFI_OPEN_PROTOCOL_BY_DRIVER
. It then
retrieves the current set of PCI I/O Protocol attributes and saves them in the
private context data structure field called ABC_PRIVATE_DATA
. It then
determines what attribute the PCI I/O Protocol supports and enables the I/O
decode, MMIO decode, and Bus Master, and Dual Address Cycle capabilities. If a
PCI Controller does not support DAC, the only change is the removal of
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
from the last call to the
Attributes()
service of the PCI I/O Protocol.
Example 171-Start() for a 64-bit DMA-capable PCI controller
#include <Uefi.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/PciIo.h>
#include <Library/UefiBootServicesTableLib.h>
typedef struct {
UINTN Signature;
//
// . .
//
UINT64 OriginalPciAttributes;
} ABC_PRIVATE_DATA;
EFI_STATUS Status;
EFI_DRIVER_BINDING_PROTOCOL *This;
EFI_HANDLE ControllerHandle;
ABC_PRIVATE_DATA *Private;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 PciSupports;
//
// Open the PCI I/O Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Retrieve original PCI attributes and save them in the private context data
// structure.
//
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationGet,
0,
&Private->OriginalPciAttributes
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Retrieve attributes that the PCI Controller supports
//
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationSupported,
0,
&PciSupports
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Enable Command register and Dual Address Cycle
//
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationEnable,
(PciSupports & EFI_PCI_DEVICE_ENABLE) |
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
NULL
);
if (EFI_ERROR (Status)) {
goto Done;
}
This example shows the code fragment from the Stop()
services of a PCI driver.
This example restores the PCI I/O Protocol attributes from a field of the
private context data structure called ABC_PRIVATE_DATA
.
Example 172-Restore PCI Attributes in Stop()
#include <Uefi.h>
#include <Protocol/PciIo.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
ABC_PRIVATE_DATA *Private;
//
// Restore original PCI attributes
//
PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationSet,
Private->OriginalPciAttributes,
NULL
);
//
// Close the PCI I/O Protocol
//
gBS->CloseProtocol (
ControllerHandle,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
The following table lists the #define
statements compatible with the
Attributes()
service. A PCI driver must use the Attributes()
service to
enable the decodes on the PCI controller, accurately describe the PCI
controller DMA capabilities, and request that specific I/O cycles are forwarded
to the device. The call to Attributes()
fails if the request cannot be
satisfied. If this failure occurs, the Start()
function must return an error.
Once again, any attributes enabled in the Start()
service must be restored in
the Stop()
service.
Table 26-PCI Attributes
Attribute | Description |
---|---|
EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO |
Used to request the forwarding of I/O cycles 0x0000-0x00FF (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_ISA_IO |
Used to request the forwarding of I/O cycles 0x100-0x3FF (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO |
Used to request the forwarding of I/O cycles 0x3C6, 0x3C8, and 0x3C9 (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
Used to request the forwarding of MMIO cycles 0xA0000-0xBFFFF (24-bit decode). |
EFI_PCI_IO_ATTRIBUTE_VGA_IO |
Used to request the forwarding of I/O cycles 0x3B0-0x3BB and 0x3C0- 0x3DF (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |
Used to request the forwarding of I/O cycles 0x1F0-0x1F7, 0x3F6, 0x3F7 (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO |
Used to request the forwarding of I/O cycles 0x170-0x177, 0x376, 0x377 (10-bit decode). |
EFI_PCI_IO_ATTRIBUTE_IO |
Enable the I/O decode bit in the Command register. |
EFI_PCI_IO_ATTRIBUTE_MEMORY |
Enable the Memory decode bit in the Command register. |
EFI_PCI_IO_ATTRIBUTE_BUS_MASTER |
Enable the Bus Master bit in the Command register. |
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE |
Clear for PCI controllers that cannot generate a DAC. |
EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 |
Used to request the forwarding of I/O cycles 0x100-0x3FF (16-bit decode). |
EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 |
Used to request the forwarding of I/O cycles 0x3C6, 0x3C8, and 0x3C9 (16-bit decode). |
EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |
Used to request the forwarding of I/O cycles 0x3B0-0x3BB and 0x3C0- 0x3DF (16-bit decode). |
The table below, lists #define
statements not part of the UEFI
Specification, but which are included in EDK II to simplify PCI driver
implementations. These attributes cover the typical classes of hardware
capabilities and provide a names for common combinations of attributes
described in the PCI Bus Support chapter of the UEFI Specification.
TIP: For code readability, the Enable attributes included in EDK II should be used.
Table 27-EDK II attributes #defines
Attribute | Description |
---|---|
EFI_PCI_DEVICE_ENABLE |
Equivalent to a logical OR combination of EFI_PCI_IO_ATTRIBUTE_IO , 'EFI_PCI_IO_ATTRIBUTE_MEMORY, and EFI_PCI_IO_ATTRIBUTE_BUS_MASTER`. |
EFI_VGA_DEVICE_ENABLE |
Equivalent to a logical OR combination of EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO , EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY , EFI_PCI_IO_ATTRIBUTE_VGA_IO , and EFI_PCI_IO_ATTRIBUTE_IO . |
This table lists the #define
statements that to use with the
GetBarAttributes()
and SetBarAttributes()
services to adjust the attributes
of a memory-mapped I/O region described by a Base Address Register (BAR) of a
PCI controller. The support of these attributes is optional, but in general, a
PCI driver uses these attributes to provide hints that may be used to improve
the performance of a PCI driver. Improved performance is especially important
for PCI drivers managing graphics controllers. Do note that any BAR attributes
set in the Start()
service must be restored in the Stop()
service.
Table 28-PCI BAR attributes
Attribute | Description |
---|---|
EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
Setting this bit enables platform support for memory range access in a write-combining mode. It improves write performance to a memory buffer on a PCI controller. By default, PCI memory ranges are not accessed in a write combining mode. |
EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
Setting this bit enables platform support for changing the attributes of a PCI memory range so that it is accessed in a cached mode. By default, PCI memory ranges are not cached. |
EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
Setting this bit enables platform support for disabling a PCI memory range so that it can no longer be accessed. By default, all PCI memory ranges are enabled. |
Sometimes there may be different logic paths in a UEFI Driver between a PCI
add-in card and a PCI controller integrated into a platform. The PCI I/O
Protocol provides attributes that help a UEFI Driver determine if a specific
PCI Controller and its associated PCI Option ROM image are from a PCI add-in
card in a PCI slot or if they are integrated into a platform. The attributes
shown in the following table list the #define
statements for these
attributes. These attributes are read-only and the values are established by
the PCI Bus Driver when a PCI Controller is discovered and the PCI I/O Protocol
is produced. A PCI driver may retrieve the attributes of a PCI controller with
the Attributes()
service of the PCI I/O Protocol, but a PCI Driver is not
allowed to modify these attributes.
Table 29-PCI Embedded Device Attributes
Attribute | Description |
---|---|
EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
If this bit is set, the PCI controller is an embedded device; typically a component on the system board. If this bit is clear, the PCI controller is part of an adapter populating one of the systems PCI slots. |
EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
If this bit is set, the PCI option ROM described by the RomImage and RomSize fields is not from ROM BAR of the PCI controller. If this bit is clear, the RomImage and RomSize fields were initialized based on the PCI option ROM found through the ROM BAR of the PCI controller. |