Clean up handling of unspecified names. Clarify man page.
This commit is contained in:
parent
daa21be5f0
commit
672412c27e
@ -82,14 +82,18 @@ 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. For tape
|
||||
drives, only the control device accepts it. For disk drives, only
|
||||
the RAWPART partition (partition d in 2.0) accepts it. Any device
|
||||
that comes on line as an UNKNOWN device will accept the ioctl, and
|
||||
the "super scsi"
|
||||
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 it.
|
||||
device also accepts the ioctl.
|
||||
.Pp
|
||||
Most of the SCSI library functions build up and manipulate the
|
||||
.Ar scsireq
|
||||
@ -115,7 +119,6 @@ typedef struct scsireq {
|
||||
} scsireq_t;
|
||||
.Ed
|
||||
.Pp
|
||||
The function
|
||||
.Fn scsireq_new
|
||||
allocates a new
|
||||
.Ar scsireq
|
||||
@ -166,30 +169,34 @@ indicates a data in phase (a transfer into the user buffer at
|
||||
indicates a data out phase (a transfer out of the user buffer).
|
||||
.Pp
|
||||
.Fr fmt
|
||||
is an ASCII CDB format specifier used to build up the SCSI CDB.
|
||||
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.
|
||||
The optional name is the final part of a field specifier and
|
||||
is in curly braces. A valid example is:
|
||||
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 "v:b1 {PS} 0:b1 {Reserved} v:b6 {Page Code}"
|
||||
.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.
|
||||
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" )
|
||||
a single byte value
|
||||
then a single byte value
|
||||
is copied to the next unused byte of the CDB.
|
||||
When the letter
|
||||
.Fr v
|
||||
@ -203,17 +210,17 @@ followed by a field width specifier (e.g.,
|
||||
.Fr 3:b4 ,
|
||||
.Fr 3:i3 ,
|
||||
.FR v:i3 )
|
||||
is used to specify a field of a given bit or byte width.
|
||||
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. A decimal number or the letter
|
||||
bits or bytes of the CDB.
|
||||
.Pp
|
||||
A decimal number or the letter
|
||||
.Fr b
|
||||
followed by a decimal
|
||||
number as the field width indicates a bit field of that width.
|
||||
These bit fields are packed as tightly as possible beginning with the
|
||||
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 the byte fills completely or when an
|
||||
the CDB is started whenever a byte fills completely or when an
|
||||
.Fr i
|
||||
field is encountered.
|
||||
.Pp
|
||||
@ -223,49 +230,50 @@ 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 v field specifier
|
||||
the next integer argument is taken from the variable argument
|
||||
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,
|
||||
.Fn scsireq_build
|
||||
except that the data is extracted from the data pointed to by
|
||||
.Fr scsireq->databuf.
|
||||
The stdarg list must be pointers to integers instead of integer
|
||||
The stdarg list should be pointers to integers instead of integer
|
||||
values.
|
||||
.Pp
|
||||
In addition, a seek field type and a suppression field modifier are added.
|
||||
A seek field type and a suppression modifier are added.
|
||||
The
|
||||
.Fr *
|
||||
suppression modifier to a field (e.g.,
|
||||
suppression modifier (e.g.,
|
||||
.Fr *i3
|
||||
or
|
||||
.Fr *b4 )
|
||||
suppresses the assignment from that field and can be used to skip
|
||||
over bytes or bits in the data, without copying them to a dummy variable
|
||||
in the arg list.
|
||||
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
|
||||
A seek field type
|
||||
The seek field type
|
||||
.Fr s
|
||||
is provided. This ``seeks'' to an absolute position in the data (
|
||||
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 seek value has a '+' sign.
|
||||
The value can also be
|
||||
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 will be taken from the arg list
|
||||
and used as the seek value.
|
||||
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 identically to the method
|
||||
used by the
|
||||
.Fn scsireq_decode
|
||||
function.
|
||||
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
|
||||
@ -286,10 +294,6 @@ or not, and so on.
|
||||
checks environment variables and initializes the library for
|
||||
consistent library use and then calls the regular open system call.
|
||||
.Pp
|
||||
.Fn scsi_debug and
|
||||
.Fn scsi_debug_output
|
||||
are used for debugging.
|
||||
.Pp
|
||||
.Fn scsi_debug
|
||||
prints the results of a scsireq_enter function to the specified stdio
|
||||
stream.
|
||||
@ -311,11 +315,12 @@ and
|
||||
return the same pointer as the one passed in.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn scsireq_buff_decode ,
|
||||
.Fn scsireq_buff_decode and
|
||||
.Fn scsireq_decode
|
||||
and
|
||||
return the number of assignments performed.
|
||||
.Pp
|
||||
.Fn scsireq_encode
|
||||
return the number of fields processed.
|
||||
returns the number of fields processed.
|
||||
.Pp
|
||||
The function
|
||||
.Fn scsireq_enter
|
||||
|
@ -30,7 +30,7 @@
|
||||
* 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.
|
||||
* $Id: scsi.c,v 1.1.1.1 1995/01/24 12:10:11 dufault Exp $
|
||||
* $Id: scsi.c,v 1.2 1995/01/25 00:33:50 dufault Exp $
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -132,20 +132,11 @@ scsireq_t *scsireq_new(void)
|
||||
*
|
||||
*/
|
||||
|
||||
#define ARG_PUT(ARG) \
|
||||
do \
|
||||
{ \
|
||||
if (arg_put) \
|
||||
(*arg_put)(puthook, letter, (void *)((long)(ARG)), 1, field_name); \
|
||||
else \
|
||||
*(va_arg(ap, int *)) = (ARG); \
|
||||
} while (0)
|
||||
|
||||
static int do_buff_decode(u_char *databuf, size_t len,
|
||||
void (*arg_put)(void *, int , void *, int, char *), void *puthook,
|
||||
char *fmt, va_list ap)
|
||||
{
|
||||
int decoded = 0;
|
||||
int assigned = 0;
|
||||
int width;
|
||||
int suppress;
|
||||
int plus;
|
||||
@ -156,19 +147,46 @@ char *fmt, va_list ap)
|
||||
char letter;
|
||||
char field_name[80];
|
||||
|
||||
# define ARG_PUT(ARG) \
|
||||
do \
|
||||
{ \
|
||||
if (!suppress) \
|
||||
{ \
|
||||
if (arg_put) \
|
||||
(*arg_put)(puthook, letter, \
|
||||
(void *)((long)(ARG)), 1, field_name); \
|
||||
else \
|
||||
*(va_arg(ap, int *)) = (ARG); \
|
||||
assigned++; \
|
||||
} \
|
||||
field_name[0] = 0; \
|
||||
suppress = 0; \
|
||||
} while (0)
|
||||
|
||||
u_char bits = 0; /* For bit fields */
|
||||
int shift = 0; /* Bits already shifted out */
|
||||
suppress = 0;
|
||||
field_name[0] = 0;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
switch(letter = *fmt)
|
||||
{
|
||||
case ' ':
|
||||
case ' ': /* White space */
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\f':
|
||||
fmt++;
|
||||
break;
|
||||
|
||||
case '#': /* Comment */
|
||||
while (*fmt && (*fmt != '\n'))
|
||||
fmt++;
|
||||
if (fmt)
|
||||
fmt++; /* Skip '\n' */
|
||||
break;
|
||||
|
||||
case '*': /* Suppress assignment */
|
||||
fmt++;
|
||||
suppress = 1;
|
||||
@ -185,7 +203,8 @@ char *fmt, va_list ap)
|
||||
|
||||
fmt++;
|
||||
}
|
||||
fmt++; /* Skip '}' */
|
||||
if (fmt)
|
||||
fmt++; /* Skip '}' */
|
||||
field_name[i] = 0;
|
||||
}
|
||||
break;
|
||||
@ -209,10 +228,7 @@ char *fmt, va_list ap)
|
||||
shift, bits, value, width, mask[width]);
|
||||
#endif
|
||||
|
||||
if (!suppress)
|
||||
ARG_PUT(value);
|
||||
else
|
||||
suppress = 0;
|
||||
ARG_PUT(value);
|
||||
|
||||
shift -= width;
|
||||
}
|
||||
@ -226,43 +242,31 @@ char *fmt, va_list ap)
|
||||
switch(width)
|
||||
{
|
||||
case 1:
|
||||
if (!suppress)
|
||||
ARG_PUT(*databuf);
|
||||
else
|
||||
suppress = 0;
|
||||
ARG_PUT(*databuf);
|
||||
databuf++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (!suppress)
|
||||
ARG_PUT(
|
||||
(*databuf) << 8 |
|
||||
*(databuf + 1));
|
||||
else
|
||||
suppress = 0;
|
||||
ARG_PUT(
|
||||
(*databuf) << 8 |
|
||||
*(databuf + 1));
|
||||
databuf += 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (!suppress)
|
||||
ARG_PUT(
|
||||
(*databuf) << 16 |
|
||||
(*(databuf + 1)) << 8 |
|
||||
*(databuf + 2));
|
||||
else
|
||||
suppress = 0;
|
||||
ARG_PUT(
|
||||
(*databuf) << 16 |
|
||||
(*(databuf + 1)) << 8 |
|
||||
*(databuf + 2));
|
||||
databuf += 3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (!suppress)
|
||||
ARG_PUT(
|
||||
(*databuf) << 24 |
|
||||
(*(databuf + 1)) << 16 |
|
||||
(*(databuf + 2)) << 8 |
|
||||
*(databuf + 3));
|
||||
else
|
||||
suppress = 0;
|
||||
ARG_PUT(
|
||||
(*databuf) << 24 |
|
||||
(*(databuf + 1)) << 16 |
|
||||
(*(databuf + 2)) << 8 |
|
||||
*(databuf + 3));
|
||||
databuf += 4;
|
||||
break;
|
||||
|
||||
@ -279,7 +283,6 @@ char *fmt, va_list ap)
|
||||
width = strtol(fmt, &fmt, 10);
|
||||
if (!suppress)
|
||||
{
|
||||
|
||||
if (arg_put)
|
||||
(*arg_put)(puthook, letter, databuf, width, field_name);
|
||||
else
|
||||
@ -295,11 +298,11 @@ char *fmt, va_list ap)
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
assigned++;
|
||||
}
|
||||
else
|
||||
suppress = 0;
|
||||
databuf += width;
|
||||
decoded++;
|
||||
field_name[0] = 0;
|
||||
suppress = 0;
|
||||
break;
|
||||
|
||||
case 's': /* Seek */
|
||||
@ -330,7 +333,6 @@ char *fmt, va_list ap)
|
||||
else
|
||||
databuf = base + width; /* Absolute seek */
|
||||
|
||||
decoded++;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
@ -343,7 +345,7 @@ char *fmt, va_list ap)
|
||||
}
|
||||
}
|
||||
|
||||
return decoded;
|
||||
return assigned;
|
||||
}
|
||||
|
||||
int scsireq_decode(scsireq_t *scsireq, char *fmt, ...)
|
||||
@ -438,6 +440,13 @@ char *fmt, int *width_p, int *value_p, char *name, int n_name, int *error_p)
|
||||
state = DONE;
|
||||
else if (isspace(*p))
|
||||
p++;
|
||||
else if (*p == '#')
|
||||
{
|
||||
while (*p && *p != '\n')
|
||||
p++;
|
||||
if (p)
|
||||
p++;
|
||||
}
|
||||
else if (*p == '{')
|
||||
{
|
||||
int i = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user