To provide support for using-system to using-system communications through the SSA target-mode device driver.
#include </usr/include/sys/devinfo.h>
#include </usr/include/sys/tmscsi.h>
#include </usr/include/sys/scsi.h>
#include </usr/include/sys/tmssa.h>
The Serial Storage Architecture (SSA) target-mode device driver provides an interface to allow using-system to using-system data transfer by using an SSA interface.
You can access the data transfer functions through character special files that are named dev/tmssann.xx, where nn is the node number of the node with which you are communicating. The xx can be either im (initiator-mode interface), or tm (target-mode interface). The caller uses the initiator-mode to transmit data, and the target-mode interface to receive data.
When the caller opens the initiator-mode special file, a logical path is set up. This path allows data to be transmitted. The user-mode caller issues a write, writev, writex, or writevx system call to start sending data. The kernel-mode user issues an fp_write or fp_rwuio service call to start sending data. The SSA target-mode device driver then builds a send command to describe the transfer, and the data is sent to the device. The data can be sent as a blocking write operation, or as a nonblocking write operation. When the write entry point returns, the calling program can access the transmit buffer.
When the caller opens the target-mode special file, a logical path is set up. This path allows data to be received. The user-mode caller issues a read, readv, readx, or readvx system call to start receiving data. The kernel-mode caller issues an fp_read or fp_rwuio service call to start receiving data. The SSA target-mode device driver then returns data that has been received for the application program.
The SSA target mode device driver allows an initiator-mode device to get access to the data transfer functions through the write entry point; it allows a target-mode device to get access through the read entry point.
The only rules that the SSA target mode device driver observes to manage the sending and receiving of data are:
The calling program must observe any other rules that are needed to maintain, or otherwise manage, the communication of data. Delays that occur when data is received or sent through the target mode device driver are that are characteristics of the hardware and software driver environment.
When tmssan is configured (where n is the remote node number), the tmssan.im and tmssan.tm special files are both created. An initiator-mode pair, or a target-mode pair, must exist for each device, whether either or both modes are being used. The target-mode node number for an attached device must be the same as the initiator-mode node number.
Each time that you use the cfgmgr command to configure the node, the target-mode device driver finds the remote nodes that are already connected, and automatically configures them. Each node is expected to be identified by a unique node number.
The target-mode device driver configuration entry point must be called only for the initiator-mode device number. The device driver configuration routine automatically creates the configuration data for the target-mode device minor number. This data is related to the initiator-mode data.
The target-mode device driver provides support for the following subroutines:
The open subroutine allocates and initializes target, or initiator, device-dependent structures. No commands are sent to the device as a result of running the open subroutine.
The initiator-mode device or target-mode device must be configured but not already opened for that mode; otherwise, the open subroutine does not work. Before the initiator-mode device can be successfully opened, its special file must be opened for write operations only. Before the target-mode device can be successfully opened, its special file must be opened for read operations only.
Possible return values for the errno global variable include:
The close subroutine deallocates resources that are local to the target device driver for the target or initiator device. No commands are sent to the device as a result of running the close subroutine.
Possible return values for the errno global variable include:
Support for the read subroutine is provided only for the target-mode device. Support for data scattering is provided through the user-mode readv or readvx subroutine, or through the kernel-mode fp_rwuio service call. If the read subroutine is not successful, the return value is set to -1, and the errno global variable is set to the return value from the device driver. If the return value is something other than -1, the read operation was successful, and the return code indicates the number of bytes that were read. The caller should verify the number of bytes that were read. File offsets are not applicable and are ignored for target-mode read operations.
The adapter write operations provide the boundary that determines how read requests are controlled. If more data is received than is requested in the current read operation, the requested data is passed to the caller, and the remaining data is retained and returned for the next read operation for this target device. If less data is received in the send command than is requested, the received data is passed for the read request, and the return value indicates how many bytes were read.
If a write operation has not been completely received when a read request is made, the request blocks and waits for data. However, if the target device is opened with the O_NDELAY flag set, the read does not block; it returns immediately. If no data is available for the read request, the read is not successful, and the errno global variable is set to EAGAIN. If data is available, it is returned. The return value indicates the number of bytes that were received, whether the write operation for this data has ended or not.
Note: If the O_NDELAY flag is not set, the read subroutine can for an undefined time while it waits for data. Because, in a read operation, the data can come at any time, the device driver does not maintain an internal timer to interrupt the read. Therefore, if a time-out function is required, it must be started by the calling program.
If the calling program wants to break a blocked read subroutine, the program can generate a signal. The target-mode device driver receives the signal and ends the current read subroutine. If no bytes were read, the errno global variable is set to EINTR; otherwise, the return value indicates the amount of data that was read before the interrupt occurred. The read operation returns with whatever data has been received, whether the write operation has completed or not. If the remaining data for the write operation is received, it is put into a queue, where it waits for either another read request or a close command. When the target receives the signal and the current read is returned, another read operation can be started, or the target can be closed. If the read request that the calling program wants to break ends before the signal is generated, the read operation ends normally, and the signal is ignored.
The target-mode device driver attempts to queue received data in front of requests from the application program. A read-ahead buffer area is used to store the queued data. The length of this read-ahead buffer is determined by multiplying the value of the RecvBufferSize attribute by the value of the RecvBuffers attribute. These values are in the configuration database. While the application program runs read subroutines, the queued data is copied to the application data buffer, and the read-ahead buffer space is again made available for received data. If an error occurs while he data is being copied to the caller data buffer, the read operation fails, and the errno global variable is set to EFAULT. If the read subroutines are not run quickly enough to fill almost all the read-ahead buffers for the device, data reception is delayed until the application program runs a read subroutine again. When enough area is freed, data reception capability is restored from the device. Data might be delayed, but it is not lost or ignored.
The target-mode device driver controls only received data into its read entry point. The read entry point can optionally be used with the select entry point to provide a means of asynchronous notification of received data on one or more target devices.
Possible return values for the errno global variable include:
Support for the write entry point is provided only for the initiator-mode device driver. The write entry point generates one write operation in response to a calling program write request. If the device is opened with the O_NDELAY flag set, and the write request is for a length that is greater than the total buffer size of the device, the write request fails . The errno global variable is set to EINVAL. The total buffer size for the device is determined by multiplying the value of the XmitBufferSize attribute by the value of the XmitBuffers attribute. These values are in the configuration database.
Support for data gathering is through the user-mode writev or writevx subroutine, or through the kernel-mode fp_rwuio service call. The write buffers are gathered so that they are transferred, in sequence, as one write operation. The returned errno global variable is set to EFAULT if an error occurs while the caller data is being copied to the device buffers.
If the write operation is unsuccessful, the return value is set to -1 and the errno global variable is set to the value of the return value from the device driver. If the return value is other than -1, the write operation was successful and the return value indicates the number of bytes that were written. The caller should validate the number of bytes that are sent to check for any errors. Because the whole data transfer length is sent in a single write operation, you should suspect that a return code that is not equal to the expected total length is an error. File offsets are not applicable, and are ignored for target-mode write operations.
If the calling program needs to break a blocked write operation, a signal is generated. The target-mode device driver receives that signal, and ends the current write operation. The write operation that is in progress fails, and the errno global variable is set to EINTR. The write operation returns the number of bytes that were already sent, before the signal was generated. The calling program can then continue by issuing another write operation or an ioctl operation, or it can close the device. If the write operation that the caller attempts to break completes before the signal is generated, the write operation ends normally, and the signal is ignored.
If the buffers of remote using systems are full, or no device response status is received for the write operation, the target-mode device driver automatically retries the write operation. It retries the operation up to the number of times that is specified by the value TM_MAXRETRY. This value is defined in the /usr/include/sys/tmscsi.h file. By default, the target mode device driver delays each retry attempt by approximately two seconds to allow the target device to respond successfully. The caller can change the time delayed through the TMCHGIMPARM operation. If the write operation is still unsuccessful after the specified number of retries, it tries another SSA adapter. If this write operation has already tried all the SSA adapters, it fails. The calling program can retry the write operation, or perform other appropriate error recovery. No other error conditions are retried, but are returned with the appropriate errno global variable.
The target-mode device driver, by default, generates a time-out value, which is the amount of time allowed for the write operation to end. If the write operation does not end before the time-out value expires, the write operation fails. The time-out value is related to the length of the requested transfer, in bytes, and is calculated as follows:
timeout_value = ((transfer_length / 65536) + 1) * 20
In the calculation, 20 is the default scaling factor that generates the time-out value. The caller can customize the time-out value through the TMCHGIMPARM operation. The actual period that elapses before a timeout occurs can be up to 10 seconds longer than the calculated value, because it is related to the operation of the hardware at the time of the write operation. A time-out value of zero means that no time-out occurs. A value of zero is not allowed when the write operation is nonblocking, because a deadlock might occur. Under this condition, EINVAL is returned for the write operation.
If the caller opened the initiator-mode device with the O_NDELAY flag set, the write operation is nonblocking. In this mode, the device checks whether enough buffer space is available for the write operation. If enough buffer space is not available, the write operation fails, and the errno global variable is set to EAGAIN. If enough buffer space is available, the write operation immediately ends with all the data written successfully. The write operation now occurs asynchronously. If you want to track the progress of this write operation, use the TMIOSTAT operation. The driver keeps the status of the last write operation, which is then reported by the TMIOSTAT operation.
Possible return values for the errno global variable include:
Do the appropriate error recovery routine.
The following ioctl operations are provided by the target-mode device driver. Some are specific to either the target-mode device or the initiator-mode device. All require the respective device instance be open for the operation run.
Possible return values for the errno global variable include:
The select entry point allows the caller to know when a specified event has occurred on one or more target-mode devices. The event input parameter allows the caller to specify about which of one or more conditions it wants to be notified by a bitwise OR of one or more flags. The target-mode device driver provides support for the following select events:
The additional events, POLLOUT and POLLPRI, are not applicable. The target-mode device driver does not, therefore, provide support for them.
The reventp output parameter points to the result of the conditional checks. The device driver can return a bitwise OR of the following flags:
The chan input parameter is used for specifying a channel number. This parameter is not applicable for nonmultiplexed device drivers. It should be set to 0 for the target-mode device driver.
The POLLIN event is indicated by the device driver when any data is received for this target instance. A nonblocking read subroutine, if subsequently issued by the caller, returns data. For a blocking read subroutine, the read does not return until either the requested length is received, or the write operation ends, whichever comes first.
Asynchronous notification of the POLLIN event occurs when received data is available. This notification occurs only if the select event POLLSYNC was not set.
The initiator-mode device driver provides support for the following select events:
An additional event POLLIN is not applicable and has no support from the initiator-mode device driver.
The reventp output parameter points to the result of the conditional checks. The device driver can return a bitwise OR of the following flags:
Asynchronous notification of the POLLOUT event occurs when buffer space is made available for further write operations.
Asynchronous notification of the POLLPRI event occurs if an error occurs with a write operation. Note that the error might be recovered successfully by the device driver.
Possible return values for the errno global variable include:
Errors that are detected by the target-mode device driver can be one of the following:
The target-mode device driver passes error-recovery responsibility for all detected errors to the caller. For these errors, the target-mode device driver does not know if this type of error is permanent or temporary. These types of errors are handled as temporary errors.
Only errors that the target-mode device driver can itself recover through retry operations can be determined to be either temporary or permanent. The error is ignored if it succeeds during retry (a recovered error). The return code to the caller indicates success if a recovered error occurs, or failure if an unrecovered error occurs. The caller can retry the command or operation, but success is probably low for unrecovered errors.
TMSSA does no error logging. If an error occurs, that error might be logged by the adapter device driver.