home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / doc / sg3-utils / examples / sg_simple3.c < prev    next >
Encoding:
C/C++ Source or Header  |  2005-12-20  |  6.4 KB  |  205 lines

  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include "sg_lib.h"
  11. #include "sg_io_linux.h"
  12.  
  13. /* This is a simple program executing a SCSI INQUIRY command and a
  14.    TEST UNIT READY command using the SCSI generic (sg) driver.
  15.    There is another variant of this program called "sg_simple1".
  16.    This variant demonstrates using the scatter gather facility in
  17.    the sg_io_hdr interface to break an INQUIRY response into its
  18.    component parts.
  19.  
  20. *  Copyright (C) 1999 D. Gilbert
  21. *  This program is free software; you can redistribute it and/or modify
  22. *  it under the terms of the GNU General Public License as published by
  23. *  the Free Software Foundation; either version 2, or (at your option)
  24. *  any later version.
  25.  
  26.    Invocation: sg_simple3 [-x] <sg_device>
  27.  
  28.    Version 03.58 (20020226)
  29.  
  30. 6 byte INQUIRY command:
  31. [0x12][   |lu][pg cde][res   ][al len][cntrl ]
  32.  
  33. 6 byte TEST UNIT READY command:
  34. [0x00][   |lu][res   ][res   ][res   ][res   ]
  35.  
  36. */
  37.  
  38. #define INQ_REPLY_BASE_LEN 8
  39. #define INQ_REPLY_VID_LEN 8
  40. #define INQ_REPLY_PID_LEN 16
  41. #define INQ_REPLY_PREV_LEN 4
  42. #define INQ_REPLY_IOVEC_COUNT 4
  43. #define INQ_CMD_LEN 6
  44. #define TUR_CMD_LEN 6
  45.  
  46. #define EBUFF_SZ 256
  47.  
  48. int main(int argc, char * argv[])
  49. {
  50.     int sg_fd, k, ok;
  51.     unsigned char inqCmdBlk [INQ_CMD_LEN] = {0x12, 0, 0, 0,
  52.                     INQ_REPLY_BASE_LEN + INQ_REPLY_VID_LEN +
  53.                     INQ_REPLY_PID_LEN + INQ_REPLY_PREV_LEN, 0};
  54.     unsigned char turCmdBlk [TUR_CMD_LEN] = {0x00, 0, 0, 0, 0, 0};
  55.     sg_iovec_t iovec[INQ_REPLY_IOVEC_COUNT];
  56.     unsigned char inqBaseBuff[INQ_REPLY_BASE_LEN];
  57.     char inqVidBuff[INQ_REPLY_VID_LEN];
  58.     char inqPidBuff[INQ_REPLY_PID_LEN];
  59.     char inqPRevBuff[INQ_REPLY_PREV_LEN];
  60.     sg_io_hdr_t io_hdr;
  61.     char * file_name = 0;
  62.     char ebuff[EBUFF_SZ];
  63.     unsigned char sense_buffer[32];
  64.     int do_extra = 0;
  65.  
  66.     for (k = 1; k < argc; ++k) {
  67.         if (0 == memcmp("-x", argv[k], 2))
  68.             do_extra = 1;
  69.         else if (*argv[k] == '-') {
  70.             printf("Unrecognized switch: %s\n", argv[k]);
  71.             file_name = 0;
  72.             break;
  73.         }
  74.         else if (0 == file_name)
  75.             file_name = argv[k];
  76.         else {
  77.             printf("too many arguments\n");
  78.             file_name = 0;
  79.             break;
  80.         }
  81.     }
  82.     if (0 == file_name) {
  83.         printf("Usage: 'sg_simple3 [-x] <sg_device>'\n");
  84.         return 1;
  85.     }
  86.  
  87.     /* N.B. An access mode of O_RDWR is required for some SCSI commands */
  88.     if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
  89.         snprintf(ebuff, EBUFF_SZ,
  90.                  "sg_simple3: error opening file: %s", file_name);
  91.         perror(ebuff);
  92.         return 1;
  93.     }
  94.     /* Just to be safe, check we have a new sg device by trying an ioctl */
  95.     if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
  96.         printf("sg_simple3: %s doesn't seem to be an new sg device\n",
  97.                file_name);
  98.         close(sg_fd);
  99.         return 1;
  100.     }
  101.  
  102.     /* Prepare INQUIRY command */
  103.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  104.     io_hdr.interface_id = 'S';
  105.     io_hdr.cmd_len = sizeof(inqCmdBlk);
  106.     io_hdr.iovec_count = INQ_REPLY_IOVEC_COUNT;
  107.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  108.     io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  109.     io_hdr.dxfer_len = INQ_REPLY_BASE_LEN + INQ_REPLY_VID_LEN +
  110.                        INQ_REPLY_PID_LEN + INQ_REPLY_PREV_LEN;
  111.     iovec[0].iov_base = inqBaseBuff;
  112.     iovec[0].iov_len = INQ_REPLY_BASE_LEN;
  113.     iovec[1].iov_base = inqVidBuff;
  114.     iovec[1].iov_len = INQ_REPLY_VID_LEN;
  115.     iovec[2].iov_base = inqPidBuff;
  116.     iovec[2].iov_len = INQ_REPLY_PID_LEN;
  117.     iovec[3].iov_base = inqPRevBuff;
  118.     iovec[3].iov_len = INQ_REPLY_PREV_LEN;
  119.     io_hdr.dxferp = iovec;
  120.     io_hdr.cmdp = inqCmdBlk;
  121.     io_hdr.sbp = sense_buffer;
  122.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  123.     /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
  124.     /* io_hdr.pack_id = 0; */
  125.     /* io_hdr.usr_ptr = NULL; */
  126.  
  127.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  128.         perror("sg_simple3: Inquiry SG_IO ioctl error");
  129.         close(sg_fd);
  130.         return 1;
  131.     }
  132.  
  133.     /* now for the error processing */
  134.     ok = 0;
  135.     switch (sg_err_category3(&io_hdr)) {
  136.     case SG_LIB_CAT_CLEAN:
  137.         ok = 1;
  138.         break;
  139.     case SG_LIB_CAT_RECOVERED:
  140.         printf("Recovered error on INQUIRY, continuing\n");
  141.         ok = 1;
  142.         break;
  143.     default: /* won't bother decoding other categories */
  144.         sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
  145.         break;
  146.     }
  147.  
  148.     if (ok) { /* output result if it is available */
  149.         char * p = (char *)inqBaseBuff;
  150.         int f = (int)*(p + 7);
  151.         printf("Some of the INQUIRY command's results:\n");
  152.         printf("  %.8s  %.16s  %.4s  ", inqVidBuff, inqPidBuff, inqPRevBuff);
  153.         printf("[wide=%d sync=%d cmdque=%d sftre=%d]\n",
  154.                !!(f & 0x20), !!(f & 0x10), !!(f & 2), !!(f & 1));
  155.         /* Extra info, not necessary to look at */
  156.         if (do_extra)
  157.             printf("INQUIRY duration=%u millisecs, resid=%d, msg_status=%d\n",
  158.                    io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
  159.     }
  160.  
  161.  
  162.     /* Prepare TEST UNIT READY command */
  163.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  164.     io_hdr.interface_id = 'S';
  165.     io_hdr.cmd_len = sizeof(turCmdBlk);
  166.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  167.     io_hdr.dxfer_direction = SG_DXFER_NONE;
  168.     io_hdr.cmdp = turCmdBlk;
  169.     io_hdr.sbp = sense_buffer;
  170.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  171.  
  172.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  173.         perror("sg_simple3: Test Unit Ready SG_IO ioctl error");
  174.         close(sg_fd);
  175.         return 1;
  176.     }
  177.  
  178.     /* now for the error processing */
  179.     ok = 0;
  180.     switch (sg_err_category3(&io_hdr)) {
  181.     case SG_LIB_CAT_CLEAN:
  182.         ok = 1;
  183.         break;
  184.     case SG_LIB_CAT_RECOVERED:
  185.         printf("Recovered error on Test Unit Ready, continuing\n");
  186.         ok = 1;
  187.         break;
  188.     default: /* won't bother decoding other categories */
  189.         sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1);
  190.         break;
  191.     }
  192.  
  193.     if (ok)
  194.         printf("Test Unit Ready successful so unit is ready!\n");
  195.     else
  196.         printf("Test Unit Ready failed so unit may _not_ be ready!\n");
  197.  
  198.     if (do_extra)
  199.         printf("TEST UNIT READY duration=%u millisecs, resid=%d, msg_status=%d\n",
  200.                io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
  201.  
  202.     close(sg_fd);
  203.     return 0;
  204. }
  205.