old-www/HOWTO/SCSI-Generic-HOWTO/pexample.html

256 lines
5.8 KiB
HTML

<HTML
><HEAD
><TITLE
>Programming example</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
"><LINK
REL="HOME"
TITLE="The Linux SCSI Generic (sg) HOWTO"
HREF="index.html"><LINK
REL="PREVIOUS"
TITLE="sg_header, the original sg control structure"
HREF="sg_header.html"><LINK
REL="NEXT"
TITLE="Debugging"
HREF="debugging.html"></HEAD
><BODY
CLASS="APPENDIX"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>The Linux SCSI Generic (sg) HOWTO</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="sg_header.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="debugging.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="APPENDIX"
><H1
><A
NAME="PEXAMPLE">Appendix C. Programming example</H1
><P
>This appendix contains an example program. It is an abridged version of
sg_simple2.c found in the <A
HREF="sg3_utils.html"
>sg3_utils</A
>
package. It send a SCSI INQUIRY command to the nominated sg device and
prints out some of the response or outputs error information. Hopefully
showing the error processing does not cloud what is being illustrated.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>&#13;#include &#60;unistd.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;stdio.h&#62;
#include &#60;string.h&#62;
#include &#60;errno.h&#62;
#include &#60;sys/ioctl.h&#62;
#include &#60;scsi/sg.h&#62; /* take care: fetches glibc's /usr/include/scsi/sg.h */
/* This is a simple program executing a SCSI INQUIRY command using the
sg_io_hdr interface of the SCSI generic (sg) driver.
* Copyright (C) 2001 D. Gilbert
* This program is free software. Version 1.01 (20020226)
*/
#define INQ_REPLY_LEN 96
#define INQ_CMD_CODE 0x12
#define INQ_CMD_LEN 6
int main(int argc, char * argv[])
{
int sg_fd, k;
unsigned char inqCmdBlk[INQ_CMD_LEN] =
{INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0};
/* This is a "standard" SCSI INQUIRY command. It is standard because the
* CMDDT and EVPD bits (in the second byte) are zero. All SCSI targets
* should respond promptly to a standard INQUIRY */
unsigned char inqBuff[INQ_REPLY_LEN];
unsigned char sense_buffer[32];
sg_io_hdr_t io_hdr;
if (2 != argc) {
printf("Usage: 'sg_simple0 &#60;sg_device&#62;'\n");
return 1;
}
if ((sg_fd = open(argv[1], O_RDONLY)) &#60; 0) {
/* Note that most SCSI commands require the O_RDWR flag to be set */
perror("error opening given file name");
return 1;
}
/* It is prudent to check we have a sg device by trying an ioctl */
if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &#38;k) &#60; 0) || (k &#60; 30000)) {
printf("%s is not an sg device, or old sg driver\n", argv[1]);
return 1;
}
/* Prepare INQUIRY command */
memset(&#38;io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(inqCmdBlk);
/* io_hdr.iovec_count = 0; */ /* memset takes care of this */
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = INQ_REPLY_LEN;
io_hdr.dxferp = inqBuff;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
/* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */
/* io_hdr.pack_id = 0; */
/* io_hdr.usr_ptr = NULL; */
if (ioctl(sg_fd, SG_IO, &#38;io_hdr) &#60; 0) {
perror("sg_simple0: Inquiry SG_IO ioctl error");
return 1;
}
/* now for the error processing */
if ((io_hdr.info &#38; SG_INFO_OK_MASK) != SG_INFO_OK) {
if (io_hdr.sb_len_wr &#62; 0) {
printf("INQUIRY sense data: ");
for (k = 0; k &#60; io_hdr.sb_len_wr; ++k) {
if ((k &#62; 0) &#38;&#38; (0 == (k % 10)))
printf("\n ");
printf("0x%02x ", sense_buffer[k]);
}
printf("\n");
}
if (io_hdr.masked_status)
printf("INQUIRY SCSI status=0x%x\n", io_hdr.status);
if (io_hdr.host_status)
printf("INQUIRY host_status=0x%x\n", io_hdr.host_status);
if (io_hdr.driver_status)
printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status);
}
else { /* assume INQUIRY response is present */
char * p = (char *)inqBuff;
printf("Some of the INQUIRY command's response:\n");
printf(" %.8s %.16s %.4s\n", p + 8, p + 16, p + 32);
printf("INQUIRY duration=%u millisecs, resid=%d\n",
io_hdr.duration, io_hdr.resid);
}
close(sg_fd);
return 0;
}&#13;</PRE
></FONT
></TD
></TR
></TABLE
></P
><P
>The sg_simple4.c program is an example of using mmap-ed IO in the sg3_utils
package. An example of using direct IO can be found in sg_rbuf.c in the
same package.</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="sg_header.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="debugging.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>sg_header, the original sg control structure</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Debugging</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>