The Hardware Abstraction Layer (HAL) insulates the higher-level code from the SLI-4 message details, but the higher level code must still manage domains, ports, IT nexuses, and IOs. The HAL API is designed to help the higher level manage these objects.
The HAL uses function callbacks to notify the higher-level code of events that are received from the chip. There are currently three types of functions that may be registered:
-
domain – This function is called whenever a domain event is generated within the HAL. Examples include a new FCF is discovered, a connection to a domain is disrupted, and allocation callbacks.
-
unsolicited – This function is called whenever new data is received in the SLI-4 receive queue.
-
rnode – This function is called for remote node events, such as attach status and allocation callbacks.
The FC/FCoE HAL component builds upon the SLI-4 component to establish a flexible interface for creating the necessary common objects and sending I/Os. It may be used “as is” in customer implementations or it can serve as an example of typical interactions between a driver and the SLI-4 hardware. The broad categories of functionality include:
-
Setting-up and tearing-down of the HAL.
-
Allocating and using the common objects (SLI Port, domain, remote node).
-
Sending and receiving I/Os.
HAL Setup
To set up the HAL:
-
Set up the HAL object using ocs_hal_setup().
This step performs a basic configuration of the SLI-4 component and the HAL to enable querying the hardware for its capabilities. At this stage, the HAL is not capable of general operations (such as, receiving events or sending I/Os).
-
Configure the HAL according to the driver requirements.
The HAL provides functions to discover hardware capabilities (ocs_hal_get()), as well as configures the amount of resources required (ocs_hal_set()). The driver must also register callback functions (ocs_hal_callback()) to receive notification of various asynchronous events.
Note: Once configured, the driver must initialize the HAL (ocs_hal_init()). This step creates the underlying queues, commits resources to the hardware, and prepares the hardware for operation. While the hardware is operational, the port is not online, and cannot send or receive data.
-
Finally, the driver can bring the port online (ocs_hal_port_control()).
When the link comes up, the HAL determines if a domain is present and notifies the driver using the domain callback function. This is the starting point of the driver's interaction with the common objects.
Note: For FCoE, there may be more than one domain available and, therefore, more than one callback.
Allocating and Using Common Objects
Common objects provide a mechanism through which the various OneCore Storage driver components share and track information. These data structures are primarily used to track SLI component information but can be extended by other components, if needed. The main objects are:
-
DMA – the ocs_dma_t object describes a memory region suitable for direct memory access (DMA) transactions.
-
SCSI domain – the ocs_domain_t object represents the SCSI domain, including any infrastructure devices such as FC switches and FC forwarders. The domain object contains both an FCFI and a VFI.
-
SLI Port (sport) – the ocs_sli_port_t object represents the connection between the driver and the SCSI domain. The SLI Port object contains a VPI.
-
Remote node – the ocs_remote_node_t represents a connection between the SLI Port and another device in the SCSI domain. The node object contains an RPI.
Before the driver can send I/Os, it must allocate the SCSI domain, SLI Port, and remote node common objects and establish the connections between them. The goal is to connect the driver to the SCSI domain to exchange I/Os with other devices. These common object connections are shown in the following figure, FC Driver Common Objects:
The first step is to create a connection to the domain by allocating an SLI Port object. The SLI Port object represents a particular FC ID and must be initialized with one. With the SLI Port object, the driver can discover the available SCSI domain(s). On identifying a domain, the driver allocates a domain object and attaches to it using the previous SLI port object.
Note: In some cases, the driver may need to negotiate service parameters (that is, FLOGI) with the domain before attaching.
Once attached to the domain, the driver can discover and attach to other devices (remote nodes). The exact discovery method depends on the driver, but it typically includes using a position map, querying the fabric name server, or an out-of-band method. In most cases, it is necessary to log in with devices before performing I/Os. Prior to sending login-related ELS commands (
ocs_hal_srrs_send()), the driver must allocate a remote node object (
ocs_hal_node_alloc()). If the login negotiation is successful, the driver must attach the nodes (
ocs_hal_node_attach()) to the SLI Port before exchanging FCP I/O.
Note: The HAL manages both the well known fabric address and the name server as nodes in the domain. Therefore, the driver must allocate node objects prior to communicating with either of these entities.
Sending and Receiving I/Os
The HAL provides separate interfaces for sending BLS/ ELS/ FC-CT and FCP, but the commands are conceptually similar. Since the commands complete asynchronously, the caller must provide a HAL I/O object that maintains the I/O state, as well as provide a callback function. The driver may use the same callback function for all I/O operations, but each operation must use a unique HAL I/O object. In the SLI-4 architecture, there is a direct association between the HAL I/O object and the SGL used to describe the data. Therefore, a driver typically performs the following operations:
HAL Tear Down
To tear-down the HAL:
-
Take the port offline (ocs_hal_port_control()) to prevent receiving further data andevents.
-
Destroy the HAL object (ocs_hal_teardown()).
-
Free any memory used by the HAL, such as buffers for unsolicited data.