scsi_ctl(7)
NAME
scsi_ctl − SCSI pass-through driver for sdisk, schgr, sflop, stape device drivers
DESCRIPTION
SCSI devices are controlled by a device-specific driver, when one exists. Device-specific drivers, such as those for SCSI direct access (disk) and sequential access (tape) devices coordinate device and driver states to accomplish correct logical device behavior. The scsi_ctl pass-through driver enables use of SCSI devices and commands not normally supported by these device-specific drivers.
A successful open() call by scsi_ctl requires no device I/O operations. This means that an open() call completes successfully even if there is no device at the indicated SCSI device address. Once open, ioctl() calls can be used to change SCSI communication parameters or attempt SCSI commands and other SCSI operations. Since the scsi_ctl does not attempt to logically understand the target device, read() and write() calls are not supported.
Except where noted, the ioctls described here are available through all SCSI device drivers (including device-specific drivers). Super-user privileges or device write permissions are required to use these ioctls through a SCSI device-specific driver. All reserved fields in the data structures associated with these ioctls must be zero-filled.
Special Device File Minor Number
The scsi_ctl driver is the preferred method to perform the SIOC_IO ioctl, rather than going through a device-specific driver (such as sdisk). To do this, you must create the device special file for scsi_ctl. Use mknod(1M), substituting the values in the minor number as noted:
/usr/sbin/mknod name c 203 0xiitl0o
where component parts of the minor number are constructed as follows:
ii Two hexadecimal digits, identifying the controlling interface card by its “Instance” number. The Instance value is displayed in ioscan(1M) output, under column I for the "Interface" hardware type.
t One hexadecimal digit identifying the drive or target address.
l One hexadecimal digit identifying the unit number (LUN) within the device.
0 Hexadecimal digit zero, for reserved portion of the minor number.
o Optional values as follows: 0, normal open (default); 1, ATN is not used with Select (for backward compatibility); or 2, inhibits Inquiry at open.
SCSI Communication Parameters
HP-UX supports the SCSI device protocol on parallel SCSI interfaces and Fibre Channel interfaces. The SCSI communication parameters described here may only apply to certain SCSI interfaces and are noted as such in the descriptions.
SCSI communication parameters control features related to communication for three different scope levels: bus (link), target and logical unit number (LUN). Bus communication parameters apply to all targets connected to a specific bus. Target communication parameters apply to all LUN s associated with a specific target. LUN communication parameters apply to a specific LUN. SCSI communication parameters apply to all device drivers (both device-specific and scsi_ctl).
At power-up and after being reset, all parallel SCSI devices and hosts communicate using asynchronous data transfers. Asynchronous data transfers use request (REQ) and acknowledge (ACK) signaling. The strict ordering of REQ and ACK signaling simplifies the communication protocol but limits I/O performance. A SCSI target and host pair may agree to use synchronous data transfers to increase I/O performance. Synchronous data transfers improve I/O performance by lessening the ordering requirements on REQ s and ACK s. By allowing multiple outstanding REQ s, signal propagation delays and temporary rate imbalances are better tolerated. To make use of synchronous data transfers, a SCSI target and host must negotiate to determine mutually acceptable maximum REQ-ACK -offset and data-transfer rate parameters. The maximum REQ-ACK -offset parameter indicates the maximum allowable number of outstanding REQ s. The value zero is used to indicate asynchronous data transfer. Other values indicate synchronous data transfer. The appropriate value is generally dependent on the size of the receive data FIFO. High values tend to improve data transfer rates. The maximum data-transfer rate parameter indicates the “burst” data transfer rate (minimum allowable time between successive synchronous data transfers). A SCSI synchronous data transfer request (SDTR) message, used to initiate the negotiation process, is associated with the processing of a SCSI command.
At power-up and after being reset, all parallel SCSI devices and hosts communicate using eight-bit data transfers. A SCSI target and host pair may agree to use sixteen- or thirty-two-bit (wide) data transfers to increase I/O performance. To make use of wide data transfers, a SCSI target and host must negotiate to determine a mutually acceptable data transfer width parameter. A SCSI wide data transfer request (WDTR) message, used to initiate the negotiation process, is associated with the processing of a SCSI command.
Some SCSI devices are able to simultaneously manage multiple active commands. Such a device has a command queue that holds commands for processing. Command queuing can improve I/O performance by reducing the time spent by the device waiting for new commands from the host. Note that command queuing may not improve I/O performance substantially for devices that support “read-ahead” and “immediate-reporting” (see scsi_disk(7) and scsi_tape(7)). The SCSI device and host use command tags to correctly manage these multiple simultaneously active commands. At all times when command queuing is in effect, each active command being handled by a specific LUN has a unique command tag.
SCSI devices indicate their ability to support the special communication features described above in their SCSI INQUIRY command data. Normally the SCSI INQUIRY command data and negotiation protocols allow hosts and devices to determine the optimal communication parameters so that I/O performance is maximized. The current operating communication parameters may be determined by use of the: SIOC_GET_LUN_PARMS, SIOC_GET_TGT_PARMS, and SIOC_GET_BUS_PARMS ioctls.
Occasionally, it is desirable to limit SCSI communication parameters to work around a communication problem or to provide external insight in determining optimal parameters. SCSI communication parameter limit suggestions can be specified by use of the: SIOC_SET_LUN_LIMITS, SIOC_SET_TGT_LIMITS, and SIOC_SET_BUS_LIMITS ioctls. Note that there may be substantial differences between specified communication parameter limit suggestions and the corresponding actual current communication parameters being used for communication. These differences are a result of device-specific driver capabilities, interface driver capabilities, interface hardware capabilities, device capabilities, delays due to the negotiation process, delays due to currently active commands, and delays due to commands waiting to be sent to devices. Note that communication parameter limit suggestions may not survive between close() and open() calls, when no SCSI device drivers (device-specific or scsi_ctl) have associated LUN (s) open.
The current SCSI communication parameter limit suggestions may be determined by use of the SIOC_GET_LUN_LIMITS, SIOC_GET_TGT_LIMITS, and SIOC_GET_BUS_LIMITS ioctls.
Logical unit communication parameters may be managed by use of the SIOC_GET_LUN_PARMS, SIOC_SET_LUN_LIMITS, and SIOC_GET_LUN_LIMITS ioctls. The SIOC_GET_LUN_PARMS ioctl indicates the current LUN communication parameter values. The flags field indicates what special communication features are in use. If the SCTL_ENABLE_TAGS flag is set, commands being sent to the corresponding LUN can be tagged in support of command queuing. If the SCTL_TAGS_ACTIVE flag is set, commands being sent to the corresponding LUN are currently being tagged for support of command queuing. The max_q_depth field indicates the current maximum number of simultaneously active commands the host might send to that LUN. Note that the SCTL_TAGS_ACTIVE flag may be set when the max_q_depth field contains the value “1” to indicate commands are being tagged but are still being serially processed. The SIOC_SET_LUN_LIMITS ioctl may be used to provide LUN communication parameter limit suggestions. The flags field indicates what special communication features should be used. Setting the SCTL_ENABLE_TAGS flag specifies that commands should be tagged. Clearing the SCTL_ENABLE_TAGS flag specifies that commands should not be tagged. The max_q_depth field specifies the maximum number of simultaneously active commands that should be attempted by the host. The SIOC_GET_LUN_LIMITS ioctl indicates the current LUN communication parameter limit suggestions.
Target communication parameters may be managed by use of the SIOC_GET_TGT_PARMS, SIOC_SET_TGT_LIMITS, and SIOC_GET_TGT_LIMITS ioctls to any associated LUN. The SIOC_GET_TGT_PARMS ioctl indicates the current target communication parameter values. The flags field indicates what special communication features are in use. If the SCTL_ENABLE_SDTR flag is set, synchronous data transfer request negotiation with the corresponding target is permitted. If the SCTL_SDTR_DONE flag is set, the synchronous data transfer request negotiation process has been completed and the negotiation results are available in the reqack_offset and xfer_rate fields. If the SCTL_ENABLE_WDTR flag is set, wide data transfer request negotiation with the corresponding target is permitted. If the SCTL_WDTR_DONE flag is set, the wide data transfer request negotiation process has been completed and the negotiation results are available in the width field. The width field indicates the current data transfer bus width in bits. The reqack_offset field indicates the current maximum number of outstanding REQ s being attempted. The value zero indicates asynchronous data transfer signaling is currently being used. The xfer_rate field indicates the current maximum “burst” data transfer rate in bytes per second. The SIOC_SET_TGT_LIMITS ioctl specifies the target communication parameter limit suggestions. The flags field specifies what special communication features should be used. Setting the SCTL_ENABLE_SDTR flag specifies that synchronous data transfer request negotiation with the corresponding target should be attempted when appropriate. Clearing the SCTL_ENABLE_SDTR flag specifies that synchronous data transfer request negotiation should not be attempted. Setting the SCTL_ENABLE_WDTR flag specifies that wide data transfer request negotiation with the corresponding target should be attempted when appropriate. Clearing the SCTL_ENABLE_WDTR flag specifies that wide data transfer request negotiation should not be attempted. The max_width field specifies maximum bus width that should be used for data transfers. The max_reqack_offset field specifies the maximum number of outstanding REQ s that should be attempted during data transfers. The max_xfer_rate field specifies the maximum “burst” data rate that should be allowed during data transfers. The SIOC_GET_TGT_LIMITS ioctl indicates the current target communication parameter limit suggestions. The SCTL_ENABLE_SDTR, SCTL_SDTR_DONE, SCTL_ENABLE_WDTR, SCTL_WDTR_DONE flags and width, reqack_offset, xfer_rate, max_width, max_reqack_offset, max_xfer_rate fields only apply to parallel SCSI.
Bus communication parameters may be managed by use of the SIOC_GET_BUS_PARMS, SIOC_SET_BUS_LIMITS, and SIOC_GET_BUS_LIMITS ioctls to any associated LUN. The SIOC_GET_BUS_PARMS ioctl indicates the current bus communication parameter values. The max_width field indicates the maximum data transfer width that will be attempted for data transfers to any target device connected to the associated bus. The max_reqack_offset field indicates the maximum number of outstanding REQ s that will be attempted during data transfers to any target device connected to the associated bus. The max_xfer_rate field indicates the maximum “burst” data transfer rate that will be attempted for data transfers to any target device connected to the associated bus. The SIOC_SET_BUS_LIMITS ioctl specifies the bus communication parameter limit suggestions for targets connected to the associated bus. The max_width field specifies the suggested maximum data transfer width that should be attempted for data transfers to any target device connected to the associated bus. The max_reqack_offset field specifies the maximum number of outstanding REQ s that should be attempted during data transfers to any target device connected to the associated bus. The max_xfer_rate field specifies the maximum “burst” data transfer rate that should be attempted for data transfers to any target device connected to the associated bus. The SIOC_GET_BUS_LIMITS ioctl indicates the current bus communication parameter limit suggestions. The max_width, max_reqack_offset and max_xfer_rate fields only apply to parallel SCSI.
The following is included from <sys/scsi.h>:
/* SCSI communication parameter ioctls */
#define SIOC_GET_LUN_PARMS _IOR(’S’, 58, struct sioc_lun_parms)
#define SIOC_GET_TGT_PARMS _IOR(’S’, 59, struct sioc_tgt_parms)
#define SIOC_GET_BUS_PARMS _IOR(’S’, 60, struct sioc_bus_parms)
#define SIOC_GET_LUN_LIMITS _IOR(’S’, 61, struct sioc_lun_limits)
#define SIOC_GET_TGT_LIMITS _IOR(’S’, 62, struct sioc_tgt_limits)
#define SIOC_GET_BUS_LIMITS _IOR(’S’, 63, struct sioc_bus_limits)
#define SIOC_SET_LUN_LIMITS _IOW(’S’, 64, struct sioc_lun_limits)
#define SIOC_SET_TGT_LIMITS _IOW(’S’, 65, struct sioc_tgt_limits)
#define SIOC_SET_BUS_LIMITS _IOW(’S’, 66, struct sioc_bus_limits)
struct sioc_lun_parms {
unsigned int flags;
unsigned int max_q_depth;/* maximum active I/O’s */
unsigned int reserved[4];/* reserved for future use */
};
struct sioc_lun_limits {
unsigned int flags;
unsigned int max_q_depth;
unsigned int reserved[4];/* reserved for future use */
};
struct sioc_tgt_parms {
unsigned int flags;
unsigned int width;/* bits */
unsigned int reqack_offset;
unsigned int xfer_rate;/* bytes/sec */
unsigned int reserved[4];/* reserved for future use */
};
struct sioc_tgt_limits {
unsigned int flags;
unsigned int max_reqack_offset;
unsigned int max_xfer_rate;/* bytes/sec */
unsigned int max_width;/* bits */
unsigned int reserved[4];/* reserved for future use */
};
struct sioc_bus_parms {
unsigned int flags;/* reserved for future use */
unsigned int max_width;
unsigned int max_reqack_offset;
unsigned int max_xfer_rate;/* bytes/sec */
unsigned int reserved[4];/* reserved for future use */
};
struct sioc_bus_limits {
unsigned int flags;/* reserved for future use */
unsigned int max_width;
unsigned int max_reqack_offset;
unsigned int max_xfer_rate;/* bytes/sec */
unsigned int reserved[4];/* reserved for future use */
};
SCSI Commands and Operations
The SIOC_IO ioctl allows an arbitrary SCSI command to be sent to a device. All details of the SCSI command protocol are handled automatically.
The following flags can be used to specify the flags field value:
SCTL_READ Data-in phase expected if the data_length field is non-zero. The absence of this flag implies that a data-out phase is expected if the data_length field is non-zero.
SCTL_INIT_SDTR synchronous data transfer request negotiations should be attempted with this command. This flag only applies to parallel SCSI.
SCTL_INIT_WDTR wide data transfer request negotiations should be attempted with this command. This flag only applies to parallel SCSI.
SCTL_NO_ATN device should be selected without attention (ATN). This implies that no SCSI message phase should be attempted with this command. This flag only applies to parallel SCSI.
The cdb field specifies the SCSI command bytes. The number of command bytes is specified by the cdb_length field. These command bytes are sent to the target device during the SCSI command phase.
The address of the data area for the data phase of the SCSI command is specified by the data field. The data_length field specifies the maximum number of data bytes to be transferred. A zero-valued data_length indicates that no data phase should occur. Most SCSI commands with a data phase expect the data length information to be included somewhere in the command bytes. The caller is responsible for correctly specifying both the data_length field and any cdb data length values. The length may not be larger than SCSI_MAXPHYS and some implementations further restrict this length.
The max_msecs field specifies the maximum time, in milliseconds, that the device should need to complete the command. If this period of time expires without command completion, the system attempts recovery procedures to regain the device’s attention. These recovery procedures may include device and bus reset operations. A zero value in the max_msec field indicates that the timeout period is infinite and the system should wait indefinitely for command completion. Note that very large (or infinite) timeout values can cause a parallel SCSI bus (potentially the entire system) to “hang”.
When the SIOC_IO ioctl call returns, all command processing has been completed. Most SIOC_IO ioctl calls will return zero (success). The resulting detailed ioctl data should be used to evaluate “success” or “failure” from the caller’s perspective. The cdb_status field indicates the results of the cdb command. If the cdb_status field indicates a S_CHECK_CONDITION status, the sense_status field indicates the results of the SCSI REQUEST SENSE command used to collect the associated sense data. These status fields will contain one of the following values:
SCTL_INVALID_REQUEST The SCSI command request is invalid and thus not attempted.
SCTL_SELECT_TIMEOUT The target device does not answer to selection by the host SCSI interface (the device does not exist or does not respond).
SCTL_INCOMPLETE The device answered selection but the command is not completed (the device took too long or a communication failure occurred).
S_GOOD Device successfully completed the command.
S_CHECK_CONDITION Device indicated sense data is available.
S_CONDITION_MET Device successfully completed the command and the requested (search or pre-fetch) operation is satisfied.
S_BUSY Device indicated it is unable to accept the command because it is busy doing other operations.
S_INTERMEDIATE Device successfully completed this command, which is one in a series of linked commands (not supported, see WARNINGS ).
S_I_CONDITION_MET Device indicated both S_INTERMEDIATE and S_CONDITION_MET (not supported, see WARNINGS ).
S_RESV_CONFLICT Device indicated the command conflicted with an existing reservation.
S_COMMAND_TERMINATED Device indicated the command is terminated early by the host system.
S_QUEUE_FULL Device indicated it is unable to accept the command because its command queue is currently full.
The data_xfer field indicates the number of data bytes actually transferred during the data phase of the cdb command. This field is valid only when the cdb_status field contains one of the following values: S_GOOD or S_CHECK_CONDITION. The sense_xfer field indicates the number of valid sense data bytes. This field is valid only when the cdb_status field contains the value S_CHECK_CONDITION and the sense_status field contains the value S_GOOD.
The SIOC_RESET_DEV ioctl causes a SCSI device to be reset (including clearing all active commands). On parallel SCSI a SIOC_RESET_DEV ioctl causes a SCSI BUS DEVICE RESET message to be sent to the associated target. On Fibre Channel a SIOC_RESET_DEV ioctl causes a TARGET RESET task management function to be sent to the associated target followed by a Global Process Logout (GPRLO).
The SIOC_RESET_BUS ioctl causes the system to generate a SCSI bus reset condition on the associated bus. A SCSI bus reset condition causes all devices on the bus to be reset (including clearing all active commands on all devices). The SIOC_RESET_BUS ioctl does not apply to Fibre Channel.
Often it is necessary or useful to prohibit other SCSI commands while performing device-control operations. Normally this should be done by gaining exclusive access via the SIOC_EXCLUSIVE ioctl. The associated argument points to an integer with one of these values:
0release exclusive access to logical unit;
1obtain exclusive access to logical unit;
2release exclusive access to target;
3obtain exclusive access to target;
4release exclusive access to bus;
5obtain exclusive access to bus.
Occasionally exclusive access not possible (for example, diagnostic operations on a device containing a mounted file system). “Priority mode” causes all device-specific driver I/O operations (e.g. file system I/O and virtual memory page swapping) and all SCSI device driver open calls (including scsi_ctl open calls) to the associated LUN to block. These I/O operations and open calls are blocked for the entire duration that priority mode is in effect. While priority mode is in effect only SIOC_IO operations should be attempted (these operations will not be blocked). The SIOC_PRIORITY ioctl controls the LUN priority mode. This ioctl is only available via the device-control driver. The value “1” enables priority mode. The value zero disables priority mode.
The header file <sys/scsi.h> has useful information for SCSI device control. The following is included from <sys/scsi.h>:
/* SCSI device control ioctls */
#define SIOC_IO _IOWR(’S’, 22, struct sctl_io)
#define SIOC_RESET_DEV _IO(’S’, 16)
#define SIOC_RESET_BUS _IO(’S’, 9)
#define SIOC_PRIORITY_MODE _IOW(’S’, 67, int)
/* Structure for SIOC_IO ioctl */
struct sctl_io
{
unsigned flags;
unsigned char cdb_length;
unsigned char cdb[16];
void *data;
unsigned data_length;
unsigned max_msecs;
unsigned data_xfer;
unsigned cdb_status;
unsigned char sense[256];
unsigned sense_status;
unsigned char sense_xfer;
unsigned char reserved[64];
};
EXAMPLES
Assume that fildes is a valid file descriptor for a SCSI device. The first example attempts a SCSI INQUIRY command:
#include <sys/scsi.h>
struct sctl_io sctl_io;
#define MAX_LEN 255
unsigned char inquiry_data[MAX_LEN];
memset(sctl_io, 0, sizeof(sctl_io)); /* clear reserved fields */
sctl_io.flags = SCTL_READ; /* input data expected */
sctl_io.cdb[0] = 0x12; /* can use scsi.h CMDinquiry */
sctl_io.cdb[1] = 0x00;
sctl_io.cdb[2] = 0x00;
sctl_io.cdb[3] = 0x00;
sctl_io.cdb[4] = MAX_LEN; /* allocation length */
sctl_io.cdb[5] = 0x00;
sctl_io.cdb_length = 6; /* 6 byte command */
sctl_io.data = &inquiry_data[0]; /* data buffer location */
sctl_io.data_length = MAX_LEN; /* maximum transfer length */
sctl_io.max_msecs = 10000; /* allow 10 seconds for cmd */
if (ioctl(fildes, SIOC_IO, &sctl_io) < 0)
{
/* request is invalid */
}
The following example attempts a SCSI TEST UNIT READY command and checks to see if the device is ready, not ready, or in some other state.
#include <sys/scsi.h>
struct sctl_io sctl_io;
memset(sctl_io, 0, sizeof(sctl_io)); /* clear reserved fields */
sctl_io.flags = 0; /* no data transfer expected */
sctl_io.cdb[0] = 0x00; /* can use CMDtest_unit_ready */
sctl_io.cdb[1] = 0x00;
sctl_io.cdb[2] = 0x00;
sctl_io.cdb[3] = 0x00;
sctl_io.cdb[4] = 0x00;
sctl_io.cdb[5] = 0x00;
sctl_io.cdb_length = 6; /* 6 byte command */
sctl_io.data = NULL; /* no data buffer is provided */
sctl_io.data_length = 0; /* do not transfer data */
sctl_io.max_msecs = 10000; /* allow 10 seconds for cmd */
if (ioctl(fildes, SIOC_IO, &sctl_io) < 0)
{
/* request is invalid */
}
else if (sctl_io.cdb_status == S_GOOD)
{
/* device is ready */
}
else if (sctl_io.cdb_status == S_BUSY ||
(sctl_io.cdb_status == S_CHECK_CONDITION &&
sctl_io.sense_status == S_GOOD &&
sctl_io.sense_xfer > 2 &&
(sctl_io.sense[2] & 0x0F) == 2)) /* can use sense_data */
{
/* device is not ready */
}
else
{
/* unknown state */
}
WARNINGS
Incorrect use of scsi_ctl operations (even those attempting access to non-existent devices) can cause data loss, system panics, and device damage.
The SIOC_EXCLUSIVE ioctl should be used to gain exclusive access to a device prior to attempting SIOC_IO commands. If exclusive access is not obtained, SIOC_IO commands will be intermixed with device-specific driver commands, which can lead to undesirable results.
Device-specific drivers can reject inappropriate or troublesome SIOC_IO commands. However, since not all such operations are known and detected, care should be exercised to avoid disrupting device-specific drivers when using commands that modify internal device states.
It is very easy to cause system deadlock through incorrect use of the SIOC_PRIORITY_MODE ioctl. Normally it is necessary to lock the calling process into memory (see plock(2)) prior to enabling priority mode.
Most SCSI commands have a logical unit number (LUN) field. Parallel SCSI implementations on the HP-UX operating system select logical units via the SCSI IDENTIFY message. The LUN portion of the cdb should normally be set to zero, even when the LUN being accessed is not zero.
Use of linked commands is not supported.
Most SCSI commands with a data phase expect the data length information to be included somewhere in the command bytes. Both the data_length field and any cdb data length values must be correctly specified to get correct command results.
Very large (or infinite) timeout values can cause a parallel SCSI bus (potentially the entire system) to hang.
Device and/or bus reset operations can be used to regain a device’s attention when a timeout expires.
Resetting a device can cause I/O errors and/or loss of cached data. This can result in loss of data and/or system panics.
Obtaining SCSI INQUIRY data by use of the SIOC_INQUIRY ioctl instead of by use of the SIOC_IO ioctl is generally preferable since SCSI implementations on the HP-UX operating system synchronize access of inquiry data during driver open calls.
Since communication parameters can be affected by device-specific driver capabilities, device-specific driver use may result in communication parameter changes.
The SIOC_CAPACITY ioctl is not supported by scsi_ctl because the meaning of capacity is device-specific.
FILES
/usr/include/sys/scsi.h
/usr/include/sys/scsi_ctl.h
SEE ALSO
Hewlett-Packard Company — HP-UX Release 10.20: July 1996