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__sat_identify.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-01-30  |  7.6 KB  |  216 lines

  1. /*
  2.  * Copyright (c) 2006-2007 Douglas Gilbert.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. The name of the author may not be used to endorse or promote products
  14.  *    derived from this software without specific prior written permission.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26.  * SUCH DAMAGE.
  27.  *
  28.  */
  29.  
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <sys/ioctl.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include "sg_lib.h"
  40. #include "sg_io_linux.h"
  41.  
  42. /* This program uses a ATA PASS-THROUGH (16) SCSI command to package
  43.    an ATA IDENTIFY DEVICE (A1h) command. If the '-p' option is given,
  44.    it will package an ATA IDENTIFY PACKET DEVICE (Ech) instead (for
  45.    ATAPI device like cd/dvd drives) See http://www.t10.org
  46.    SAT draft at time of writing: sat-r08a.pdf
  47.  
  48.    Invocation: sg__sat_identify [-p] [-v] [-V] <device>
  49.  
  50.    With SAT, the user can find out whether a device is an ATA disk or
  51.    an ATAPI device. The ATA Information VPD page contains a "command
  52.    code" field in byte 56. Its values are either ECh for a (s/p)ATA
  53.    disk, A1h for a (s/p)ATAPI device, or 0 for unknown.
  54.  
  55. */
  56.  
  57. #define SAT_ATA_PASS_THROUGH16 0x85
  58. #define SAT_ATA_PASS_THROUGH16_LEN 16
  59. #define SAT_ATA_RETURN_DESC 9  /* ATA Return (sense) Descriptor */
  60.  
  61. #define ATA_IDENTIFY_DEVICE 0xec
  62. #define ATA_IDENTIFY_PACKET_DEVICE 0xa1
  63. #define ID_RESPONSE_LEN 512
  64.  
  65. #define EBUFF_SZ 256
  66.  
  67. static char * version_str = "1.02 20070130";
  68.  
  69. static void usage()
  70. {
  71.     fprintf(stderr, "Usage: "
  72.           "sg__sat_identify [-p] [-v] [-V] <device>\n"
  73.           "  where: -p    do IDENTIFY PACKET DEVICE (def: IDENTIFY "
  74.           "DEVICE) command\n"
  75.           "         -v    increase verbosity\n"
  76.           "         -V    print version string and exit\n\n"
  77.           "Performs a IDENTIFY (PACKET) DEVICE ATA command via a SAT "
  78.           "pass through\n");
  79. }
  80.  
  81. int main(int argc, char * argv[])
  82. {
  83.     int sg_fd, k, ok;
  84.     unsigned char aptCmdBlk[SAT_ATA_PASS_THROUGH16_LEN] =
  85.                 {SAT_ATA_PASS_THROUGH16, 0, 0, 0, 0, 0, 0, 0,
  86.                  0, 0, 0, 0, 0, 0, 0, 0};
  87.     sg_io_hdr_t io_hdr;
  88.     char * file_name = 0;
  89.     char ebuff[EBUFF_SZ];
  90.     unsigned char inBuff[ID_RESPONSE_LEN];
  91.     unsigned char sense_buffer[32];
  92.     int do_packet = 0;
  93.     int verbose = 0;
  94.     int extend = 0;
  95.     int chk_cond = 0;   /* set to 1 to read register(s) back */
  96.     int protocol = 4;   /* PIO data-in */
  97.     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
  98.     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
  99.     int t_length = 2;   /* 0 -> no data transferred, 2 -> sector count */
  100.     const unsigned char * cucp;
  101.  
  102.     memset(inBuff, 0, sizeof(inBuff));
  103.     for (k = 1; k < argc; ++k) {
  104.         if (0 == strcmp(argv[k], "-p"))
  105.             ++do_packet;
  106.         else if (0 == strcmp(argv[k], "-v"))
  107.             ++verbose;
  108.         else if (0 == strcmp(argv[k], "-vv"))
  109.             verbose += 2;
  110.         else if (0 == strcmp(argv[k], "-vvv"))
  111.             verbose += 3;
  112.         else if (0 == strcmp(argv[k], "-V")) {
  113.             fprintf(stderr, "version: %s\n", version_str);
  114.             exit(0);
  115.         } else if (*argv[k] == '-') {
  116.             printf("Unrecognized switch: %s\n", argv[k]);
  117.             file_name = 0;
  118.             break;
  119.         }
  120.         else if (0 == file_name)
  121.             file_name = argv[k];
  122.         else {
  123.             printf("too many arguments\n");
  124.             file_name = 0;
  125.             break;
  126.         }
  127.     }
  128.     if (0 == file_name) {
  129.         usage();
  130.         return 1;
  131.     }
  132.  
  133.     if ((sg_fd = open(file_name, O_RDWR)) < 0) {
  134.         snprintf(ebuff, EBUFF_SZ,
  135.                  "sg__sat_identify: error opening file: %s", file_name);
  136.         perror(ebuff);
  137.         return 1;
  138.     }
  139.  
  140.     /* Prepare ATA PASS-THROUGH COMMAND (16) command */
  141.     aptCmdBlk[6] = 1;   /* sector count */
  142.     aptCmdBlk[14] = (do_packet ? ATA_IDENTIFY_PACKET_DEVICE :
  143.                                  ATA_IDENTIFY_DEVICE);
  144.     aptCmdBlk[1] = (protocol << 1) | extend;
  145.     aptCmdBlk[2] = (chk_cond << 5) | (t_dir << 3) |
  146.                    (byte_block << 2) | t_length;
  147.     if (verbose) {
  148.         fprintf(stderr, "    ata pass through(16) cdb: ");
  149.         for (k = 0; k < SAT_ATA_PASS_THROUGH16_LEN; ++k)
  150.             fprintf(stderr, "%02x ", aptCmdBlk[k]);
  151.         fprintf(stderr, "\n");
  152.     }
  153.  
  154.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  155.     io_hdr.interface_id = 'S';
  156.     io_hdr.cmd_len = sizeof(aptCmdBlk);
  157.     /* io_hdr.iovec_count = 0; */  /* memset takes care of this */
  158.     io_hdr.mx_sb_len = sizeof(sense_buffer);
  159.     io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  160.     io_hdr.dxfer_len = ID_RESPONSE_LEN;
  161.     io_hdr.dxferp = inBuff;
  162.     io_hdr.cmdp = aptCmdBlk;
  163.     io_hdr.sbp = sense_buffer;
  164.     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
  165.     /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
  166.     /* io_hdr.pack_id = 0; */
  167.     /* io_hdr.usr_ptr = NULL; */
  168.  
  169.     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
  170.         perror("sg__sat_identify: SG_IO ioctl error");
  171.         close(sg_fd);
  172.         return 1;
  173.     }
  174.  
  175.     /* now for the error processing */
  176.     ok = 0;
  177.     switch (sg_err_category3(&io_hdr)) {
  178.     case SG_LIB_CAT_CLEAN:
  179.         ok = 1;
  180.         break;
  181.     case SG_LIB_CAT_RECOVERED:
  182.         if (verbose)
  183.             sg_chk_n_print3(">>> ATA_16 command", &io_hdr, 1);
  184.         /* check for ATA Return Descriptor */
  185.         cucp = sg_scsi_sense_desc_find(io_hdr.sbp, io_hdr.sb_len_wr,
  186.                                        SAT_ATA_RETURN_DESC);
  187.         if (cucp && (cucp[3])) {
  188.             if (cucp[3] & 0x4) {
  189.                 printf("error in returned FIS: aborted command\n");
  190.                 printf("    try again with%s '-p' option\n",
  191.                        (do_packet ? "out" : ""));
  192.                 break;
  193.             }
  194.         }
  195.         ok = 1;         /* not sure what is happening so output response */
  196.         if (0 == verbose) {
  197.             printf(">>> Recovered error on ATA_16, may have failed\n");
  198.             printf("    Add '-v' for more information\n");
  199.         }
  200.         break;
  201.     default: /* won't bother decoding other categories */
  202.         sg_chk_n_print3("ATA_16 command error", &io_hdr, 1);
  203.         break;
  204.     }
  205.  
  206.     if (ok) { /* output result if it is available */
  207.         printf("Response for IDENTIFY %sDEVICE ATA command:\n",
  208.                (do_packet ? "PACKET " : ""));
  209.         dWordHex((const unsigned short *)inBuff, 256, 0,
  210.                  sg_is_big_endian());
  211.     }
  212.  
  213.     close(sg_fd);
  214.     return 0;
  215. }
  216.