diff options
Diffstat (limited to 'archive')
-rw-r--r-- | archive/Makefile | 74 | ||||
-rw-r--r-- | archive/README | 40 | ||||
-rw-r--r-- | archive/isosize.8 | 38 | ||||
-rw-r--r-- | archive/isosize.c | 189 | ||||
-rw-r--r-- | archive/llseek.h | 14 | ||||
-rw-r--r-- | archive/scsi_devfs_scan.8 | 42 | ||||
-rw-r--r-- | archive/scsi_devfs_scan.c | 358 | ||||
-rw-r--r-- | archive/sg3_utils.spec113 | 234 | ||||
-rw-r--r-- | archive/sg_bus_xfer.c | 194 | ||||
-rw-r--r-- | archive/sg_dd2048.c | 586 | ||||
-rw-r--r-- | archive/sg_dd512.c | 586 | ||||
-rw-r--r-- | archive/sg_dd_old.c | 612 | ||||
-rw-r--r-- | archive/sg_debug.c | 71 | ||||
-rw-r--r-- | archive/sg_hold.c | 144 | ||||
l--------- | archive/sg_io_linux.h | 1 | ||||
l--------- | archive/sg_lib.h | 1 | ||||
l--------- | archive/sg_linux_inc.h | 1 | ||||
-rw-r--r-- | archive/sg_poll.c | 351 | ||||
-rw-r--r-- | archive/sg_simple0.c | 93 | ||||
-rw-r--r-- | archive/sgq_dd.c | 1151 | ||||
-rw-r--r-- | archive/sgq_dd.c.orig | 1139 | ||||
-rw-r--r-- | archive/sgq_old_dd.c | 838 | ||||
-rw-r--r-- | archive/sgs_dd.c | 893 |
23 files changed, 6 insertions, 7644 deletions
diff --git a/archive/Makefile b/archive/Makefile deleted file mode 100644 index a2848016..00000000 --- a/archive/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -SHELL = /bin/sh - -INSTDIR=/usr/local/bin -MANDIR=/usr/local/man - -CC = gcc -LD = gcc - -EXECS = sgq_dd sg_poll sg_bus_xfer sg_hold sg_debug isosize scsi_devfs_scan - -COMMON = isosize - -MAN_PGS = isosize.8 -MAN_PREF = man8 - -CFLAGS = -g -O2 -W -Wall -D_REENTRANT -# CFLAGS = -g -O2 -Wall -pedantic -std=c99 -D_REENTRANT - -LDFLAGS = - -all: $(EXECS) - -common: $(COMMON) - -depend dep: - for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \ - done > .depend - -clean: - /bin/rm -f *.o $(EXECS) core .depend - -sg_poll: sg_poll.o ../sg_lib.o ../sg_io_linux.o - $(LD) -o $@ $(LDFLAGS) $^ - -sgq_dd: sgq_dd.o ../sg_lib.o ../sg_io_linux.o ../llseek.o - $(LD) -o $@ $(LDFLAGS) $^ - -sg_bus_xfer: sg_bus_xfer.o ../sg_lib.o ../sg_io_linux.o - $(LD) -o $@ $(LDFLAGS) $^ - -sg_hold: sg_hold.o - $(LD) -o $@ $(LDFLAGS) $^ - -isosize: isosize.o - $(LD) -o $@ $(LDFLAGS) $^ - -scsi_devfs_scan: scsi_devfs_scan.o ../sg_lib.o ../sg_io_linux.o - $(LD) -o $@ $(LDFLAGS) $^ - -sg_debug: sg_debug.o - $(LD) -o $@ $(LDFLAGS) $^ - -install: $(EXECS) $(COMMON) - install -d $(INSTDIR) - for name in $^; \ - do install -s -o root -g root -m 755 $$name $(INSTDIR); \ - done - for mp in $(MAN_PGS); \ - do install -o root -g root -m 644 $$mp $(MANDIR)/$(MAN_PREF); \ - gzip -9f $(MANDIR)/$(MAN_PREF)/$$mp; \ - done - -uninstall: - dists="$(EXECS)"; \ - for name in $$dists; do \ - rm -f $(INSTDIR)/$$name; \ - done - for mp in $(MAN_PGS); do \ - rm -f $(MANDIR)/$(MAN_PREF)/$$mp.gz; \ - done - -ifeq (.depend,$(wildcard .depend)) -include .depend -endif diff --git a/archive/README b/archive/README index 9732d3f9..5763cac0 100644 --- a/archive/README +++ b/archive/README @@ -1,35 +1,7 @@ -This archive directory contains programs the use the Linux SCSI -subsystem and typically use the SCSI generic interface (sg) as -well. +In order to save source code space, the files is this directory have +been removed (apart from the rescan-scsi-bus.sh script). See the +sg3_utils-1.22 source tarball for the most recent version that +included this source. -The programs in this directory are fully functional but have been -"retired" from the main sg3_utils directory most likely because -their functionality is done in another (perhaps better) way. - -The last time I checked these programs compiled and built and -didn't depend on too many other things (see the Makefile in the -parent directory for ideas). - -Since I actively use some of these programs for testing, a Makefile has -been set up which builds: - - sgq_dd [a dd variant the uses a dispatch loop rather than - POSIX threads (as does sgp_dd)] - - sg_hold holds a sg device open and periodically sends a TEST - UNIT READY command to the device - - sg_poll [internal testing] - - isosize available in util-linux-2.10s and later - -The sg_lib.h and llseek.h headers have simply been copied from the parent -directory. - -The very useful rescan-scsi-bus.sh script from Kurt Garloff -<kurt at garloff dot de> is included in this directory. - -A test program called sg_bus_xfer.c exercises a patch that adds a -SG_FLAG_BUS_ADDR capability. This allows a bus address (e.g. PCI -video card's frame buffer) to be passed through to a SCSI adapter -to side step various buffer copies. See: -http://www.torque.net/sg/mem2disk.html - -Doug Gilbert -3rd September 2004 +Douglas Gilbert +10th October 2006 diff --git a/archive/isosize.8 b/archive/isosize.8 deleted file mode 100644 index f9fb4180..00000000 --- a/archive/isosize.8 +++ /dev/null @@ -1,38 +0,0 @@ -.TH ISOSIZE "8" "December 2000" "sg3_utils-0.92" SG_UTILS -.SH NAME -isosize \- outputs the length of a iso9660 file system -.SH SYNOPSIS -.B isosize -[\fI-x\fR] [\fI-d <num>\fR] \fI<iso9660_image_file>\fR -.SH DESCRIPTION -.\" Add any additional description here -.PP -This command outputs the length of an iso9660 file system that -is contained in the given file. That file may be a normal file or -a block device (e.g. /dev/hdd or /dev/sr0). In the absence of -any switches (or errors) it will output the size of the iso9660 -file system in bytes. This can now be a large number (> > 4 GB). -.TP --x -output in humanly readable form the block count and the block -size. Output uses the term "sectors" for "blocks". -.TP --d <num> -only has affect when "-x" is not given. The number output (if no errors) -is the iso9660 file size in bytes divided by <num>. So if <num> is -the block size then the output number will be the block count. -.PP -The size of the file (or block device) holding a iso9660 file -system can be marginally larger than the actual size of the -iso9660 file system. One reason for this is that cd writers -are allowed to add "run out" sectors at the end of a iso9660 -image. -.SH AUTHOR -Written by Andries Brouwer -.SH "REPORTING BUGS" -Report bugs to <Andries.Brouwer at cwi dot nl>. -.SH COPYRIGHT -Copyright \(co 2000 Andries Brouwer -.br -This software is distributed under the GPL version 2. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/archive/isosize.c b/archive/isosize.c deleted file mode 100644 index d570afa4..00000000 --- a/archive/isosize.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * isosize : use iso9660 header info to find size of associated - * iso9660 file system - * - * Copyright (C) 2000 Andries Brouwer - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * isosize.c - Andries Brouwer, 000608 - * - * Synopsis: - * isosize [-x] [-d <num>] <filename> - * where "-x" gives length in sectors and sector size while - * without this argument the size is given in bytes - * without "-x" gives length in bytes unless "-d <num>" is - * given. In the latter case the length in bytes divided - * by <num> is given - * - * Version 2.03 2000/12/21 - * - add "-d <num>" option and use long long to fix things > 2 GB - * Version 2.02 2000/10/11 - * - error messages on IO failures [D. Gilbert] - * - */ -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> - -#define ISODCL(from, to) (to - from + 1) - -int xflag; - -int -isonum_721 (unsigned char * p) { - return ((p[0] & 0xff) - | ((p[1] & 0xff) << 8)); -} - -int -isonum_722 (unsigned char * p) { - return ((p[1] & 0xff) - | ((p[0] & 0xff) << 8)); -} - -int -isonum_723 (unsigned char * p) { - int le = isonum_721 (p); - int be = isonum_722 (p+2); - if (xflag && le != be) - fprintf(stderr, "723error: le=%d be=%d\n", le, be); - return (le); -} - -int -isonum_731 (unsigned char * p) { - return ((p[0] & 0xff) - | ((p[1] & 0xff) << 8) - | ((p[2] & 0xff) << 16) - | ((p[3] & 0xff) << 24)); -} - -int -isonum_732 (unsigned char * p) { - return ((p[3] & 0xff) - | ((p[2] & 0xff) << 8) - | ((p[1] & 0xff) << 16) - | ((p[0] & 0xff) << 24)); -} - - -int -isonum_733 (unsigned char * p) { - int le = isonum_731 (p); - int be = isonum_732 (p+4); - if (xflag && le != be) - fprintf(stderr, "733error: le=%d be=%d\n", le, be); - return (le); -} - -struct iso_primary_descriptor { - unsigned char type [ISODCL ( 1, 1)]; /* 711 */ - unsigned char id [ISODCL ( 2, 6)]; - unsigned char version [ISODCL ( 7, 7)]; /* 711 */ - unsigned char unused1 [ISODCL ( 8, 8)]; - unsigned char system_id [ISODCL ( 9, 40)]; /* auchars */ - unsigned char volume_id [ISODCL ( 41, 72)]; /* duchars */ - unsigned char unused2 [ISODCL ( 73, 80)]; - unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ - unsigned char unused3 [ISODCL ( 89, 120)]; - unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ - unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ - unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ - unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ - unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ - unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ - unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ - unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ - unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ - unsigned char volume_set_id [ISODCL (191, 318)]; /* duchars */ - unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ - unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ - unsigned char application_id [ISODCL (575, 702)]; /* achars */ - unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ - unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ - unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ - unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ - unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ - unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ - unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ - unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ - unsigned char unused4 [ISODCL (883, 883)]; - unsigned char application_data [ISODCL (884, 1395)]; - unsigned char unused5 [ISODCL (1396, 2048)]; -}; - -int main(int argc, char * argv[]) { - struct iso_primary_descriptor ipd; - int fd, nsecs, ssize, j, m; - int divisor = 0; - const char * filenamep = NULL; - - for (j = 1; j < argc; ++j) { - if (0 == strncmp("-d", argv[j], 2)) { - if (strlen(argv[j]) > 2) - m = 2; - else { - ++j; - if (j >= argc) { - filenamep = NULL; - break; - } - m = 0; - } - if (1 != sscanf(argv[j] + m, "%d", &divisor)) { - fprintf(stderr, "Couldn't decode number after '-d' switch\n"); - filenamep = NULL; - break; - } - } - else if (0 == strcmp("-x", argv[j])) - xflag = 1; - else if (*argv[j] == '-') { - fprintf(stderr, "Unrecognized switch: %s\n", argv[j]); - filenamep = NULL; - break; - } - else - filenamep = argv[j]; - } - - if(filenamep == NULL) { - fprintf(stderr, "Usage: isosize [-x] [-d <num>] iso9660-image\n"); - return 1; - } - - if ((fd = open(filenamep,O_RDONLY)) < 0) { - fprintf(stderr, "failed to open: %s", filenamep); - perror(", error"); - return 1; - } - if (lseek(fd, 16 << 11, 0) == (off_t)-1) { - perror("lseek error"); - return 1; - } - if (read(fd, &ipd, sizeof(ipd)) < 0) { - perror("read error"); - return 1; - } - - nsecs = isonum_733(ipd.volume_space_size); - ssize = isonum_723(ipd.logical_block_size); /* nowadays always 2048 */ - - if (xflag) - printf ("sector count: %d, sector size: %d\n", nsecs, ssize); - else { - long long product = nsecs; - - if (0 == divisor) - printf ("%lld\n", product * ssize); - else if (divisor == ssize) - printf ("%d\n", nsecs); - else - printf ("%lld\n", (product * ssize) / divisor); - } - return 0; -} diff --git a/archive/llseek.h b/archive/llseek.h deleted file mode 100644 index 2f6aef0f..00000000 --- a/archive/llseek.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LLSEEK_H -#define LLSEEK_H - -#if defined(__GNUC__) || defined(HAS_LONG_LONG) -typedef long long llse_loff_t; -#else -typedef long llse_loff_t; -#endif - -extern llse_loff_t llse_llseek(unsigned int fd, - llse_loff_t offset, - unsigned int origin); - -#endif diff --git a/archive/scsi_devfs_scan.8 b/archive/scsi_devfs_scan.8 deleted file mode 100644 index c371b24c..00000000 --- a/archive/scsi_devfs_scan.8 +++ /dev/null @@ -1,42 +0,0 @@ -.TH SG_DEVFS_SCAN "8" "April 2003" "sg3_utils-1.03" SG3_UTILS -.SH NAME -sg_devfs_scan \- Scan SCSI devices within a devfs tree -.SH SYNOPSIS -.B sg_devfs_scan -[\fI-d <dir>\fR] -[\fI-i\fR] -[\fI-ide\fR] -[\fI-l [-x]\fR] -[\fI-q\fR] -<\fIgeneric device\fR> -.SH DESCRIPTION -.\" Add any additional description here -.PP -scsi_devfs_scan is a utility for doing a directory scan on a system -running devfs to identify SCSI (and optionally IDE) devices. Various -information (including an INQUIRY) can be listed for each found device. -.TP --d <dir> -location of devfs [default: /dev ] -.TP --i -show INQUIRY data for each SCSI device -.TP --ide -show scan of IDE devices after SCSI ones -.TP --l -show device file names in leaf directory -.TP --x -add (major,minor) information to '-l' -.TP --q -just output host, bus, target, lun numbers -.SH AUTHORS -Written by D. Gilbert -.SH COPYRIGHT -Copyright \(co 2001 Douglas Gilbert -.br -This software is distributed under the GPL version 2. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/archive/scsi_devfs_scan.c b/archive/scsi_devfs_scan.c deleted file mode 100644 index 6cd526a0..00000000 --- a/archive/scsi_devfs_scan.c +++ /dev/null @@ -1,358 +0,0 @@ -#define _XOPEN_SOURCE 500 -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <dirent.h> -#include <errno.h> -#include <unistd.h> -#include "sg_lib.h" -#include "sg_io_linux.h" - -/* Code for scanning for SCSI devices within a Linux device pseudo file - system. - * Copyright (C) 2001 D. Gilbert - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - - This program scans the /dev directory structure looking for the - devfs "primary" scsi (and optionally IDE) device names. - - Version 0.13 20030430 -*/ - -void usage() -{ - printf("Usage: 'scsi_devfs_scan [-d <dir>] [-i] [-ide] [-l [-x]] " - "[-q]'\n"); - printf(" where: -d <dir> location of devfs [default: /dev ]\n"); - printf(" -i show INQUIRY data for each SCSI device\n"); - printf(" -ide show scan of IDE devices after SCSI devices\n"); - printf(" -l show device file names in leaf directory\n"); - printf(" -q just output host, bus, target, lun numbers\n"); - printf(" -x add (major,minor) information to '-l'\n"); -} - -#define NAME_LEN_MAX 256 -#define LEVELS 4 - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */ -#define INQUIRY_CMD 0x12 -#define INQUIRY_CMDLEN 6 - -static const char * level_arr[LEVELS] = {"host", "bus", "target", "lun"}; - -static int do_ide = 0; -static int do_inq = 0; -static int do_leaf = 0; -static int do_extra = 0; -static int do_quiet = 0; -static int checked_sg = 0; - -static void ddStrHex(const char* str, int len) -{ - const char* p = str; - unsigned char c; - char buff[82]; - int a = 0; - const int bpstart = 5; - const int cpstart = 60; - int cpos = cpstart; - int bpos = bpstart; - int i, k; - - if (len <= 0) return; - memset(buff,' ',80); - buff[80]='\0'; - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - if (bpos >= ((bpstart + (9 * 3)))) - bpos++; - - for(i = 0; i < len; i++) - { - c = *p++; - bpos += 3; - if (bpos == (bpstart + (9 * 3))) - bpos++; - sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c); - buff[bpos + 2] = ' '; - if ((c < ' ') || (c >= 0x7f)) - c='.'; - buff[cpos++] = c; - if (cpos > (cpstart+15)) - { - printf("%s\n", buff); - bpos = bpstart; - cpos = cpstart; - a += 16; - memset(buff,' ',80); - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - } - } - if (cpos > cpstart) - { - printf("%s\n", buff); - } -} - -static int do_inquiry(int sg_fd, void * resp, int mx_resp_len) -{ - int res; - unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0}; - unsigned char sense_b[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - - inqCmdBlk[4] = (unsigned char)mx_resp_len; - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(inqCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV; - io_hdr.dxfer_len = mx_resp_len; - io_hdr.dxferp = resp; - io_hdr.cmdp = inqCmdBlk; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("SG_IO (inquiry) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - switch (res) { - case SG_LIB_CAT_CLEAN: - case SG_LIB_CAT_RECOVERED: - return 0; - default: - sg_chk_n_print3("Failed INQUIRY", &io_hdr, 1); - return -1; - } -} - -void leaf_dir(const char * lf, unsigned int * larr) -{ - char name[NAME_LEN_MAX * 2]; - int res; - - if (do_quiet) { - printf("%u\t%u\t%u\t%u\n", larr[0], larr[1], larr[2], larr[3]); - return; - } - printf("%u\t%u\t%u\t%u\t%s\n", larr[0], larr[1], larr[2], larr[3], lf); - if (do_leaf) { - struct dirent * de_entry; - struct dirent * de_result; - DIR * sdir; - int outpos; - - if (NULL == (sdir = opendir(lf))) { - fprintf(stderr, "leaf_dir: opendir of %s: failed\n", lf); - return; - } - de_entry = (struct dirent *)malloc(sizeof(struct dirent) + - NAME_LEN_MAX); - if (NULL == de_entry) - return; - res = 0; - printf("\t"); - outpos = 8; - while (1) { - res = readdir_r(sdir, de_entry, &de_result); - if (0 != res) { - fprintf(stderr, "leaf_dir: readdir_r of %s: %s\n", - lf, strerror(res)); - res = -2; - break; - } - if (de_result == NULL) - break; - strncpy(name, de_entry->d_name, NAME_LEN_MAX * 2); - if ((0 == strcmp("..", name)) ||(0 == strcmp(".", name))) - continue; - if (do_extra) { - struct stat st; - char devname[NAME_LEN_MAX * 2]; - - strncpy(devname, lf, NAME_LEN_MAX * 2); - strcat(devname, "/"); - strcat(devname, name); - if (stat(devname, &st) < 0) - return; - if (S_ISCHR(st.st_mode)) { - strcat(name, "(c "); - sprintf(name + strlen(name), "%d %d)", major(st.st_rdev), - minor(st.st_rdev)); - } - else if (S_ISBLK(st.st_mode)) { - strcat(name, "(b "); - sprintf(name + strlen(name), "%d %d)", major(st.st_rdev), - minor(st.st_rdev)); - } - } - res = strlen(name); - if ((outpos + res + 2) > 80) { - printf("\n\t"); - outpos = 8; - } - printf("%s ", name); - outpos += res + 2; - } - printf("\n"); - } - if (do_inq) { - int sg_fd; - char buff[64]; - - memset(buff, 0, sizeof(buff)); - strncpy(name, lf, NAME_LEN_MAX * 2); - strcat(name, "/generic"); - if ((sg_fd = open(name, O_RDONLY)) < 0) { - if (! checked_sg) { - checked_sg = 1; - if ((sg_fd = open("/dev/sg0", O_RDONLY)) >= 0) - close(sg_fd); /* try and get sg module loaded */ - sg_fd = open(name, O_RDONLY); - } - if (sg_fd < 0) { - printf("Unable to open sg device: %s, %s\n", name, - strerror(errno)); - return; - } - } - if (0 != do_inquiry(sg_fd, buff, 64)) - return; - close(sg_fd); - ddStrHex(buff, 64); - } -} - -/* Return 0 -> ok, -1 -> opendir() error, -2 -> readdir_r error, - -3 -> malloc error */ -int hbtl_scan(const char * path, int level, unsigned int *larr) -{ - struct dirent * de_entry; - struct dirent * de_result; - char new_path[NAME_LEN_MAX * 2]; - DIR * sdir; - int res; - size_t level_slen; - - level_slen = strlen(level_arr[level]); - if (NULL == (sdir = opendir(path))) { - fprintf(stderr, "hbtl_scan: opendir of %s: failed\n", path); - return -1; - } - de_entry = (struct dirent *)malloc(sizeof(struct dirent) + NAME_LEN_MAX); - if (NULL == de_entry) - return -3; - res = 0; - while (1) { - res = readdir_r(sdir, de_entry, &de_result); - if (0 != res) { - fprintf(stderr, "hbtl_scan: readdir_r of %s: %s\n", - path, strerror(res)); - res = -2; - break; - } - if (de_result == NULL) - break; - if (0 == strncmp(level_arr[level], de_entry->d_name, level_slen)) { - if (1 != sscanf(de_entry->d_name + level_slen, "%u", larr + level)) - larr[level] = UINT_MAX; - strncpy(new_path, path, NAME_LEN_MAX * 2); - strcat(new_path, "/"); - strcat(new_path, de_entry->d_name); - if ((level + 1) < LEVELS) { - res = hbtl_scan(new_path, level + 1, larr); - if (res < 0) - break; - } - else - leaf_dir(new_path, larr); - } - } - free(de_entry); - closedir(sdir); - return res; -} - -#define D_ROOT_SZ 512 - - -int main(int argc, char * argv[]) -{ - int k, res; - char ds_root[D_ROOT_SZ]; - char di_root[D_ROOT_SZ]; - unsigned int larr[LEVELS]; - struct stat st; - - strncpy(ds_root, "/dev", D_ROOT_SZ); - for (k = 1; k < argc; ++k) { - if (0 == strcmp("-ide", argv[k])) - do_ide = 1; - else if (0 == strcmp("-i", argv[k])) - do_inq = 1; - else if (0 == strcmp("-l", argv[k])) - do_leaf = 1; - else if (0 == strcmp("-x", argv[k])) - do_extra = 1; - else if (0 == strcmp("-q", argv[k])) - do_quiet = 1; - else if (0 == strncmp("-d", argv[k], 2)) { - if (strlen(argv[k]) > 2) - strncpy(ds_root, argv[k] + 2, D_ROOT_SZ); - else if (++k < argc) - strncpy(ds_root, argv[k], D_ROOT_SZ); - } - else if ((0 == strcmp("-?", argv[k])) || - (0 == strncmp("-h", argv[k], 2))) { - printf("Scan SCSI devices within a devfs tree\n\n"); - usage(); - return 1; - } - else if (*argv[k] == '-') { - printf("Unknown switch: %s\n", argv[k]); - usage(); - return 1; - } - else if (*argv[k] != '-') { - printf("Unknown argument\n"); - usage(); - return 1; - } - } - strncpy(di_root, ds_root, D_ROOT_SZ); - strcat(di_root, "/.devfsd"); - if (stat(di_root, &st) < 0) - printf("Didn't find %s so perhaps devfs is not present," - " continuing ...\n", di_root); - strncpy(di_root, ds_root, D_ROOT_SZ); - strcat(ds_root, "/scsi"); - strcat(di_root, "/ide"); - - if (do_ide) - printf("SCSI scan:\n"); - res = hbtl_scan(ds_root, 0, larr); - if (res < 0) - printf("main: scsi hbtl_scan res=%d\n", res); - do_inq = 0; /* won't try SCSI INQUIRY on IDE devices */ - if (do_ide) { - printf("\nIDE scan:\n"); - res = hbtl_scan(di_root, 0, larr); - if (res < 0) - printf("main: ide hbtl_scan res=%d\n", res); - } - return 0; -} diff --git a/archive/sg3_utils.spec113 b/archive/sg3_utils.spec113 deleted file mode 100644 index 3dfc4873..00000000 --- a/archive/sg3_utils.spec113 +++ /dev/null @@ -1,234 +0,0 @@ -Summary: Utilities for SCSI devices in Linux -Name: sg3_utils -Version: 1.13 -Release: 1 -Packager: Douglas Gilbert <dgilbert at interlog dot com> -License: GPL/FreeBSD -Group: Utilities/System -Source: ftp://www.torque.net/sg/p/sg3_utils-%{version}.tgz -Url: http://www.torque.net/sg/u_index.html -Provides: sg_utils -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root/ - -%description -Collection of Linux utilities for devices that use the SCSI command set. -Includes utilities to copy data based on "dd" syntax and semantics (called -sg_dd, sgp_dd and sgm_dd); check INQUIRY data and VPD pages (sg_inq); check -mode and log pages (sginfo, sg_modes and sg_logs); spin up and down -disks (sg_start); do self tests (sg_senddiag); and various other functions. -See the README, CHANGELOG and COVERAGE files. Requires the linux kernel 2.4 -series or later. In the 2.4 series SCSI generic device names (e.g. /dev/sg0) -must be used. In the 2.6 series other device names may be used as -well (e.g. /dev/sda). - -Warning: Some of these tools access the internals of your system and their -incorrect usage may render your system inoperable. - -Authors: --------- - Doug Gilbert <dgilbert at interlog dot com> - See CREDITS file - -%package devel -Summary: Files needed for developing applications using the SCSI command set -Group: Development/Libraries -Requires: %{name} = %{version}-%{release} - -%description devel -sg3_utils-devel contains a static library (libsgutils.a) and header files -to support using the SCSI command set on devices in Linux. - -%prep -%setup - -%build -make LIBDIR=/usr/lib - -%install -if [ "$RPM_BUILD_ROOT" != "/" ]; then - rm -rf $RPM_BUILD_ROOT -fi -make install INSTDIR=$RPM_BUILD_ROOT/usr/bin MANDIR=$RPM_BUILD_ROOT/usr/share/man LIBDIR=$RPM_BUILD_ROOT/usr/lib INCLUDEDIR=$RPM_BUILD_ROOT/usr/include - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) -%attr(-,root,root) %doc CREDITS README README.sg_start -%attr(-,root,root) %doc CHANGELOG INSTALL COVERAGE -%attr(755,root,root) %{_bindir}/sg_dd -%attr(755,root,root) %{_bindir}/sg_inq -%attr(755,root,root) %{_bindir}/sg_scan -%attr(755,root,root) %{_bindir}/sg_rbuf -%attr(755,root,root) %{_bindir}/sginfo -%attr(755,root,root) %{_bindir}/sg_readcap -%attr(755,root,root) %{_bindir}/sgp_dd -%attr(755,root,root) %{_bindir}/sg_map -%attr(755,root,root) %{_bindir}/sg_turs -%attr(755,root,root) %{_bindir}/sg_test_rwbuf -%attr(755,root,root) %{_bindir}/sg_start -%attr(755,root,root) %{_bindir}/sgm_dd -%attr(755,root,root) %{_bindir}/sg_read -%attr(755,root,root) %{_bindir}/sg_reset -%attr(755,root,root) %{_bindir}/sg_modes -%attr(755,root,root) %{_bindir}/sg_logs -%attr(755,root,root) %{_bindir}/sg_senddiag -%attr(755,root,root) %{_bindir}/sg_opcodes -%attr(755,root,root) %{_bindir}/sg_persist -%attr(755,root,root) %{_bindir}/sg_write_long -%attr(755,root,root) %{_bindir}/sg_read_long -%attr(755,root,root) %{_bindir}/sg_requests -%attr(755,root,root) %{_bindir}/sg_ses -%attr(755,root,root) %{_bindir}/sg_verify -%attr(755,root,root) %{_bindir}/sg_emc_trespass -%attr(755,root,root) %{_bindir}/sg_luns -%attr(755,root,root) %{_bindir}/sg_sync -%attr(755,root,root) %{_bindir}/sg_prevent -%attr(755,root,root) %{_bindir}/sg_get_config -%attr(755,root,root) %{_bindir}/sg_wr_mode -%attr(755,root,root) %{_bindir}/sg_rtpg -%attr(755,root,root) %{_bindir}/sg_reassign -%attr(755,root,root) %{_bindir}/sg_format -%attr(755,root,root) %{_libdir}/libsgutils.so -%attr(755,root,root) %{_libdir}/libsgutils.so.1 -%attr(755,root,root) %{_libdir}/libsgutils.so.1.0.0 -# Mandrake compresses man pages with bzip2, RedHat with gzip -%attr(-,root,root) %doc %{_mandir}/man8/sg_dd.8* -%attr(-,root,root) %doc %{_mandir}/man8/sgp_dd.8* -%attr(-,root,root) %doc %{_mandir}/man8/sgm_dd.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_read.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_map.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_scan.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_rbuf.8* -%attr(-,root,root) %doc %{_mandir}/man8/sginfo.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_readcap.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_turs.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_inq.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_test_rwbuf.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_start.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_reset.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_modes.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_logs.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_senddiag.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_opcodes.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_persist.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_write_long.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_read_long.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_requests.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_ses.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_verify.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_emc_trespass.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_luns.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_sync.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_prevent.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_get_config.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_wr_mode.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_rtpg.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_reassign.8* -%attr(-,root,root) %doc %{_mandir}/man8/sg_format.8* - -%files devel -%defattr(-,root,root) -%attr(644,root,root) %{_includedir}/scsi/sg_lib.h -%attr(644,root,root) %{_includedir}/scsi/sg_cmds.h -%attr(755,root,root) %{_libdir}/libsgutils.la -%attr(644,root,root) %{_libdir}/libsgutils.a - - -%changelog -* Sun Mar 13 2005 - dgilbert at interlog dot com -- add sg_format, sg_dd extensions - * sg3_utils-1.13 - -* Fri Jan 21 2005 - dgilbert at interlog dot com -- add sg_wr_mode, sg_rtpg + sg_reassign; sginfo sas tweaks - * sg3_utils-1.12 - -* Fri Nov 26 2004 - dgilbert at interlog dot com -- add sg_sync, sg_prevent and sg_get_config; fix sg_requests - * sg3_utils-1.11 - -* Sat Oct 30 2004 - dgilbert at interlog dot com -- fix read capacity (10+16), add sg_luns - * sg3_utils-1.10 - -* Thu Oct 21 2004 - dgilbert at interlog dot com -- sg_requests, sg_ses, sg_verify, libsgutils(sg_lib.c+sg_cmds.c), devel rpm - * sg3_utils-1.09 - -* Tue Aug 31 2004 - dgilbert at interlog dot com -- 'register+move' in sg_persist, sg_opcodes sorts, sg_write_long - * sg3_utils-1.08 - -* Thu Jul 08 2004 - dgilbert at interlog dot com -- add '-fHead' to sginfo, '-i' for sg_inq, new sg_opcodes + sg_persist - * sg3_utils-1.07 - -* Mon Apr 26 2004 - dgilbert at interlog dot com -- sg3_utils.spec for mandrake; more sginfo work, sg_scan, sg_logs - * sg3_utils-1.06 - -* Wed Nov 12 2003 - dgilbert at interlog dot com -- sg_readcap: sizes; sg_logs: double fetch; sg_map 256 sg devices; sginfo - * sg3_utils-1.05 - -* Tue May 13 2003 - dgilbert at interlog dot com -- default sg_turs '-n=' to 1, sg_logs gets '-t' for temperature, CREDITS - * sg3_utils-1.04 - -* Wed Apr 02 2003 - dgilbert at interlog dot com -- 6 byte CDBs for sg_modes, sg_start on block devs, sg_senddiag, man pages - * sg3_utils-1.03 - -* Wed Jan 01 2003 - dgilbert at interlog dot com -- interwork with block SG_IO, fix in sginfo, '-t' for sg_turs - * sg3_utils-1.02 - -* Wed Aug 14 2002 - dgilbert at interlog dot com -- raw switch in sg_inq - * sg3_utils-1.01 - -* Sun Jul 28 2002 - dgilbert at interlog dot com -- decode sg_logs pages, add dio to sgm_dd, drop "gen=1" arg, "of=/dev/null" - * sg3_utils-1.00 - -* Sun Mar 17 2002 - dgilbert at interlog dot com -- add sg_modes+sg_logs for sense pages, expand sg_inq, add fua+sync to sg_dd++ - * sg3_utils-0.99 - -* Sat Feb 16 2002 - dgilbert at interlog dot com -- resurrect sg_reset; snprintf cleanup, time,gen+cdbsz args to sg_dd++ - * sg3_utils-0.98 - -* Sun Dec 23 2001 - dgilbert at interlog dot com -- move isosize to archive directory; now found in util-linux-2.10s and later - * sg3_utils-0.97 - -* Fri Dec 21 2001 - dgilbert at interlog dot com -- add sgm_dd, sg_read, sg_simple4 and sg_simple16 [add mmap-ed IO support] - * sg3_utils-0.96 - -* Sun Sep 15 2001 - dgilbert at interlog dot com -- sg_map can do inquiry; sg_dd, sgp_dd + sgq_dd dio help - * sg3_utils-0.95 - -* Sun Apr 19 2001 - dgilbert at interlog dot com -- add sg_start, improve sginfo and sg_map [Kurt Garloff] - * sg3_utils-0.94 - -* Sun Mar 5 2001 - dgilbert at interlog dot com -- add scsi_devfs_scan, add sg_include.h, 'coe' more general in sgp_dd - * sg3_utils-0.93 - -* Tue Jan 16 2001 - dgilbert at interlog dot com -- clean sg_err.h include dependencies, bug fixes, Makefile in archive directory - * sg3_utils-0.92 - -* Mon Dec 21 2000 - dgilbert at interlog dot com -- signals for sg_dd, man pages and additions for sg_rbuf and isosize - * sg3_utils-0.91 - -* Mon Dec 11 2000 - dgilbert at interlog dot com -- Initial creation of package, containing - * sg3_utils-0.90 diff --git a/archive/sg_bus_xfer.c b/archive/sg_bus_xfer.c deleted file mode 100644 index eada35fd..00000000 --- a/archive/sg_bus_xfer.c +++ /dev/null @@ -1,194 +0,0 @@ -#include <unistd.h> -#include <signal.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_io_linux.h" - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 2001 D. Gilbert -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program tests the SG_FLAG_BUS_ADDR capability. - It is for moving data to and from fixed memory addresses (e.g. memory - mapped io used by video frame buffers) directly to a SCSI device via - the sg driver. The given address is passed straight through by sg to the - scsi adapter driver. The adapter typically does a "virtual to bus" - address transformation and gives the new address to its DMA engine. - Large amounts of data (in physically contiguous memory) can be moved - (quickly) in a single SCSI command. - - This will probably only work on i386 architecture with PCI cards that - memory map their IO area (e.g. video frame buffer). On i386 the - "virt_to_bus" transformation involves subtracting 0xC0000000 from the - given address. So from the addresses seen in the lspci command, - subtracting 0x40000000 would be an appropriate correction (due to - 32 bit wrap around). - - The SG_FLAG_BUS_ADDR logic is not in normal sg drivers, you need a - patch, see the sg web site. - - Version 0.11 (20010210) -*/ - -#ifndef SG_FLAG_BUS_ADDR -#define SG_FLAG_BUS_ADDR 0x10 -#endif - - -#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */ - -#define SGP_READ10 0x28 -#define SGP_WRITE10 0x2a - -/* #define SG_DEBUG */ - - -int main(int argc, char * argv[]) -{ - int sg_fd, res, j, m; - unsigned int k, num; - unsigned char rwCmdBlk[S_RW_LEN]; - unsigned char sense_buffer[32]; - int do_wr = -1; /* 1 -> write, 0 -> read */ - unsigned long addr = ULONG_MAX; - int bs = 512; - int skip = -1; - int count = -1; - char * file_name = 0; - sg_io_hdr_t io_hdr; - - for (j = 1; j < argc; ++j) { - if (0 == strncmp("-a=", argv[j], 3)) { - m = 3; - num = sscanf(argv[j] + m, "%lx", &addr); - if (1 != num) { - printf("Couldn't decode number after '-a=' switch\n"); - file_name = 0; - break; - } - } - else if (0 == strncmp("-bs=", argv[j], 4)) { - m = 4; - bs = sg_get_num(argv[j] + m); - if (-1 == bs) { - printf("Couldn't decode number after '-bs=' switch\n"); - file_name = 0; - break; - } - } - else if (0 == strncmp("-skip=", argv[j], 6)) { - m = 6; - skip = sg_get_num(argv[j] + m); - if (-1 == skip) { - printf("Couldn't decode number after '-skip=' switch\n"); - file_name = 0; - break; - } - } - else if (0 == strncmp("-count=", argv[j], 7)) { - m = 7; - count = sg_get_num(argv[j] + m); - if (-1 == count) { - printf("Couldn't decode number after '-count=' switch\n"); - file_name = 0; - break; - } - } - else if (0 == strcmp("-r", argv[j])) - do_wr = 0; - else if (0 == strcmp("-w", argv[j])) - do_wr = 1; - else if (*argv[j] == '-') { - printf("Unrecognized switch: %s\n", argv[j]); - file_name = 0; - break; - } - else - file_name = argv[j]; - } - if ((0 == file_name) || (count < 0) || (do_wr < 0) || (addr == ULONG_MAX) - || (skip < 0)) { - printf("Probabably missing parameter\n\n"); - printf( - "Usage: 'sg_bus_xfer -r|w -a=hex_num [-bs=num] -skip=num" - " <sg_device>'\n"); - printf(" where: -r|w read from (or write to) sg device\n"); - printf(" -a=hex_num memory address (virtual ?)\n"); - printf(" -bs=num blocks size in bytes (default 512)\n"); - printf(" -skip=num num is blocks to skip/seek on sg dev\n"); - printf(" -count=num num of blocks to xfer\n"); - printf("\n BEWARE you could do damage with this command " - "(needs root access)\n"); - printf("\n bs, skip and count may take k,K,m,M etc multipliers\n"); - return 1; - } - - sg_fd = open(file_name, O_RDWR); - if (sg_fd < 0) { - perror("sg_bus_xfer: open error"); - return 1; - } - /* Don't worry, being very careful not to write to a none-sg file ... */ - res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k); - if ((res < 0) || (k < 30000)) { - printf("sg_bus_xfer: not a sg device, or driver prior to 3.x\n"); - return 1; - } - - memset(rwCmdBlk, 0, S_RW_LEN); - rwCmdBlk[0] = do_wr ? SGP_WRITE10 : SGP_READ10; - rwCmdBlk[2] = (unsigned char)((skip >> 24) & 0xFF); - rwCmdBlk[3] = (unsigned char)((skip >> 16) & 0xFF); - rwCmdBlk[4] = (unsigned char)((skip >> 8) & 0xFF); - rwCmdBlk[5] = (unsigned char)(skip & 0xFF); - rwCmdBlk[6] = (unsigned char)((count >> 16) & 0xff); - rwCmdBlk[7] = (unsigned char)((count >> 8) & 0xff); - rwCmdBlk[8] = (unsigned char)(count & 0xff); - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rwCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_buffer); - io_hdr.dxfer_direction = do_wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = bs * count; - // io_hdr.dxferp = malloc(1024 * 1024); /* <<<<<<<<<<<<<<<< */ - io_hdr.dxferp = (void *)addr; - io_hdr.cmdp = rwCmdBlk; - io_hdr.flags = SG_FLAG_BUS_ADDR; - io_hdr.sbp = sense_buffer; - io_hdr.timeout = 10000; /* 10000 millisecs == 10 seconds */ - - printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count); -#ifdef SG_DEBUG - sg_print_command(rwCmdBlk); - printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count); - return 0; -#endif - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("sg_bus_xfer: SG_IO failed"); - return 1; - } - - /* now for the error processing */ - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error, continuing\n"); - break; - default: /* won't bother decoding other categories */ - sg_chk_n_print3("SG_IO error", &io_hdr, 1); - return 1; - } - return 0; -} diff --git a/archive/sg_dd2048.c b/archive/sg_dd2048.c deleted file mode 100644 index ea9bf415..00000000 --- a/archive/sg_dd2048.c +++ /dev/null @@ -1,586 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. It assumes - a 'bs' (block size) of 2048 and complains if 'bs' ('ibs' or 'obs') is - given with some other value. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given of 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - As an experiment added an argument "tq" to allow 'tagged queuing' to - be enabled (1), disabled(0) or left as is (-1) which is the default. - BEWARE: If the 'of' file is a 'sg' device (eg a disk) then it _will_ - be written to, potentially destroying its previous contents. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . - - Version 3.96 991208 - - -6 byte commands [READ: 0x08, WRITE: 0x0a]: -[cmd ][had|lu][midAdd][lowAdd][count ][flags ] -10 byte commands [EREAD: 0x28, EWRITE: 0x2a, READ_CAPACITY 0x25]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][ ][hiCnt ][lowCnt][flags ] -12 byte commands [LREAD: 0xd8, LWRITE: 0xda]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][hiCnt ][hmCnt ][lmCnt ][lowCnt] - ... [ ][flags ] -*/ - -#define BLOCK_SIZE 2048 - -#define BLOCKS_PER_WBUFF 32 /* this implies 64 KByte working buffer */ - -// #define SG_DEBUG - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ - - -void usage() -{ - printf("Usage: " - "sg_dd2048 [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [count=<n>] [tq=<n>] {2048 byte 'bs' assumed}\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'tq' is tagged queuing, 1->enable, 0->disable, -1->leave(def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -/* printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); */ - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_read(int sg_fd, unsigned char * buff, int blocks, int from_block) -{ - unsigned char rdCmd[10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - rdCmd[2] = (unsigned char)((from_block >> 24) & 0xFF); - rdCmd[3] = (unsigned char)((from_block >> 16) & 0xFF); - rdCmd[4] = (unsigned char)((from_block >> 8) & 0xFF); - rdCmd[5] = (unsigned char)(from_block & 0xFF); - rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - rdCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rdCmd); - io_hdr.cmdp = rdCmd; - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = from_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("reading (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("reading (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while reading block=%d, num=%d\n", - from_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("reading", &io_hdr); - return -1; - } - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_write(int sg_fd, unsigned char * buff, int blocks, int to_block) -{ - unsigned char wrCmd[10] = {0x2a, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - wrCmd[2] = (unsigned char)((to_block >> 24) & 0xFF); - wrCmd[3] = (unsigned char)((to_block >> 16) & 0xFF); - wrCmd[4] = (unsigned char)((to_block >> 8) & 0xFF); - wrCmd[5] = (unsigned char)(to_block & 0xFF); - wrCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - wrCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(wrCmd); - io_hdr.cmdp = wrCmd; - io_hdr.dxfer_direction = SG_DXFER_TO_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = to_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("writing (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("writing (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while writing block=%d, num=%d\n", - to_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("writing", &io_hdr); - return -1; - } - return 0; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int count = -1; - char str[512]; - char * key; - char * buf; - char inf[512]; - int in_is_sg = 0; - char outf[512]; - int out_is_sg = 0; - int bs_bad = 0; - int tq = -1; - int res, k, t, buf_sz; - int infd, outfd, blocks; - unsigned char * wrkBuff; - unsigned char * wrkPos; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz; - int in_full = 0; - int in_partial = 0; - int out_full = 0; - int out_partial = 0; - char ebuff[256]; - int blocks_per; - - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strcpy(str, argv[k]); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strcpy(inf, buf); - else if (strcmp(key,"of") == 0) - strcpy(outf, buf); - else if (0 == strcmp(key,"ibs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"obs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"bs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"tq")) - tq = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (bs_bad) { - printf("If bs/ibs/obs given, must=%d\n", BLOCK_SIZE); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sg_dd2048: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - infd = STDIN_FILENO; - outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((infd = open(inf, O_RDWR)) >= 0) { - if (ioctl(infd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(infd); - } - else { - in_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd2048: SCSI_IOCTL_TAGGED error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(infd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd2048: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd2048: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! in_is_sg) { - if ((infd = open(inf, O_RDONLY)) < 0) { - sprintf(ebuff, "sg_dd2048: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - off_t offset = skip; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(infd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd2048: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - if ((outfd = open(outf, O_RDWR)) >= 0) { - if (ioctl(outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(outfd); - } - else { - out_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd2048: SCSI_IOCTL_TAGGED(o) error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd2048: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd2048: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! out_is_sg) { - if ((outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - sprintf(ebuff, - "sg_dd2048: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(outfd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd2048: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } -#if 1 - if (! (in_is_sg || out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } -#endif - if (0 == count) - return 0; - else if (count < 0) { - if (in_is_sg) { - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { -#if 0 - if (0 == in_sect_sz) - in_sect_sz = BLOCK_SIZE; - else if (in_sect_sz > BLOCK_SIZE) - in_num_sect *= (in_sect_sz / BLOCK_SIZE); - else if (in_sect_sz < BLOCK_SIZE) - in_num_sect /= (BLOCK_SIZE / in_sect_sz); -#endif - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (out_is_sg) { - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } - if (in_num_sect > 0) { - if (out_num_sect > 0) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - - wrkBuff= malloc(BLOCK_SIZE * BLOCKS_PER_WBUFF); - if (0 == wrkBuff) { - printf("Not enough user memory\n"); - return 1; - } - wrkPos = wrkBuff; - - blocks_per = BLOCKS_PER_WBUFF; - while (count) { - blocks = (count > blocks_per) ? blocks_per : count; - if (in_is_sg) { - res = sg_read(infd, wrkBuff, blocks, skip); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing read to %d blocks per loop\n", blocks_per); - res = sg_read(infd, wrkBuff, blocks, skip); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (r)\n"); - res = sg_read(infd, wrkBuff, blocks, skip); - } - if (0 != res) { - printf("sg_read failed, skip=%d\n", skip); - break; - } - else - in_full += blocks; - } - else { - while (((res = read(infd, wrkPos, blocks * BLOCK_SIZE)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_dd2048: reading, skip=%d ", skip); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - count = 0; - blocks = res / BLOCK_SIZE; - if ((res % BLOCK_SIZE) > 0) { - blocks++; - in_partial++; - } - } - in_full += blocks; - } - - if (out_is_sg) { - res = sg_write(outfd, wrkBuff, blocks, seek); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing write to %d blocks per loop\n", blocks); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (w)\n"); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (0 != res) { - printf("sg_write failed, seek=%d\n", seek); - break; - } - else - out_full += blocks; - } - else { - while (((res = write(outfd, wrkPos, blocks * BLOCK_SIZE)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_ddd2048: writing, seek=%d ", seek); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - printf("output file probably full, seek=%d ", seek); - blocks = res / BLOCK_SIZE; - out_full += blocks; - if ((res % BLOCK_SIZE) > 0) - out_partial++; - break; - } - else - out_full += blocks; - } - if (count > 0) - count -= blocks; - skip += blocks; - seek += blocks; - } - - free(wrkBuff); - if (STDIN_FILENO != infd) - close(infd); - if (STDOUT_FILENO != outfd) - close(outfd); - if (0 != count) { - printf("Some error occurred, count=%d\n", count); - return 1; - } - printf("%d+%d records in\n", in_full, in_partial); - printf("%d+%d records out\n", out_full, out_partial); - return 0; -} diff --git a/archive/sg_dd512.c b/archive/sg_dd512.c deleted file mode 100644 index 6291ef43..00000000 --- a/archive/sg_dd512.c +++ /dev/null @@ -1,586 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. It assumes - a 'bs' (block size) of 512 and complains if 'bs' ('ibs' or 'obs') is - given with some other value. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given of 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - As an experiment added an argument "tq" to allow 'tagged queuing' to - be enabled (1), disabled(0) or left as is (-1) which is the default. - BEWARE: If the 'of' file is a 'sg' device (eg a disk) then it _will_ - be written to, potentially destroying its previous contents. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . - - Version 3.96 991208 - - -6 byte commands [READ: 0x08, WRITE: 0x0a]: -[cmd ][had|lu][midAdd][lowAdd][count ][flags ] -10 byte commands [EREAD: 0x28, EWRITE: 0x2a, READ_CAPACITY 0x25]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][ ][hiCnt ][lowCnt][flags ] -12 byte commands [LREAD: 0xd8, LWRITE: 0xda]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][hiCnt ][hmCnt ][lmCnt ][lowCnt] - ... [ ][flags ] -*/ - -#define BLOCK_SIZE 512 - -#define BLOCKS_PER_WBUFF 128 /* this implies 64 KByte working buffer */ - -// #define SG_DEBUG - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ - - -void usage() -{ - printf("Usage: " - "sg_dd512 [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [count=<n>] [tq=<n>] {512 byte 'bs' assumed}\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'tq' is tagged queuing, 1->enable, 0->disable, -1->leave(def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -/* printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); */ - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_read(int sg_fd, unsigned char * buff, int blocks, int from_block) -{ - unsigned char rdCmd[10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - rdCmd[2] = (unsigned char)((from_block >> 24) & 0xFF); - rdCmd[3] = (unsigned char)((from_block >> 16) & 0xFF); - rdCmd[4] = (unsigned char)((from_block >> 8) & 0xFF); - rdCmd[5] = (unsigned char)(from_block & 0xFF); - rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - rdCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rdCmd); - io_hdr.cmdp = rdCmd; - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = from_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("reading (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("reading (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while reading block=%d, num=%d\n", - from_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("reading", &io_hdr); - return -1; - } - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_write(int sg_fd, unsigned char * buff, int blocks, int to_block) -{ - unsigned char wrCmd[10] = {0x2a, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - wrCmd[2] = (unsigned char)((to_block >> 24) & 0xFF); - wrCmd[3] = (unsigned char)((to_block >> 16) & 0xFF); - wrCmd[4] = (unsigned char)((to_block >> 8) & 0xFF); - wrCmd[5] = (unsigned char)(to_block & 0xFF); - wrCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - wrCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(wrCmd); - io_hdr.cmdp = wrCmd; - io_hdr.dxfer_direction = SG_DXFER_TO_DEV; - io_hdr.dxfer_len = BLOCK_SIZE * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = to_block; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("writing (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("writing (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while writing block=%d, num=%d\n", - to_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("writing", &io_hdr); - return -1; - } - return 0; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int count = -1; - char str[512]; - char * key; - char * buf; - char inf[512]; - int in_is_sg = 0; - char outf[512]; - int out_is_sg = 0; - int bs_bad = 0; - int tq = -1; - int res, k, t, buf_sz; - int infd, outfd, blocks; - unsigned char * wrkBuff; - unsigned char * wrkPos; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz; - int in_full = 0; - int in_partial = 0; - int out_full = 0; - int out_partial = 0; - char ebuff[256]; - int blocks_per; - - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strcpy(str, argv[k]); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strcpy(inf, buf); - else if (strcmp(key,"of") == 0) - strcpy(outf, buf); - else if (0 == strcmp(key,"ibs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"obs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"bs")) { - if (BLOCK_SIZE != sg_get_num(buf)) - bs_bad = 1; - } - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"tq")) - tq = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (bs_bad) { - printf("If bs/ibs/obs given, must=%d\n", BLOCK_SIZE); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sg_dd512: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - infd = STDIN_FILENO; - outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((infd = open(inf, O_RDWR)) >= 0) { - if (ioctl(infd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(infd); - } - else { - in_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(infd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd512: SCSI_IOCTL_TAGGED error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(infd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd512: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd512: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! in_is_sg) { - if ((infd = open(inf, O_RDONLY)) < 0) { - sprintf(ebuff, "sg_dd512: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - off_t offset = skip; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(infd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd512: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - if ((outfd = open(outf, O_RDWR)) >= 0) { - if (ioctl(outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(outfd); - } - else { - out_is_sg = 1; - res = 0; - if (0 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_DISABLE, &t); - if (1 == tq) - res = ioctl(outfd, SCSI_IOCTL_TAGGED_ENABLE, &t); - if (res < 0) - perror("sg_dd512: SCSI_IOCTL_TAGGED(o) error"); - t = BLOCK_SIZE * BLOCKS_PER_WBUFF; - res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd512: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd512: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! out_is_sg) { - if ((outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - sprintf(ebuff, - "sg_dd512: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= BLOCK_SIZE; /* could overflow here! */ - if (lseek(outfd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd512: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } -#if 1 - if (! (in_is_sg || out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } -#endif - if (0 == count) - return 0; - else if (count < 0) { - if (in_is_sg) { - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { -#if 0 - if (0 == in_sect_sz) - in_sect_sz = BLOCK_SIZE; - else if (in_sect_sz > BLOCK_SIZE) - in_num_sect *= (in_sect_sz / BLOCK_SIZE); - else if (in_sect_sz < BLOCK_SIZE) - in_num_sect /= (BLOCK_SIZE / in_sect_sz); -#endif - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (out_is_sg) { - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } - if (in_num_sect > 0) { - if (out_num_sect > 0) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - - wrkBuff= malloc(BLOCK_SIZE * BLOCKS_PER_WBUFF); - if (0 == wrkBuff) { - printf("Not enough user memory\n"); - return 1; - } - wrkPos = wrkBuff; - - blocks_per = BLOCKS_PER_WBUFF; - while (count) { - blocks = (count > blocks_per) ? blocks_per : count; - if (in_is_sg) { - res = sg_read(infd, wrkBuff, blocks, skip); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing read to %d blocks per loop\n", blocks_per); - res = sg_read(infd, wrkBuff, blocks, skip); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (r)\n"); - res = sg_read(infd, wrkBuff, blocks, skip); - } - if (0 != res) { - printf("sg_read failed, skip=%d\n", skip); - break; - } - else - in_full += blocks; - } - else { - while (((res = read(infd, wrkPos, blocks * BLOCK_SIZE)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_dd512: reading, skip=%d ", skip); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - count = 0; - blocks = res / BLOCK_SIZE; - if ((res % BLOCK_SIZE) > 0) { - blocks++; - in_partial++; - } - } - in_full += blocks; - } - - if (out_is_sg) { - res = sg_write(outfd, wrkBuff, blocks, seek); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + BLOCK_SIZE - 1) / BLOCK_SIZE; - blocks = blocks_per; - printf("Reducing write to %d blocks per loop\n", blocks); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (w)\n"); - res = sg_write(outfd, wrkBuff, blocks, seek); - } - else if (0 != res) { - printf("sg_write failed, seek=%d\n", seek); - break; - } - else - out_full += blocks; - } - else { - while (((res = write(outfd, wrkPos, blocks * BLOCK_SIZE)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_ddd512: writing, seek=%d ", seek); - perror(ebuff); - break; - } - else if (res < blocks * BLOCK_SIZE) { - printf("output file probably full, seek=%d ", seek); - blocks = res / BLOCK_SIZE; - out_full += blocks; - if ((res % BLOCK_SIZE) > 0) - out_partial++; - break; - } - else - out_full += blocks; - } - if (count > 0) - count -= blocks; - skip += blocks; - seek += blocks; - } - - free(wrkBuff); - if (STDIN_FILENO != infd) - close(infd); - if (STDOUT_FILENO != outfd) - close(outfd); - if (0 != count) { - printf("Some error occurred, count=%d\n", count); - return 1; - } - printf("%d+%d records in\n", in_full, in_partial); - printf("%d+%d records out\n", out_full, out_partial); - return 0; -} diff --git a/archive/sg_dd_old.c b/archive/sg_dd_old.c deleted file mode 100644 index 83dc6451..00000000 --- a/archive/sg_dd_old.c +++ /dev/null @@ -1,612 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* A utility program for the Linux OS SCSI generic ("sg") device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. A block size - ('bs') is assumed to be 512 if not given. This program complains if - 'ibs' or 'obs' are given with some other value. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given or 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - - A non-standard argument "bpt" (blocks per transfer) is added to control - the maximum number of blocks in each transfer. The default value is 128. - For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB - in this case) are transferred to or from the sg device in a single SCSI - command. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . - - Version 3.992 20000823 -*/ - -#define DEF_BLOCK_SIZE 512 -#define DEF_BLOCKS_PER_TRANSFER 128 - -// #define SG_DEBUG - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define READ_CAP_REPLY_LEN 8 -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ - -static int sum_of_resids = 0; - - -void usage() -{ - printf("Usage: " - "sg_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [bs=<num>] [bpt=<num>] [count=<n>]" - " [dio=<n>]\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'bpt' is blocks_per_transfer (default is 128)\n" - " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[READ_CAP_REPLY_LEN]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -#ifdef SG_DEBUG - printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); -#endif - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_read(int sg_fd, unsigned char * buff, int blocks, int from_block, - int bs, int * diop) -{ - unsigned char rdCmd[10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - rdCmd[2] = (unsigned char)((from_block >> 24) & 0xFF); - rdCmd[3] = (unsigned char)((from_block >> 16) & 0xFF); - rdCmd[4] = (unsigned char)((from_block >> 8) & 0xFF); - rdCmd[5] = (unsigned char)(from_block & 0xFF); - rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - rdCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rdCmd); - io_hdr.cmdp = rdCmd; - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = bs * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = from_block; - if (diop && *diop) - io_hdr.flags |= SG_FLAG_DIRECT_IO; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("reading (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("reading (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while reading block=%d, num=%d\n", - from_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("reading", &io_hdr); - return -1; - } - if (diop && *diop && - ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - *diop = 0; /* flag that dio not done (completely) */ - sum_of_resids += io_hdr.resid; -#if SG_DEBUG - printf("duration=%u ms\n", io_hdr.duration); -#endif - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM), - 2 -> try again */ -int sg_write(int sg_fd, unsigned char * buff, int blocks, int to_block, - int bs, int * diop) -{ - unsigned char wrCmd[10] = {0x2a, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char senseBuff[SENSE_BUFF_LEN]; - sg_io_hdr_t io_hdr; - int res; - - wrCmd[2] = (unsigned char)((to_block >> 24) & 0xFF); - wrCmd[3] = (unsigned char)((to_block >> 16) & 0xFF); - wrCmd[4] = (unsigned char)((to_block >> 8) & 0xFF); - wrCmd[5] = (unsigned char)(to_block & 0xFF); - wrCmd[7] = (unsigned char)((blocks >> 8) & 0xff); - wrCmd[8] = (unsigned char)(blocks & 0xff); - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(wrCmd); - io_hdr.cmdp = wrCmd; - io_hdr.dxfer_direction = SG_DXFER_TO_DEV; - io_hdr.dxfer_len = bs * blocks; - io_hdr.dxferp = buff; - io_hdr.mx_sb_len = SENSE_BUFF_LEN; - io_hdr.sbp = senseBuff; - io_hdr.timeout = DEF_TIMEOUT; - io_hdr.pack_id = to_block; - if (diop && *diop) - io_hdr.flags |= SG_FLAG_DIRECT_IO; - - while (((res = write(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - perror("writing (wr) on sg device, error"); - return -1; - } - - while (((res = read(sg_fd, &io_hdr, sizeof(io_hdr))) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - perror("writing (rd) on sg device, error"); - return -1; - } - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error while writing block=%d, num=%d\n", - to_block, blocks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 2; - default: - sg_chk_n_print3("writing", &io_hdr); - return -1; - } - if (diop && *diop && - ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - *diop = 0; /* flag that dio not done (completely) */ - return 0; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int bs = 0; - int ibs = 0; - int obs = 0; - int bpt = DEF_BLOCKS_PER_TRANSFER; - int count = -1; - char str[512]; - char * key; - char * buf; - char inf[512]; - int in_is_sg = 0; - char outf[512]; - int out_is_sg = 0; - int dio = 0; - int dio_incomplete = 0; - int res, k, t, buf_sz, dio_tmp; - int infd, outfd, blocks; - unsigned char * wrkBuff; - unsigned char * wrkPos; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz; - int in_full = 0; - int in_partial = 0; - int out_full = 0; - int out_partial = 0; - char ebuff[256]; - int blocks_per; - - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strcpy(str, argv[k]); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strcpy(inf, buf); - else if (strcmp(key,"of") == 0) - strcpy(outf, buf); - else if (0 == strcmp(key,"ibs")) - ibs = sg_get_num(buf); - else if (0 == strcmp(key,"obs")) - obs = sg_get_num(buf); - else if (0 == strcmp(key,"bs")) - bs = sg_get_num(buf); - else if (0 == strcmp(key,"bpt")) - bpt = sg_get_num(buf); - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"dio")) - dio = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (bs <= 0) { - bs = DEF_BLOCK_SIZE; - printf("Assume default 'bs' (block size) of %d bytes\n", bs); - } - if ((ibs && (ibs != bs)) || (obs && (obs != bs))) { - printf("If 'ibs' or 'obs' given must be same as 'bs'\n"); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sg_dd: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - infd = STDIN_FILENO; - outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((infd = open(inf, O_RDWR)) >= 0) { - if (ioctl(infd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(infd); - } - else { - in_is_sg = 1; - res = 0; - t = bs * bpt; - res = ioctl(infd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd: SG_SET_RESERVED_SIZE error"); - res = ioctl(infd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! in_is_sg) { - if ((infd = open(inf, O_RDONLY)) < 0) { - sprintf(ebuff, "sg_dd: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - off_t offset = skip; - - offset *= bs; /* could overflow here! */ - if (lseek(infd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - if ((outfd = open(outf, O_RDWR)) >= 0) { - if (ioctl(outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(outfd); - } - else { - out_is_sg = 1; - res = 0; - t = bs * bpt; - res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sg_dd: SG_SET_RESERVED_SIZE error"); - res = ioctl(outfd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sg_dd: sg driver prior to 3.x.y\n"); - return 1; - } - } - } - if (! out_is_sg) { - if ((outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - sprintf(ebuff, - "sg_dd: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= bs; /* could overflow here! */ - if (lseek(outfd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sg_dd: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } -#if 1 - if (! (in_is_sg || out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } -#endif - if (0 == count) - return 0; - else if (count < 0) { - if (in_is_sg) { - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { -#if 0 - if (0 == in_sect_sz) - in_sect_sz = bs; - else if (in_sect_sz > bs) - in_num_sect *= (in_sect_sz / bs); - else if (in_sect_sz < bs) - in_num_sect /= (bs / in_sect_sz); -#endif - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (out_is_sg) { - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } -#ifdef SG_DEBUG - printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n", - count, in_num_sect, out_num_sect); -#endif - if (in_num_sect > 0) { - if (out_num_sect > 0) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - - wrkBuff= malloc(bs * bpt); - if (0 == wrkBuff) { - printf("Not enough user memory\n"); - return 1; - } - wrkPos = wrkBuff; - - blocks_per = bpt; -#ifdef SG_DEBUG - printf("Start of loop, count=%d, blocks_per=%d\n", count, blocks_per); -#endif - while (count) { - blocks = (count > blocks_per) ? blocks_per : count; - if (in_is_sg) { - dio_tmp = dio; - res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(infd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + bs - 1) / bs; - blocks = blocks_per; - printf("Reducing read to %d blocks per loop\n", blocks_per); - res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (r)\n"); - res = sg_read(infd, wrkBuff, blocks, skip, bs, &dio_tmp); - } - if (0 != res) { - printf("sg_read failed, skip=%d\n", skip); - break; - } - else { - in_full += blocks; - if (dio && (0 == dio_tmp)) - dio_incomplete++; - } - } - else { - while (((res = read(infd, wrkPos, blocks * bs)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_dd: reading, skip=%d ", skip); - perror(ebuff); - break; - } - else if (res < blocks * bs) { - count = 0; - blocks = res / bs; - if ((res % bs) > 0) { - blocks++; - in_partial++; - } - } - in_full += blocks; - } - - if (out_is_sg) { - dio_tmp = dio; - res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if (ioctl(outfd, SG_GET_RESERVED_SIZE, &buf_sz) < 0) { - perror("RESERVED_SIZE ioctls failed"); - break; - } - blocks_per = (buf_sz + bs - 1) / bs; - blocks = blocks_per; - printf("Reducing write to %d blocks per loop\n", blocks); - res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp); - } - else if (2 == res) { - printf("Unit attention, media changed, try again (w)\n"); - res = sg_write(outfd, wrkBuff, blocks, seek, bs, &dio_tmp); - } - else if (0 != res) { - printf("sg_write failed, seek=%d\n", seek); - break; - } - else { - out_full += blocks; - if (dio && (0 == dio_tmp)) - dio_incomplete++; - } - } - else { - while (((res = write(outfd, wrkPos, blocks * bs)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sg_ddd512: writing, seek=%d ", seek); - perror(ebuff); - break; - } - else if (res < blocks * bs) { - printf("output file probably full, seek=%d ", seek); - blocks = res / bs; - out_full += blocks; - if ((res % bs) > 0) - out_partial++; - break; - } - else - out_full += blocks; - } - if (count > 0) - count -= blocks; - skip += blocks; - seek += blocks; - } - - free(wrkBuff); - if (STDIN_FILENO != infd) - close(infd); - if (STDOUT_FILENO != outfd) - close(outfd); - if (0 != count) { - printf("Some error occurred, count=%d\n", count); - return 1; - } - printf("%d+%d records in\n", in_full, in_partial); - printf("%d+%d records out\n", out_full, out_partial); - if (dio_incomplete) - printf(">> Direct IO requested but incomplete %d times\n", - dio_incomplete); - if (sum_of_resids) - printf(">> Non-zero sum of residual counts=%d\n", sum_of_resids); - return 0; -} diff --git a/archive/sg_debug.c b/archive/sg_debug.c deleted file mode 100644 index c29b87b3..00000000 --- a/archive/sg_debug.c +++ /dev/null @@ -1,71 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/fcntl.h> -#include <sys/ioctl.h> -#include "sg_linux_inc.h" - - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999 D. Gilbert -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program outputs debug information to the console/log for _all_ - active sg devices. - - Version 3.55 (20020115) -*/ - -#define EBUFF_SZ 256 - - -int main(int argc, char * argv[]) -{ - int fd, res, debug, t; - char ebuff[EBUFF_SZ]; - - if ((argc != 2) || ('-' == *argv[1])) { - printf("Usage: sg_debug <sg_device>\n"); - return 1; - } - fd = open(argv[1], O_RDONLY | O_NONBLOCK); - if (fd < 0) { - if (EBUSY == errno) - printf("Failed trying to open %s because it is busy\n", argv[1]); - else { - snprintf(ebuff, EBUFF_SZ, "sg_debug: Error trying to open %s ", - argv[1]); - perror(ebuff); - } - return 1; - } - res = ioctl(fd, SG_GET_VERSION_NUM, &t); - if ((res >= 0) || (t >= 30000)) { - printf("System is using sg version 3 driver. Hence the user can"); - printf(" execute:\n 'cat /proc/scsi/sg/debug' themselves. "); - printf("Here is an example:\n"); - system("cat /proc/scsi/sg/debug"); - return 0; - } - debug = 10; - res = ioctl(fd, SG_SET_DEBUG, &debug); - if (res < 0) { - perror("sg_debug: ioctl error on SG_SET_DEBUG"); - return 1; - } - - res = close(fd); - if (res < 0) { - snprintf(ebuff, EBUFF_SZ, "sg_debug: trying to close %s ", argv[1]); - perror(ebuff); - return 1; - } - return 0; -} diff --git a/archive/sg_hold.c b/archive/sg_hold.c deleted file mode 100644 index 01c73d35..00000000 --- a/archive/sg_hold.c +++ /dev/null @@ -1,144 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_linux_inc.h" - -/* This is a program that periodically executes a TEST UNIT READY - SCSI command using the SCSI generic (sg) driver. - -* Copyright (C) 2001 D. Gilbert -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - Invocation: sg_hold [-t<secs>] [-d] <sg_device> - - Version 1.00 (20010312) - -6 byte TEST UNIT READY command: -[0x00][ |lu][res ][res ][res ][res ] - -*/ -#define TUR_CMD_LEN 6 - - -int main(int argc, char * argv[]) -{ - int sg_fd, k, j, res; - unsigned char turCmdBlk [TUR_CMD_LEN] = - {0x00, 0, 0, 0, 0, 0}; - sg_io_hdr_t io_hdr; - char * file_name = 0; - char ebuff[128]; - unsigned char sense_buffer[32]; - int sleep_period = 1; - int debug = 0; - size_t len; - - for (k = 1; k < argc; ++k) { - if (0 == memcmp("-t", argv[k], 2)) { - len = strlen(argv[k]); - if (len > 2) - res = sscanf(argv[k] + 2, "%d", &sleep_period); - else if (++k < argc) - res = sscanf(argv[k], "%d", &sleep_period); - else - res = 0; - if ((1 != res) || (sleep_period < 1)) { - file_name = 0; - printf("Bad '-t' argument\n"); - break; - } - } - else if (0 == memcmp("-d", argv[k], 2)) - debug = 1; - else if (*argv[k] == '-') { - printf("Unrecognized switch: %s\n", argv[k]); - file_name = 0; - break; - } - else if (0 == file_name) - file_name = argv[k]; - else { - printf("too many arguments\n"); - file_name = 0; - break; - } - } - if (0 == file_name) { - printf("Usage: 'sg_hold [-t<secs>] [-d] <sg_device>'\n"); - printf(" where: -t<secs> time in seconds between TURs " - "(default: 1 sec)\n"); - printf(" -d output message with each TUR\n"); - return 1; - } - - if ((sg_fd = open(file_name, O_RDONLY)) < 0) { - sprintf(ebuff, "sg_hold: error opening file: %s", file_name); - perror(ebuff); - return 1; - } - /* Just to be safe, check we have a new sg device by trying an ioctl */ - if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { - printf("sg_hold: %s doesn't seem to be an new sg device\n", - file_name); - close(sg_fd); - return 1; - } - - for (j = 1; ; ++j) { - /* Prepare TEST UNIT READY command */ - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(turCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_buffer); - io_hdr.dxfer_direction = SG_DXFER_NONE; - io_hdr.cmdp = turCmdBlk; - io_hdr.sbp = sense_buffer; - io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */ - io_hdr.pack_id = j; /* marching pack_id starting at 1 */ - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("sg_hold: Test Unit Ready SG_IO ioctl error"); - close(sg_fd); - return 1; - } - - /* now for the error processing */ - if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { - if (io_hdr.sb_len_wr > 0) { - printf("TEST UNIT READY sense data: "); - for (k = 0; k < io_hdr.sb_len_wr; ++k) { - if ((k > 0) && (0 == (k % 10))) - printf("\n "); - printf("0x%02x ", sense_buffer[k]); - } - printf("\n"); - } - else if (io_hdr.masked_status) - printf("TEST UNIT READY SCSI status=0x%x\n", io_hdr.status); - else if (io_hdr.host_status) - printf("TEST UNIT READY host_status=0x%x\n", - io_hdr.host_status); - else if (io_hdr.driver_status) - printf("TEST UNIT READY driver_status=0x%x\n", - io_hdr.driver_status); - else - printf("TEST UNIT READY unexpected error\n"); - printf("Test Unit Ready failed so unit may _not_ be ready!\n"); - } - else if (debug) - printf("Test Unit Ready successful so unit is ready!\n"); - - sleep(sleep_period); - } - close(sg_fd); - return 0; -} diff --git a/archive/sg_io_linux.h b/archive/sg_io_linux.h deleted file mode 120000 index 6c9c2ba9..00000000 --- a/archive/sg_io_linux.h +++ /dev/null @@ -1 +0,0 @@ -../sg_io_linux.h
\ No newline at end of file diff --git a/archive/sg_lib.h b/archive/sg_lib.h deleted file mode 120000 index f6ce0761..00000000 --- a/archive/sg_lib.h +++ /dev/null @@ -1 +0,0 @@ -../sg_lib.h
\ No newline at end of file diff --git a/archive/sg_linux_inc.h b/archive/sg_linux_inc.h deleted file mode 120000 index 55808134..00000000 --- a/archive/sg_linux_inc.h +++ /dev/null @@ -1 +0,0 @@ -../sg_linux_inc.h
\ No newline at end of file diff --git a/archive/sg_poll.c b/archive/sg_poll.c deleted file mode 100644 index e6fb28f8..00000000 --- a/archive/sg_poll.c +++ /dev/null @@ -1,351 +0,0 @@ -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/poll.h> -#include <sys/ipc.h> -#include <sys/sem.h> -#include "sg_lib.h" -#include "sg_io_linux.h" - -/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999-2001 D. Gilbert -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program tests out asynchronous parts of the 'sg' device driver. - It only uses the SCSI read command on the 'sg' device. - This program performs unbalanced, non-polling "write-write-read" - sequences. Asynchronous notification is turned on and signals are - counted. Due to the imbalance, when the close() is executed there - are several packets still to be read() [some of which may not yet - be awaiting a read()]. This tests how the device driver cleans up - after an unexpected close(). - If the "-deb" flag is given then outputs state to console/log - (for all active sg devices). - - Version 0.76 20010112 -*/ - - -/* -6 byte commands [READ: 0x08, WRITE: 0x0a]: -[cmd ][had|lu][midAdd][lowAdd][count ][flags ] -10 byte commands [EREAD: 0x28, EWRITE: 0x2a, READ_CAPACITY 0x25]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][ ][hiCnt ][lowCnt][flags ] -12 byte commands [LREAD: 0xd8, LWRITE: 0xda]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][hiCnt ][hmCnt ][lmCnt ][lowCnt] - ... [ ][flags ] -*/ - -#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) - /* union semun is defined by including <sys/sem.h> */ -#else - /* according to X/OPEN we have to define it ourselves */ -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ - unsigned short int *array; /* array for GETALL, SETALL */ - struct seminfo *__buf; /* buffer for IPC_INFO */ -}; -#endif - -#ifdef O_ASYNC -#define MY_ASYNC O_ASYNC -#else -#define MY_ASYNC FASYNC -#endif - - -// #define SG_DEBUG - -#define OFF sizeof(struct sg_header) -// #define NUM_SECTORS 7777 -// #define NUM_SECTORS 577 -// #define NUM_SECTORS 97 -#define NUM_SECTORS 150 -#define BLOCK_SIZE 2048 - -volatile int hand_count = 0; -volatile int signo = 0; -volatile int poll_res = 0; -volatile short revents = 0; -volatile int sg_fd = 0; -int semset_id = 0; - -int do_poll() -{ - struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0}; - - a_pollfd.fd = sg_fd; - if ((poll_res = poll(&a_pollfd, 1, 0)) < 0) { - perror("poll error"); - return 0; - } - revents = a_pollfd.revents; - return (a_pollfd.revents & POLLIN) ? 1 : 0; -} - -void sg_sa_handler(int sig, siginfo_t *si, void * data) -{ - signo = sig; - if (SIGRTMIN != sig) - fprintf(stderr, "Unexpected signal, signum=%d\n", sig); - if (sg_fd != si->si_fd) - fprintf(stderr, "Unexpected fd, fd=%d\n", si->si_fd); - ++hand_count; - if (do_poll()) { - struct sembuf a_sembuf; - - a_sembuf.sem_num = 0; - a_sembuf.sem_op = 1; - a_sembuf.sem_flg = 0; - if (semop(semset_id, &a_sembuf, 1) < 0) - perror("semop(sh) error"); - } -} - -int main(int argc, char * argv[]) -{ - int flags; - int res; - int k; - unsigned char rdCmdBlk [10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char * rdBuff = malloc(OFF + sizeof(rdCmdBlk) + - (BLOCK_SIZE * NUM_SECTORS)); - unsigned char * rdBuff2 = malloc(OFF + sizeof(rdCmdBlk) + - (BLOCK_SIZE * NUM_SECTORS)); - int rdInLen = OFF + sizeof(rdCmdBlk); - int rdOutLen; - unsigned char * rdCmd = rdBuff + OFF; - unsigned char * rdCmd2 = rdBuff + OFF; - struct sg_header * rsghp = (struct sg_header *)rdBuff; - struct sg_header * rsghp2 = (struct sg_header *)rdBuff2; - int sectorNo = 10000; - int sectorNo2; - int numSectors = NUM_SECTORS; - const int times = 3; - struct sigaction s_action; - union semun a_semun; - struct sembuf a_sembuf; - struct sg_scsi_id sg_id; - char ebuff[256]; - int deb = 0; - char * file_name = 0; - - for (k = 1; k < argc; ++k) { - if (0 == memcmp("-deb", argv[k], 4)) - deb = 10; - else if (*argv[k] != '-') - file_name = argv[k]; - } - if (0 == file_name) { -printf("Usage: 'sg_poll [-deb] <generic_device>' eg: sg_poll /dev/sg0\n"); - return 1; - } - - semset_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); - if (-1 == semset_id) { - perror("semget error"); - return 1; - } - a_semun.val = 0; - res = semctl(semset_id, 0, SETVAL, a_semun); - if (-1 == res) { - perror("semctl(val) error"); - return 1; - } - - - sg_fd = open(file_name, O_RDWR | O_NONBLOCK); - if (sg_fd < 0) { - sprintf(ebuff, "sg_poll: open error on %s", file_name); - perror(ebuff); - return 1; - } - res = ioctl(sg_fd, SG_GET_SCSI_ID, &sg_id); - if (res < 0) { - /* perror("ioctl on generic device, error"); */ - printf("sg_poll: %s not a scsi generic device\n", file_name); - return 1; - } - printf("scsi%d, channel=%d, device=%d, lun=%d, scsi_type=%d\n", - sg_id.host_no, sg_id.channel, sg_id.scsi_id, sg_id.lun, - sg_id.scsi_type); - -#ifdef SG_DEBUG - ioctl(sg_fd, SG_SET_DEBUG, &deb); -#endif - res = ioctl(sg_fd, SG_GET_COMMAND_Q, &k); - if (res < 0) { - perror("SG_GET_COMMAND_Q ioctl error"); - return 1; - } - if (0 == k) { - k = 1; - res = ioctl(sg_fd, SG_SET_COMMAND_Q, &k); - if (res < 0) { - perror("SG_SET_COMMAND_Q ioctl error"); - return 1; - } - } - - s_action.sa_flags = SA_SIGINFO; - s_action.sa_sigaction = sg_sa_handler; - sigemptyset(&s_action.sa_mask); - res = sigaction(SIGRTMIN, &s_action, NULL); - if (res == -1) { - perror("sg_poll: sigaction error"); - return 1; - } - res = fcntl(sg_fd, F_SETOWN, getpid()); - if (res == -1) { - perror("sg_poll: fcntl(setown) error"); - return 1; - } - flags = fcntl(sg_fd, F_GETFL); - res = fcntl(sg_fd, F_SETFL, flags | MY_ASYNC); - if (res == -1) { - perror("sg_poll: fcntl(setfl) error"); - return 1; - } - fcntl(sg_fd, F_SETSIG, SIGRTMIN); - - do_poll(); - printf("pre-loop check, poll_res=%d, revents=%d\n", poll_res, (int)revents); - - - for (k = 0; k < times; ++k, sectorNo += numSectors) { - - rdOutLen = OFF + (BLOCK_SIZE * numSectors); - rsghp->pack_len = 999; /* don't care */ - rsghp->pack_id = k; - rsghp->reply_len = rdOutLen; - rsghp->twelve_byte = 0; - rsghp->result = 0; - memcpy(rdBuff + OFF, rdCmdBlk, sizeof(rdCmdBlk)); - rdCmd[3] = (unsigned char)((sectorNo >> 16) & 0xFF); - rdCmd[4] = (unsigned char)((sectorNo >> 8) & 0xFF); - rdCmd[5] = (unsigned char)(sectorNo & 0xFF); - rdCmd[7] = (unsigned char)((numSectors >> 8) & 0xff); - rdCmd[8] = (unsigned char)(numSectors & 0xff); - - res = write(sg_fd, rdBuff, rdInLen); - if (res < 0) { - perror("sg_poll: write (rd) error"); - return 1; - } - if (res < rdInLen) { - printf("sg_poll: wrote less (rd), ask=%d, got=%d", rdInLen, res); - return 1; - } - - rsghp2->pack_len = 888; /* don't care */ - rsghp2->pack_id = k + 100; - rsghp2->reply_len = rdOutLen; - rsghp2->twelve_byte = 0; - rsghp2->result = 0; - memcpy(rdBuff2 + OFF, rdCmdBlk, sizeof(rdCmdBlk)); - sectorNo2 = sectorNo + 6666; - rdCmd2[3] = (unsigned char)((sectorNo2 >> 16) & 0xFF); - rdCmd2[4] = (unsigned char)((sectorNo2 >> 8) & 0xFF); - rdCmd2[5] = (unsigned char)(sectorNo2 & 0xFF); - rdCmd2[7] = (unsigned char)((numSectors >> 8) & 0xff); - rdCmd2[8] = (unsigned char)(numSectors & 0xff); - -#if 1 - res = write(sg_fd, rdBuff2, rdInLen); - if (res < 0) { - perror("sg_poll: write2 (rd) error"); - return 1; - } - if (res < rdInLen) { - printf("sg_poll: wrote less (rd), ask=%d, got=%d", rdInLen, res); - return 1; - } -#endif - - do_poll(); - printf("pre-write pause, k=%d, " - "hand_count=%d, signo=%d, poll_res=%d, revents=%d\n", - k, hand_count, signo, poll_res, (int)revents); -#ifdef SG_DEBUG - ioctl(sg_fd, SG_SET_DEBUG, &deb); -#endif - system("cat /proc/scsi/sg/debug"); - - a_sembuf.sem_num = 0; - a_sembuf.sem_op = -1; - a_sembuf.sem_flg = 0; - while (semop(semset_id, &a_sembuf, 1) < 0) { - if (EINTR != errno) { - perror("semop(main) error"); - return 0; - } - } - /* pause(); */ - - printf("post-write pause, k=%d, " - "hand_count=%d, signo=%d, poll_res=%d, revents=%d\n", - k, hand_count, signo, poll_res, (int)revents); -#ifdef SG_DEBUG - ioctl(sg_fd, SG_SET_DEBUG, &deb); -#endif - - res = read(sg_fd, rdBuff, rdOutLen); - if (res < 0) { - perror("sg_poll: read (rd) error"); - return 1; - } - if (res < rdOutLen) { - printf("sg_poll: read less (rd), ask=%d, got=%d", rdOutLen, res); - return 1; - } - sg_chk_n_print("after read(rd)", rsghp->target_status, - rsghp->host_status, rsghp->driver_status, - rsghp->sense_buffer, SG_MAX_SENSE, 1); - - } - printf("\treq_len=%d, dma_count=%d\n", rsghp->reply_len, rsghp->pack_len); - -#ifdef SG_DEBUG - ioctl(sg_fd, SG_SET_DEBUG, &deb); -#endif - res = close(sg_fd); - if (res < 0) { - perror("sg_poll: close error"); - return 1; - } - - if (deb > 0) { - sg_fd = open(file_name, O_RDONLY); - if (sg_fd < 0) { - sprintf(ebuff, "sg_poll: open (2) error on %s", file_name); - perror(ebuff); - return 1; - } - res = ioctl(sg_fd, SG_SET_DEBUG, &deb); - if (res < 0) { - perror("ioctl (2) error"); - return 1; - } - res = close(sg_fd); - if (res < 0) { - perror("sg_poll: close (2) error"); - return 1; - } - } - - return 0; -} diff --git a/archive/sg_simple0.c b/archive/sg_simple0.c deleted file mode 100644 index 7e1d8db7..00000000 --- a/archive/sg_simple0.c +++ /dev/null @@ -1,93 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <scsi/sg.h> /* 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.00 (20011204) -*/ - -#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 <sg_device>'\n"); - return 1; - } - if ((sg_fd = open(argv[1], O_RDONLY)) < 0) { - 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, &k) < 0) || (k < 30000)) { - printf("%s is not an sg device, or old sg driver\n", argv[1]); - return 1; - } - /* Prepare INQUIRY command */ - memset(&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, &io_hdr) < 0) { - perror("sg_simple0: Inquiry SG_IO ioctl error"); - return 1; - } - - /* now for the error processing */ - if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { - if (io_hdr.sb_len_wr > 0) { - printf("INQUIRY sense data: "); - for (k = 0; k < io_hdr.sb_len_wr; ++k) { - if ((k > 0) && (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; -} diff --git a/archive/sgq_dd.c b/archive/sgq_dd.c deleted file mode 100644 index 52de5184..00000000 --- a/archive/sgq_dd.c +++ /dev/null @@ -1,1151 +0,0 @@ -#define _XOPEN_SOURCE 500 - -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <sys/poll.h> -#include <linux/major.h> -#include <sys/time.h> -typedef unsigned char u_char; /* horrible, for scsi.h */ -#include "sg_lib.h" -#include "sg_io_linux.h" -#include "llseek.h" - -/* A utility program for the Linux OS SCSI generic ("sg") device driver. -* Copyright (C) 1999-2002 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device or a raw - device. A block size ('bs') is assumed to be 512 if not given. This - program complains if 'ibs' or 'obs' are given with some other value - than 'bs'. If 'if' is not given or 'if=-' then stdin is assumed. If - 'of' is not given or 'of=-' then stdout assumed. Multipliers: - 'c','C' *1 'b','B' *512 'k' *1024 'K' *1000 - 'm' *(1024^2) 'M' *(1000^2) 'g' *(1024^3) 'G' *(1000^3) - - A non-standard argument "bpt" (blocks per transfer) is added to control - the maximum number of blocks in each transfer. The default value is 128. - For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB - in this case) are transferred to or from the sg device in a single SCSI - command. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . This version uses posix threads. - -*/ - -static char * version_str = "0.55 20020509"; - -#define DEF_BLOCK_SIZE 512 -#define DEF_BLOCKS_PER_TRANSFER 128 - -/* #define SG_DEBUG */ - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */ -#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */ - -#define SGP_READ10 0x28 -#define SGP_WRITE10 0x2a -#define DEF_NUM_THREADS 4 /* actually degree of concurrency */ -#define MAX_NUM_THREADS 32 - -#ifndef RAW_MAJOR -#define RAW_MAJOR 255 /*unlikey value */ -#endif - -#define FT_OTHER 0 /* filetype other than sg or raw device */ -#define FT_SG 1 /* filetype is sg char device */ -#define FT_RAW 2 /* filetype is raw char device */ - -#define QS_IDLE 0 /* ready to start a copy cycle */ -#define QS_IN_STARTED 1 /* commenced read */ -#define QS_IN_FINISHED 2 /* finished read, ready for write */ -#define QS_OUT_STARTED 3 /* commenced write */ - -#define QS_IN_POLL 11 -#define QS_OUT_POLL 12 - -#define STR_SZ 1024 -#define INOUTF_SZ 512 -#define EBUFF_SZ 512 - - -struct request_element; - -typedef struct request_collection -{ /* one instance visible to all threads */ - int infd; - int skip; - int in_type; - int in_scsi_type; - int in_blk; /* next block address to read */ - int in_count; /* blocks remaining for next read */ - int in_done_count; /* count of completed in blocks */ - int in_partial; - int outfd; - int seek; - int out_type; - int out_scsi_type; - int out_blk; /* next block address to write */ - int out_count; /* blocks remaining for next write */ - int out_done_count; /* count of completed out blocks */ - int out_partial; - int bs; - int bpt; - int dio; - int dio_incomplete; - int sum_of_resids; - int coe; - int debug; - int num_rq_elems; - struct request_element * req_arr; -} Rq_coll; - -typedef struct request_element -{ /* one instance per worker thread */ - int qstate; /* "QS" state */ - int infd; - int outfd; - int wr; - int blk; - int num_blks; - unsigned char * buffp; - unsigned char * alloc_bp; - sg_io_hdr_t io_hdr; - unsigned char cmd[S_RW_LEN]; - unsigned char sb[SENSE_BUFF_LEN]; - int bs; - int dio; - int dio_incomplete; - int resid; - int in_scsi_type; - int out_scsi_type; - int debug; -} Rq_elem; - -static Rq_coll rcoll; -static struct pollfd in_pollfd_arr[MAX_NUM_THREADS]; -static struct pollfd out_pollfd_arr[MAX_NUM_THREADS]; -static int dd_count = -1; - -static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio"; - -int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep); -int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep); -int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks); -int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks); -int sg_start_io(Rq_elem * rep); -int sg_finish_io(int wr, Rq_elem * rep); - - -static void install_handler (int sig_num, void (*sig_handler) (int sig)) -{ - struct sigaction sigact; - sigaction (sig_num, NULL, &sigact); - if (sigact.sa_handler != SIG_IGN) - { - sigact.sa_handler = sig_handler; - sigemptyset (&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction (sig_num, &sigact, NULL); - } -} - -void print_stats() -{ - int infull, outfull; - - if (0 != rcoll.out_count) - fprintf(stderr, " remaining block count=%d\n", rcoll.out_count); - infull = dd_count - rcoll.in_done_count - rcoll.in_partial; - fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial); - outfull = dd_count - rcoll.out_done_count - rcoll.out_partial; - fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial); -} - -static void interrupt_handler(int sig) -{ - struct sigaction sigact; - - sigact.sa_handler = SIG_DFL; - sigemptyset (&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction (sig, &sigact, NULL); - fprintf(stderr, "Interrupted by signal,"); - print_stats (); - kill (getpid (), sig); -} - -static void siginfo_handler(int sig) -{ - fprintf(stderr, "Progress report, continuing ...\n"); - print_stats (); -} - -int dd_filetype(const char * filename) -{ - struct stat st; - - if (stat(filename, &st) < 0) - return FT_OTHER; - if (S_ISCHR(st.st_mode)) { - if (RAW_MAJOR == major(st.st_rdev)) - return FT_RAW; - else if (SCSI_GENERIC_MAJOR == major(st.st_rdev)) - return FT_SG; - } - return FT_OTHER; -} - -void usage() -{ - fprintf(stderr, "Usage: " - "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>] " - "[bs=<num>]\n" - " [bpt=<num>] [count=<n>] [dio=0|1] [thr=<n>] " - "[coe=0|1] [gen=<n>]\n" - " [time=0|1] [deb=<n>] [--version]\n" - " usually either 'if' or 'of' is a sg or raw device\n" - " 'bpt' is blocks_per_transfer (default is 128)\n" - " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n" - " 'thr' is number of queues, must be > 0, default 4, max 32\n"); - fprintf(stderr, " 'coe' continue on sg error, 0->exit (def), " - "1->zero + continue\n" - " 'time' 0->no timing(def), 1->time plus calculate throughput\n" - " 'gen' 0-> 1 file is special(def), 1-> any files allowed\n" - " 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n"); -} - -/* Returns -1 for error, 0 for nothing found, QS_IN_POLL or QS_OUT_POLL */ -int do_poll(Rq_coll * clp, int timeout, int * req_indexp) -{ - int k, res; - - if (FT_SG == clp->out_type) { - while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - perror("poll error on output fds"); - return -1; - } - else if (res > 0) { - for (k = 0; k < clp->num_rq_elems; ++k) { - if (out_pollfd_arr[k].revents & POLLIN) { - if (req_indexp) - *req_indexp = k; - return QS_OUT_POLL; - } - } - } - } - if (FT_SG == clp->in_type) { - while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - perror("poll error on input fds"); - return -1; - } - else if (res > 0) { - for (k = 0; k < clp->num_rq_elems; ++k) { - if (in_pollfd_arr[k].revents & POLLIN) { - if (req_indexp) - *req_indexp = k; - return QS_IN_POLL; - } - } - } - } - return 0; -} - - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr, 1); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -#ifdef SG_DEBUG - fprintf(stderr, "number of sectors=%d, sector size=%d\n", - *num_sect, *sect_sz); -#endif - return 0; -} - -/* 0 -> ok, 1 -> short read, -1 -> error */ -int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks) -{ - int res; - int stop_after_write = 0; - - rep->qstate = QS_IN_STARTED; - if (rep->debug > 8) - fprintf(stderr, "normal_in_operation: start blk=%d num_blks=%d\n", - rep->blk, rep->num_blks); - while (((res = read(rep->infd, rep->buffp, - blocks * rep->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - fprintf(stderr, "sgq_dd: reading, in_blk=%d, errno=%d\n", rep->blk, - errno); - return -1; - } - if (res < blocks * rep->bs) { - int o_blocks = blocks; - stop_after_write = 1; - blocks = res / rep->bs; - if ((res % rep->bs) > 0) { - blocks++; - clp->in_partial++; - } - /* Reverse out + re-apply blocks on clp */ - clp->in_blk -= o_blocks; - clp->in_count += o_blocks; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - } - clp->in_done_count -= blocks; - rep->qstate = QS_IN_FINISHED; - return stop_after_write; -} - -/* 0 -> ok, -1 -> error */ -int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks) -{ - int res; - - rep->qstate = QS_OUT_STARTED; - if (rep->debug > 8) - fprintf(stderr, "normal_out_operation: start blk=%d num_blks=%d\n", - rep->blk, rep->num_blks); - while (((res = write(rep->outfd, rep->buffp, - rep->num_blks * rep->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - fprintf(stderr, "sgq_dd: output, out_blk=%d, errno=%d\n", rep->blk, - errno); - return -1; - } - if (res < blocks * rep->bs) { - blocks = res / rep->bs; - if ((res % rep->bs) > 0) { - blocks++; - clp->out_partial++; - } - rep->num_blks = blocks; - } - clp->out_done_count -= blocks; - rep->qstate = QS_IDLE; - return 0; -} - -/* Returns 1 for retryable, 0 for ok, -ve for error */ -int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep) -{ - int res; - - rep->qstate = QS_IN_FINISHED; - res = sg_finish_io(rep->wr, rep); - if (res < 0) { - if (clp->coe) { - memset(rep->buffp, 0, rep->num_blks * rep->bs); - fprintf(stderr, ">> substituted zeros for in blk=%d for " - "%d bytes\n", rep->blk, rep->num_blks * rep->bs); - res = 0; - } - else { - fprintf(stderr, "error finishing sg in command\n"); - return res; - } - } - if (0 == res) { /* looks good, going to return */ - if (rep->dio_incomplete || rep->resid) { - clp->dio_incomplete += rep->dio_incomplete; - clp->sum_of_resids += rep->resid; - } - clp->in_done_count -= rep->num_blks; - } - return res; -} - -/* Returns 1 for retryable, 0 for ok, -ve for error */ -int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep) -{ - int res; - - rep->qstate = QS_IDLE; - res = sg_finish_io(rep->wr, rep); - if (res < 0) { - if (clp->coe) { - fprintf(stderr, ">> ignored error for out blk=%d for " - "%d bytes\n", rep->blk, rep->num_blks * rep->bs); - res = 0; - } - else { - fprintf(stderr, "error finishing sg out command\n"); - return res; - } - } - if (0 == res) { - if (rep->dio_incomplete || rep->resid) { - clp->dio_incomplete += rep->dio_incomplete; - clp->sum_of_resids += rep->resid; - } - clp->out_done_count -= rep->num_blks; - } - return res; -} - -int sg_start_io(Rq_elem * rep) -{ - sg_io_hdr_t * hp = &rep->io_hdr; - int res; - - rep->qstate = rep->wr ? QS_OUT_STARTED : QS_IN_STARTED; - memset(rep->cmd, 0, sizeof(rep->cmd)); - rep->cmd[0] = rep->wr ? SGP_WRITE10 : SGP_READ10; - rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF); - rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF); - rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF); - rep->cmd[5] = (unsigned char)(rep->blk & 0xFF); - rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff); - rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff); - memset(hp, 0, sizeof(sg_io_hdr_t)); - hp->interface_id = 'S'; - hp->cmd_len = sizeof(rep->cmd); - hp->cmdp = rep->cmd; - hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - hp->dxfer_len = rep->bs * rep->num_blks; - hp->dxferp = rep->buffp; - hp->mx_sb_len = sizeof(rep->sb); - hp->sbp = rep->sb; - hp->timeout = DEF_TIMEOUT; - hp->usr_ptr = rep; - hp->pack_id = rep->blk; - if (rep->dio) - hp->flags |= SG_FLAG_DIRECT_IO; - if (rep->debug > 8) { - fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n", - rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks); - sg_print_command(hp->cmdp); - fprintf(stderr, " len=%d, dxfrp=%p, cmd_len=%d\n", - hp->dxfer_len, hp->dxferp, hp->cmd_len); - } - - while (((res = write(rep->wr ? rep->outfd : rep->infd, hp, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - return res; - } - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */ -int sg_finish_io(int wr, Rq_elem * rep) -{ - int res; - sg_io_hdr_t io_hdr; - sg_io_hdr_t * hp; -#if 0 - static int testing = 0; /* thread dubious! */ -#endif - - memset(&io_hdr, 0 , sizeof(sg_io_hdr_t)); - /* FORCE_PACK_ID active set only read packet with matching pack_id */ - io_hdr.interface_id = 'S'; - io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - io_hdr.pack_id = rep->blk; - - while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - perror("finishing io on sg device, error"); - return -1; - } - if (rep != (Rq_elem *)io_hdr.usr_ptr) { - fprintf(stderr, - "sg_finish_io: bad usr_ptr, request-response mismatch\n"); - exit(1); - } - memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t)); - hp = &rep->io_hdr; - - switch (sg_err_category3(hp)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - fprintf(stderr, "Recovered error on block=%d, num=%d\n", - rep->blk, rep->num_blks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 1; - default: - { - char ebuff[EBUFF_SZ]; - snprintf(ebuff, EBUFF_SZ, "%s blk=%d", - rep->wr ? "writing": "reading", rep->blk); - sg_chk_n_print3(ebuff, hp, 1); - return -1; - } - } -#if 0 - if (0 == (++testing % 100)) return -1; -#endif - if (rep->dio && - ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - rep->dio_incomplete = 1; /* count dios done as indirect IO */ - else - rep->dio_incomplete = 0; - rep->resid = hp->resid; - if (rep->debug > 8) - fprintf(stderr, "sg_finish_io: completed %s, blk=%d\n", - wr ? "WRITE" : "READ", rep->blk); - return 0; -} - -/* Returns scsi_type or -1 for error */ -int sg_prepare(int fd, int sz) -{ - int res, t; - struct sg_scsi_id info; - - res = ioctl(fd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - fprintf(stderr, "sgq_dd: sg driver prior to 3.x.y\n"); - return -1; - } - res = ioctl(fd, SG_SET_RESERVED_SIZE, &sz); - if (res < 0) - perror("sgq_dd: SG_SET_RESERVED_SIZE error"); -#if 0 - t = 1; - res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t); - if (res < 0) - perror("sgq_dd: SG_SET_FORCE_PACK_ID error"); -#endif - res = ioctl(fd, SG_GET_SCSI_ID, &info); - if (res < 0) { - perror("sgq_dd: SG_SET_SCSI_ID error"); - return -1; - } - else - return info.scsi_type; -} - -/* Return 0 for ok, anything else for errors */ -int prepare_rq_elems(Rq_coll * clp, const char * inf, const char * outf) -{ - int k; - Rq_elem * rep; - size_t psz; - char ebuff[EBUFF_SZ]; - int sz = clp->bpt * clp->bs; - int scsi_type; - - clp->req_arr = malloc(sizeof(Rq_elem) * clp->num_rq_elems); - if (NULL == clp->req_arr) - return 1; - for (k = 0; k < clp->num_rq_elems; ++k) { - rep = &clp->req_arr[k]; - memset(rep, 0, sizeof(Rq_elem)); - psz = getpagesize(); - if (NULL == (rep->alloc_bp = malloc(sz + psz))) - return 1; - rep->buffp = (unsigned char *) - (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1))); - rep->qstate = QS_IDLE; - rep->bs = clp->bs; - rep->dio = clp->dio; - rep->debug = clp->debug; - rep->out_scsi_type = clp->out_scsi_type; - if (FT_SG == clp->in_type) { - if (0 == k) - rep->infd = clp->infd; - else { - if ((rep->infd = open(inf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg reading", inf); - perror(ebuff); - return 1; - } - } - in_pollfd_arr[k].fd = rep->infd; - in_pollfd_arr[k].events = POLLIN; - if ((scsi_type = sg_prepare(rep->infd, sz)) < 0) - return 1; - if (0 == k) - clp->in_scsi_type = scsi_type; - rep->in_scsi_type = clp->in_scsi_type; - } - else - rep->infd = clp->infd; - - if (FT_SG == clp->out_type) { - if (0 == k) - rep->outfd = clp->outfd; - else { - if ((rep->outfd = open(outf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg writing", outf); - perror(ebuff); - return 1; - } - } - out_pollfd_arr[k].fd = rep->outfd; - out_pollfd_arr[k].events = POLLIN; - if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0) - return 1; - if (0 == k) - clp->out_scsi_type = scsi_type; - rep->out_scsi_type = clp->out_scsi_type; - } - else - rep->outfd = clp->outfd; - } - return 0; -} - -/* Returns a "QS" code and req index, or QS_IDLE and position of first idle - (-1 if no idle position). Returns -1 on poll error. */ -int decider(Rq_coll * clp, int first_xfer, int * req_indexp) -{ - int k, res; - Rq_elem * rep; - int first_idle_index = -1; - int lowest_blk_index = -1; - int times; - int try_poll = 0; - int lowest_blk = INT_MAX; - - times = first_xfer ? 1 : clp->num_rq_elems; - for (k = 0; k < times; ++k) { - rep = &clp->req_arr[k]; - if ((QS_IN_STARTED == rep->qstate) || - (QS_OUT_STARTED == rep->qstate)) - try_poll = 1; - else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) { - lowest_blk = rep->blk; - lowest_blk_index = k; - } - else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0)) - first_idle_index = k; - } - if (try_poll) { - res = do_poll(clp, 0, req_indexp); - if (0 != res) - return res; - } - - if (lowest_blk_index >= 0) { - if (req_indexp) - *req_indexp = lowest_blk_index; - return QS_IN_FINISHED; - } -#if 0 - if (try_poll) { - res = do_poll(clp, 2, req_indexp); - if (0 != res) - return res; - } -#endif - if (req_indexp) - *req_indexp = first_idle_index; - return QS_IDLE; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int ibs = 0; - int obs = 0; - char str[STR_SZ]; - char * key; - char * buf; - char inf[INOUTF_SZ]; - char outf[INOUTF_SZ]; - int res, k; - int in_num_sect = 0; - int out_num_sect = 0; - int num_threads = DEF_NUM_THREADS; - int gen = 0; - int do_time = 0; - int in_sect_sz, out_sect_sz, first_xfer, qstate, req_index, seek_skip; - int blocks, stop_after_write, terminate; - char ebuff[EBUFF_SZ]; - Rq_elem * rep; - struct timeval start_tm, end_tm; - - memset(&rcoll, 0, sizeof(Rq_coll)); - rcoll.bpt = DEF_BLOCKS_PER_TRANSFER; - rcoll.in_type = FT_OTHER; - rcoll.out_type = FT_OTHER; - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strncpy(str, argv[k], STR_SZ); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strncpy(inf, buf, INOUTF_SZ); - else if (strcmp(key,"of") == 0) - strncpy(outf, buf, INOUTF_SZ); - else if (0 == strcmp(key,"ibs")) - ibs = sg_get_num(buf); - else if (0 == strcmp(key,"obs")) - obs = sg_get_num(buf); - else if (0 == strcmp(key,"bs")) - rcoll.bs = sg_get_num(buf); - else if (0 == strcmp(key,"bpt")) - rcoll.bpt = sg_get_num(buf); - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - dd_count = sg_get_num(buf); - else if (0 == strcmp(key,"dio")) - rcoll.dio = sg_get_num(buf); - else if (0 == strcmp(key,"thr")) - num_threads = sg_get_num(buf); - else if (0 == strcmp(key,"coe")) - rcoll.coe = sg_get_num(buf); - else if (0 == strcmp(key,"gen")) - gen = sg_get_num(buf); - else if (0 == strncmp(key,"deb", 3)) - rcoll.debug = sg_get_num(buf); - else if (0 == strcmp(key,"time")) - do_time = sg_get_num(buf); - else if (0 == strncmp(key, "--vers", 6)) { - fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n", - version_str); - return 0; - } - else { - fprintf(stderr, "Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (rcoll.bs <= 0) { - rcoll.bs = DEF_BLOCK_SIZE; - fprintf(stderr, "Assume default 'bs' (block size) of %d bytes\n", - rcoll.bs); - } - if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) { - fprintf(stderr, "If 'ibs' or 'obs' given must be same as 'bs'\n"); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - fprintf(stderr, "skip and seek cannot be negative\n"); - return 1; - } - if ((num_threads < 1) || (num_threads > MAX_NUM_THREADS)) { - fprintf(stderr, "too few or too many threads requested\n"); - usage(); - return 1; - } - if (rcoll.debug) - fprintf(stderr, "sgq_dd: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, dd_count); - install_handler (SIGINT, interrupt_handler); - install_handler (SIGQUIT, interrupt_handler); - install_handler (SIGPIPE, interrupt_handler); - install_handler (SIGUSR1, siginfo_handler); - - rcoll.infd = STDIN_FILENO; - rcoll.outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - rcoll.in_type = dd_filetype(inf); - - if (FT_SG == rcoll.in_type) { - if ((rcoll.infd = open(inf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg reading", inf); - perror(ebuff); - return 1; - } - } - if (FT_SG != rcoll.in_type) { - if ((rcoll.infd = open(inf, O_RDONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - llse_loff_t offset = skip; - - offset *= rcoll.bs; /* could exceed 32 here! */ - if (llse_llseek(rcoll.infd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - rcoll.out_type = dd_filetype(outf); - - if (FT_SG == rcoll.out_type) { - if ((rcoll.outfd = open(outf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg writing", outf); - perror(ebuff); - return 1; - } - } - else { - if (FT_OTHER == rcoll.out_type) { - if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - } - else { - if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for raw writing", outf); - perror(ebuff); - return 1; - } - } - if (seek > 0) { - llse_loff_t offset = seek; - - offset *= rcoll.bs; /* could exceed 32 bits here! */ - if (llse_llseek(rcoll.outfd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) { - fprintf(stderr, "Disallow both if and of to be stdin and stdout"); - return 1; - } - if ((FT_OTHER == rcoll.in_type) && (FT_OTHER == rcoll.out_type) && !gen) { - fprintf(stderr, "Either 'if' or 'of' must be a sg or raw device\n"); - return 1; - } - if (0 == dd_count) - return 0; - else if (dd_count < 0) { - if (FT_SG == rcoll.in_type) { - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - fprintf(stderr, "Unit attention, media changed(in), repeat\n"); - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - fprintf(stderr, "Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (FT_SG == rcoll.out_type) { - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - fprintf(stderr, "Unit attention, media changed(out), repeat\n"); - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - fprintf(stderr, "Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } - if (in_num_sect > 0) { - if (out_num_sect > 0) - dd_count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - dd_count = in_num_sect; - } - else - dd_count = out_num_sect; - } - if (rcoll.debug > 1) - fprintf(stderr, "Start of loop, count=%d, in_num_sect=%d, " - "out_num_sect=%d\n", dd_count, in_num_sect, out_num_sect); - if (dd_count <= 0) { - fprintf(stderr, "Couldn't calculate count, please give one\n"); - return 1; - } - - rcoll.in_count = dd_count; - rcoll.in_done_count = dd_count; - rcoll.skip = skip; - rcoll.in_blk = skip; - rcoll.out_count = dd_count; - rcoll.out_done_count = dd_count; - rcoll.seek = seek; - rcoll.out_blk = seek; - - if ((FT_SG == rcoll.in_type) || (FT_SG == rcoll.out_type)) - rcoll.num_rq_elems = num_threads; - else - rcoll.num_rq_elems = 1; - if (prepare_rq_elems(&rcoll, inf, outf)) { - fprintf(stderr, "Setup failure, perhaps no memory\n"); - return 1; - } - - first_xfer = 1; - stop_after_write = 0; - terminate = 0; - seek_skip = rcoll.seek - rcoll.skip; - if (do_time) { - start_tm.tv_sec = 0; - start_tm.tv_usec = 0; - gettimeofday(&start_tm, NULL); - } - while (rcoll.out_done_count > 0) { /* >>>>>>>>> main loop */ - req_index = -1; - qstate = decider(&rcoll, first_xfer, &req_index); - rep = (req_index < 0) ? NULL : (rcoll.req_arr + req_index); - switch (qstate) { - case QS_IDLE: - if ((NULL == rep) || (rcoll.in_count <= 0)) { - /* usleep(1000); */ - /* do_poll(&rcoll, 10, NULL); */ - /* do_poll(&rcoll, 0, NULL); */ - break; - } - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: non-sleeping QS_IDLE state, " - "req_index=%d\n", req_index); - if (first_xfer >= 2) - first_xfer = 0; - else if (1 == first_xfer) - ++first_xfer; - if (stop_after_write) { - terminate = 1; - break; - } - blocks = (rcoll.in_count > rcoll.bpt) ? rcoll.bpt : rcoll.in_count; - rep->wr = 0; - rep->blk = rcoll.in_blk; - rep->num_blks = blocks; - rcoll.in_blk += blocks; - rcoll.in_count -= blocks; - - if (FT_SG == rcoll.in_type) { - res = sg_start_io(rep); - if (0 != res) { - if (1 == res) - fprintf(stderr, "Out of memory starting sg io\n"); - terminate = 1; - } - } - else { - res = normal_in_operation(&rcoll, rep, blocks); - if (res < 0) - terminate = 1; - else if (res > 0) - stop_after_write = 1; - } - break; - case QS_IN_FINISHED: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_IN_FINISHED, " - "req_index=%d\n", req_index); - if ((rep->blk + seek_skip) != rcoll.out_blk) { - /* if write would be out of sequence then wait */ - if (rcoll.debug > 4) - fprintf(stderr, " sgq_dd: QS_IN_FINISHED, " - "out of sequence\n"); - usleep(200); - break; - } - rep->wr = 1; - rep->blk = rcoll.out_blk; - blocks = rep->num_blks; - rcoll.out_blk += blocks; - rcoll.out_count -= blocks; - - if (FT_SG == rcoll.out_type) { - res = sg_start_io(rep); - if (0 != res) { - if (1 == res) - fprintf(stderr, "Out of memory starting sg io\n"); - terminate = 1; - } - } - else { - if (normal_out_operation(&rcoll, rep, blocks) < 0) - terminate = 1; - } - break; - case QS_IN_POLL: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_IN_POLL, " - "req_index=%d\n", req_index); - res = sg_fin_in_operation(&rcoll, rep); - if (res < 0) - terminate = 1; - else if (res > 1) { - if (first_xfer) { - /* only retry on first xfer */ - if (0 != sg_start_io(rep)) - terminate = 1; - } - else - terminate = 1; - } - break; - case QS_OUT_POLL: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_OUT_POLL, " - "req_index=%d\n", req_index); - res = sg_fin_out_operation(&rcoll, rep); - if (res < 0) - terminate = 1; - else if (res > 1) { - if (first_xfer) { - /* only retry on first xfer */ - if (0 != sg_start_io(rep)) - terminate = 1; - } - else - terminate = 1; - } - break; - default: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is ?????\n"); - terminate = 1; - break; - } - if (terminate) - break; - } /* >>>>>>>>>>>>> end of main loop */ - - if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) { - struct timeval res_tm; - double a, b; - - gettimeofday(&end_tm, NULL); - res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec; - res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec; - if (res_tm.tv_usec < 0) { - --res_tm.tv_sec; - res_tm.tv_usec += 1000000; - } - a = res_tm.tv_sec; - a += (0.000001 * res_tm.tv_usec); - b = (double)rcoll.bs * (dd_count - rcoll.out_done_count); - printf("time to transfer data was %d.%06d secs", - (int)res_tm.tv_sec, (int)res_tm.tv_usec); - if ((a > 0.00001) && (b > 511)) - printf(", %.2f MB/sec\n", b / (a * 1000000.0)); - else - printf("\n"); - } - - if (STDIN_FILENO != rcoll.infd) - close(rcoll.infd); - if (STDOUT_FILENO != rcoll.outfd) - close(rcoll.outfd); - res = 0; - if (0 != rcoll.out_count) { - fprintf(stderr, ">>>> Some error occurred,\n"); - res = 2; - } - print_stats(); - if (rcoll.dio_incomplete) { - int fd; - char c; - - fprintf(stderr, ">> Direct IO requested but incomplete %d times\n", - rcoll.dio_incomplete); - if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) { - if (1 == read(fd, &c, 1)) { - if ('0' == c) - fprintf(stderr, ">>> %s set to '0' but should be set " - "to '1' for direct IO\n", proc_allow_dio); - } - close(fd); - } - } - if (rcoll.sum_of_resids) - fprintf(stderr, ">> Non-zero sum of residual counts=%d\n", - rcoll.sum_of_resids); - return res; -} diff --git a/archive/sgq_dd.c.orig b/archive/sgq_dd.c.orig deleted file mode 100644 index c55280ea..00000000 --- a/archive/sgq_dd.c.orig +++ /dev/null @@ -1,1139 +0,0 @@ -#define _XOPEN_SOURCE 500 - -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <sys/poll.h> -#include <linux/major.h> -#include <sys/time.h> -typedef unsigned char u_char; /* horrible, for scsi.h */ -#include "sg_lib.h" -#include "sg_linux_inc.h" -#include "llseek.h" - -/* A utility program for the Linux OS SCSI generic ("sg") device driver. -* Copyright (C) 1999-2002 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device or a raw - device. A block size ('bs') is assumed to be 512 if not given. This - program complains if 'ibs' or 'obs' are given with some other value - than 'bs'. If 'if' is not given or 'if=-' then stdin is assumed. If - 'of' is not given or 'of=-' then stdout assumed. Multipliers: - 'c','C' *1 'b','B' *512 'k' *1024 'K' *1000 - 'm' *(1024^2) 'M' *(1000^2) 'g' *(1024^3) 'G' *(1000^3) - - A non-standard argument "bpt" (blocks per transfer) is added to control - the maximum number of blocks in each transfer. The default value is 128. - For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB - in this case) are transferred to or from the sg device in a single SCSI - command. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . This version uses posix threads. - -*/ - -static char * version_str = "0.54 20020223"; - -#define DEF_BLOCK_SIZE 512 -#define DEF_BLOCKS_PER_TRANSFER 128 - -/* #define SG_DEBUG */ - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */ -#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */ - -#define SGP_READ10 0x28 -#define SGP_WRITE10 0x2a -#define DEF_NUM_THREADS 4 /* actually degree of concurrency */ -#define MAX_NUM_THREADS 32 - -#ifndef RAW_MAJOR -#define RAW_MAJOR 255 /*unlikey value */ -#endif - -#define FT_OTHER 0 /* filetype other than sg or raw device */ -#define FT_SG 1 /* filetype is sg char device */ -#define FT_RAW 2 /* filetype is raw char device */ - -#define QS_IDLE 0 /* ready to start a copy cycle */ -#define QS_IN_STARTED 1 /* commenced read */ -#define QS_IN_FINISHED 2 /* finished read, ready for write */ -#define QS_OUT_STARTED 3 /* commenced write */ - -#define QS_IN_POLL 11 -#define QS_OUT_POLL 12 - -#define STR_SZ 1024 -#define INOUTF_SZ 512 -#define EBUFF_SZ 512 - - -struct request_element; - -typedef struct request_collection -{ /* one instance visible to all threads */ - int infd; - int skip; - int in_type; - int in_scsi_type; - int in_blk; /* next block address to read */ - int in_count; /* blocks remaining for next read */ - int in_done_count; /* count of completed in blocks */ - int in_partial; - int outfd; - int seek; - int out_type; - int out_scsi_type; - int out_blk; /* next block address to write */ - int out_count; /* blocks remaining for next write */ - int out_done_count; /* count of completed out blocks */ - int out_partial; - int bs; - int bpt; - int dio; - int dio_incomplete; - int sum_of_resids; - int coe; - int debug; - int num_rq_elems; - struct request_element * req_arr; -} Rq_coll; - -typedef struct request_element -{ /* one instance per worker thread */ - int qstate; /* "QS" state */ - int infd; - int outfd; - int wr; - int blk; - int num_blks; - unsigned char * buffp; - unsigned char * alloc_bp; - sg_io_hdr_t io_hdr; - unsigned char cmd[S_RW_LEN]; - unsigned char sb[SENSE_BUFF_LEN]; - int bs; - int dio; - int dio_incomplete; - int resid; - int in_scsi_type; - int out_scsi_type; - int debug; -} Rq_elem; - -static Rq_coll rcoll; -static struct pollfd in_pollfd_arr[MAX_NUM_THREADS]; -static struct pollfd out_pollfd_arr[MAX_NUM_THREADS]; -static int dd_count = -1; - -static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio"; - -int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep); -int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep); -int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks); -int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks); -int sg_start_io(Rq_elem * rep); -int sg_finish_io(int wr, Rq_elem * rep); - - -static void install_handler (int sig_num, void (*sig_handler) (int sig)) -{ - struct sigaction sigact; - sigaction (sig_num, NULL, &sigact); - if (sigact.sa_handler != SIG_IGN) - { - sigact.sa_handler = sig_handler; - sigemptyset (&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction (sig_num, &sigact, NULL); - } -} - -void print_stats() -{ - int infull, outfull; - - if (0 != rcoll.out_count) - fprintf(stderr, " remaining block count=%d\n", rcoll.out_count); - infull = dd_count - rcoll.in_done_count - rcoll.in_partial; - fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial); - outfull = dd_count - rcoll.out_done_count - rcoll.out_partial; - fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial); -} - -static void interrupt_handler(int sig) -{ - struct sigaction sigact; - - sigact.sa_handler = SIG_DFL; - sigemptyset (&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction (sig, &sigact, NULL); - fprintf(stderr, "Interrupted by signal,"); - print_stats (); - kill (getpid (), sig); -} - -static void siginfo_handler(int sig) -{ - fprintf(stderr, "Progress report, continuing ...\n"); - print_stats (); -} - -int dd_filetype(const char * filename) -{ - struct stat st; - - if (stat(filename, &st) < 0) - return FT_OTHER; - if (S_ISCHR(st.st_mode)) { - if (RAW_MAJOR == major(st.st_rdev)) - return FT_RAW; - else if (SCSI_GENERIC_MAJOR == major(st.st_rdev)) - return FT_SG; - } - return FT_OTHER; -} - -void usage() -{ - fprintf(stderr, "Usage: " - "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>] " - "[bs=<num>]\n" - " [bpt=<num>] [count=<n>] [dio=<n>] [thr=<n>] " - "[coe=<n>] [gen=<n>]\n" - " [dio=<n>] [thr=<n>] [coe=<n>] [gen=<n>] " - "[deb=<n>] [--version]\n" - " usually either 'if' or 'of' is a sg or raw device\n" - " 'bpt' is blocks_per_transfer (default is 128)\n" - " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n" - " 'thr' is number of queues, must be > 0, default 4, max 32\n"); - fprintf(stderr, " 'coe' continue on sg error, 0->exit (def), " - "1->zero + continue\n" - " 'gen' 0-> 1 file is special(def), 1-> any files allowed\n" - " 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n"); -} - -/* Returns -1 for error, 0 for nothing found, QS_IN_POLL or QS_OUT_POLL */ -int do_poll(Rq_coll * clp, int timeout, int * req_indexp) -{ - int k, res; - - if (FT_SG == clp->out_type) { - while (((res = poll(out_pollfd_arr, clp->num_rq_elems, timeout)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - perror("poll error on output fds"); - return -1; - } - else if (res > 0) { - for (k = 0; k < clp->num_rq_elems; ++k) { - if (out_pollfd_arr[k].revents & POLLIN) { - if (req_indexp) - *req_indexp = k; - return QS_OUT_POLL; - } - } - } - } - if (FT_SG == clp->in_type) { - while (((res = poll(in_pollfd_arr, clp->num_rq_elems, timeout)) < 0) - && (EINTR == errno)) - ; - if (res < 0) { - perror("poll error on input fds"); - return -1; - } - else if (res > 0) { - for (k = 0; k < clp->num_rq_elems; ++k) { - if (in_pollfd_arr[k].revents & POLLIN) { - if (req_indexp) - *req_indexp = k; - return QS_IN_POLL; - } - } - } - } - return 0; -} - - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_ERR_CAT_MEDIA_CHANGED == res) - return 2; /* probably have another go ... */ - else if (SG_ERR_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -#ifdef SG_DEBUG - fprintf(stderr, "number of sectors=%d, sector size=%d\n", - *num_sect, *sect_sz); -#endif - return 0; -} - -/* 0 -> ok, 1 -> short read, -1 -> error */ -int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks) -{ - int res; - int stop_after_write = 0; - - rep->qstate = QS_IN_STARTED; - if (rep->debug > 8) - fprintf(stderr, "normal_in_operation: start blk=%d num_blks=%d\n", - rep->blk, rep->num_blks); - while (((res = read(rep->infd, rep->buffp, - blocks * rep->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - fprintf(stderr, "sgq_dd: reading, in_blk=%d, errno=%d\n", rep->blk, - errno); - return -1; - } - if (res < blocks * rep->bs) { - int o_blocks = blocks; - stop_after_write = 1; - blocks = res / rep->bs; - if ((res % rep->bs) > 0) { - blocks++; - clp->in_partial++; - } - /* Reverse out + re-apply blocks on clp */ - clp->in_blk -= o_blocks; - clp->in_count += o_blocks; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - } - clp->in_done_count -= blocks; - rep->qstate = QS_IN_FINISHED; - return stop_after_write; -} - -/* 0 -> ok, -1 -> error */ -int normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks) -{ - int res; - - rep->qstate = QS_OUT_STARTED; - if (rep->debug > 8) - fprintf(stderr, "normal_out_operation: start blk=%d num_blks=%d\n", - rep->blk, rep->num_blks); - while (((res = write(rep->outfd, rep->buffp, - rep->num_blks * rep->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - fprintf(stderr, "sgq_dd: output, out_blk=%d, errno=%d\n", rep->blk, - errno); - return -1; - } - if (res < blocks * rep->bs) { - blocks = res / rep->bs; - if ((res % rep->bs) > 0) { - blocks++; - clp->out_partial++; - } - rep->num_blks = blocks; - } - clp->out_done_count -= blocks; - rep->qstate = QS_IDLE; - return 0; -} - -/* Returns 1 for retryable, 0 for ok, -ve for error */ -int sg_fin_in_operation(Rq_coll * clp, Rq_elem * rep) -{ - int res; - - rep->qstate = QS_IN_FINISHED; - res = sg_finish_io(rep->wr, rep); - if (res < 0) { - if (clp->coe) { - memset(rep->buffp, 0, rep->num_blks * rep->bs); - fprintf(stderr, ">> substituted zeros for in blk=%d for " - "%d bytes\n", rep->blk, rep->num_blks * rep->bs); - res = 0; - } - else { - fprintf(stderr, "error finishing sg in command\n"); - return res; - } - } - if (0 == res) { /* looks good, going to return */ - if (rep->dio_incomplete || rep->resid) { - clp->dio_incomplete += rep->dio_incomplete; - clp->sum_of_resids += rep->resid; - } - clp->in_done_count -= rep->num_blks; - } - return res; -} - -/* Returns 1 for retryable, 0 for ok, -ve for error */ -int sg_fin_out_operation(Rq_coll * clp, Rq_elem * rep) -{ - int res; - - rep->qstate = QS_IDLE; - res = sg_finish_io(rep->wr, rep); - if (res < 0) { - if (clp->coe) { - fprintf(stderr, ">> ignored error for out blk=%d for " - "%d bytes\n", rep->blk, rep->num_blks * rep->bs); - res = 0; - } - else { - fprintf(stderr, "error finishing sg out command\n"); - return res; - } - } - if (0 == res) { - if (rep->dio_incomplete || rep->resid) { - clp->dio_incomplete += rep->dio_incomplete; - clp->sum_of_resids += rep->resid; - } - clp->out_done_count -= rep->num_blks; - } - return res; -} - -int sg_start_io(Rq_elem * rep) -{ - sg_io_hdr_t * hp = &rep->io_hdr; - int res; - - rep->qstate = rep->wr ? QS_OUT_STARTED : QS_IN_STARTED; - memset(rep->cmd, 0, sizeof(rep->cmd)); - rep->cmd[0] = rep->wr ? SGP_WRITE10 : SGP_READ10; - rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF); - rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF); - rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF); - rep->cmd[5] = (unsigned char)(rep->blk & 0xFF); - rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff); - rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff); - memset(hp, 0, sizeof(sg_io_hdr_t)); - hp->interface_id = 'S'; - hp->cmd_len = sizeof(rep->cmd); - hp->cmdp = rep->cmd; - hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - hp->dxfer_len = rep->bs * rep->num_blks; - hp->dxferp = rep->buffp; - hp->mx_sb_len = sizeof(rep->sb); - hp->sbp = rep->sb; - hp->timeout = DEF_TIMEOUT; - hp->usr_ptr = rep; - hp->pack_id = rep->blk; - if (rep->dio) - hp->flags |= SG_FLAG_DIRECT_IO; - if (rep->debug > 8) { - fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n", - rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks); - sg_print_command(hp->cmdp); - fprintf(stderr, "dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n", - hp->dxfer_direction, hp->dxfer_len, hp->dxferp, hp->cmd_len); - } - - while (((res = write(rep->wr ? rep->outfd : rep->infd, hp, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - return res; - } - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */ -int sg_finish_io(int wr, Rq_elem * rep) -{ - int res; - sg_io_hdr_t io_hdr; - sg_io_hdr_t * hp; -#if 0 - static int testing = 0; /* thread dubious! */ -#endif - - memset(&io_hdr, 0 , sizeof(sg_io_hdr_t)); - /* FORCE_PACK_ID active set only read packet with matching pack_id */ - io_hdr.interface_id = 'S'; - io_hdr.dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - io_hdr.pack_id = rep->blk; - - while (((res = read(wr ? rep->outfd : rep->infd, &io_hdr, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - perror("finishing io on sg device, error"); - return -1; - } - if (rep != (Rq_elem *)io_hdr.usr_ptr) { - fprintf(stderr, - "sg_finish_io: bad usr_ptr, request-response mismatch\n"); - exit(1); - } - memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t)); - hp = &rep->io_hdr; - - switch (sg_err_category3(hp)) { - case SG_ERR_CAT_CLEAN: - break; - case SG_ERR_CAT_RECOVERED: - fprintf(stderr, "Recovered error on block=%d, num=%d\n", - rep->blk, rep->num_blks); - break; - case SG_ERR_CAT_MEDIA_CHANGED: - return 1; - default: - { - char ebuff[EBUFF_SZ]; - snprintf(ebuff, EBUFF_SZ, "%s blk=%d", - rep->wr ? "writing": "reading", rep->blk); - sg_chk_n_print3(ebuff, hp); - return -1; - } - } -#if 0 - if (0 == (++testing % 100)) return -1; -#endif - if (rep->dio && - ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - rep->dio_incomplete = 1; /* count dios done as indirect IO */ - else - rep->dio_incomplete = 0; - rep->resid = hp->resid; - if (rep->debug > 8) - fprintf(stderr, "sg_finish_io: completed %s\n", wr ? "WRITE" : "READ"); - return 0; -} - -/* Returns scsi_type or -1 for error */ -int sg_prepare(int fd, int sz) -{ - int res, t; - struct sg_scsi_id info; - - res = ioctl(fd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - fprintf(stderr, "sgq_dd: sg driver prior to 3.x.y\n"); - return -1; - } - res = ioctl(fd, SG_SET_RESERVED_SIZE, &sz); - if (res < 0) - perror("sgq_dd: SG_SET_RESERVED_SIZE error"); -#if 0 - t = 1; - res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t); - if (res < 0) - perror("sgq_dd: SG_SET_FORCE_PACK_ID error"); -#endif - res = ioctl(fd, SG_GET_SCSI_ID, &info); - if (res < 0) { - perror("sgq_dd: SG_SET_SCSI_ID error"); - return -1; - } - else - return info.scsi_type; -} - -/* Return 0 for ok, anything else for errors */ -int prepare_rq_elems(Rq_coll * clp, const char * inf, const char * outf) -{ - int k; - Rq_elem * rep; - size_t psz; - char ebuff[EBUFF_SZ]; - int sz = clp->bpt * clp->bs; - int scsi_type; - - clp->req_arr = malloc(sizeof(Rq_elem) * clp->num_rq_elems); - if (NULL == clp->req_arr) - return 1; - for (k = 0; k < clp->num_rq_elems; ++k) { - rep = &clp->req_arr[k]; - memset(rep, 0, sizeof(Rq_elem)); - psz = getpagesize(); - if (NULL == (rep->alloc_bp = malloc(sz + psz))) - return 1; - rep->buffp = (unsigned char *) - (((unsigned long)rep->alloc_bp + psz - 1) & (~(psz - 1))); - rep->qstate = QS_IDLE; - rep->bs = clp->bs; - rep->dio = clp->dio; - rep->debug = clp->debug; - rep->out_scsi_type = clp->out_scsi_type; - if (FT_SG == clp->in_type) { - if (0 == k) - rep->infd = clp->infd; - else { - if ((rep->infd = open(inf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg reading", inf); - perror(ebuff); - return 1; - } - } - in_pollfd_arr[k].fd = rep->infd; - in_pollfd_arr[k].events = POLLIN; - if ((scsi_type = sg_prepare(rep->infd, sz)) < 0) - return 1; - if (0 == k) - clp->in_scsi_type = scsi_type; - rep->in_scsi_type = clp->in_scsi_type; - } - else - rep->infd = clp->infd; - - if (FT_SG == clp->out_type) { - if (0 == k) - rep->outfd = clp->outfd; - else { - if ((rep->outfd = open(outf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg writing", outf); - perror(ebuff); - return 1; - } - } - out_pollfd_arr[k].fd = rep->outfd; - out_pollfd_arr[k].events = POLLIN; - if ((scsi_type = sg_prepare(rep->outfd, sz)) < 0) - return 1; - if (0 == k) - clp->out_scsi_type = scsi_type; - rep->out_scsi_type = clp->out_scsi_type; - } - else - rep->outfd = clp->outfd; - } - return 0; -} - -/* Returns a "QS" code and req index, or QS_IDLE and position of first idle - (-1 if no idle position). Returns -1 on poll error. */ -int decider(Rq_coll * clp, int first_xfer, int * req_indexp) -{ - int k, res; - Rq_elem * rep; - int first_idle_index = -1; - int lowest_blk_index = -1; - int times; - int try_poll = 0; - int lowest_blk = INT_MAX; - - times = first_xfer ? 1 : clp->num_rq_elems; - for (k = 0; k < times; ++k) { - rep = &clp->req_arr[k]; - if ((QS_IN_STARTED == rep->qstate) || - (QS_OUT_STARTED == rep->qstate)) - try_poll = 1; - else if ((QS_IN_FINISHED == rep->qstate) && (rep->blk < lowest_blk)) { - lowest_blk = rep->blk; - lowest_blk_index = k; - } - else if ((QS_IDLE == rep->qstate) && (first_idle_index < 0)) - first_idle_index = k; - } - if (try_poll) { - res = do_poll(clp, 0, req_indexp); - if (0 != res) - return res; - } - - if (lowest_blk_index >= 0) { - if (req_indexp) - *req_indexp = lowest_blk_index; - return QS_IN_FINISHED; - } - if (req_indexp) - *req_indexp = first_idle_index; - return QS_IDLE; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int ibs = 0; - int obs = 0; - char str[STR_SZ]; - char * key; - char * buf; - char inf[INOUTF_SZ]; - char outf[INOUTF_SZ]; - int res, k; - int in_num_sect = 0; - int out_num_sect = 0; - int num_threads = DEF_NUM_THREADS; - int gen = 0; - int do_time = 0; - int in_sect_sz, out_sect_sz, first_xfer, qstate, req_index, seek_skip; - int blocks, stop_after_write, terminate; - char ebuff[EBUFF_SZ]; - Rq_elem * rep; - struct timeval start_tm, end_tm; - - memset(&rcoll, 0, sizeof(Rq_coll)); - rcoll.bpt = DEF_BLOCKS_PER_TRANSFER; - rcoll.in_type = FT_OTHER; - rcoll.out_type = FT_OTHER; - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strncpy(str, argv[k], STR_SZ); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strncpy(inf, buf, INOUTF_SZ); - else if (strcmp(key,"of") == 0) - strncpy(outf, buf, INOUTF_SZ); - else if (0 == strcmp(key,"ibs")) - ibs = sg_get_num(buf); - else if (0 == strcmp(key,"obs")) - obs = sg_get_num(buf); - else if (0 == strcmp(key,"bs")) - rcoll.bs = sg_get_num(buf); - else if (0 == strcmp(key,"bpt")) - rcoll.bpt = sg_get_num(buf); - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - dd_count = sg_get_num(buf); - else if (0 == strcmp(key,"dio")) - rcoll.dio = sg_get_num(buf); - else if (0 == strcmp(key,"thr")) - num_threads = sg_get_num(buf); - else if (0 == strcmp(key,"coe")) - rcoll.coe = sg_get_num(buf); - else if (0 == strcmp(key,"gen")) - gen = sg_get_num(buf); - else if (0 == strncmp(key,"deb", 3)) - rcoll.debug = sg_get_num(buf); - else if (0 == strcmp(key,"time")) - do_time = sg_get_num(buf); - else if (0 == strncmp(key, "--vers", 6)) { - fprintf(stderr, "sgq_dd for sg version 3 driver: %s\n", - version_str); - return 0; - } - else { - fprintf(stderr, "Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (rcoll.bs <= 0) { - rcoll.bs = DEF_BLOCK_SIZE; - fprintf(stderr, "Assume default 'bs' (block size) of %d bytes\n", - rcoll.bs); - } - if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) { - fprintf(stderr, "If 'ibs' or 'obs' given must be same as 'bs'\n"); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - fprintf(stderr, "skip and seek cannot be negative\n"); - return 1; - } - if ((num_threads < 1) || (num_threads > MAX_NUM_THREADS)) { - fprintf(stderr, "too few or too many threads requested\n"); - usage(); - return 1; - } - if (rcoll.debug) - fprintf(stderr, "sgq_dd: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, dd_count); - install_handler (SIGINT, interrupt_handler); - install_handler (SIGQUIT, interrupt_handler); - install_handler (SIGPIPE, interrupt_handler); - install_handler (SIGUSR1, siginfo_handler); - - rcoll.infd = STDIN_FILENO; - rcoll.outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - rcoll.in_type = dd_filetype(inf); - - if (FT_SG == rcoll.in_type) { - if ((rcoll.infd = open(inf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg reading", inf); - perror(ebuff); - return 1; - } - } - if (FT_SG != rcoll.in_type) { - if ((rcoll.infd = open(inf, O_RDONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - else if (skip > 0) { - llse_loff_t offset = skip; - - offset *= rcoll.bs; /* could exceed 32 here! */ - if (llse_llseek(rcoll.infd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - } - if (outf[0] && ('-' != outf[0])) { - rcoll.out_type = dd_filetype(outf); - - if (FT_SG == rcoll.out_type) { - if ((rcoll.outfd = open(outf, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for sg writing", outf); - perror(ebuff); - return 1; - } - } - else { - if (FT_OTHER == rcoll.out_type) { - if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - } - else { - if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: could not open %s for raw writing", outf); - perror(ebuff); - return 1; - } - } - if (seek > 0) { - llse_loff_t offset = seek; - - offset *= rcoll.bs; /* could exceed 32 bits here! */ - if (llse_llseek(rcoll.outfd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgq_dd: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) { - fprintf(stderr, "Disallow both if and of to be stdin and stdout"); - return 1; - } - if ((FT_OTHER == rcoll.in_type) && (FT_OTHER == rcoll.out_type) && !gen) { - fprintf(stderr, "Either 'if' or 'of' must be a sg or raw device\n"); - return 1; - } - if (0 == dd_count) - return 0; - else if (dd_count < 0) { - if (FT_SG == rcoll.in_type) { - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - fprintf(stderr, "Unit attention, media changed(in), repeat\n"); - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - fprintf(stderr, "Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (FT_SG == rcoll.out_type) { - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - fprintf(stderr, "Unit attention, media changed(out), repeat\n"); - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - fprintf(stderr, "Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } - if (in_num_sect > 0) { - if (out_num_sect > 0) - dd_count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - dd_count = in_num_sect; - } - else - dd_count = out_num_sect; - } - if (rcoll.debug > 1) - fprintf(stderr, "Start of loop, count=%d, in_num_sect=%d, " - "out_num_sect=%d\n", dd_count, in_num_sect, out_num_sect); - if (dd_count <= 0) { - fprintf(stderr, "Couldn't calculate count, please give one\n"); - return 1; - } - - rcoll.in_count = dd_count; - rcoll.in_done_count = dd_count; - rcoll.skip = skip; - rcoll.in_blk = skip; - rcoll.out_count = dd_count; - rcoll.out_done_count = dd_count; - rcoll.seek = seek; - rcoll.out_blk = seek; - - if ((FT_SG == rcoll.in_type) || (FT_SG == rcoll.out_type)) - rcoll.num_rq_elems = num_threads; - else - rcoll.num_rq_elems = 1; - if (prepare_rq_elems(&rcoll, inf, outf)) { - fprintf(stderr, "Setup failure, perhaps no memory\n"); - return 1; - } - - first_xfer = 1; - stop_after_write = 0; - terminate = 0; - seek_skip = rcoll.seek - rcoll.skip; - if (do_time) { - start_tm.tv_sec = 0; - start_tm.tv_usec = 0; - gettimeofday(&start_tm, NULL); - } - while (rcoll.out_done_count > 0) { /* >>>>>>>>> main loop */ - req_index = -1; - qstate = decider(&rcoll, first_xfer, &req_index); - rep = (req_index < 0) ? NULL : (rcoll.req_arr + req_index); - switch (qstate) { - case QS_IDLE: - if ((NULL == rep) || (rcoll.in_count <= 0)) { - /* usleep(1000); */ - do_poll(&rcoll, 10, NULL); - break; - } - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: non-sleeping QS_IDLE state, " - "req_index=%d\n", req_index); - if (first_xfer >= 2) - first_xfer = 0; - else if (1 == first_xfer) - ++first_xfer; - if (stop_after_write) { - terminate = 1; - break; - } - blocks = (rcoll.in_count > rcoll.bpt) ? rcoll.bpt : rcoll.in_count; - rep->wr = 0; - rep->blk = rcoll.in_blk; - rep->num_blks = blocks; - rcoll.in_blk += blocks; - rcoll.in_count -= blocks; - - if (FT_SG == rcoll.in_type) { - res = sg_start_io(rep); - if (0 != res) { - if (1 == res) - fprintf(stderr, "Out of memory starting sg io\n"); - terminate = 1; - } - } - else { - res = normal_in_operation(&rcoll, rep, blocks); - if (res < 0) - terminate = 1; - else if (res > 0) - stop_after_write = 1; - } - break; - case QS_IN_FINISHED: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_IN_FINISHED, " - "req_index=%d\n", req_index); - if ((rep->blk + seek_skip) != rcoll.out_blk) { - /* if write would be out of sequence then wait */ - usleep(1000); - break; - } - rep->wr = 1; - rep->blk = rcoll.out_blk; - blocks = rep->num_blks; - rcoll.out_blk += blocks; - rcoll.out_count -= blocks; - - if (FT_SG == rcoll.out_type) { - res = sg_start_io(rep); - if (0 != res) { - if (1 == res) - fprintf(stderr, "Out of memory starting sg io\n"); - terminate = 1; - } - } - else { - if (normal_out_operation(&rcoll, rep, blocks) < 0) - terminate = 1; - } - break; - case QS_IN_POLL: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_IN_POLL, " - "req_index=%d\n", req_index); - res = sg_fin_in_operation(&rcoll, rep); - if (res < 0) - terminate = 1; - else if (res > 1) { - if (first_xfer) { - /* only retry on first xfer */ - if (0 != sg_start_io(rep)) - terminate = 1; - } - else - terminate = 1; - } - break; - case QS_OUT_POLL: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is QS_OUT_POLL, " - "req_index=%d\n", req_index); - res = sg_fin_out_operation(&rcoll, rep); - if (res < 0) - terminate = 1; - else if (res > 1) { - if (first_xfer) { - /* only retry on first xfer */ - if (0 != sg_start_io(rep)) - terminate = 1; - } - else - terminate = 1; - } - break; - default: - if (rcoll.debug > 8) - fprintf(stderr, " sgq_dd: state is ?????\n"); - terminate = 1; - break; - } - if (terminate) - break; - } /* >>>>>>>>>>>>> end of main loop */ - - if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) { - struct timeval res_tm; - double a, b; - - gettimeofday(&end_tm, NULL); - res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec; - res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec; - if (res_tm.tv_usec < 0) { - --res_tm.tv_sec; - res_tm.tv_usec += 1000000; - } - a = res_tm.tv_sec; - a += (0.000001 * res_tm.tv_usec); - b = (double)rcoll.bs * (dd_count - rcoll.out_done_count); - printf("time to transfer data was %d.%06d secs", - (int)res_tm.tv_sec, (int)res_tm.tv_usec); - if ((a > 0.00001) && (b > 511)) - printf(", %.2f MB/sec\n", b / (a * 1000000.0)); - else - printf("\n"); - } - - if (STDIN_FILENO != rcoll.infd) - close(rcoll.infd); - if (STDOUT_FILENO != rcoll.outfd) - close(rcoll.outfd); - res = 0; - if (0 != rcoll.out_count) { - fprintf(stderr, ">>>> Some error occurred,\n"); - res = 2; - } - print_stats(); - if (rcoll.dio_incomplete) { - int fd; - char c; - - fprintf(stderr, ">> Direct IO requested but incomplete %d times\n", - rcoll.dio_incomplete); - if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) { - if (1 == read(fd, &c, 1)) { - if ('0' == c) - fprintf(stderr, ">>> %s set to '0' but should be set " - "to '1' for direct IO\n", proc_allow_dio); - } - close(fd); - } - } - if (rcoll.sum_of_resids) - fprintf(stderr, ">> Non-zero sum of residual counts=%d\n", - rcoll.sum_of_resids); - return res; -} diff --git a/archive/sgq_old_dd.c b/archive/sgq_old_dd.c deleted file mode 100644 index 66c149b3..00000000 --- a/archive/sgq_old_dd.c +++ /dev/null @@ -1,838 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <poll.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* A utility program for the Linux OS SCSI generic ("sg") device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. A block size - ('bs') is assumed to be 512 if not given. This program complains if - 'ibs' or 'obs' are given with some other value than 'bs'. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given of 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - - A non-standard argument "bpt" (blocks per transfer) is added to control - the maximum number of blocks in each transfer. The default value is 128. - For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB - in this case) are transferred to or from the sg device in a single SCSI - command. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . This version uses usleep() for a delay loop. - - Version 3.982 20000827 -*/ - -#define DEF_BLOCK_SIZE 512 -#define DEF_BLOCKS_PER_TRANSFER 128 - -/* #define SG_DEBUG */ - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ -#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */ -#define RCAP_REPLY_LEN 8 -#define SGQ_MAX_RD_AHEAD 4 -#define SGQ_MAX_WR_AHEAD 4 -#define SGQ_NUM_ELEMS (SGQ_MAX_RD_AHEAD+ SGQ_MAX_WR_AHEAD + 1) - -#define SGQ_FREE 0 -#define SGQ_IO_STARTED 1 -#define SGQ_IO_FINISHED 2 -#define SGQ_IO_ERR 3 -#define SGQ_IO_WAIT 4 - -#define SGQ_CAN_DO_NOTHING 0 /* only temporarily in use */ -#define SGQ_CAN_READ 1 -#define SGQ_CAN_WRITE 2 -#define SGQ_TIMEOUT 4 - -typedef struct request_element -{ - struct request_element * nextp; - int state; - int wr; - int blk; - int num_blks; - unsigned char * buffp; - unsigned char * alloc_bp; - sg_io_hdr_t io_hdr; - unsigned char cmd[S_RW_LEN]; - unsigned char sb[SENSE_BUFF_LEN]; - int result; - int stop_after_wr; -} Rq_elem; - -typedef struct request_collection -{ - int infd; - int in_is_sg; - int in_blk; /* next block address to read */ - int in_count; /* blocks remaining for next read */ - int in_done_count; /* count of completed in blocks */ - int in_partial; - int outfd; - int out_is_sg; - int lowest_seek; - int out_blk; /* next block address to write */ - int out_count; /* blocks remaining for next write */ - int out_done_count; /* count of completed out blocks */ - int out_partial; - int bs; - int bpt; - int dio; - int dio_incomplete; - int sum_of_resids; - int debug; - Rq_elem * rd_posp; - Rq_elem * wr_posp; - Rq_elem elem[SGQ_NUM_ELEMS]; -} Rq_coll; - - -void usage() -{ - printf("Usage: " - "sgq_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [bs=<num>] [bpt=<num>] [count=<n>]" - " [dio=<n>] [deb=<n>]\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'bpt' is blocks_per_transfer (default is 128)\n" - " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n" - " 'deb' is debug, 1->output some, 0->no debug (def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = RCAP_REPLY_LEN; - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -#ifdef SG_DEBUG - printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); -#endif - return 0; -} - -/* -ve -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM) */ -int sg_start_io(Rq_coll * clp, Rq_elem * rep) -{ - sg_io_hdr_t * hp = &rep->io_hdr; - int res; -#if 0 - static int testing = 0; -#endif - - memset(rep->cmd, 0, sizeof(rep->cmd)); - rep->cmd[0] = rep->wr ? 0x2a : 0x28; - rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF); - rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF); - rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF); - rep->cmd[5] = (unsigned char)(rep->blk & 0xFF); - rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff); - rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff); - memset(hp, 0, sizeof(sg_io_hdr_t)); - hp->interface_id = 'S'; - hp->cmd_len = sizeof(rep->cmd); - hp->cmdp = rep->cmd; - hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - hp->dxfer_len = clp->bs * rep->num_blks; - hp->dxferp = rep->buffp; - hp->mx_sb_len = sizeof(rep->sb); - hp->sbp = rep->sb; - hp->timeout = DEF_TIMEOUT; - hp->usr_ptr = rep; - hp->pack_id = rep->blk; - if (clp->dio) - hp->flags |= SG_FLAG_DIRECT_IO; -#ifdef SG_DEBUG - printf("sg_start_io: SCSI %s, blk=%d num_blks=%d\n", - rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks); - sg_print_command(hp->cmdp); - printf("dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n", hp->dxfer_direction, - hp->dxfer_len, hp->dxferp, hp->cmd_len); -#endif - -#if 0 - testing++; - if (0 == (testing % 10)) { - rep->state = SGQ_IO_WAIT; /* busy so wait */ - return 0; - } -#endif - - while (((res = write(rep->wr ? clp->outfd : clp->infd, hp, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - if ((EDOM == errno) || (EAGAIN == errno)) { - rep->state = SGQ_IO_WAIT; /* busy so wait */ - return 0; - } - perror("starting io on sg device, error"); - rep->state = SGQ_IO_ERR; - return res; - } - rep->state = SGQ_IO_STARTED; - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */ -int sg_finish_io(Rq_coll * clp, int wr, Rq_elem ** repp) -{ - int res; - sg_io_hdr_t io_hdr; - sg_io_hdr_t * hp; - Rq_elem * rep; - - memset(&io_hdr, 0 , sizeof(sg_io_hdr_t)); - while (((res = read(wr ? clp->outfd : clp->infd, &io_hdr, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - rep = (Rq_elem *)io_hdr.usr_ptr; - if (res < 0) { - perror("finishing io on sg device, error"); - rep->state = SGQ_IO_ERR; - return -1; - } - if (! (rep && (SGQ_IO_STARTED == rep->state))) { - printf("sg_finish_io: bad usr_ptr\n"); - rep->state = SGQ_IO_ERR; - return -1; - } - memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t)); - hp = &rep->io_hdr; - if (repp) - *repp = rep; - - switch (sg_err_category3(hp)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error on block=%d, num=%d\n", - rep->blk, rep->num_blks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 1; - default: - sg_chk_n_print3(rep->wr ? "writing": "reading", hp); - rep->state = SGQ_IO_ERR; - return -1; - } - if (clp->dio && - ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - ++clp->dio_incomplete; /* count dios done as indirect IO */ - clp->sum_of_resids += hp->resid; - rep->state = SGQ_IO_FINISHED; -#ifdef SG_DEBUG - printf("sg_finish_io: %s ", wr ? "writing" : "reading"); - printf(" SGQ_IO_FINISHED elem idx=%d\n", rep - clp->elem); -#endif - return 0; -} - -int sz_reserve(int fd, int bs, int bpt) -{ - int res, t; - - res = ioctl(fd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sgq_dd: sg driver prior to 3.x.y\n"); - return 1; - } - res = 0; - t = bs * bpt; - res = ioctl(fd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sgq_dd: SG_SET_RESERVED_SIZE error"); - return 0; -} - -void init_elems(Rq_coll * clp) -{ - Rq_elem * rep; - int k; - int off = 0; - int sz = clp->bpt * clp->bs; - - if (clp->dio) { - off = getpagesize(); - sz += off; - } - clp->wr_posp = &clp->elem[0]; /* making ring buffer */ - clp->rd_posp = clp->wr_posp; - for (k = 0; k < SGQ_NUM_ELEMS - 1; ++k) - clp->elem[k].nextp = &clp->elem[k + 1]; - clp->elem[SGQ_NUM_ELEMS - 1].nextp = &clp->elem[0]; - for (k = 0; k < SGQ_NUM_ELEMS; ++k) { - rep = &clp->elem[k]; - rep->state = SGQ_FREE; - if (NULL == (rep->alloc_bp = malloc(sz))) { - printf("out of memory creating user buffers\n"); - exit(1); - } - else - rep->buffp = rep->alloc_bp + off; - } -} - -int start_read(Rq_coll * clp) -{ - int blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count; - Rq_elem * rep = clp->rd_posp; - int buf_sz, res; - char ebuff[256]; - -#ifdef SG_DEBUG - printf("start_read, elem idx=%d\n", rep - clp->elem); -#endif - rep->wr = 0; - rep->blk = clp->in_blk; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - if (clp->in_is_sg) { - res = sg_start_io(clp, rep); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if ((res = ioctl(clp->infd, SG_GET_RESERVED_SIZE, &buf_sz)) < 0) { - perror("RESERVED_SIZE ioctls failed"); - return res; - } - clp->bpt = (buf_sz + clp->bs - 1) / clp->bs; - printf("Reducing blocks per transfer to %d\n", clp->bpt); - if (clp->bpt < 1) - return -ENOMEM; - res = sg_start_io(clp, rep); - if (1 == res) - res = -ENOMEM; - } - else if (res < 0) { - printf("sgq_dd inputting from sg failed, blk=%d\n", rep->blk); - rep->state = SGQ_IO_ERR; - return res; - } - } - else { - rep->state = SGQ_IO_STARTED; - while (((res = read(clp->infd, rep->buffp, blocks * clp->bs)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sgq_dd: reading, in_blk=%d ", rep->blk); - perror(ebuff); - rep->state = SGQ_IO_ERR; - return res; - } - if (res < blocks * clp->bs) { - int o_blocks = blocks; - rep->stop_after_wr = 1; - blocks = res / clp->bs; - if ((res % clp->bs) > 0) { - blocks++; - clp->in_partial++; - } - /* Reverse out + re-apply blocks on clp */ - clp->in_blk -= o_blocks; - clp->in_count += o_blocks; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - } - clp->in_done_count -= blocks; - rep->state = SGQ_IO_FINISHED; - } - clp->rd_posp = rep->nextp; - return blocks; -} - -int start_write(Rq_coll * clp) -{ - Rq_elem * rep = clp->wr_posp; - int res, blocks; - char ebuff[256]; - - while ((0 != rep->wr) || (SGQ_IO_FINISHED != rep->state)) { - rep = rep->nextp; - if (rep == clp->rd_posp) - return -1; - } -#ifdef SG_DEBUG - printf("start_write, elem idx=%d\n", rep - clp->elem); -#endif - rep->wr = 1; - blocks = rep->num_blks; - rep->blk = clp->out_blk; - clp->out_blk += blocks; - clp->out_count -= blocks; - if (clp->out_is_sg) { - res = sg_start_io(clp, rep); - if (1 == res) /* ENOMEM, give up */ - return -ENOMEM; - else if (res < 0) { - printf("sgq_dd output to sg failed, blk=%d\n", rep->blk); - rep->state = SGQ_IO_ERR; - return res; - } - } - else { - rep->state = SGQ_IO_STARTED; - while (((res = write(clp->outfd, rep->buffp, - rep->num_blks * clp->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - sprintf(ebuff, "sgq_dd: output, out_blk=%d ", rep->blk); - perror(ebuff); - rep->state = SGQ_IO_ERR; - return res; - } - if (res < blocks * clp->bs) { - blocks = res / clp->bs; - if ((res % clp->bs) > 0) { - blocks++; - clp->out_partial++; - } - rep->num_blks = blocks; - } - rep->state = SGQ_IO_FINISHED; - } - return blocks; -} - -int do_poll(int fd) -{ - struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0}; - - a_pollfd.fd = fd; - if (poll(&a_pollfd, 1, 0) < 0) { - perror("poll error"); - return 0; - } - /* printf("do_poll: revents=0x%x\n", (int)a_pollfd.revents); */ - return (a_pollfd.revents & POLLIN) ? 1 : 0; -} - -int can_read_write(Rq_coll * clp) -{ - Rq_elem * rep = NULL; - int res = 0; - int reading = 0; - int writing = 0; - int writeable = 0; - int rd_waiting = 0; - int wr_waiting = 0; - int sg_finished = 0; - - /* if write completion pending, then complete it + start read */ - if (clp->out_is_sg) { - while ((res = do_poll(clp->outfd))) { - if (res < 0) - return res; - res = sg_finish_io(clp, 1, &rep); - if (res < 0) - return res; - else if (1 == res) { - res = sg_start_io(clp, rep); - if (0 != res) - return -1; /* give up if any problems with retry */ - } - else - sg_finished++; - } - while ((rep = clp->wr_posp) && (SGQ_IO_FINISHED == rep->state) && - (1 == rep->wr) && (rep != clp->rd_posp)) { - rep->state = SGQ_FREE; - clp->out_done_count -= rep->num_blks; - clp->wr_posp = rep->nextp; - if (rep->stop_after_wr) - return -1; - } - } - else if ((rep = clp->wr_posp) && (1 == rep->wr) && - (SGQ_IO_FINISHED == rep->state)) { - rep->state = SGQ_FREE; - clp->out_done_count -= rep->num_blks; - clp->wr_posp = rep->nextp; - if (rep->stop_after_wr) - return -1; - } - - /* if read completion pending, then complete it + start maybe write */ - if (clp->in_is_sg) { - while ((res = do_poll(clp->infd))) { - if (res < 0) - return res; - res = sg_finish_io(clp, 0, &rep); - if (res < 0) - return res; - if (1 == res) { - res = sg_start_io(clp, rep); - if (0 != res) - return -1; /* give up if any problems with retry */ - } - else { - sg_finished++; - clp->in_done_count -= rep->num_blks; - } - } - } - - for (rep = clp->wr_posp, res = 1; - rep != clp->rd_posp; rep = rep->nextp) { - if (SGQ_IO_STARTED == rep->state) { - if (rep->wr) - ++writing; - else { - res = 0; - ++reading; - } - } - else if ((0 == rep->wr) && (SGQ_IO_FINISHED == rep->state)) { - if (res) - writeable = 1; - } - else if (SGQ_IO_WAIT == rep->state) { - res = 0; - if (rep->wr) - ++wr_waiting; - else - ++rd_waiting; - } - else - res = 0; - } - if (clp->debug) { - if ((clp->debug >= 9) || wr_waiting || rd_waiting) - printf("%d/%d (nwb/nrb): read=%d/%d (do/wt) " - "write=%d/%d (do/wt) writeable=%d sg_fin=%d\n", - clp->out_blk, clp->in_blk, reading, rd_waiting, - writing, wr_waiting, writeable, sg_finished); - } - if (writeable && (writing < SGQ_MAX_WR_AHEAD) && (clp->out_count > 0)) - return SGQ_CAN_WRITE; - if ((reading < SGQ_MAX_RD_AHEAD) && (clp->in_count > 0) && - (0 == rd_waiting) && (clp->rd_posp->nextp != clp->wr_posp)) - return SGQ_CAN_READ; - - if (clp->out_done_count <= 0) - return SGQ_CAN_DO_NOTHING; - - usleep(3000); /* hang about for 10 milliseconds */ - /* Now check the _whole_ buffer for pending requests */ - for (rep = clp->rd_posp->nextp; rep != clp->rd_posp; rep = rep->nextp) { - if (SGQ_IO_WAIT == rep->state) { - res = sg_start_io(clp, rep); - if (res < 0) - return res; - if (res > 0) - return -1; - break; - } - } - return SGQ_CAN_DO_NOTHING; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int ibs = 0; - int obs = 0; - int count = -1; - char str[512]; - char * key; - char * buf; - char inf[512]; - char outf[512]; - int res, k; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz, crw; - char ebuff[256]; - Rq_coll rcoll; - - memset(&rcoll, 0, sizeof(Rq_coll)); - rcoll.bpt = DEF_BLOCKS_PER_TRANSFER; - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) - strcpy(str, argv[k]); - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strcpy(inf, buf); - else if (strcmp(key,"of") == 0) - strcpy(outf, buf); - else if (0 == strcmp(key,"ibs")) - ibs = sg_get_num(buf); - else if (0 == strcmp(key,"obs")) - obs = sg_get_num(buf); - else if (0 == strcmp(key,"bs")) - rcoll.bs = sg_get_num(buf); - else if (0 == strcmp(key,"bpt")) - rcoll.bpt = sg_get_num(buf); - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"dio")) - rcoll.dio = sg_get_num(buf); - else if (0 == strcmp(key,"deb")) - rcoll.debug = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (rcoll.bs <= 0) { - rcoll.bs = DEF_BLOCK_SIZE; - printf("Assume default 'bs' (block size) of %d bytes\n", rcoll.bs); - } - if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) { - printf("If 'ibs' or 'obs' given must be same as 'bs'\n"); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sgq_dd: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - rcoll.infd = STDIN_FILENO; - rcoll.outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((rcoll.infd = open(inf, O_RDONLY)) < 0) { - sprintf(ebuff, "sgq_dd: could not open %s for reading", inf); - perror(ebuff); - return 1; - } - if (ioctl(rcoll.infd, SG_GET_TIMEOUT, 0) < 0) { - rcoll.in_is_sg = 0; - if (skip > 0) { - off_t offset = skip; - - offset *= rcoll.bs; /* could overflow here! */ - if (lseek(rcoll.infd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sgq_dd: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - else { /* looks like sg device so close then re-open it RW */ - close(rcoll.infd); - if ((rcoll.infd = open(inf, O_RDWR | O_NONBLOCK)) < 0) { - printf("If %s is a sg device, need read+write permissions," - " even to read it!\n", inf); - return 1; - } - rcoll.in_is_sg = 1; - if (sz_reserve(rcoll.infd, rcoll.bs, rcoll.bpt)) - return 1; - } - } - if (outf[0] && ('-' != outf[0])) { - if ((rcoll.outfd = open(outf, O_RDWR | O_NONBLOCK)) >= 0) { - if (ioctl(rcoll.outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(rcoll.outfd); - } - else { - rcoll.out_is_sg = 1; - if (sz_reserve(rcoll.outfd, rcoll.bs, rcoll.bpt)) - return 1; - } - } - if (! rcoll.out_is_sg) { - if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - sprintf(ebuff, - "sgq_dd: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= rcoll.bs; /* could overflow here! */ - if (lseek(rcoll.outfd, offset, SEEK_SET) < 0) { - sprintf(ebuff, - "sgq_dd: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } - if (! (rcoll.in_is_sg || rcoll.out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } - if (0 == count) - return 0; - else if (count < 0) { - if (rcoll.in_is_sg) { - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (rcoll.out_is_sg) { - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } -#ifdef SG_DEBUG - printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n", - count, in_num_sect, out_num_sect); -#endif - if (in_num_sect > 0) { - if (out_num_sect > 0) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - -#ifdef SG_DEBUG - printf("Start of loop, count=%d, bpt=%d\n", count, rcoll.bpt); -#endif - - rcoll.in_count = count; - rcoll.in_done_count = count; - rcoll.in_blk = skip; - rcoll.out_count = count; - rcoll.out_done_count = count; - rcoll.out_blk = seek; - init_elems(&rcoll); - -/* vvvvvvvvvvvvvvvvv Main Loop vvvvvvvvvvvvvvvvvvvvvvvv */ - while (rcoll.out_done_count > 0) { - crw = can_read_write(&rcoll); - if (crw < 0) - break; - if (SGQ_CAN_READ & crw) { - res = start_read(&rcoll); - if (res <= 0) { - printf("start_read: res=%d\n", res); - break; - } - } - if (SGQ_CAN_WRITE & crw) { - res = start_write(&rcoll); - if (res <= 0) { - printf("start_write: res=%d\n", res); - break; - } - } - } - - if (STDIN_FILENO != rcoll.infd) - close(rcoll.infd); - if (STDOUT_FILENO != rcoll.outfd) - close(rcoll.outfd); - if (0 != rcoll.out_count) { - printf("Some error occurred, remaining blocks=%d\n", rcoll.out_count); - return 1; - } - printf("%d+%d records in\n", count - rcoll.in_done_count, - rcoll.in_partial); - printf("%d+%d records out\n", count - rcoll.out_done_count, - rcoll.out_partial); - if (rcoll.dio_incomplete) - printf(">> Direct IO requested but incomplete %d times\n", - rcoll.dio_incomplete); - if (rcoll.sum_of_resids) - printf(">> Non-zero sum of residual counts=%d\n", - rcoll.sum_of_resids); - return 0; -} diff --git a/archive/sgs_dd.c b/archive/sgs_dd.c deleted file mode 100644 index fa34d7b1..00000000 --- a/archive/sgs_dd.c +++ /dev/null @@ -1,893 +0,0 @@ -/* We need F_SETSIG, (signal redirect), so following define */ -#define _GNU_SOURCE 1 - -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include "sg_lib.h" -#include "sg_linux_inc.h" - -/* Test code for the extensions to the Linux OS SCSI generic ("sg") - device driver. -* Copyright (C) 1999 D. Gilbert and P. Allworth -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - This program is a specialization of the Unix "dd" command in which - one or both of the given files is a scsi generic device. A block size - ('bs') is assumed to be 512 if not given. This program complains if - 'ibs' or 'obs' are given with some other value than 'bs'. - If 'if' is not given or 'if=-' then stdin is assumed. If 'of' is - not given of 'of=-' then stdout assumed. The multipliers "c, b, k, m" - are recognized on numeric arguments. - - A non-standard argument "bpt" (blocks per transfer) is added to control - the maximum number of blocks in each transfer. The default value is 128. - For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB - in this case) are transferred to or from the sg device in a single SCSI - command. - - BEWARE: If the 'of' file is a 'sg' device (eg a disk) then it _will_ - be written to, potentially destroying its previous contents. - - This version should compile with Linux sg drivers with version numbers - >= 30000 . Also this version tries to use real time signals. - - Version 3.99 20020126 - - -6 byte commands [READ: 0x08, WRITE: 0x0a]: -[cmd ][had|lu][midAdd][lowAdd][count ][flags ] -10 byte commands [EREAD: 0x28, EWRITE: 0x2a, READ_CAPACITY 0x25]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][ ][hiCnt ][lowCnt][flags ] -12 byte commands [LREAD: 0xd8, LWRITE: 0xda]: -[cmd ][ |lu][hiAddr][hmAddr][lmAddr][lowAdd][hiCnt ][hmCnt ][lmCnt ][lowCnt] - ... [ ][flags ] -*/ - -#define DEF_BLOCK_SIZE 512 -#define DEF_BLOCKS_PER_TRANSFER 128 - -/* #define SG_DEBUG */ - -#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */ -#define DEF_TIMEOUT 40000 /* 40,000 millisecs == 40 seconds */ -#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */ -#define SGQ_MAX_RD_AHEAD 4 -#define SGQ_MAX_WR_AHEAD 4 -#define SGQ_NUM_ELEMS (SGQ_MAX_RD_AHEAD+ SGQ_MAX_WR_AHEAD + 1) - -#define SGQ_FREE 0 -#define SGQ_IO_STARTED 1 -#define SGQ_IO_FINISHED 2 -#define SGQ_IO_ERR 3 -#define SGQ_IO_WAIT 4 - -#define SGQ_CAN_DO_NOTHING 0 /* only temporarily in use */ -#define SGQ_CAN_READ 1 -#define SGQ_CAN_WRITE 2 -#define SGQ_TIMEOUT 4 - - -#define STR_SZ 1024 -#define INOUTF_SZ 512 -#define EBUFF_SZ 512 - - -typedef struct request_element -{ - struct request_element * nextp; - int state; - int wr; - int blk; - int num_blks; - unsigned char * buffp; - sg_io_hdr_t io_hdr; - unsigned char cmd[S_RW_LEN]; - unsigned char sb[SENSE_BUFF_LEN]; - int result; - int stop_after_wr; -} Rq_elem; - -typedef struct request_collection -{ - int infd; - int in_is_sg; - int in_blk; /* most recent read */ - int in_count; /* most recent read */ - int in_done_count; /* count of completed in blocks */ - int in_partial; - int outfd; - int out_is_sg; - int lowest_seek; - int out_blk; /* most recent write */ - int out_count; /* most recent write */ - int out_done_count; /* count of completed out blocks */ - int out_partial; - int bs; - int bpt; - int dio; - int dio_incomplete; - int sum_of_resids; - int debug; - sigset_t blocked_sigs; - int sigs_waiting; - Rq_elem * rd_posp; - Rq_elem * wr_posp; - Rq_elem elem[SGQ_NUM_ELEMS]; -} Rq_coll; - - -void usage() -{ - printf("Usage: " - "sgs_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n" - " [bs=<num>] [bpt=<num>] [count=<n>]" - " [dio=<n>] [deb=<n>]\n" - " either 'if' or 'of' must be a scsi generic device\n" - " 'bpt' is blocks_per_transfer (default is 128)\n" - " 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n" - " 'deb' is debug, 1->output some, 0->no debug (def)\n"); -} - -/* Return of 0 -> success, -1 -> failure, 2 -> try again */ -int read_capacity(int sg_fd, int * num_sect, int * sect_sz) -{ - int res; - unsigned char rcCmdBlk [10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char rcBuff[64]; - unsigned char sense_b[64]; - sg_io_hdr_t io_hdr; - - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(rcCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_b); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = sizeof(rcBuff); - io_hdr.dxferp = rcBuff; - io_hdr.cmdp = rcCmdBlk; - io_hdr.sbp = sense_b; - io_hdr.timeout = DEF_TIMEOUT; - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("read_capacity (SG_IO) error"); - return -1; - } - res = sg_err_category3(&io_hdr); - if (SG_LIB_CAT_UNIT_ATTENTION == res) - return 2; /* probably have another go ... */ - else if (SG_LIB_CAT_CLEAN != res) { - sg_chk_n_print3("read capacity", &io_hdr); - return -1; - } - *num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) | - (rcBuff[2] << 8) | rcBuff[3]); - *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) | - (rcBuff[6] << 8) | rcBuff[7]; -#ifdef SG_DEBUG - printf("number of sectors=%d, sector size=%d\n", *num_sect, *sect_sz); -#endif - return 0; -} - -/* -ve -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM) */ -int sg_start_io(Rq_coll * clp, Rq_elem * rep) -{ - sg_io_hdr_t * hp = &rep->io_hdr; - int res; - - memset(rep->cmd, 0, sizeof(rep->cmd)); - rep->cmd[0] = rep->wr ? 0x2a : 0x28; - rep->cmd[2] = (unsigned char)((rep->blk >> 24) & 0xFF); - rep->cmd[3] = (unsigned char)((rep->blk >> 16) & 0xFF); - rep->cmd[4] = (unsigned char)((rep->blk >> 8) & 0xFF); - rep->cmd[5] = (unsigned char)(rep->blk & 0xFF); - rep->cmd[7] = (unsigned char)((rep->num_blks >> 8) & 0xff); - rep->cmd[8] = (unsigned char)(rep->num_blks & 0xff); - memset(hp, 0, sizeof(sg_io_hdr_t)); - hp->interface_id = 'S'; - hp->cmd_len = sizeof(rep->cmd); - hp->cmdp = rep->cmd; - hp->dxfer_direction = rep->wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV; - hp->dxfer_len = clp->bs * rep->num_blks; - hp->dxferp = rep->buffp; - hp->mx_sb_len = sizeof(rep->sb); - hp->sbp = rep->sb; - hp->timeout = DEF_TIMEOUT; - hp->usr_ptr = rep; - hp->pack_id = rep->blk; - if (clp->dio) - hp->flags |= SG_FLAG_DIRECT_IO; -#ifdef SG_DEBUG - printf("sg_start_io: SCSI %s, blk=%d num_blks=%d\n", - rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks); - sg_print_command(hp->cmdp); - printf("dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n", hp->dxfer_direction, - hp->dxfer_len, hp->dxferp, hp->cmd_len); -#endif - - while (((res = write(rep->wr ? clp->outfd : clp->infd, hp, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - if (res < 0) { - if (ENOMEM == errno) - return 1; - if ((EDOM == errno) || (EAGAIN == errno)) { - rep->state = SGQ_IO_WAIT; /* busy so wait */ - return 0; - } - perror("starting io on sg device, error"); - rep->state = SGQ_IO_ERR; - return res; - } - rep->state = SGQ_IO_STARTED; - clp->sigs_waiting++; - return 0; -} - -/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */ -int sg_finish_io(Rq_coll * clp, int wr, Rq_elem ** repp) -{ - int res; - sg_io_hdr_t io_hdr; - sg_io_hdr_t * hp; - Rq_elem * rep; - - memset(&io_hdr, 0 , sizeof(sg_io_hdr_t)); - while (((res = read(wr ? clp->outfd : clp->infd, &io_hdr, - sizeof(sg_io_hdr_t))) < 0) && (EINTR == errno)) - ; - rep = (Rq_elem *)io_hdr.usr_ptr; - if (res < 0) { - perror("finishing io on sg device, error"); - rep->state = SGQ_IO_ERR; - return -1; - } - if (! (rep && (SGQ_IO_STARTED == rep->state))) { - printf("sg_finish_io: bad usr_ptr\n"); - rep->state = SGQ_IO_ERR; - return -1; - } - memcpy(&rep->io_hdr, &io_hdr, sizeof(sg_io_hdr_t)); - hp = &rep->io_hdr; - if (repp) - *repp = rep; - - switch (sg_err_category3(hp)) { - case SG_LIB_CAT_CLEAN: - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error on block=%d, num=%d\n", - rep->blk, rep->num_blks); - break; - case SG_LIB_CAT_UNIT_ATTENTION: - return 1; - default: - sg_chk_n_print3(rep->wr ? "writing": "reading", hp); - rep->state = SGQ_IO_ERR; - return -1; - } - if (clp->dio && - ((hp->info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO)) - ++clp->dio_incomplete; /* count dios done as indirect IO */ - clp->sum_of_resids += hp->resid; - rep->state = SGQ_IO_FINISHED; -#ifdef SG_DEBUG - printf("sg_finish_io: %s ", wr ? "writing" : "reading"); - printf(" SGQ_IO_FINISHED elem idx=%d\n", rep - clp->elem); -#endif - return 0; -} - -int sz_reserve(int fd, int bs, int bpt) -{ - int res, t, flags; - - res = ioctl(fd, SG_GET_VERSION_NUM, &t); - if ((res < 0) || (t < 30000)) { - printf("sgs_dd: sg driver prior to 3.x.y\n"); - return 1; - } - res = 0; - t = bs * bpt; - res = ioctl(fd, SG_SET_RESERVED_SIZE, &t); - if (res < 0) - perror("sgs_dd: SG_SET_RESERVED_SIZE error"); - if (-1 == fcntl(fd, F_SETOWN, getpid())) { - perror("fcntl(,F_SETOWN,)"); - return 1; - } - flags = fcntl(fd, F_GETFL, 0); - if (-1 == fcntl(fd, F_SETFL, flags | O_ASYNC)) { - perror("fcntl(,F_SETFL,)"); - return 1; - } - fcntl(fd, F_SETSIG, SIGRTMIN + 1); - return 0; -} - -void init_elems(Rq_coll * clp) -{ - Rq_elem * rep; - int k; - - clp->wr_posp = &clp->elem[0]; /* making ring buffer */ - clp->rd_posp = clp->wr_posp; - for (k = 0; k < SGQ_NUM_ELEMS - 1; ++k) - clp->elem[k].nextp = &clp->elem[k + 1]; - clp->elem[SGQ_NUM_ELEMS - 1].nextp = &clp->elem[0]; - for (k = 0; k < SGQ_NUM_ELEMS; ++k) { - rep = &clp->elem[k]; - rep->state = SGQ_FREE; - if (NULL == (rep->buffp = malloc(clp->bpt * clp->bs))) - printf("out of memory creating user buffers\n"); - } -} - -int start_read(Rq_coll * clp) -{ - int blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count; - Rq_elem * rep = clp->rd_posp; - int buf_sz, res; - char ebuff[EBUFF_SZ]; - -#ifdef SG_DEBUG - printf("start_read, elem idx=%d\n", rep - clp->elem); -#endif - rep->wr = 0; - rep->blk = clp->in_blk; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - if (clp->in_is_sg) { - res = sg_start_io(clp, rep); - if (1 == res) { /* ENOMEM, find what's available+try that */ - if ((res = ioctl(clp->infd, SG_GET_RESERVED_SIZE, &buf_sz)) < 0) { - perror("RESERVED_SIZE ioctls failed"); - return res; - } - clp->bpt = (buf_sz + clp->bs - 1) / clp->bs; - printf("Reducing blocks per transfer to %d\n", clp->bpt); - if (clp->bpt < 1) - return -ENOMEM; - res = sg_start_io(clp, rep); - if (1 == res) - res = -ENOMEM; - } - else if (res < 0) { - printf("sgs_dd inputting from sg failed, blk=%d\n", rep->blk); - rep->state = SGQ_IO_ERR; - return res; - } - } - else { - rep->state = SGQ_IO_STARTED; - while (((res = read(clp->infd, rep->buffp, blocks * clp->bs)) < 0) && - (EINTR == errno)) - ; - if (res < 0) { - snprintf(ebuff, EBUFF_SZ, "sgs_dd: reading, in_blk=%d ", rep->blk); - perror(ebuff); - rep->state = SGQ_IO_ERR; - return res; - } - if (res < blocks * clp->bs) { - int o_blocks = blocks; - rep->stop_after_wr = 1; - blocks = res / clp->bs; - if ((res % clp->bs) > 0) { - blocks++; - clp->in_partial++; - } - /* Reverse out + re-apply blocks on clp */ - clp->in_blk -= o_blocks; - clp->in_count += o_blocks; - rep->num_blks = blocks; - clp->in_blk += blocks; - clp->in_count -= blocks; - } - clp->in_done_count -= blocks; - rep->state = SGQ_IO_FINISHED; - } - clp->rd_posp = rep->nextp; - return blocks; -} - -int start_write(Rq_coll * clp) -{ - Rq_elem * rep = clp->wr_posp; - int res, blocks; - char ebuff[EBUFF_SZ]; - - while ((0 != rep->wr) || (SGQ_IO_FINISHED != rep->state)) { - rep = rep->nextp; - if (rep == clp->rd_posp) - return -1; - } -#ifdef SG_DEBUG - printf("start_write, elem idx=%d\n", rep - clp->elem); -#endif - rep->wr = 1; - blocks = rep->num_blks; - rep->blk = clp->out_blk; - clp->out_blk += blocks; - clp->out_count -= blocks; - if (clp->out_is_sg) { - res = sg_start_io(clp, rep); - if (1 == res) /* ENOMEM, give up */ - return -ENOMEM; - else if (res < 0) { - printf("sgs_dd output to sg failed, blk=%d\n", rep->blk); - rep->state = SGQ_IO_ERR; - return res; - } - } - else { - rep->state = SGQ_IO_STARTED; - while (((res = write(clp->outfd, rep->buffp, - rep->num_blks * clp->bs)) < 0) && (EINTR == errno)) - ; - if (res < 0) { - snprintf(ebuff, EBUFF_SZ, "sgs_dd: output, out_blk=%d ", rep->blk); - perror(ebuff); - rep->state = SGQ_IO_ERR; - return res; - } - if (res < blocks * clp->bs) { - blocks = res / clp->bs; - if ((res % clp->bs) > 0) { - blocks++; - clp->out_partial++; - } - rep->num_blks = blocks; - } - rep->state = SGQ_IO_FINISHED; - } - return blocks; -} - -int do_poll(Rq_coll * clp, int fd) -{ - struct pollfd a_pollfd = {0, POLLIN | POLLOUT, 0}; - siginfo_t info; - - a_pollfd.fd = fd; - if (poll(&a_pollfd, 1, 0) < 0) { - perror("poll error"); - return 0; - } - /* printf("do_poll: revents=0x%x\n", (int)a_pollfd.revents); */ - if (a_pollfd.revents & POLLIN) { - if (clp->sigs_waiting) { - while (sigwaitinfo(&clp->blocked_sigs, &info) < 0) { - if (EINTR != errno) { - perror("sigwaitinfo"); /* consume signal */ - return -1; - } - } - if ((SIGRTMIN + 1) == info.si_signo) - clp->sigs_waiting--; - if (SIGIO == info.si_signo) { - printf("SIGIO received, continue\n"); - clp->sigs_waiting = 0; - } - else - return -1; - } - return 1; - } - else - return 0; -} - -int can_read_write(Rq_coll * clp) -{ - Rq_elem * rep = NULL; - int res = 0; - int reading = 0; - int writing = 0; - int writeable = 0; - int rd_waiting = 0; - int wr_waiting = 0; - int sg_finished = 0; - siginfo_t info; - - /* if write completion pending, then complete it + start read */ - if (clp->out_is_sg) { - while ((res = do_poll(clp, clp->outfd))) { - if (res < 0) - return res; - res = sg_finish_io(clp, 1, &rep); - if (res < 0) - return res; - else if (1 == res) { - res = sg_start_io(clp, rep); - if (0 != res) - return -1; /* give up if any problems with retry */ - } - else - sg_finished++; - } - while ((rep = clp->wr_posp) && (SGQ_IO_FINISHED == rep->state) && - (1 == rep->wr) && (rep != clp->rd_posp)) { - rep->state = SGQ_FREE; - clp->out_done_count -= rep->num_blks; - clp->wr_posp = rep->nextp; - if (rep->stop_after_wr) - return -1; - } - } - else if ((rep = clp->wr_posp) && (1 == rep->wr) && - (SGQ_IO_FINISHED == rep->state)) { - rep->state = SGQ_FREE; - clp->out_done_count -= rep->num_blks; - clp->wr_posp = rep->nextp; - if (rep->stop_after_wr) - return -1; - } - - /* if read completion pending, then complete it + start maybe write */ - if (clp->in_is_sg) { - while ((res = do_poll(clp, clp->infd))) { - if (res < 0) - return res; - res = sg_finish_io(clp, 0, &rep); - if (res < 0) - return res; - if (1 == res) { - res = sg_start_io(clp, rep); - if (0 != res) - return -1; /* give up if any problems with retry */ - } - else { - sg_finished++; - clp->in_done_count -= rep->num_blks; - } - } - } - - for (rep = clp->wr_posp, res = 1; - rep != clp->rd_posp; rep = rep->nextp) { - if (SGQ_IO_STARTED == rep->state) { - if (rep->wr) - ++writing; - else { - res = 0; - ++reading; - } - } - else if ((0 == rep->wr) && (SGQ_IO_FINISHED == rep->state)) { - if (res) - writeable = 1; - } - else if (SGQ_IO_WAIT == rep->state) { - res = 0; - if (rep->wr) - ++wr_waiting; - else - ++rd_waiting; - } - else - res = 0; - } - if (clp->debug) { - if ((clp->debug >= 9) || wr_waiting || rd_waiting) - printf("%d/%d (nwb/nrb): read=%d/%d (do/wt) " - "write=%d/%d (do/wt) writeable=%d sg_fin=%d\n", - clp->out_blk, clp->in_blk, reading, rd_waiting, - writing, wr_waiting, writeable, sg_finished); - fflush(stdout); - } - if (writeable && (writing < SGQ_MAX_WR_AHEAD) && (clp->out_count > 0)) - return SGQ_CAN_WRITE; - if ((reading < SGQ_MAX_RD_AHEAD) && (clp->in_count > 0) && - (0 == rd_waiting) && (clp->rd_posp->nextp != clp->wr_posp)) - return SGQ_CAN_READ; - - if (clp->out_done_count <= 0) - return SGQ_CAN_DO_NOTHING; - - /* usleep(10000); */ /* hang about for 10 milliseconds */ - if (clp->sigs_waiting) { - while (sigwaitinfo(&clp->blocked_sigs, &info) < 0) { - if (EINTR != errno) { - perror("sigwaitinfo"); /* consume signal */ - return -1; - } - } - if ((SIGRTMIN + 1) != info.si_signo) - return -1; - clp->sigs_waiting--; - } - /* Now check the _whole_ buffer for pending requests */ - for (rep = clp->rd_posp->nextp; rep != clp->rd_posp; rep = rep->nextp) { - if (SGQ_IO_WAIT == rep->state) { - res = sg_start_io(clp, rep); - if (res < 0) - return res; - if (res > 0) - return -1; - break; - } - } - return SGQ_CAN_DO_NOTHING; -} - - -int main(int argc, char * argv[]) -{ - int skip = 0; - int seek = 0; - int ibs = 0; - int obs = 0; - int count = -1; - char str[STR_SZ]; - char * key; - char * buf; - char inf[INOUTF_SZ]; - char outf[INOUTF_SZ]; - int res, k; - int in_num_sect = 0; - int out_num_sect = 0; - int in_sect_sz, out_sect_sz, crw; - char ebuff[EBUFF_SZ]; - Rq_coll rcoll; - - memset(&rcoll, 0, sizeof(Rq_coll)); - rcoll.bpt = DEF_BLOCKS_PER_TRANSFER; - inf[0] = '\0'; - outf[0] = '\0'; - if (argc < 2) { - usage(); - return 1; - } - - for(k = 1; k < argc; k++) { - if (argv[k]) { - strncpy(str, argv[k], STR_SZ); - str[STR_SZ - 1] = '\0'; - } - else - continue; - for(key = str, buf = key; *buf && *buf != '=';) - buf++; - if (*buf) - *buf++ = '\0'; - if (strcmp(key,"if") == 0) - strncpy(inf, buf, INOUTF_SZ); - else if (strcmp(key,"of") == 0) - strncpy(outf, buf, INOUTF_SZ); - else if (0 == strcmp(key,"ibs")) - ibs = sg_get_num(buf); - else if (0 == strcmp(key,"obs")) - obs = sg_get_num(buf); - else if (0 == strcmp(key,"bs")) - rcoll.bs = sg_get_num(buf); - else if (0 == strcmp(key,"bpt")) - rcoll.bpt = sg_get_num(buf); - else if (0 == strcmp(key,"skip")) - skip = sg_get_num(buf); - else if (0 == strcmp(key,"seek")) - seek = sg_get_num(buf); - else if (0 == strcmp(key,"count")) - count = sg_get_num(buf); - else if (0 == strcmp(key,"dio")) - rcoll.dio = sg_get_num(buf); - else if (0 == strcmp(key,"deb")) - rcoll.debug = sg_get_num(buf); - else { - printf("Unrecognized argument '%s'\n", key); - usage(); - return 1; - } - } - if (rcoll.bs <= 0) { - rcoll.bs = DEF_BLOCK_SIZE; - printf("Assume default 'bs' (block size) of %d bytes\n", rcoll.bs); - } - if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) { - printf("If 'ibs' or 'obs' given must be same as 'bs'\n"); - usage(); - return 1; - } - if ((skip < 0) || (seek < 0)) { - printf("skip and seek cannot be negative\n"); - return 1; - } -#ifdef SG_DEBUG - printf("sgs_dd: if=%s skip=%d of=%s seek=%d count=%d\n", - inf, skip, outf, seek, count); -#endif - rcoll.infd = STDIN_FILENO; - rcoll.outfd = STDOUT_FILENO; - if (inf[0] && ('-' != inf[0])) { - if ((rcoll.infd = open(inf, O_RDONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, "sgs_dd: could not open %s for reading", - inf); - perror(ebuff); - return 1; - } - if (ioctl(rcoll.infd, SG_GET_TIMEOUT, 0) < 0) { - rcoll.in_is_sg = 0; - if (skip > 0) { - off_t offset = skip; - - offset *= rcoll.bs; /* could overflow here! */ - if (lseek(rcoll.infd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgs_dd: couldn't skip to required position on %s", inf); - perror(ebuff); - return 1; - } - } - } - else { /* looks like sg device so close then re-open it RW */ - close(rcoll.infd); - if ((rcoll.infd = open(inf, O_RDWR | O_NONBLOCK)) < 0) { - printf("If %s is a sg device, need read+write permissions," - " even to read it!\n", inf); - return 1; - } - rcoll.in_is_sg = 1; - if (sz_reserve(rcoll.infd, rcoll.bs, rcoll.bpt)) - return 1; - } - } - if (outf[0] && ('-' != outf[0])) { - if ((rcoll.outfd = open(outf, O_RDWR | O_NONBLOCK)) >= 0) { - if (ioctl(rcoll.outfd, SG_GET_TIMEOUT, 0) < 0) { - /* not a scsi generic device so now try and open RDONLY */ - close(rcoll.outfd); - } - else { - rcoll.out_is_sg = 1; - if (sz_reserve(rcoll.outfd, rcoll.bs, rcoll.bpt)) - return 1; - } - } - if (! rcoll.out_is_sg) { - if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgs_dd: could not open %s for writing", outf); - perror(ebuff); - return 1; - } - else if (seek > 0) { - off_t offset = seek; - - offset *= rcoll.bs; /* could overflow here! */ - if (lseek(rcoll.outfd, offset, SEEK_SET) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sgs_dd: couldn't seek to required position on %s", outf); - perror(ebuff); - return 1; - } - } - } - } - if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) { - printf("Can't have both 'if' as stdin _and_ 'of' as stdout\n"); - return 1; - } - if (! (rcoll.in_is_sg || rcoll.out_is_sg)) { - printf("Either 'if' or 'of' must be a scsi generic device\n"); - return 1; - } - if (0 == count) - return 0; - else if (count < 0) { - if (rcoll.in_is_sg) { - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(in), try again\n"); - res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", inf); - in_num_sect = -1; - } - else { - if (in_num_sect > skip) - in_num_sect -= skip; - } - } - if (rcoll.out_is_sg) { - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - if (2 == res) { - printf("Unit attention, media changed(out), try again\n"); - res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz); - } - if (0 != res) { - printf("Unable to read capacity on %s\n", outf); - out_num_sect = -1; - } - else { - if (out_num_sect > seek) - out_num_sect -= seek; - } - } -#ifdef SG_DEBUG - printf("Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n", - count, in_num_sect, out_num_sect); -#endif - if (in_num_sect > 0) { - if (out_num_sect > 0) - count = (in_num_sect > out_num_sect) ? out_num_sect : - in_num_sect; - else - count = in_num_sect; - } - else - count = out_num_sect; - } - -#ifdef SG_DEBUG - printf("Start of loop, count=%d, bpt=%d\n", count, rcoll.bpt); -#endif - - sigemptyset(&rcoll.blocked_sigs); - sigaddset(&rcoll.blocked_sigs, SIGRTMIN + 1); - sigaddset(&rcoll.blocked_sigs, SIGINT); - sigaddset(&rcoll.blocked_sigs, SIGIO); - sigprocmask(SIG_BLOCK, &rcoll.blocked_sigs, 0); - rcoll.in_count = count; - rcoll.in_done_count = count; - rcoll.in_blk = skip; - rcoll.out_count = count; - rcoll.out_done_count = count; - rcoll.out_blk = seek; - init_elems(&rcoll); - -/* vvvvvvvvvvvvvvvvv Main Loop vvvvvvvvvvvvvvvvvvvvvvvv */ - while (rcoll.out_done_count > 0) { - crw = can_read_write(&rcoll); - if (crw < 0) - break; - if (SGQ_CAN_READ & crw) { - res = start_read(&rcoll); - if (res <= 0) { - printf("start_read: res=%d\n", res); - break; - } - } - if (SGQ_CAN_WRITE & crw) { - res = start_write(&rcoll); - if (res <= 0) { - printf("start_write: res=%d\n", res); - break; - } - } - } - - if (STDIN_FILENO != rcoll.infd) - close(rcoll.infd); - if (STDOUT_FILENO != rcoll.outfd) - close(rcoll.outfd); - if (0 != rcoll.out_count) { - printf("Some error occurred, remaining blocks=%d\n", rcoll.out_count); - return 1; - } - printf("%d+%d records in\n", count - rcoll.in_done_count, - rcoll.in_partial); - printf("%d+%d records out\n", count - rcoll.out_done_count, - rcoll.out_partial); - if (rcoll.dio_incomplete) - printf(">> Direct IO requested but incomplete %d times\n", - rcoll.dio_incomplete); - if (rcoll.sum_of_resids) - printf(">> Non-zero sum of residual counts=%d\n", - rcoll.sum_of_resids); - return 0; -} |