aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2009-02-16 17:00:56 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2009-02-16 17:00:56 +0000
commitcdd183119bc2ee236b588d92789d69f4b7187770 (patch)
tree46debd5facd428353a97677bdc614fb63e0ebd18
parent5da81155e2db153d9c3a3c7385463b6b1fe2bc04 (diff)
downloadsg3_utils-cdd183119bc2ee236b588d92789d69f4b7187770.tar.gz
try separating some linux and win32 code and doco
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@214 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog3
-rw-r--r--doc/Makefile.am18
-rw-r--r--doc/sg_scan.8.linux (renamed from doc/sg_scan.8)0
-rw-r--r--doc/sg_scan.8.win32 (renamed from doc/sg_scan.8w)0
-rw-r--r--doc/sg_scan.8l71
-rw-r--r--src/Makefile.am18
-rw-r--r--src/sg_scan.c.linux612
-rw-r--r--src/sg_scan.c.win32 (renamed from src/sg_scan.c)620
8 files changed, 650 insertions, 692 deletions
diff --git a/ChangeLog b/ChangeLog
index b14e198d..904e289c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.27 [20090210] [svn: r213]
+Changelog for sg3_utils-1.27 [20090215] [svn: r214]
- sg_inq: sync version descriptors with spc4r17
- sg_map26: fix for lk 2.6.26 when CONFIG_SYSFS_DEPRECATED_V2
is not defined
@@ -25,6 +25,7 @@ Changelog for sg3_utils-1.27 [20090210] [svn: r213]
- add scsi_pt_version() and clear_scsi_pt_obj() calls
- clear os_err at start of do_scsi_pt()
- sg_cmds: add sg_cmds_open_device_flags() call previous entry
+ - clearer split between Linux and Windows only code and doc
- autotools infrastructure: changes after upgrade to Ubuntu 8.10
- autotools infrastructure: revert back to Debian 4.0
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 3fcd2d60..3db809c2 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -19,6 +19,12 @@ man_MANS = \
sg_ses.8 sg_start.8 sg_stpg.8 sg_sync.8 sg_test_rwbuf.8 sg_turs.8 \
sg_verify.8 sg_vpd.8 sg_write_buffer.8 sg_write_long.8 sg_wr_mode.8
+distclean-local:
+ rm -f sg_scan.8
+
+sg_scan.8 : sg_scan.8.linux
+ cp -p sg_scan.8.linux sg_scan.8
+
endif
@@ -36,6 +42,12 @@ man_MANS = \
sg_stpg.8 sg_sync.8 sg_turs.8 sg_verify.8 sg_vpd.8 sg_write_buffer.8 \
sg_write_long.8 sg_wr_mode.8
+distclean-local:
+ rm -f sg_scan.8
+
+sg_scan.8 : sg_scan.8.win32
+ cp -p sg_scan.8.win32 sg_scan.8
+
endif
@@ -53,6 +65,12 @@ man_MANS = \
sg_stpg.8 sg_sync.8 sg_turs.8 sg_verify.8 sg_vpd.8 sg_write_buffer.8 \
sg_write_long.8 sg_wr_mode.8
+distclean-local:
+ rm -f sg_scan.8
+
+sg_scan.8 : sg_scan.8.win32
+ cp -p sg_scan.8.win32 sg_scan.8
+
endif
diff --git a/doc/sg_scan.8 b/doc/sg_scan.8.linux
index fb600df0..fb600df0 100644
--- a/doc/sg_scan.8
+++ b/doc/sg_scan.8.linux
diff --git a/doc/sg_scan.8w b/doc/sg_scan.8.win32
index 1ce68e35..1ce68e35 100644
--- a/doc/sg_scan.8w
+++ b/doc/sg_scan.8.win32
diff --git a/doc/sg_scan.8l b/doc/sg_scan.8l
deleted file mode 100644
index 81da76c5..00000000
--- a/doc/sg_scan.8l
+++ /dev/null
@@ -1,71 +0,0 @@
-.TH SG_SCAN "8" "December 2006" "sg3_utils\-1.23" SG3_UTILS
-.SH NAME
-sg_scan \- does a scan of sg devices (or given SCSI/ATAPI/ATA devices) and
-prints the results
-.SH SYNOPSIS
-.B sg_scan
-[\fI\-a\fR]
-[\fI\-i\fR]
-[\fI\-n\fR]
-[\fI\-w\fR]
-[\fI\-x\fR]
-[\fIDEVICE\fR]*
-.SH DESCRIPTION
-.\" Add any additional description here
-.PP
-If no \fIDEVICE\fR names are given, sg_scan does a scan of the sg
-devices and outputs a line of information for each sg device that is
-currently bound to a SCSI device. If one or more \fIDEVICE\fRs are given
-only those devices are scanned.
-Each device is opened with the O_NONBLOCK flag so that the scan will
-not "hang" on any device that another process holds an O_EXCL lock on.
-.PP
-Any given \fIDEVICE\fR name is expected to comply
-with (to some extent) the Storage Architecture Model (SAM see www.t10.org).
-Any device names associated with the Linux SCSI subsystem (e.g. /dev/sda
-and /dev/st0m) are suitable. Devices names associated with ATAPI
-devices (e.g. most CD/DVD drives and ATAPI tape drives) are also suitable.
-If the device does not fall into the above categories then an ATA
-IDENTIFY command is tried.
-.SH OPTIONS
-.TP
-\fB\-a\fR
-do alphabetical scan (i.e. sga, sgb, sgc). Note that sg device nodes with
-an alphabetical index have been deprecated since the linux kernel 2.2
-series.
-.TP
-\fB\-i\fR
-do a SCSI INQUIRY, output results in a second (indented) line. If the device
-is an ATA disk then output information from an ATA IDENTIFY command
-.TP
-\fB\-n\fR
-do numeric scan (i.e. sg0, sg1...) [default]
-.TP
-\fB\-w\fR
-use a read/write flag when opening sg device (default is read\-only)
-.TP
-\fB\-x\fR
-extra information output about queuing
-.SH NOTES
-This utility was written at a time when hotplugging of SCSI devices
-was not supported in Linux. It used a simple algorithm to scan sg
-device nodes in ascending numeric or alphabetical order, stopping
-after there were 4 consecutive errors.
-.PP
-In the linux kernel 2.6 series, this utility uses sysfs to find which
-sg device nodes are active and only checks those. Hence there can be
-large "holes" in the numbering of sg device nodes (e.g. after an
-adapter has been removed) and still all active sg device nodes will
-be listed. This utility assumes that sg device nodes are named using
-the normal conventions and searches from /dev/sg0 to /dev/sg4095
-inclusive.
-.SH EXIT STATUS
-The exit status of sg_scan is 0 when it is successful. Otherwise see
-the sg3_utils(8) man page.
-.SH AUTHORS
-Written by D. Gilbert and F. Jansen
-.SH COPYRIGHT
-Copyright \(co 1999\-2006 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/src/Makefile.am b/src/Makefile.am
index d9fec972..6c47a36b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,12 @@ bin_PROGRAMS = \
sg_sync sg_test_rwbuf sg_turs sg_verify sg_vpd sg_write_buffer \
sg_write_long sg_wr_mode
+distclean-local:
+ rm -f sg_scan.c
+
+sg_scan.c : sg_scan.c.linux
+ cp sg_scan.c.linux sg_scan.c
+
endif
@@ -34,6 +40,12 @@ bin_PROGRAMS = \
sg_sync sg_turs sg_verify sg_vpd sg_write_buffer sg_write_long \
sg_wr_mode
+distclean-local:
+ rm -f sg_scan.c
+
+sg_scan.c : sg_scan.c.win32
+ cp sg_scan.c.win32 sg_scan.c
+
endif
@@ -50,6 +62,12 @@ bin_PROGRAMS = \
sg_sync sg_turs sg_verify sg_vpd sg_write_buffer sg_write_long \
sg_wr_mode
+distclean-local:
+ rm -f sg_scan.c
+
+sg_scan.c : sg_scan.c.win32
+ cp sg_scan.c.win32 sg_scan.c
+
endif
diff --git a/src/sg_scan.c.linux b/src/sg_scan.c.linux
new file mode 100644
index 00000000..6b6f61ef
--- /dev/null
+++ b/src/sg_scan.c.linux
@@ -0,0 +1,612 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <scsi/scsi_ioctl.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 - 2009 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 "sg" device space (ie actual + simulated SCSI
+ generic devices). Optionally sg_scan can be given other device names
+ to scan (in place of the sg devices).
+ Options: -a alpha scan: scan /dev/sga,b,c, ....
+ -i do SCSI inquiry on device (implies -w)
+ -n numeric scan: scan /dev/sg0,1,2, ....
+ -V output version string and exit
+ -w open writable (new driver opens readable unless -i)
+ -x extra information output
+
+ By default this program will look for /dev/sg0 first (i.e. numeric scan)
+
+ Note: This program is written to work under both the original and
+ the new sg driver.
+
+ F. Jansen - modification to extend beyond 26 sg devices.
+*/
+
+static char * version_str = "4.09 20070714";
+
+#define ME "sg_scan: "
+
+#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
+
+#define INQ_REPLY_LEN 36
+#define INQ_CMD_LEN 6
+#define MAX_ERRORS 4
+
+#define EBUFF_SZ 256
+#define FNAME_SZ 64
+#define PRESENT_ARRAY_SIZE 4096
+
+static const char * sysfs_sg_dir = "/sys/class/scsi_generic";
+static int * gen_index_arr;
+
+typedef struct my_scsi_idlun {
+/* why can't userland see this structure ??? */
+ int dev_id;
+ int host_unique_id;
+} My_scsi_idlun;
+
+typedef struct my_sg_scsi_id {
+ int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
+ int channel;
+ int scsi_id; /* scsi id of target device */
+ int lun;
+ int scsi_type; /* TYPE_... defined in scsi/scsi.h */
+ short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
+ short d_queue_depth;/* device (or adapter) maximum queue length */
+ int unused1; /* probably find a good use, set 0 for now */
+ int unused2; /* ditto */
+} My_sg_scsi_id;
+
+int sg3_inq(int sg_fd, unsigned char * inqBuff, int do_extra);
+int scsi_inq(int sg_fd, unsigned char * inqBuff);
+int try_ata_identity(const char * file_namep, int ata_fd, int do_inq);
+
+static unsigned char inqCmdBlk[INQ_CMD_LEN] =
+ {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
+
+
+void usage()
+{
+ printf("Usage: sg_scan [-a] [-i] [-n] [-v] [-V] [-w] [-x] "
+ "[DEVICE]*\n");
+ printf(" where:\n");
+ printf(" -a do alpha scan (ie sga, sgb, sgc)\n");
+ printf(" -i do SCSI INQUIRY, output results\n");
+ printf(" -n do numeric scan (ie sg0, sg1...) [default]\n");
+ printf(" -v increase verbosity\n");
+ printf(" -V output version string then exit\n");
+ printf(" -w force open with read/write flag\n");
+ printf(" -x extra information output about queuing\n");
+ printf(" DEVICE name of device\n");
+}
+
+static int scandir_select(const struct dirent * s)
+{
+ int k;
+
+ if (1 == sscanf(s->d_name, "sg%d", &k)) {
+ if ((k >= 0) && (k < PRESENT_ARRAY_SIZE)) {
+ gen_index_arr[k] = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int sysfs_sg_scan(const char * dir_name)
+{
+ struct dirent ** namelist;
+ int num, k;
+
+ num = scandir(dir_name, &namelist, scandir_select, NULL);
+ if (num < 0)
+ return -errno;
+ for (k = 0; k < num; ++k)
+ free(namelist[k]);
+ free(namelist);
+ return num;
+}
+
+void make_dev_name(char * fname, int k, int do_numeric)
+{
+ char buff[FNAME_SZ];
+ int big,little;
+
+ strcpy(fname, "/dev/sg");
+ if (do_numeric) {
+ snprintf(buff, sizeof(buff), "%d", k);
+ strcat(fname, buff);
+ }
+ else {
+ if (k < 26) {
+ buff[0] = 'a' + (char)k;
+ buff[1] = '\0';
+ strcat(fname, buff);
+ }
+ else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */
+ big = k/26;
+ little = k - (26 * big);
+ big = big - 1;
+
+ buff[0] = 'a' + (char)big;
+ buff[1] = 'a' + (char)little;
+ buff[2] = '\0';
+ strcat(fname, buff);
+ }
+ else
+ strcat(fname, "xxxx");
+ }
+}
+
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, res, k, j, f, plen, jmp_out;
+ unsigned char inqBuff[INQ_REPLY_LEN];
+ int do_numeric = NUMERIC_SCAN_DEF;
+ int do_inquiry = 0;
+ int do_extra = 0;
+ int verbose = 0;
+ int writeable = 0;
+ int num_errors = 0;
+ int num_silent = 0;
+ int sg_ver3 = -1;
+ int eacces_err = 0;
+ char fname[FNAME_SZ];
+ char * file_namep;
+ char ebuff[EBUFF_SZ];
+ My_scsi_idlun my_idlun;
+ int host_no;
+ int flags;
+ int emul = -1;
+ int has_file_args = 0;
+ int has_sysfs_sg = 0;
+ const int max_file_args = PRESENT_ARRAY_SIZE;
+ const char * cp;
+ struct stat a_stat;
+
+ if ((gen_index_arr = (int *)malloc(max_file_args * sizeof(int))))
+ memset(gen_index_arr, 0, max_file_args * sizeof(int));
+ else {
+ printf(ME "Out of memory\n");
+ return SG_LIB_CAT_OTHER;
+ }
+
+ for (k = 1, j = 0; k < argc; ++k) {
+ cp = argv[k];
+ plen = strlen(cp);
+ if (plen <= 0)
+ continue;
+ if ('-' == *cp) {
+ for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
+ switch (*cp) {
+ case 'a':
+ do_numeric = 0;
+ break;
+ case 'h':
+ case '?':
+ printf("Scan sg device names and optionally do an "
+ "INQUIRY\n\n");
+ usage();
+ return 0;
+ case 'i':
+ do_inquiry = 1;
+ break;
+ case 'n':
+ do_numeric = 1;
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ case 'V':
+ fprintf(stderr, "Version string: %s\n", version_str);
+ exit(0);
+ case 'w':
+ writeable = 1;
+ break;
+ case 'x':
+ do_extra = 1;
+ break;
+ default:
+ jmp_out = 1;
+ break;
+ }
+ if (jmp_out)
+ break;
+ }
+ if (plen <= 0)
+ continue;
+ if (jmp_out) {
+ fprintf(stderr, "Unrecognized option: %s\n", cp);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else {
+ if (j < max_file_args) {
+ has_file_args = 1;
+ gen_index_arr[j++] = k;
+ } else {
+ printf("Too many command line arguments\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ }
+
+ if ((! has_file_args) && (stat(sysfs_sg_dir, &a_stat) >= 0) &&
+ (S_ISDIR(a_stat.st_mode)))
+ has_sysfs_sg = sysfs_sg_scan(sysfs_sg_dir);
+
+ flags = O_NONBLOCK | (writeable ? O_RDWR : O_RDONLY);
+
+ for (k = 0, res = 0, j = 0, sg_fd = -1;
+ (k < max_file_args) && (has_file_args || (num_errors < MAX_ERRORS));
+ ++k, res = ((sg_fd >= 0) ? close(sg_fd) : 0)) {
+ if (res < 0) {
+ snprintf(ebuff, EBUFF_SZ, ME "Error closing %s ", fname);
+ perror(ebuff);
+ return SG_LIB_FILE_ERROR;
+ }
+ if (has_file_args) {
+ if (gen_index_arr[j])
+ file_namep = argv[gen_index_arr[j++]];
+ else
+ break;
+ } else if (has_sysfs_sg) {
+ if (0 == gen_index_arr[k]) {
+ sg_fd = -1;
+ continue;
+ }
+ make_dev_name(fname, k, 1);
+ file_namep = fname;
+ } else {
+ make_dev_name(fname, k, do_numeric);
+ file_namep = fname;
+ }
+
+ sg_fd = open(file_namep, flags);
+ if (sg_fd < 0) {
+ if (EBUSY == errno) {
+ printf("%s: device busy (O_EXCL lock), skipping\n", file_namep);
+ continue;
+ }
+ else if ((ENODEV == errno) || (ENOENT == errno) ||
+ (ENXIO == errno)) {
+ if (verbose)
+ fprintf(stderr, "Unable to open: %s, errno=%d\n",
+ file_namep, errno);
+ ++num_errors;
+ ++num_silent;
+ continue;
+ }
+ else {
+ if (EACCES == errno)
+ eacces_err = 1;
+ snprintf(ebuff, EBUFF_SZ, ME "Error opening %s ", file_namep);
+ perror(ebuff);
+ ++num_errors;
+ continue;
+ }
+ }
+ res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
+ if (res < 0) {
+ res = try_ata_identity(file_namep, sg_fd, do_inquiry);
+ if (res == 0)
+ continue;
+ snprintf(ebuff, EBUFF_SZ, ME "device %s failed on scsi+ata "
+ "ioctl, skip", file_namep);
+ perror(ebuff);
+ ++num_errors;
+ continue;
+ }
+ res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
+ if (res < 0) {
+ snprintf(ebuff, EBUFF_SZ, ME "device %s failed on scsi "
+ "ioctl(2), skip", file_namep);
+ perror(ebuff);
+ ++num_errors;
+ continue;
+ }
+ res = ioctl(sg_fd, SG_EMULATED_HOST, &emul);
+ if (res < 0)
+ emul = -1;
+ printf("%s: scsi%d channel=%d id=%d lun=%d", file_namep, host_no,
+ (my_idlun.dev_id >> 16) & 0xff, my_idlun.dev_id & 0xff,
+ (my_idlun.dev_id >> 8) & 0xff);
+ if (1 == emul)
+ printf(" [em]");
+#if 0
+ printf(", huid=%d", my_idlun.host_unique_id);
+#endif
+ if (! has_file_args) {
+ My_sg_scsi_id m_id; /* compatible with sg_scsi_id_t in sg.h */
+
+ res = ioctl(sg_fd, SG_GET_SCSI_ID, &m_id);
+ if (res < 0) {
+ snprintf(ebuff, EBUFF_SZ, ME "device %s failed "
+ "SG_GET_SCSI_ID ioctl(4), skip", file_namep);
+ perror(ebuff);
+ ++num_errors;
+ continue;
+ }
+ /* printf(" type=%d", m_id.scsi_type); */
+ if (do_extra)
+ printf(" cmd_per_lun=%hd queue_depth=%hd\n",
+ m_id.h_cmd_per_lun, m_id.d_queue_depth);
+ else
+ printf("\n");
+ }
+ else
+ printf("\n");
+ if (do_inquiry) {
+ if (-1 == sg_ver3) {
+ sg_ver3 = 0;
+ if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &f) >= 0) &&
+ (f >= 30000))
+ sg_ver3 = 1;
+ }
+ if (1 == sg_ver3)
+ res = sg3_inq(sg_fd, inqBuff, do_extra);
+ }
+ }
+ if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors) &&
+ (! has_file_args)) {
+ printf("Stopping because there are too many error\n");
+ if (eacces_err)
+ printf(" root access may be required\n");
+ }
+ return 0;
+}
+
+int sg3_inq(int sg_fd, unsigned char * inqBuff, int do_extra)
+{
+ struct sg_io_hdr io_hdr;
+ unsigned char sense_buffer[32];
+ int ok, err, sg_io;
+
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+ memset(inqBuff, 0, INQ_REPLY_LEN);
+ inqBuff[0] = 0x7f;
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(inqCmdBlk);
+ 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 */
+
+ ok = 1;
+ sg_io = 0;
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ if ((err = scsi_inq(sg_fd, inqBuff)) < 0) {
+ perror(ME "Inquiry SG_IO + SCSI_IOCTL_SEND_COMMAND ioctl error");
+ return 1;
+ } else if (err) {
+ printf(ME "SCSI_IOCTL_SEND_COMMAND ioctl error=0x%x\n", err);
+ return 1;
+ }
+ } else {
+ sg_io = 1;
+ /* now for the error processing */
+ switch (sg_err_category3(&io_hdr)) {
+ case SG_LIB_CAT_RECOVERED:
+ sg_chk_n_print3("Inquiry, continuing", &io_hdr, 1);
+ /* fall through */
+ case SG_LIB_CAT_CLEAN:
+ break;
+ default: /* won't bother decoding other categories */
+ ok = 0;
+ sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
+ break;
+ }
+ }
+
+ if (ok) { /* output result if it is available */
+ char * p = (char *)inqBuff;
+
+ printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32);
+ printf("[rmb=%d cmdq=%d pqual=%d pdev=0x%x] ",
+ !!(p[1] & 0x80), !!(p[7] & 2), (p[0] & 0xe0) >> 5,
+ (p[0] & 0x1f));
+ if (do_extra && sg_io)
+ printf("dur=%ums\n", io_hdr.duration);
+ else
+ printf("\n");
+ }
+ return 0;
+}
+
+struct lscsi_ioctl_command {
+ unsigned int inlen; /* _excluding_ scsi command length */
+ unsigned int outlen;
+ unsigned char data[1]; /* was 0 but that's not ISO C!! */
+ /* on input, scsi command starts here then opt. data */
+};
+
+/* fallback INQUIRY using scsi mid-level's SCSI_IOCTL_SEND_COMMAND ioctl */
+int scsi_inq(int sg_fd, unsigned char * inqBuff)
+{
+ int res;
+ unsigned char buff[512];
+ struct lscsi_ioctl_command * sicp = (struct lscsi_ioctl_command *)buff;
+
+ memset(buff, 0, sizeof(buff));
+ sicp->inlen = 0;
+ sicp->outlen = INQ_REPLY_LEN;
+ memcpy(sicp->data, inqCmdBlk, INQ_CMD_LEN);
+ res = ioctl(sg_fd, SCSI_IOCTL_SEND_COMMAND, sicp);
+ if (0 == res)
+ memcpy(inqBuff, sicp->data, INQ_REPLY_LEN);
+ return res;
+}
+
+/* Following code permits ATA IDENTIFY commands to be performed on
+ ATA non "Packet Interface" devices (e.g. ATA disks).
+ GPL-ed code borrowed from smartmontools (smartmontools.sf.net).
+ Copyright (C) 2002-4 Bruce Allen
+ <smartmontools-support@lists.sourceforge.net>
+ */
+#ifndef ATA_IDENTIFY_DEVICE
+#define ATA_IDENTIFY_DEVICE 0xec
+#endif
+#ifndef HDIO_DRIVE_CMD
+#define HDIO_DRIVE_CMD 0x031f
+#endif
+
+/* Needed parts of the ATA DRIVE IDENTIFY Structure. Those labeled
+ * word* are NOT used.
+ */
+struct ata_identify_device {
+ unsigned short words000_009[10];
+ unsigned char serial_no[20];
+ unsigned short words020_022[3];
+ unsigned char fw_rev[8];
+ unsigned char model[40];
+ unsigned short words047_079[33];
+ unsigned short major_rev_num;
+ unsigned short minor_rev_num;
+ unsigned short command_set_1;
+ unsigned short command_set_2;
+ unsigned short command_set_extension;
+ unsigned short cfs_enable_1;
+ unsigned short word086;
+ unsigned short csf_default;
+ unsigned short words088_255[168];
+};
+
+/* Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
+ * bytes.
+ */
+void swapbytes(char *out, const char *in, size_t n)
+{
+ size_t k;
+
+ if (n > 1) {
+ for (k = 0; k < (n - 1); k += 2) {
+ out[k] = in[k + 1];
+ out[k + 1] = in[k];
+ }
+ }
+}
+
+/* Copies in to out, but removes leading and trailing whitespace. */
+void trim(char *out, const char *in)
+{
+ int k, first, last;
+
+ /* Find the first non-space character (maybe none). */
+ first = -1;
+ for (k = 0; in[k]; k++) {
+ if (! isspace((int)in[k])) {
+ first = k;
+ break;
+ }
+ }
+
+ if (first == -1) {
+ /* There are no non-space characters. */
+ out[0] = '\0';
+ return;
+ }
+
+ /* Find the last non-space character. */
+ for (k = strlen(in) - 1; k >= first && isspace((int)in[k]); k--)
+ ;
+ last = k;
+ strncpy(out, in + first, last - first + 1);
+ out[last - first + 1] = '\0';
+}
+
+/* Convenience function for formatting strings from ata_identify_device */
+void formatdriveidstring(char *out, const char *in, int n)
+{
+ char tmp[65];
+
+ n = n > 64 ? 64 : n;
+ swapbytes(tmp, in, n);
+ tmp[n] = '\0';
+ trim(out, tmp);
+}
+
+/* Function for printing ASCII byte-swapped strings, skipping white
+ * space. Please note that this is needed on both big- and
+ * little-endian hardware.
+ */
+void printswap(char *output, char *in, unsigned int n)
+{
+ formatdriveidstring(output, in, n);
+ if (*output)
+ printf("%.*s ", (int)n, output);
+ else
+ printf("%.*s ", (int)n, "[No Information Found]\n");
+}
+
+#define ATA_IDENTIFY_BUFF_SZ sizeof(struct ata_identify_device)
+#define HDIO_DRIVE_CMD_OFFSET 4
+
+int ata_command_interface(int device, char *data)
+{
+ unsigned char buff[ATA_IDENTIFY_BUFF_SZ + HDIO_DRIVE_CMD_OFFSET];
+ int retval;
+
+ buff[0] = ATA_IDENTIFY_DEVICE;
+ buff[3] = 1;
+ /* We are now doing the HDIO_DRIVE_CMD type ioctl. */
+ if ((retval = ioctl(device, HDIO_DRIVE_CMD, buff)))
+ return retval;
+
+ /* if the command returns data, copy it back */
+ memcpy(data, buff + HDIO_DRIVE_CMD_OFFSET, ATA_IDENTIFY_BUFF_SZ);
+ return 0;
+}
+
+int try_ata_identity(const char * file_namep, int ata_fd, int do_inq)
+{
+ struct ata_identify_device ata_ident;
+ char model[64];
+ char serial[64];
+ char firm[64];
+ int res;
+
+ res = ata_command_interface(ata_fd, (char *)&ata_ident);
+ if (res)
+ return res;
+ printf("%s: ATA device\n", file_namep);
+ if (do_inq) {
+ printf(" ");
+ printswap(model, (char *)ata_ident.model, 40);
+ printswap(serial, (char *)ata_ident.serial_no, 20);
+ printswap(firm, (char *)ata_ident.fw_rev, 8);
+ printf("\n");
+ }
+ return res;
+}
diff --git a/src/sg_scan.c b/src/sg_scan.c.win32
index abb61431..599bfc7f 100644
--- a/src/sg_scan.c
+++ b/src/sg_scan.c.win32
@@ -1,625 +1,7 @@
-/* N.B. There are two programs in this file, the first is for linux
- * and the second is for Windows.
- */
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#ifdef SG3_UTILS_LINUX
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <dirent.h>
-#include <libgen.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <scsi/scsi_ioctl.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 - 2007 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 "sg" device space (ie actual + simulated SCSI
- generic devices). Optionally sg_scan can be given other device names
- to scan (in place of the sg devices).
- Options: -a alpha scan: scan /dev/sga,b,c, ....
- -i do SCSI inquiry on device (implies -w)
- -n numeric scan: scan /dev/sg0,1,2, ....
- -V output version string and exit
- -w open writable (new driver opens readable unless -i)
- -x extra information output
-
- By default this program will look for /dev/sg0 first (i.e. numeric scan)
-
- Note: This program is written to work under both the original and
- the new sg driver.
-
- F. Jansen - modification to extend beyond 26 sg devices.
-*/
-
-static char * version_str = "4.09 20070714";
-
-#define ME "sg_scan: "
-
-#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
-
-#define INQ_REPLY_LEN 36
-#define INQ_CMD_LEN 6
-#define MAX_ERRORS 4
-
-#define EBUFF_SZ 256
-#define FNAME_SZ 64
-#define PRESENT_ARRAY_SIZE 4096
-
-static const char * sysfs_sg_dir = "/sys/class/scsi_generic";
-static int * gen_index_arr;
-
-typedef struct my_scsi_idlun {
-/* why can't userland see this structure ??? */
- int dev_id;
- int host_unique_id;
-} My_scsi_idlun;
-
-typedef struct my_sg_scsi_id {
- int host_no; /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
- int channel;
- int scsi_id; /* scsi id of target device */
- int lun;
- int scsi_type; /* TYPE_... defined in scsi/scsi.h */
- short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
- short d_queue_depth;/* device (or adapter) maximum queue length */
- int unused1; /* probably find a good use, set 0 for now */
- int unused2; /* ditto */
-} My_sg_scsi_id;
-
-int sg3_inq(int sg_fd, unsigned char * inqBuff, int do_extra);
-int scsi_inq(int sg_fd, unsigned char * inqBuff);
-int try_ata_identity(const char * file_namep, int ata_fd, int do_inq);
-
-static unsigned char inqCmdBlk[INQ_CMD_LEN] =
- {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
-
-
-void usage()
-{
- printf("Usage: sg_scan [-a] [-i] [-n] [-v] [-V] [-w] [-x] "
- "[DEVICE]*\n");
- printf(" where:\n");
- printf(" -a do alpha scan (ie sga, sgb, sgc)\n");
- printf(" -i do SCSI INQUIRY, output results\n");
- printf(" -n do numeric scan (ie sg0, sg1...) [default]\n");
- printf(" -v increase verbosity\n");
- printf(" -V output version string then exit\n");
- printf(" -w force open with read/write flag\n");
- printf(" -x extra information output about queuing\n");
- printf(" DEVICE name of device\n");
-}
-
-static int scandir_select(const struct dirent * s)
-{
- int k;
-
- if (1 == sscanf(s->d_name, "sg%d", &k)) {
- if ((k >= 0) && (k < PRESENT_ARRAY_SIZE)) {
- gen_index_arr[k] = 1;
- return 1;
- }
- }
- return 0;
-}
-
-static int sysfs_sg_scan(const char * dir_name)
-{
- struct dirent ** namelist;
- int num, k;
-
- num = scandir(dir_name, &namelist, scandir_select, NULL);
- if (num < 0)
- return -errno;
- for (k = 0; k < num; ++k)
- free(namelist[k]);
- free(namelist);
- return num;
-}
-
-void make_dev_name(char * fname, int k, int do_numeric)
-{
- char buff[FNAME_SZ];
- int big,little;
-
- strcpy(fname, "/dev/sg");
- if (do_numeric) {
- snprintf(buff, sizeof(buff), "%d", k);
- strcat(fname, buff);
- }
- else {
- if (k < 26) {
- buff[0] = 'a' + (char)k;
- buff[1] = '\0';
- strcat(fname, buff);
- }
- else if (k <= 255) { /* assumes sequence goes x,y,z,aa,ab,ac etc */
- big = k/26;
- little = k - (26 * big);
- big = big - 1;
-
- buff[0] = 'a' + (char)big;
- buff[1] = 'a' + (char)little;
- buff[2] = '\0';
- strcat(fname, buff);
- }
- else
- strcat(fname, "xxxx");
- }
-}
-
-
-int main(int argc, char * argv[])
-{
- int sg_fd, res, k, j, f, plen, jmp_out;
- unsigned char inqBuff[INQ_REPLY_LEN];
- int do_numeric = NUMERIC_SCAN_DEF;
- int do_inquiry = 0;
- int do_extra = 0;
- int verbose = 0;
- int writeable = 0;
- int num_errors = 0;
- int num_silent = 0;
- int sg_ver3 = -1;
- int eacces_err = 0;
- char fname[FNAME_SZ];
- char * file_namep;
- char ebuff[EBUFF_SZ];
- My_scsi_idlun my_idlun;
- int host_no;
- int flags;
- int emul = -1;
- int has_file_args = 0;
- int has_sysfs_sg = 0;
- const int max_file_args = PRESENT_ARRAY_SIZE;
- const char * cp;
- struct stat a_stat;
-
- if ((gen_index_arr = (int *)malloc(max_file_args * sizeof(int))))
- memset(gen_index_arr, 0, max_file_args * sizeof(int));
- else {
- printf(ME "Out of memory\n");
- return SG_LIB_CAT_OTHER;
- }
-
- for (k = 1, j = 0; k < argc; ++k) {
- cp = argv[k];
- plen = strlen(cp);
- if (plen <= 0)
- continue;
- if ('-' == *cp) {
- for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
- switch (*cp) {
- case 'a':
- do_numeric = 0;
- break;
- case 'h':
- case '?':
- printf("Scan sg device names and optionally do an "
- "INQUIRY\n\n");
- usage();
- return 0;
- case 'i':
- do_inquiry = 1;
- break;
- case 'n':
- do_numeric = 1;
- break;
- case 'v':
- ++verbose;
- break;
- case 'V':
- fprintf(stderr, "Version string: %s\n", version_str);
- exit(0);
- case 'w':
- writeable = 1;
- break;
- case 'x':
- do_extra = 1;
- break;
- default:
- jmp_out = 1;
- break;
- }
- if (jmp_out)
- break;
- }
- if (plen <= 0)
- continue;
- if (jmp_out) {
- fprintf(stderr, "Unrecognized option: %s\n", cp);
- usage();
- return SG_LIB_SYNTAX_ERROR;
- }
- } else {
- if (j < max_file_args) {
- has_file_args = 1;
- gen_index_arr[j++] = k;
- } else {
- printf("Too many command line arguments\n");
- return SG_LIB_SYNTAX_ERROR;
- }
- }
- }
-
- if ((! has_file_args) && (stat(sysfs_sg_dir, &a_stat) >= 0) &&
- (S_ISDIR(a_stat.st_mode)))
- has_sysfs_sg = sysfs_sg_scan(sysfs_sg_dir);
-
- flags = O_NONBLOCK | (writeable ? O_RDWR : O_RDONLY);
-
- for (k = 0, res = 0, j = 0, sg_fd = -1;
- (k < max_file_args) && (has_file_args || (num_errors < MAX_ERRORS));
- ++k, res = ((sg_fd >= 0) ? close(sg_fd) : 0)) {
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "Error closing %s ", fname);
- perror(ebuff);
- return SG_LIB_FILE_ERROR;
- }
- if (has_file_args) {
- if (gen_index_arr[j])
- file_namep = argv[gen_index_arr[j++]];
- else
- break;
- } else if (has_sysfs_sg) {
- if (0 == gen_index_arr[k]) {
- sg_fd = -1;
- continue;
- }
- make_dev_name(fname, k, 1);
- file_namep = fname;
- } else {
- make_dev_name(fname, k, do_numeric);
- file_namep = fname;
- }
-
- sg_fd = open(file_namep, flags);
- if (sg_fd < 0) {
- if (EBUSY == errno) {
- printf("%s: device busy (O_EXCL lock), skipping\n", file_namep);
- continue;
- }
- else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- if (verbose)
- fprintf(stderr, "Unable to open: %s, errno=%d\n",
- file_namep, errno);
- ++num_errors;
- ++num_silent;
- continue;
- }
- else {
- if (EACCES == errno)
- eacces_err = 1;
- snprintf(ebuff, EBUFF_SZ, ME "Error opening %s ", file_namep);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
- if (res < 0) {
- res = try_ata_identity(file_namep, sg_fd, do_inquiry);
- if (res == 0)
- continue;
- snprintf(ebuff, EBUFF_SZ, ME "device %s failed on scsi+ata "
- "ioctl, skip", file_namep);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s failed on scsi "
- "ioctl(2), skip", file_namep);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- res = ioctl(sg_fd, SG_EMULATED_HOST, &emul);
- if (res < 0)
- emul = -1;
- printf("%s: scsi%d channel=%d id=%d lun=%d", file_namep, host_no,
- (my_idlun.dev_id >> 16) & 0xff, my_idlun.dev_id & 0xff,
- (my_idlun.dev_id >> 8) & 0xff);
- if (1 == emul)
- printf(" [em]");
-#if 0
- printf(", huid=%d", my_idlun.host_unique_id);
-#endif
- if (! has_file_args) {
- My_sg_scsi_id m_id; /* compatible with sg_scsi_id_t in sg.h */
-
- res = ioctl(sg_fd, SG_GET_SCSI_ID, &m_id);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s failed "
- "SG_GET_SCSI_ID ioctl(4), skip", file_namep);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- /* printf(" type=%d", m_id.scsi_type); */
- if (do_extra)
- printf(" cmd_per_lun=%hd queue_depth=%hd\n",
- m_id.h_cmd_per_lun, m_id.d_queue_depth);
- else
- printf("\n");
- }
- else
- printf("\n");
- if (do_inquiry) {
- if (-1 == sg_ver3) {
- sg_ver3 = 0;
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &f) >= 0) &&
- (f >= 30000))
- sg_ver3 = 1;
- }
- if (1 == sg_ver3)
- res = sg3_inq(sg_fd, inqBuff, do_extra);
- }
- }
- if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors) &&
- (! has_file_args)) {
- printf("Stopping because there are too many error\n");
- if (eacces_err)
- printf(" root access may be required\n");
- }
- return 0;
-}
-
-int sg3_inq(int sg_fd, unsigned char * inqBuff, int do_extra)
-{
- struct sg_io_hdr io_hdr;
- unsigned char sense_buffer[32];
- int ok, err, sg_io;
-
- memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
- memset(inqBuff, 0, INQ_REPLY_LEN);
- inqBuff[0] = 0x7f;
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inqCmdBlk);
- 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 */
-
- ok = 1;
- sg_io = 0;
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- if ((err = scsi_inq(sg_fd, inqBuff)) < 0) {
- perror(ME "Inquiry SG_IO + SCSI_IOCTL_SEND_COMMAND ioctl error");
- return 1;
- } else if (err) {
- printf(ME "SCSI_IOCTL_SEND_COMMAND ioctl error=0x%x\n", err);
- return 1;
- }
- } else {
- sg_io = 1;
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_LIB_CAT_RECOVERED:
- sg_chk_n_print3("Inquiry, continuing", &io_hdr, 1);
- /* fall through */
- case SG_LIB_CAT_CLEAN:
- break;
- default: /* won't bother decoding other categories */
- ok = 0;
- sg_chk_n_print3("INQUIRY command error", &io_hdr, 1);
- break;
- }
- }
-
- if (ok) { /* output result if it is available */
- char * p = (char *)inqBuff;
-
- printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32);
- printf("[rmb=%d cmdq=%d pqual=%d pdev=0x%x] ",
- !!(p[1] & 0x80), !!(p[7] & 2), (p[0] & 0xe0) >> 5,
- (p[0] & 0x1f));
- if (do_extra && sg_io)
- printf("dur=%ums\n", io_hdr.duration);
- else
- printf("\n");
- }
- return 0;
-}
-
-struct lscsi_ioctl_command {
- unsigned int inlen; /* _excluding_ scsi command length */
- unsigned int outlen;
- unsigned char data[1]; /* was 0 but that's not ISO C!! */
- /* on input, scsi command starts here then opt. data */
-};
-
-/* fallback INQUIRY using scsi mid-level's SCSI_IOCTL_SEND_COMMAND ioctl */
-int scsi_inq(int sg_fd, unsigned char * inqBuff)
-{
- int res;
- unsigned char buff[512];
- struct lscsi_ioctl_command * sicp = (struct lscsi_ioctl_command *)buff;
-
- memset(buff, 0, sizeof(buff));
- sicp->inlen = 0;
- sicp->outlen = INQ_REPLY_LEN;
- memcpy(sicp->data, inqCmdBlk, INQ_CMD_LEN);
- res = ioctl(sg_fd, SCSI_IOCTL_SEND_COMMAND, sicp);
- if (0 == res)
- memcpy(inqBuff, sicp->data, INQ_REPLY_LEN);
- return res;
-}
-
-/* Following code permits ATA IDENTIFY commands to be performed on
- ATA non "Packet Interface" devices (e.g. ATA disks).
- GPL-ed code borrowed from smartmontools (smartmontools.sf.net).
- Copyright (C) 2002-4 Bruce Allen
- <smartmontools-support@lists.sourceforge.net>
- */
-#ifndef ATA_IDENTIFY_DEVICE
-#define ATA_IDENTIFY_DEVICE 0xec
-#endif
-#ifndef HDIO_DRIVE_CMD
-#define HDIO_DRIVE_CMD 0x031f
-#endif
-
-/* Needed parts of the ATA DRIVE IDENTIFY Structure. Those labeled
- * word* are NOT used.
- */
-struct ata_identify_device {
- unsigned short words000_009[10];
- unsigned char serial_no[20];
- unsigned short words020_022[3];
- unsigned char fw_rev[8];
- unsigned char model[40];
- unsigned short words047_079[33];
- unsigned short major_rev_num;
- unsigned short minor_rev_num;
- unsigned short command_set_1;
- unsigned short command_set_2;
- unsigned short command_set_extension;
- unsigned short cfs_enable_1;
- unsigned short word086;
- unsigned short csf_default;
- unsigned short words088_255[168];
-};
-
-/* Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
- * bytes.
- */
-void swapbytes(char *out, const char *in, size_t n)
-{
- size_t k;
-
- if (n > 1) {
- for (k = 0; k < (n - 1); k += 2) {
- out[k] = in[k + 1];
- out[k + 1] = in[k];
- }
- }
-}
-
-/* Copies in to out, but removes leading and trailing whitespace. */
-void trim(char *out, const char *in)
-{
- int k, first, last;
-
- /* Find the first non-space character (maybe none). */
- first = -1;
- for (k = 0; in[k]; k++) {
- if (! isspace((int)in[k])) {
- first = k;
- break;
- }
- }
-
- if (first == -1) {
- /* There are no non-space characters. */
- out[0] = '\0';
- return;
- }
-
- /* Find the last non-space character. */
- for (k = strlen(in) - 1; k >= first && isspace((int)in[k]); k--)
- ;
- last = k;
- strncpy(out, in + first, last - first + 1);
- out[last - first + 1] = '\0';
-}
-
-/* Convenience function for formatting strings from ata_identify_device */
-void formatdriveidstring(char *out, const char *in, int n)
-{
- char tmp[65];
-
- n = n > 64 ? 64 : n;
- swapbytes(tmp, in, n);
- tmp[n] = '\0';
- trim(out, tmp);
-}
-
-/* Function for printing ASCII byte-swapped strings, skipping white
- * space. Please note that this is needed on both big- and
- * little-endian hardware.
- */
-void printswap(char *output, char *in, unsigned int n)
-{
- formatdriveidstring(output, in, n);
- if (*output)
- printf("%.*s ", (int)n, output);
- else
- printf("%.*s ", (int)n, "[No Information Found]\n");
-}
-
-#define ATA_IDENTIFY_BUFF_SZ sizeof(struct ata_identify_device)
-#define HDIO_DRIVE_CMD_OFFSET 4
-
-int ata_command_interface(int device, char *data)
-{
- unsigned char buff[ATA_IDENTIFY_BUFF_SZ + HDIO_DRIVE_CMD_OFFSET];
- int retval;
-
- buff[0] = ATA_IDENTIFY_DEVICE;
- buff[3] = 1;
- /* We are now doing the HDIO_DRIVE_CMD type ioctl. */
- if ((retval = ioctl(device, HDIO_DRIVE_CMD, buff)))
- return retval;
-
- /* if the command returns data, copy it back */
- memcpy(data, buff + HDIO_DRIVE_CMD_OFFSET, ATA_IDENTIFY_BUFF_SZ);
- return 0;
-}
-
-int try_ata_identity(const char * file_namep, int ata_fd, int do_inq)
-{
- struct ata_identify_device ata_ident;
- char model[64];
- char serial[64];
- char firm[64];
- int res;
-
- res = ata_command_interface(ata_fd, (char *)&ata_ident);
- if (res)
- return res;
- printf("%s: ATA device\n", file_namep);
- if (do_inq) {
- printf(" ");
- printswap(model, (char *)ata_ident.model, 40);
- printswap(serial, (char *)ata_ident.serial_no, 20);
- printswap(firm, (char *)ata_ident.fw_rev, 8);
- printf("\n");
- }
- return res;
-}
-
-#endif
-
-#ifdef SG3_UTILS_WIN32
-
/*
* Copyright (c) 2006 Douglas Gilbert.
* All rights reserved.
@@ -1413,5 +795,3 @@ int main(int argc, char * argv[])
free(w_scsi_arr);
return ret;
}
-
-#endif