dslib(3X) dslib(3X) NAME dslib: dsopen, dsclose - communicate with generic SCSI devices SYNOPSIS #include <dslib.h> struct dsreq *dsopen(opath, oflags) dsclose(dsp) ds_showcmd(dsp) testunitready00(dsp) requestsense03(dsp, data, datalen, vu) read08(dsp, data, datalen, lba, vu) write0a(dsp, data, datalen, lba, vu) inquiry12(dsp, data, datalen, vu) modeselect15(dsp, data, datalen, save, vu) modeselect55(dsp, data, datalen, save, vu) reserveunit16(dsp, data, datalen, tpr, tpdid, extent, resid, vu) releaseunit17(dsp, tpr, tpdid, extent, resid, vu) modesense1a(dsp, data, datalen, pagectrl, pagecode, vu) modesense5a(dsp, data, datalen, pagectrl, pagecode, vu) modesenseNB_5a(dsp, data, datalen, pagectrl, pagecode, vu) senddiagnostic1d(dsp, data, datalen, self, dofl, uofl, vu) readcapacity25(dsp, data, datalen, lba, pmi, vu) readextended28(dsp, data, datalen, lba, vu) writeextended2a(dsp, data, datalen, lba, vu) getfd(dsp) doscsireq(fd, dsp) void fillg0cmd(dsp, cmdbuf, b0, ..., b5) void fillg1cmd(dsp, cmdbuf, b0, ..., b9) void fillg2cmd(dsp, cmdbuf, b0, ..., b9) void fillg5cmd(dsp, cmdbuf, b0, ..., b11) void filldsreq(dsp, data, datalen, flags) void vtostr(value, table) extern int dsdebug; extern int ds_default_timeout; extern long dsreqflags; DSDBG(statement; ...) struct dsreq *dsp; struct vtab *table; char *opath, *cmdbuf, *data; char b0, ..., b9, dofl, extent, pagecode, pagectrl, pmi, resid, save, self, tpdid, tpr, uofl, vu; int fd, oflags; long datalen, lba, value; DESCRIPTION These routines form the basis for a simplified interface to ds(7M) devices. They are included in a program by compiling with the -lds option. An application would typically use dsopen, dsclose, and a set of command-specific routines such as testunitready00. The source to this library can be obtained by loading the irix_dev.gifts.scsi subsystem, with the source code for the library in the files dstab.c and dslib.c in the directory /usr/share/src/irix/examples/scsi. There are also several sample programs using the dslib library in the same directory. The number of truly general SCSI commands is quite limited, so provision is made for supporting vendor-specific commands. This is normally done by using one of the existing routines as a template, and creating a new routine of your own. This might be useful if support for a SCSI command group other than Group 0, 1, 2, or 5 is needed. It is expected that most non-trivial uses of the library will involve creating or modifying existing routines. As of release 4.0 of IRIX, any SCSI command length from 1 to 12 bytes is supported by the underlying kernel drivers, providing the ds_cmdlen field is set correctly. A set of helper routines (fillg0cmd and so on) are used as the basis for creating your own routines. The utility function ds_showcmd(dsp) can be used to show information about the most recently executed command, in cases where the use of dsdebug is too verbose. testunitready00, for instance, is implemented as: testunitready00(dsp) struct dsreq *dsp; { fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0); filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE); return(doscsireq(getfd(dsp), dsp)); } Note that many of these routines depend upon the exact setup of the dsreq structure used by dsopen. It is therefore not recommended that users attempt to use independently derived dsreq structures with them. dsopen passes opath and oflags to the open system call. If the open succeeds, dsopen allocates and fills a dsreq structure, along with some associated context information. dsclose deallocates the specified dsreq structure, then calls close to close the device. fillg0cmd, fillg1cmd, fillg2cmd, and fillg5cmd are used to fill Group 0, 1, 2, and 5 command buffers, respectively. filldsreq fills a dsreq structure with commonly needed data. The value of dsreqflags is ORed into the ds_flags field. This is useful if you want a flag (such as DSRQ_SENSE) set for some or all commands, as it allows you to avoid duplicating the library routines when you need a special flag set. It also sets the default timeout (for functions that do not explicitly set a timeout). The timeout is set from the global variable ds_default_timeout, and that variable is initialized to 10 seconds. It may be changed for applications that want longer default timeouts. Individual functions may still need to set longer (or shorter) timeouts, after calling filldsreq. doscsireq issues the SCSI ioctl, performs a variety of error-handling functions, and returns the SCSI status byte. Also of interest on return is the ds_ret field, which is 0 on successful returns, and on failures indicates what type of error occurred (the DSRT_* values in <sys/dsreq.h>. ds_vtostr Takes a value, and a table to look it up in. If the value is found in the given table, a string describing the value is returned, else the empty string. Five tables are provided: dsrqnametab for the DSRQ_* flags dsrtnametab for the DSRT_* flags cmdstatustab for the SCSI status byte return in ds_status msgnametab for the SCSI message bytes cmdnametab for the SCSI commands, such as Testunitready (value is the command byte; G0_TEST in this case) The dsdebug variable, and the DSDBG() macro can be used to enable debug printfs, and to add your own. If the dsdebug variable is non-zero, debugging information is printed by the library routines. The DSDBG macro is used for this purpose. A more or less arbitrary sequence of statements can be used within the parentheses of the DSDBG macro, but some form of print statement is most frequently used. Overlay structures define the layouts of the three (Group 0, 1, 6) Common Command Set command buffers. Bytes are named both by position (g0_b0) and by typical function in the command buffer (g1_op_code). Mnemonic names are also defined for all CCS command codes (G0_TEST), message bytes (MSG_ABORT), and status bytes (STA_BUSY). There are also a number of macros suitable for accessing dsreq structures, SCSI byte and bit fields, etc. A set of structures contains values, name strings, and descriptions for commonly used codes and values. The structures document DSRQ_* and DSRT_* codes, CCS command codes, and CCS status and message bytes. They are principally useful in generating explicit error messages. EXAMPLE PROGRAM The following code fragment illustrates simple use of the library, and of some /dev/scsi support macros. If you have installed the 4Dgifts.src.full image, the full source code for this program can be found in the file /usr/people/4Dgifts/examples/devices/devscsi/inquire.c, while (--argc > 0) { fn = *++argv; printf("%-17s ", fn); if ((dsp = dsopen(fn, O_RDONLY)) == NULL) { fflush(stdout); perror("cannot open"); continue; } if(inquiry12(dsp, inqbuf, sizeof inqbuf, 0) != 0) printf("%-10s inquiry failure0, "---"); else { pdt = DATABUF(dsp)[0] & 0x7F; if (DATASENT(dsp) >= 1) printf("%-10s", pdt_types[(pdt<NPDT) ? pdt : NPDT-1]); if (DATASENT(dsp) >= 16) printf(" %-12.8s", &DATABUF(dsp)[8]); if (DATASENT(dsp) >= 32) printf(" %.16s", &DATABUF(dsp)[16]); if (DATASENT(dsp) >= 36) printf(" %.4s", &DATABUF(dsp)[32]); /* do test unit ready only if inquiry successful, since many devices, such as tapes, return inquiry info, even if not ready (i.e., no tape in a tape drive). */ if(testunitready00(dsp) != 0) { printf(" %s0, (RET(dsp)==DSRT_NOSEL) ? "cannot select" : "not ready"); } else printf(" ready0); } dsclose(dsp); } Each device is opened, and the necessary data structures created. An inquiry is done to see if the device exists; if so, it's type is printed. A test unit ready is done to see if the device is ready for I/O. Finally, the device is closed, releasing the data structures. The normal output is of the form: /dev/scsi/sc0d2l0 Tape ARCHIVE VIPER 150 21247 -605 not ready DIAGNOSTICS dsopen returns a NULL pointer on failure. doscsireq returns -1 on absolute failure, and the status byte otherwise. A status byte of 0xff indicates an invalid status byte because the scsi command didn't complete. The RET(dsp) macro returns a result code, which can be consulted for any error or 'unusual' status from the driver; a value of 0 indicates a normal return. NOTE A common failure occurs when the byte count passed to the dslib routines doesn't match the byte count implied by the values in the SCSI command descriptor (as filled by fillg0cmd and so on). This is particularly common with read08,write0a,readextended28, and writeextended2a. This is because these commands occur in a number of device specific forms. If you get console error messages similar to SCSI Bus=# ID=# LUN=#: Too much data (probable SCSI bus cabling problem) then you are probably seeing this kind of mismatch. See the comments in the dslib.c source file for more information. As of IRIX 5.1, this library and the underlying driver are supported on all Silicon Graphics SCSI adapters (wd93, wd95, and jag) for all controllers that are installed. Prior to that release, it was supported only on the wd93 controller. As of IRIX 5.1, devices can be open via both the ds and other high level drivers at the same time (except for tpsc). Only one program can have any ds device open at a time, however. FILES /dev/scsi/* SEE ALSO hinv(1M), ds(7M). IRIX Device Driver Programmer's Guide Page 5