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_iovec_tst.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-01-21  |  5.8 KB  |  195 lines

  1. #include <unistd.h>
  2. #include <signal.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "sg_lib.h"
  12. #include "sg_io_linux.h"
  13.  
  14. /* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
  15.    device driver.
  16. *  Copyright (C) 2003-2007 D. Gilbert
  17. *  This program is free software; you can redistribute it and/or modify
  18. *  it under the terms of the GNU General Public License as published by
  19. *  the Free Software Foundation; either version 2, or (at your option)
  20. *  any later version.
  21.  
  22.    This program will read a certain number of blocks of a given block size
  23.    from a given sg device node and write what is retrieved out to a
  24.    normal file. The purpose is to test the sg_iovec mechanism within the
  25.    sg_io_hdr structure.
  26.  
  27.    Version 0.12 (20070121)
  28. */
  29.  
  30.  
  31. #define ME "sg_iovec_tst: "
  32.  
  33. #define A_PRIME 509
  34. #define IOVEC_ELEMS 2048
  35.  
  36. #define SENSE_BUFF_LEN 32
  37. #define DEF_TIMEOUT 40000       /* 40,000 milliseconds */
  38.  
  39. struct sg_iovec iovec[IOVEC_ELEMS];
  40.  
  41. /* Returns 0 if everything ok */
  42. int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block,
  43.             int bs)
  44. {
  45.     unsigned char rdCmd[10] = {READ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  46.     unsigned char senseBuff[SENSE_BUFF_LEN];
  47.     struct sg_io_hdr io_hdr;
  48.     int dxfer_len = bs * num_blocks;
  49.     int k, pos, rem;
  50.  
  51.     rdCmd[2] = (unsigned char)((from_block >> 24) & 0xff);
  52.     rdCmd[3] = (unsigned char)((from_block >> 16) & 0xff);
  53.     rdCmd[4] = (unsigned char)((from_block >> 8) & 0xff);
  54.     rdCmd[5] = (unsigned char)(from_block & 0xff);
  55.     rdCmd[7] = (unsigned char)((num_blocks >> 8) & 0xff);
  56.     rdCmd[8] = (unsigned char)(num_blocks & 0xff);
  57.  
  58.     for (k = 0, pos = 0, rem = dxfer_len; k < IOVEC_ELEMS; ++k) {
  59.         iovec[k].iov_base = buff + pos;
  60.         iovec[k].iov_len = (rem > A_PRIME) ? A_PRIME : rem;
  61.         if (rem <= A_PRIME)
  62.             break;
  63.         pos += A_PRIME;
  64.         rem -= A_PRIME;
  65.     }
  66.     if (k >= IOVEC_ELEMS) {
  67.         fprintf(stderr, "Can't fit dxfer_len=%d bytes in iovec\n", dxfer_len);
  68.         return -1;
  69.     }
  70.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  71.     io_hdr.interface_id = 'S';
  72.     io_hdr.cmd_len = sizeof(rdCmd);
  73.     io_hdr.cmdp = rdCmd;
  74.     io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  75.     io_hdr.dxfer_len = dxfer_len;
  76.     io_hdr.iovec_count = k + 1;
  77.     io_hdr.dxferp = iovec;
  78.     io_hdr.mx_sb_len = SENSE_BUFF_LEN;
  79.     io_hdr.sbp = senseBuff;
  80.     io_hdr.timeout = DEF_TIMEOUT;
  81.     io_hdr.pack_id = from_block;
  82.  
  83.     if (ioctl(sg_fd, SG_IO, &io_hdr)) {
  84.         perror("reading (SG_IO) on sg device, error");
  85.         return -1;
  86.     }
  87.     switch (sg_err_category3(&io_hdr)) {
  88.     case SG_LIB_CAT_CLEAN:
  89.         break;
  90.     case SG_LIB_CAT_RECOVERED:
  91.         fprintf(stderr, "Recovered error while reading block=%d, num=%d\n",
  92.                from_block, num_blocks);
  93.         break;
  94.     case SG_LIB_CAT_UNIT_ATTENTION:
  95.         fprintf(stderr, "Unit attention\n");
  96.         return -1;
  97.     default:
  98.         sg_chk_n_print3("reading", &io_hdr, 1);
  99.         return -1;
  100.     }
  101.     return 0;
  102. }
  103.  
  104.  
  105. int main(int argc, char * argv[])
  106. {
  107.     int sg_fd, fd, res, j, m, dxfer_len;
  108.     unsigned int k, num;
  109.     int do_help = 0;
  110.     int blk_size = 512;
  111.     int count = 0;
  112.     char * sg_file_name = 0;
  113.     char * out_file_name = 0;
  114.     unsigned char * buffp;
  115.  
  116.     for (j = 1; j < argc; ++j) {
  117.         if (0 == strncmp("-b=", argv[j], 3)) {
  118.             m = 3;
  119.             num = sscanf(argv[j] + m, "%d", &blk_size);
  120.             if ((1 != num) || (blk_size <= 0)) {
  121.                 printf("Couldn't decode number after '-b' switch\n");
  122.                 sg_file_name = 0;
  123.                 break;
  124.             }
  125.         }
  126.         else if (0 == strncmp("-c=", argv[j], 3)) {
  127.             m = 3;
  128.             num = sscanf(argv[j] + m, "%d", &count);
  129.             if (1 != num) {
  130.                 printf("Couldn't decode number after '-c' switch\n");
  131.                 sg_file_name = 0;
  132.                 break;
  133.             }
  134.         }
  135.         else if (0 == strcmp("-h", argv[j]))
  136.             do_help = 1;
  137.         else if (*argv[j] == '-') {
  138.             printf("Unrecognized switch: %s\n", argv[j]);
  139.             sg_file_name = 0;
  140.             break;
  141.         }
  142.         else if (NULL == sg_file_name)
  143.             sg_file_name = argv[j];
  144.         else
  145.             out_file_name = argv[j];
  146.     }
  147.     if ((NULL == sg_file_name) || (NULL == out_file_name) || (0 == count)) {
  148.         printf("Usage: sg_iovec_tst [-h] [-b=num] -c=num <generic_device> "
  149.                "<output_filename>\n");
  150.         printf("  where: -h       this usage message\n");
  151.         printf("         -b=num   block size (default 512 Bytes)\n");
  152.         printf("         -c=num   count of blocks to transfer\n");
  153.         printf(" reads from <generic_device> and sends to <output_filename>\n");
  154.         return 1;
  155.     }
  156.  
  157.     sg_fd = open(sg_file_name, O_RDONLY);
  158.     if (sg_fd < 0) {
  159.         perror(ME "sg device node open error");
  160.         return 1;
  161.     }
  162.     /* Don't worry, being very careful not to write to a none-sg file ... */
  163.     res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k);
  164.     if ((res < 0) || (k < 30000)) {
  165.         printf(ME "not a sg device, or driver prior to 3.x\n");
  166.         return 1;
  167.     }
  168.     fd = open(out_file_name, O_WRONLY | O_CREAT, 0666);
  169.     if (fd < 0) {
  170.         perror(ME "output file open error");
  171.         return 1;
  172.     }
  173.     dxfer_len = count * blk_size;
  174.     buffp = (unsigned char *)malloc(dxfer_len);
  175.     if (buffp) {
  176.         if (0 == sg_read(sg_fd, buffp, count, 0, blk_size)) {
  177.             if (write(fd, buffp, dxfer_len) < 0)
  178.                 perror(ME "output write failed");
  179.         }
  180.         free(buffp);
  181.     }
  182.     res = close(fd);
  183.     if (res < 0) {
  184.         perror(ME "output file close error");
  185.         close(sg_fd);
  186.         return 1;
  187.     }
  188.     res = close(sg_fd);
  189.     if (res < 0) {
  190.         perror(ME "sg device close error");
  191.         return 1;
  192.     }
  193.     return 0;
  194. }
  195.