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:
-
link – This function is called whenever a link event is generated within the HAL. This is generated whenever the link is disrupted or established.
-
unsolicited – This function is called whenever new data is received in the SLI-4 receive queue.
-
connection – This function is called for remote node events, such as a new incoming connection, a target data disgest occurred, or the firmware has invalidated the connection.
The iSCSI 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, connections).
-
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.
-
After initializing the device, the driver can provide buffers to receive unsolicited frames (ocs_hal_rxbuffer()).
-
The driver must also configure the IP network. The simplest way is to add a static IP address using ocs_hal_portal_portal_ip_add() and to start listening on that address using ocs_hal_portal_listen_start(). When the link comes up, the HAL notifies the driver using the link callback function. This is the starting point of the driverís interaction with the common objects.
Allocating and Using Common Objects
Common objects provide a mechanism through which the various OneCore Storage driver components share and track information. The main objects are:
-
SCSI domain – For iSCSI, the SCSI domain is maintained internally by the driver, and typically contains information on available iSCSI targets. The creation of domains is under the control of the iSCSI driver. However, a pointer to the domain must be registered with the HAL via the ocs_hal_domain_add() function.
-
SLI Port (sport) – Represents the SLI Port and tracks the various VLANs. The creation of SLI Port objects is under the control of the iSCSI driver.
-
Connection – the connection between the SLI Port and another device in the SCSI domain.
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, iSCSI Driver Common Objects:
The first step to create a connection to the SCSI domain is by allocating an SLI Port object. The iSCSI device creates a default interface handle that may be used if no VLANs are desired. The value of this handle may be retrieved by the driver through the
ocs_hal_portal_get_default() function. On identifying a domain, the driver allocates a domain object and attaches to it using the previous SLI Port object. 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 sending a request for available targets, querying an iSNS server, or an using an out-of-band method. It is necessary to log in with devices before performing I/Os. Prior to sending login-related protocol data units (PDUs) by using
ocs_hal_io_send(), the driver must allocate a remote node object (
ocs_hal_cxn_alloc()). If the login negotiation is successful, then the driver may start exchanging I/Os.
Sending and Receiving I/Os
Since 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:
-
Disable the interrupts to prevent receiving further data and events.
-
Destroy the HAL object (ocs_hal_teardown()).
-
Free any memory used by the HAL, such as buffers for unsolicited data.