SCO OpenServer


scsi_io_req -- SCSI request block


#include "scsi.h"


The request block structure is used by a SCSI peripheral driver to communicate with the host adapter driver. This structure is is also called REQ_IO. When a peripheral driver wishes to send a command, it must fill in a scsi_io_req structure with the appropriate information and call the adapter driver's _entry(D2osdi) function to communicate with the device.

All members in the request block are writable by the peripheral driver except host_sts, target_sts, and req_status. All other members must be set before sending the request to the host adapter driver. Some members are not implemented for some host adapter drivers. The request block structure contains information needed by a wide variety of host adapter drivers. As an example, the supported host adapter driver does not support linked commands at present. Thus the link_ptr and link_id members are not accessed by the host adapter driver supplied with your software. Future support for the link command capability is possible; set these members to 0 (zero) to ensure that conflicts do not occur.

The members of the scsi_io_req structure can be grouped according to whether they are set by the peripheral driver or the host adapter driver, whether they are reserved, or used internally by the peripheral driver.

Members set by the peripheral driver

The following members are filled in by the peripheral driver. The adapter driver may examine these members, but may not change them.

char id;
SCSI ID of the target of this command.

char lun;
SCSI logical unit number of the target of this command.

char ha_num;
host adapter number to which the target of this command is attached.

char bus_num;
SCSI bus number of the host adapter bus to which the target of this command is attached. For host adapters that do not have multiple buses, this should be set to 0.

struct exten *ext_p;
If req_type is equal to SCSI_INFO, then this member is used to return special information from the adapter driver. (See the section below on the SCSI_INFO command for a full description.) Otherwise, this member is reserved and should be set to 0.

char opcode;
SCSI command opcode contained in this command. If there is no SCSI opcode, this member is set to 0.

char dir;
direction in which data will be transferred as a result of this command. Possible values are SCSI_IN for data transferred from the peripheral to the host, or SCSI_OUT for data transferred from the host to the peripheral.

char cmdlen;
length in bytes of the SCSI command.

paddr_t data_len;
length in bytes of the data that is to be transferred by this command.

For scatter/gather operations, this is the total length in bytes of all the scatter/gather requests added together.

paddr_t data_ptr;
This member is a pointer to the physical address to or from which data will be transferred.

For scatter/gather operations, this is the address of an array of type long that contains the physical memory locations into which to transfer data. In other words, there are the kernel I/O buffers.

paddr_t data_blk;
should contain the logical block number addressed by the command if this command addresses a logical block on a devicel Otherwise, it may contain any value. This member is intended to make it easy to extract the block number from a request without having to examine the SCSI CDB (for example, for printing error messages).

For scatter/gather operations, this is the offset into the disk media from which the scatter/gather request will start, in blocks.

union scsi_cdb scsi_cmd;
contains the 6, 10, or 12 byte SCSI command to be sent to the target. Its format is described in the SCSI-2 standard. Note that this member can also be set by the HA.

char r_count;
indicates the number of times the adapter should retry the command if there is an error that does not result in a CHECK CONDITION status from the target. Support for retrying commands is optional. Adapter drivers must not retry commands that result in CHECK CONDITION status from the target device.

char hacmd;
used to select among options available for a particular request type. See the sections below under ``Types of commands'' for more information.

int (*io_intr)();
contains a pointer to the peripheral driver's callback function. The callback function will be called by the adapter driver when processing of the request block is completed.

char sense_len;
length of sense command

paddr_t scsi_sense;
if non 0 (zero), the address to which the sense information should be written.

paddr_t link_ptr;
link pointer, used for scatter/gather operations. This is the address of an array of type long that contains 1K records that define the length of each I/O request.

Members for internal use by the peripheral driver:

paddr_t req_id;
request block ID

char use_flag;
zero if available

char internal;
driver internal request, if non-zero

char jq;
job queue index

char ctlr;
controller address

char req_status;
request block status in xxintr( )

char adapter;
adapter base address

struct buf *rbuf;
request per this buffer, if non-zero

char *s1;

char *s2;

char link_id;
ID of linked blocks

Members set by the adapter

The following members are set by the adapter driver when the request is processed. The peripheral driver should expect that any of these members may be changed by the adapter driver.

struct scsi_io_req *req_forw;
used by the adapter driver to chain requests together.

char host_sts;
if this member is nonzero, it indicates an error in the processing of the command by the host adapter.

char target_sts;
if this member is nonzero, it indicates an error in the processing of the command by the target, and sense data from the target will be returned. Sense data is valid only if this member is nonzero.

Types of commands

Different command types are distinguished by different values in the req_type member of the request block. All SCSI peripheral drivers must be coded to process these types of requests and all SCSI host adapter drivers must be coded to handle these types of requests. See the sample code on the AHDK CD-ROM disk for examples of both SCSI peripheral and SCSI host adapter drivers. Note that special coding is required to process scatter/gather requests.

The possible values of the req_type member are:

Prepare the adapter to send commands to a target. This command must be sent before any other commands by the peripheral driver for a single target.

The id, ha, bus, and lun members identify the target.

This command may be sent more than once for a given target.

If the hacmd member is set to the value SCSI_DISK_INFO, the adapter will return information about any BIOS-compatibility geometry that it supports. The ext_p member in the request block must point to a struct exten which will be filled in by the adapter.

The members are filled in as follows:


set to NULL

unused -- set to 0

number of heads

number of sectors per track

Note that these values need not have any relation to the actual physical geometry of the device. If an adapter does not have a BIOS-compatible geometry, it may return the actual values for these members as reported by the device.

If the operating system is to be able to boot from disks attached to this adapter, the BIOS and operating system must agree on the disk's geometry. The exact mechansm of agreement may vary. Some BIOSes (and corresponding drivers) use fixed geometries such as [64 heads, 32 sectors/track] or [255 heads, 63 sectors/track]. Others select between several fixed geometries according to the total capacity of the disk. The values may also come from other sources such as user preferences, configured in the BIOS setup. In this case, some mechanism specific to the driver and the BIOS is required to communicate those values.

The boot program can only access the first 1024 cylinders of a disk; that is approximately the first 1GB of a [64, 32] geometry or the first 7.8GB of a [255,63] geometry. For the device to multi-boot different operating system, it must use a geometry that provides large bootable areas.

The operating system is limited to a total of 65535 cyliders per disk. Disks up to 64GB can be accessed under a [64, 32] geometry; disks up to 502GB can be accessed under a [255, 63] geometry;
Peripheral drivers should use the capacity of the target unit (from the READ CAPACITY SCSI command), and the number of heads and sectors per track to calculate the number of cylinders for the device. The host adapter only sends back heads and sectors; the SCSI peripheral driver must calculate the cylinders. Note that the number of blocks is zero-based, so you need to add 1 to the last block to get the correct r_count value.

Peripheral drivers that are not interested in this information should set the hacmd member to the value SCSI_NO_INFO which is equal to ``FFh''.

Some adapter drivers in SCO UNIX System V Release 3.2 Operating System Version 2.0 and earlier required that the hacmd member be set to indicate whether the target is a direct-access device or a sequential-access device. Direct-access (disk) devices were required to set hacmd to SCSI_DISK_INFO, and sequential-access (tape) devices were required to set hacmd to SCSI_TAPE_INFO.

Return information about the adapter's capabilities. The data_ptr member must point to a struct scsi_ha_info which will be filled in by the adapter. The data_len member should contain the size, in bytes, of the scsi_ha_info structure.

Send a normal SCSI command. Use the NC form to bypass the host controller cache.

If the adapter driver receives a command with the req_type member set to a value other than the ones above, it should return the value -1 and take no other action.

Scatter/gather request. Use the NC form to bypass the host controller cache.

Version applicability

osdi: 1, 2, 3, 4, 5

Differences between versions

The earliest releases of the SCO SCSI interface did not support scatter/gather operations and all sense data was bundled at the end of scsi_cmd. For those releases, the following members of the scsi_io_req structure were reserved and set to 0: sense_len, scsi_sense, link_ptr, and link_id.

The ODDI 4 (SCO OpenServer Release 5.0.4) Sdsk peripheral driver is changed to send

   req_type = SCSI_INIT req_p->hacmd = SCSI_VER_INFO
early in its open(D2osdi) routine. This hacmd is a -1. Some drivers are coded so that if they don't understand the hacmd value, they may panic or fail.

To avoid this problem, the driver should check for a req_p->ext_p value so it can then provide the version info.

This change was implemented so that the Sdsk driver can do its own read cap cmd and pass that value to the HBA when asking for the heads and sectors. In earlier OSDI versions, the Sdsk driver was asking for disk heads and sectors from the HBA and then doing it's own read capicty command to figure out the disk geometry ( cylinders ). This required the HBA vendor to submit its own read capacity so it could figure out the proper heads and sectors if it changed with disk size. The information is passed in an unused area of the scsi_disk_info(D4osdi) structure. If there are non zero values there, a driver can make use of them.


scsi_cdb(D4osdi), scsi_dev_cfg(D4osdi), scsi_ha_cfg(D4osdi),

``Scatter/gather operations'' in HDK Technical Reference

19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 5 HDK - June 2005