|
@ -0,0 +1,350 @@ |
|
|
|
|
|
.\" $OpenBSD: scsi.3,v 1.1 1996/06/12 11:21:34 deraadt Exp $ |
|
|
|
|
|
.\" Copyright (c) 1994 HD Associates (hd@world.std.com) |
|
|
|
|
|
.\" All rights reserved. |
|
|
|
|
|
.\" |
|
|
|
|
|
.\" Redistribution and use in source and binary forms, with or without |
|
|
|
|
|
.\" modification, are permitted provided that the following conditions |
|
|
|
|
|
.\" are met: |
|
|
|
|
|
.\" 1. Redistributions of source code must retain the above copyright |
|
|
|
|
|
.\" notice, this list of conditions and the following disclaimer. |
|
|
|
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright |
|
|
|
|
|
.\" notice, this list of conditions and the following disclaimer in the |
|
|
|
|
|
.\" documentation and/or other materials provided with the distribution. |
|
|
|
|
|
.\" 3. All advertising materials mentioning features or use of this software |
|
|
|
|
|
.\" must display the following acknowledgement: |
|
|
|
|
|
.\" This product includes software developed by HD Associates |
|
|
|
|
|
.\" 4. Neither the name of the HD Associates nor the names of its contributors |
|
|
|
|
|
.\" may be used to endorse or promote products derived from this software |
|
|
|
|
|
.\" without specific prior written permission. |
|
|
|
|
|
.\" |
|
|
|
|
|
.\" THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND |
|
|
|
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|
|
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|
|
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE |
|
|
|
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
|
|
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
|
|
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
|
|
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
|
|
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
|
|
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
|
|
|
|
.\" SUCH DAMAGE. |
|
|
|
|
|
.\" |
|
|
|
|
|
.\" |
|
|
|
|
|
.Dd November 20, 1994 |
|
|
|
|
|
.Dt SCSI 3 |
|
|
|
|
|
.Os |
|
|
|
|
|
.Sh NAME |
|
|
|
|
|
.Nm scsireq_buff_decode , |
|
|
|
|
|
.Nm scsireq_build , |
|
|
|
|
|
.Nm scsireq_decode , |
|
|
|
|
|
.Nm scsireq_encode , |
|
|
|
|
|
.Nm scsireq_enter , |
|
|
|
|
|
.Nm scsireq_new , |
|
|
|
|
|
.Nm scsireq_reset , |
|
|
|
|
|
.Nm SCSIREQ_ERROR , |
|
|
|
|
|
.Nm scsi_open , |
|
|
|
|
|
.Nm scsi_debug , |
|
|
|
|
|
.Nm scsi_debug_output |
|
|
|
|
|
.Nd SCSI User library |
|
|
|
|
|
.Sh SYNOPSIS |
|
|
|
|
|
.Fd #include <sys/types.h> |
|
|
|
|
|
.Fd #include <sys/scsiio.h> |
|
|
|
|
|
.Fd #include <scsi.h> |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn scsireq_buff_decode "u_char *ptr, size_t len, char *fmt, ..." |
|
|
|
|
|
.Ft struct scsireq * |
|
|
|
|
|
.Fn scsireq_build "struct scsireq *s, u_long len, caddr_t buf, u_long flags, char *fmt, ..." |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn scsireq_decode "struct scsireq *, char *fmt, ..." |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn scsireq_encode "struct scsireq *, char *fmt, ..." |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn scsireq_enter "int fid, struct scsireq *s" |
|
|
|
|
|
.Ft struct scsireq * |
|
|
|
|
|
.Fn scsireq_new void |
|
|
|
|
|
.Ft struct scsireq * |
|
|
|
|
|
.Fn scsireq_reset "struct scsireq *" |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn SCSIREQ_ERROR "struct scsireq *" |
|
|
|
|
|
.Ft int |
|
|
|
|
|
.Fn scsi_open "const char *path, int flags" |
|
|
|
|
|
.Ft void |
|
|
|
|
|
.Fn scsi_debug "FILE *f, int ret, struct scsireq *s" |
|
|
|
|
|
.Ft FILE * |
|
|
|
|
|
.Fn scsi_debug_output "char *s" |
|
|
|
|
|
.Sh DESCRIPTION |
|
|
|
|
|
These functions |
|
|
|
|
|
use the SCIOCCOMMAND |
|
|
|
|
|
.Xr ioctl 2 |
|
|
|
|
|
of the SCSI subsystem |
|
|
|
|
|
to provide user level access to SCSI commands. |
|
|
|
|
|
The programmer must know the SCSI CDB (Command Descriptor |
|
|
|
|
|
Block) to perform the desired command. These functions assist in |
|
|
|
|
|
building up the CDB, submitting it to the SCSI subsystem, and decoding |
|
|
|
|
|
the result. |
|
|
|
|
|
.Pp |
|
|
|
|
|
Look at the |
|
|
|
|
|
.Xr scsi 8 |
|
|
|
|
|
command before using the library directly - simple programs are |
|
|
|
|
|
best implemented as scripts using that facility. |
|
|
|
|
|
.Pp |
|
|
|
|
|
To provide for security, |
|
|
|
|
|
not all devices accept the SCIOCCOMAND ioctl. It is accepted by the |
|
|
|
|
|
control device for tape drives, partition D for disk drives, partition C |
|
|
|
|
|
for CD ROM drives, and any "unknown" device. |
|
|
|
|
|
The "super scsi" |
|
|
|
|
|
.Xr ssc 4 |
|
|
|
|
|
device also accepts the ioctl. |
|
|
|
|
|
.Pp |
|
|
|
|
|
Most of the SCSI library functions build up and manipulate the |
|
|
|
|
|
.Ar scsireq |
|
|
|
|
|
structure found in the include file |
|
|
|
|
|
.Aq Pa sys/scsiio.h : |
|
|
|
|
|
.Bd -literal -offset indent |
|
|
|
|
|
#define SENSEBUFLEN 48 |
|
|
|
|
|
.Pp |
|
|
|
|
|
typedef struct scsireq { |
|
|
|
|
|
u_long flags; /* info about the request status and type */ |
|
|
|
|
|
u_long timeout; |
|
|
|
|
|
u_char cmd[16]; /* 12 is actually the max */ |
|
|
|
|
|
u_char cmdlen; |
|
|
|
|
|
caddr_t databuf; /* address in user space of buffer */ |
|
|
|
|
|
u_long datalen; /* size of user buffer (request) */ |
|
|
|
|
|
u_long datalen_used; /* size of user buffer (used)*/ |
|
|
|
|
|
u_char sense[SENSEBUFLEN]; /* returned sense will be in here */ |
|
|
|
|
|
u_char senselen; /* sensedata request size (MAX of SENSEBUFLEN)*/ |
|
|
|
|
|
u_char senselen_used; /* return value only */ |
|
|
|
|
|
u_char status; /* what the scsi status was from the adapter */ |
|
|
|
|
|
u_char retsts; /* the return status for the command */ |
|
|
|
|
|
int error; /* error bits */ |
|
|
|
|
|
} scsireq_t; |
|
|
|
|
|
.Ed |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_new |
|
|
|
|
|
allocates a new |
|
|
|
|
|
.Ar scsireq |
|
|
|
|
|
structure and returns a pointer to it or NULL if it can't allocate |
|
|
|
|
|
memory. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_reset |
|
|
|
|
|
resets the structure to reasonable values and returns the same pointer passed |
|
|
|
|
|
in to it. |
|
|
|
|
|
It gracefully handles the NULL pointer passed in to it so that you can |
|
|
|
|
|
unconditionally use |
|
|
|
|
|
.Ar scsireq_new . |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_build |
|
|
|
|
|
builds up a scsireq structure based on the information provided in |
|
|
|
|
|
the variable argument list. |
|
|
|
|
|
It gracefully handles a NULL pointer passed to it. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fr len |
|
|
|
|
|
is the length of the data phase; the data transfer direction is |
|
|
|
|
|
determined by the |
|
|
|
|
|
.Ar flags |
|
|
|
|
|
argument. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fr buf |
|
|
|
|
|
is the data buffer used during the SCSI data phase. If it is NULL it |
|
|
|
|
|
is allocated via malloc and |
|
|
|
|
|
.Ar scsireq->databuf |
|
|
|
|
|
is set to point to the newly allocated memory. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fr flags |
|
|
|
|
|
are the flags defined in |
|
|
|
|
|
.Aq Pa sys/scsiio.h : |
|
|
|
|
|
.Bd -literal -offset indent |
|
|
|
|
|
/* bit definitions for flags */ |
|
|
|
|
|
#define SCCMD_READ 0x00000001 |
|
|
|
|
|
#define SCCMD_WRITE 0x00000002 |
|
|
|
|
|
#define SCCMD_IOV 0x00000004 |
|
|
|
|
|
#define SCCMD_ESCAPE 0x00000010 |
|
|
|
|
|
#define SCCMD_TARGET 0x00000020 |
|
|
|
|
|
.Ed |
|
|
|
|
|
Only two of these flags are supported in this release of the software: |
|
|
|
|
|
.Fr SCCMD_READ |
|
|
|
|
|
indicates a data in phase (a transfer into the user buffer at |
|
|
|
|
|
.Ar scsireg->databuf |
|
|
|
|
|
), and |
|
|
|
|
|
.Fr SCCMD_WRITE |
|
|
|
|
|
indicates a data out phase (a transfer out of the user buffer). |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fr fmt |
|
|
|
|
|
is a CDB format specifier used to build up the SCSI CDB. |
|
|
|
|
|
This text string is made up of a list of field specifiers. Field |
|
|
|
|
|
specifiers specify the value for each CDB field (including indicating |
|
|
|
|
|
that the value be taken from the next argument in the |
|
|
|
|
|
variable argument list), the width |
|
|
|
|
|
of the field in bits or bytes, and an optional name. White space is |
|
|
|
|
|
ignored, and the pound sign ('#') introduces a comment that ends at the |
|
|
|
|
|
end of the current line. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The optional name is the first part of a field specifier and |
|
|
|
|
|
is in curly braces. The text in curly braces in this example are |
|
|
|
|
|
the names: |
|
|
|
|
|
.Bd -literal -offset indent |
|
|
|
|
|
.Fr "{PS} v:b1 {Reserved} 0:b1 {Page Code} v:b6 # Mode select page" |
|
|
|
|
|
.Ed |
|
|
|
|
|
.Pp |
|
|
|
|
|
This field specifier has two one bit fields and one six bit field. |
|
|
|
|
|
The second one bit field is the constant value 0 and the first |
|
|
|
|
|
one bit field and the six bit field are taken from the variable |
|
|
|
|
|
argument list. |
|
|
|
|
|
Multi byte fields are swapped into the SCSI byte order in the |
|
|
|
|
|
CDB and white space is ignored. |
|
|
|
|
|
.Pp |
|
|
|
|
|
When the field is a hex value or the letter v, (e.g., |
|
|
|
|
|
.Fr "1A" |
|
|
|
|
|
or |
|
|
|
|
|
.Fr "v" ) |
|
|
|
|
|
then a single byte value |
|
|
|
|
|
is copied to the next unused byte of the CDB. |
|
|
|
|
|
When the letter |
|
|
|
|
|
.Fr v |
|
|
|
|
|
is used the next integer argument is taken from the variable argument list |
|
|
|
|
|
and that value used. |
|
|
|
|
|
.Pp |
|
|
|
|
|
A constant hex value followed by a field width specifier or the letter |
|
|
|
|
|
.Fr v |
|
|
|
|
|
followed by a field width specifier (e.g., |
|
|
|
|
|
.Fr 3:4 , |
|
|
|
|
|
.Fr 3:b4 , |
|
|
|
|
|
.Fr 3:i3 , |
|
|
|
|
|
.FR v:i3 ) |
|
|
|
|
|
specifies a field of a given bit or byte width. |
|
|
|
|
|
Either the constant value or (for the V specifier) the next integer value from |
|
|
|
|
|
the variable argument list is copied to the next unused |
|
|
|
|
|
bits or bytes of the CDB. |
|
|
|
|
|
.Pp |
|
|
|
|
|
A decimal number or the letter |
|
|
|
|
|
.Fr b |
|
|
|
|
|
followed by a decimal number field width indicates a bit field of that width. |
|
|
|
|
|
The bit fields are packed as tightly as possible beginning with the |
|
|
|
|
|
high bit (so that it reads the same as the SCSI spec), and a new byte of |
|
|
|
|
|
the CDB is started whenever a byte fills completely or when an |
|
|
|
|
|
.Fr i |
|
|
|
|
|
field is encountered. |
|
|
|
|
|
.Pp |
|
|
|
|
|
A field width specifier consisting of the letter |
|
|
|
|
|
.Fr i |
|
|
|
|
|
followed by either |
|
|
|
|
|
1, 2, 3 or 4 indicates a 1, 2, 3 or 4 byte integral value that must |
|
|
|
|
|
be swapped into SCSI byte order (MSB first). |
|
|
|
|
|
.Pp |
|
|
|
|
|
For the |
|
|
|
|
|
.Fr v |
|
|
|
|
|
field specifier the next integer argument is taken from the variable argument |
|
|
|
|
|
list and that value is used swapped into SCSI byte order. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_decode |
|
|
|
|
|
is used to decode information from the data in phase of the SCSI |
|
|
|
|
|
transfer. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The decoding is similar to |
|
|
|
|
|
the command specifier processing of |
|
|
|
|
|
.Fn scsireq_build |
|
|
|
|
|
except that the data is extracted from the data pointed to by |
|
|
|
|
|
.Fr scsireq->databuf. |
|
|
|
|
|
The stdarg list should be pointers to integers instead of integer |
|
|
|
|
|
values. |
|
|
|
|
|
A seek field type and a suppression modifier are added. |
|
|
|
|
|
The |
|
|
|
|
|
.Fr * |
|
|
|
|
|
suppression modifier (e.g., |
|
|
|
|
|
.Fr *i3 |
|
|
|
|
|
or |
|
|
|
|
|
.Fr *b4 ) |
|
|
|
|
|
suppresses assignment from the field and can be used to skip |
|
|
|
|
|
over bytes or bits in the data, without having to copy |
|
|
|
|
|
them to a dummy variable in the arg list. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The seek field type |
|
|
|
|
|
.Fr s |
|
|
|
|
|
permits you to skip over data. |
|
|
|
|
|
This seeks to an absolute position ( |
|
|
|
|
|
.Fr s3 ) |
|
|
|
|
|
or a relative position ( |
|
|
|
|
|
.Fr s+3 ) |
|
|
|
|
|
in the data, based on whether or not the presence of the '+' sign. |
|
|
|
|
|
The seek value can be specified as |
|
|
|
|
|
.Fr v |
|
|
|
|
|
and the next integer value from the argument list will be |
|
|
|
|
|
used as the seek value. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_buff_decode |
|
|
|
|
|
decodes an arbitrary data buffer using the method |
|
|
|
|
|
described above in |
|
|
|
|
|
.Fn scsireq_decode . |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_encode |
|
|
|
|
|
encodes the data phase section of the structure. The encoding is |
|
|
|
|
|
handled identically as the encoding of the CDB structure by |
|
|
|
|
|
.Fn scsireq_build |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_enter |
|
|
|
|
|
submits the built up structure for processing using |
|
|
|
|
|
the SCIOCCOMMAND ioctl. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn SCSIREQ_ERROR |
|
|
|
|
|
is a macro that determines if the result of the SCIOCCOMMAND ioctl may |
|
|
|
|
|
have been |
|
|
|
|
|
in error by examining the host adapter return code, whether sense was sent |
|
|
|
|
|
or not, and so on. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsi_open |
|
|
|
|
|
checks environment variables and initializes the library for |
|
|
|
|
|
consistent library use and then calls the regular open system call. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsi_debug |
|
|
|
|
|
prints the results of a scsireq_enter function to the specified stdio |
|
|
|
|
|
stream. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsi_debug_output |
|
|
|
|
|
requests that the results of all transactions be debugged to the |
|
|
|
|
|
supplied file using |
|
|
|
|
|
.Fn scsi_debug . |
|
|
|
|
|
.Sh RETURN VALUES |
|
|
|
|
|
The function |
|
|
|
|
|
.Fn scsireq_new |
|
|
|
|
|
returns a pointer to storage allocated from malloc, and therefore |
|
|
|
|
|
potentially a NULL. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The functions |
|
|
|
|
|
.Fn scsireq_build |
|
|
|
|
|
and |
|
|
|
|
|
.Fn scsireq_reset |
|
|
|
|
|
return the same pointer as the one passed in. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The functions |
|
|
|
|
|
.Fn scsireq_buff_decode and |
|
|
|
|
|
.Fn scsireq_decode |
|
|
|
|
|
return the number of assignments performed. |
|
|
|
|
|
.Pp |
|
|
|
|
|
.Fn scsireq_encode |
|
|
|
|
|
returns the number of fields processed. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The function |
|
|
|
|
|
.Fn scsireq_enter |
|
|
|
|
|
returns the result of the ioctl call. |
|
|
|
|
|
.Sh SEE ALSO |
|
|
|
|
|
.Xr scsi 8 , |
|
|
|
|
|
.Xr scsi 4 |
|
|
|
|
|
.Sh BUGS |
|
|
|
|
|
This only works completely for the 1542C. The host adapter code |
|
|
|
|
|
that sets up the residual amount of data transfer has to be added |
|
|
|
|
|
to each individual adapter. This library is usable on the other |
|
|
|
|
|
host adapters, however, the SCSI driver pretends that the proper |
|
|
|
|
|
amount of data is always transferred. If you have an Adaptec 174x |
|
|
|
|
|
and can hack contact dufault@hda.com and you can have the code to |
|
|
|
|
|
calculate residual data for the 174x series to integrate and test. |
|
|
|
|
|
.Sh HISTORY |
|
|
|
|
|
Many systems have comparable interfaces to permit a user to construct a |
|
|
|
|
|
SCSI command in user space. |
|
|
|
|
|
.Pp |
|
|
|
|
|
The data structure is almost identical to the SGI /dev/scsi data |
|
|
|
|
|
structure. If anyone knows the name of the authors it should |
|
|
|
|
|
go here; Peter Dufault first read about it in a 1989 Sun Expert magazine. |
|
|
|
|
|
.Pp |
|
|
|
|
|
Peter Dufault implemented a clone of SGI's interface in 386bsd that |
|
|
|
|
|
led to this library and the related kernel ioctl. |
|
|
|
|
|
If anyone needs that for compatibility contact dufault@hda.com. |