[LTP] [RFC PATCH 3/7] fs: Remove scsi/ltpscsi testsuite
Petr Vorel
pvorel@suse.cz
Mon Oct 16 20:44:04 CEST 2023
This testsuite, which contained user space code and custom runner and
expected to be tested with ssi_debug kernel module, was written for
kernel 2.5.
It did not use LTP API and did not even build due various undefined
references:
ltpscsi/sg_err.c:165:(.text+0x2fa): undefined reference to `fwrite'
Probably not worth of fixing, thus removed.
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
testcases/kernel/fs/scsi/ltpscsi/Makefile | 47 -
testcases/kernel/fs/scsi/ltpscsi/llseek.c | 123 -
testcases/kernel/fs/scsi/ltpscsi/llseek.h | 10 -
testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh | 111 -
testcases/kernel/fs/scsi/ltpscsi/scsimain.c | 7651 -----------------
testcases/kernel/fs/scsi/ltpscsi/sg_err.c | 1379 ---
testcases/kernel/fs/scsi/ltpscsi/sg_err.h | 162 -
testcases/kernel/fs/scsi/ltpscsi/sg_include.h | 42 -
8 files changed, 9525 deletions(-)
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/Makefile
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/llseek.c
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/llseek.h
delete mode 100755 testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/scsimain.c
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/sg_err.c
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/sg_err.h
delete mode 100644 testcases/kernel/fs/scsi/ltpscsi/sg_include.h
diff --git a/testcases/kernel/fs/scsi/ltpscsi/Makefile b/testcases/kernel/fs/scsi/ltpscsi/Makefile
deleted file mode 100644
index e404ce074..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
-SHELL = /bin/sh
-
-EXECS = scsimain
-
-LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-
-CFLAGS = -g -O2 -Wall -D_REENTRANT $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -D_REENTRANT -DSG_KERNEL_INCLUDES $(LARGE_FILE_FLAGS)
-# CFLAGS = -g -O2 -Wall -pedantic -D_REENTRANT $(LARGE_FILE_FLAGS)
-
-LDFLAGS =
-
-all: $(EXECS)
-
-depend dep:
- @set -e; for i in *.c; do $(CC) $(INCLUDES) $(CFLAGS) -M $$i; \
- done > .depend
-
-clean:
- /bin/rm -f *.o $(EXECS) core .depend
-
-scsimain: scsimain.o sg_err.o llseek.o
- $(LD) -o $@ $(LDFLAGS) $^ -lpthread
-
-install: $(EXECS)
- install -d $(INSTDIR)
- @set -e; for name in $^; \
- do install -s -o root -g root -m 755 $$name $(INSTDIR); \
- done
- install -d $(MANDIR)/$(MAN_PREF)
- @set -e; 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)"; \
- @set -e; for name in $$dists; do \
- rm -f $(INSTDIR)/$$name; \
- done
- @set -e; for mp in $(MAN_PGS); do \
- rm -f $(MANDIR)/$(MAN_PREF)/$$mp.gz; \
- done
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
diff --git a/testcases/kernel/fs/scsi/ltpscsi/llseek.c b/testcases/kernel/fs/scsi/ltpscsi/llseek.c
deleted file mode 100644
index 25b77620c..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/llseek.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * llseek.c -- stub calling the llseek system call
- *
- * Copyright (C) 1994 Remy Card. This file may be redistributed
- * under the terms of the GNU Public License.
- *
- * This file is borrowed from the util-linux-2.10q tarball's implementation
- * of fdisk. It allows seeks to 64 bit offsets, if supported.
- * Changed "ext2_" prefix to "llse".
- */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <linux/unistd.h> /* for __NR_llseek */
-
-#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, llse_loff_t, unsigned int);
-
-#ifdef __linux__
-
-#if defined(__alpha__) || defined(__ia64__)
-
-#ifdef __NR_lseek
-static off_t my_lseek(int fd, off_t off, int whence)
-{
- return syscall(__NR_lseek, fd, off, whence);
-}
-#else /* undefined __NR_lseek */
-static off_t my_lseek(int fd, off_t off, int whence)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif /* __NR_lseek */
-
-#define my_llseek my_lseek
-
-#else /* !__alpha__ && !__ia64__ */
-
-static int _llseek(unsigned int, unsigned long,
- unsigned long, llse_loff_t *, unsigned int);
-
-#ifndef __NR_llseek
-/* no __NR_llseek on compilation machine - might give it explicitly */
-static int _llseek(unsigned int fd, unsigned long oh,
- unsigned long ol, llse_loff_t * result, unsigned int origin)
-{
- errno = ENOSYS;
- return -1;
-}
-#else
-static int _llseek(unsigned int fd, unsigned long oh,
- unsigned long ol, llse_loff_t * result, unsigned int origin)
-{
- return syscall(__NR_llseek, fd, oh, ol, result, origin);
-}
-#endif
-
-static llse_loff_t my_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- llse_loff_t result;
- int retval;
-
- retval = _llseek(fd, ((unsigned long long)offset) >> 32,
- ((unsigned long long)offset) & 0xffffffff,
- &result, origin);
- return (retval == -1 ? (llse_loff_t) retval : result);
-}
-
-#endif /* __alpha__ */
-
-llse_loff_t llse_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- llse_loff_t result;
- static int do_compat = 0;
-
- if (!do_compat) {
- result = my_llseek(fd, offset, origin);
- if (!(result == -1 && errno == ENOSYS))
- return result;
-
- /*
- * Just in case this code runs on top of an old kernel
- * which does not support the llseek system call
- */
- do_compat = 1;
- /*
- * Now try ordinary lseek.
- */
- }
-
- if ((sizeof(off_t) >= sizeof(llse_loff_t)) ||
- (offset < ((llse_loff_t) 1 << ((sizeof(off_t) * 8) - 1))))
- return lseek(fd, (off_t) offset, origin);
-
- errno = EINVAL;
- return -1;
-}
-
-#else /* !linux */
-
-llse_loff_t llse_llseek(unsigned int fd, llse_loff_t offset,
- unsigned int origin)
-{
- if ((sizeof(off_t) < sizeof(llse_loff_t)) &&
- (offset >= ((llse_loff_t) 1 << ((sizeof(off_t) * 8) - 1)))) {
- errno = EINVAL;
- return -1;
- }
- return lseek(fd, (off_t) offset, origin);
-}
-
-#endif /* linux */
diff --git a/testcases/kernel/fs/scsi/ltpscsi/llseek.h b/testcases/kernel/fs/scsi/ltpscsi/llseek.h
deleted file mode 100644
index cdf6fceae..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/llseek.h
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#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);
diff --git a/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh b/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh
deleted file mode 100755
index 29648d9e7..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/ltpfsscsi.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/sh
-# This script should be run to execute the filesystem tests on SCSI vitual devices.
-# 10/21/03 mridge@us.ibm.com Initial creation of testcases
-#
-#
-
-cd `dirname $0`
-export LTPROOT=${PWD}
-echo $LTPROOT | grep testscripts > /dev/null 2>&1
-if [ $? -eq 0 ]; then
- cd ..
- export LTPROOT=${PWD}
-fi
-
-export TMPBASE="/tmp"
-
-
-usage()
-{
- cat <<-END >&2
- usage: ${0##*/} [ -a part1 ] [ -b part2 ] [ -k Kernel Path - fully qualified kernel path ]
- defaults:
-
- There are no defaults, all items MUST be passed
-
- example: ${0##*/} -a sda -b sdb -k /usr/src/linux
-
- - These tests must be run after ssi_debug has been configured and built as a module so it can be loaded with
- the correct parameters.
-
- - These operations are destructive so do NOT point the tests to partitions where the data shouldn't be overwritten.
- Once these tests are started all data in the partitions you point to will be destroyed.
-
- END
-exit
-}
-
-while getopts :a:b:c:k: arg
-do case $arg in
- a) part1=$OPTARG;;
- b) part2=$OPTARG;;
- c) part3=$OPTARG;;
- k) kernpath=$OPTARG;;
-
- \?) echo "************** Help Info: ********************"
- usage;;
- esac
-done
-
-if [ ! -n "$part1" ]; then
- echo "Missing 1st partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$part2" ]; then
- echo "Missing 2nd partition. You must pass 2 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$part3" ]; then
- echo "Missing 3rd partition. You must pass 3 partitions for testing"
- usage;
- exit
-fi
-
-if [ ! -n "$kernpath" ]; then
- echo "Missing kernel path. You must pass kernel path for testing"
- usage;
- exit
-fi
-
-export PATH="${PATH}:${LTPROOT}/testcases/bin"
-
-
-mkdir /test >/dev/null 2>&1
-mkdir /test/growfiles >/dev/null 2>&1
-mkdir /test/growfiles/scsi >/dev/null 2>&1
-mkdir /test/growfiles/scsi/ext2 >/dev/null 2>&1
-mkdir /test/growfiles/scsi/ext3 >/dev/null 2>&1
-mkdir /test/growfiles/scsi/reiser >/dev/null 2>&1
-
-
-mkfs -V -t ext2 /dev/$part1 <yesenter.txt
-mkfs -V -t ext3 /dev/$part2 <yesenter.txt
-mkreiserfs -f /dev/$part3 <yesenter.txt
-
-
-mount -v -t ext2 /dev/$part1 /test/growfiles/scsi/ext2
-mount -v -t ext3 /dev/$part2 /test/growfiles/scsi/ext3
-mount -v /dev/$part3 /test/growfiles/scsi/reiser
-
-cd $kernpath/drivers/scsi
-modprobe scsi_debug max_luns=2 num_tgts=7 add_host=10
-cd ${LTPROOT}
-
-echo "************ Running tests "
-sort -R ${LTPROOT}/runtest/scsi.part1 -o ${TMPBASE}/scsi.part1
-
-${LTPROOT}/pan/pan -e -S -a scsipart1 -n scsipart1 -l scsilogfile -f ${TMPBASE}/scsi.part1 &
-
-wait $!
-
-umount -v /dev/$part1
-umount -v /dev/$part2
-umount -v /dev/$part3
-rmmod scsi_debug
-
-
-
diff --git a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c b/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
deleted file mode 100644
index ce23ae1e7..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/scsimain.c
+++ /dev/null
@@ -1,7651 +0,0 @@
-/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
- device driver.
-* Copyright (C) 1999 - 2002 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).
- Options: -w open writable (new driver opens readable unless -i)
- -n numeric scan: scan /dev/sg0,1,2, ....
- -a alpha scan: scan /dev/sga,b,c, ....
- -i do SCSI inquiry on device (implies -w)
- -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.
-
- Version 1.00 20031022
-
- F. Jansen - modification to extend beyond 26 sg devices.
- M. Ridgeway - Roll code together for SCSI testing with one command line
-
-6 byte INQUIRY command:
-[0x12][ |lu][pg cde][res ][al len][cntrl ]
-*/
-
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <limits.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <sys/sysmacros.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <linux/major.h>
-#include "sg_include.h"
-#include "sg_err.h"
-#include "llseek.h"
-
-#define ME "scsimain: "
-
-#define NUMERIC_SCAN_DEF 1 /* change to 0 to make alpha scan default */
-//static char * version_str = "0.21 20030513";
-
-#define BPI (signed)(sizeof(int))
-#define READWRITE_BASE_NUM 0x12345678
-#define DEF_BLOCK_SIZE 512
-#define DEF_NUM_THREADS 16
-#define MAX_NUM_THREADS SG_MAX_QUEUE
-#define DEF_BLOCKS_PER_TRANSFER 128
-#define DEF_SCSI_CDBSZ 10
-#define MAX_SCSI_CDBSZ 16
-#define TUR_CMD_LEN 6
-#define DEVNAME_SZ 256
-#define MAX_HOLES 4
-
-#define OFF sizeof(struct sg_header)
-#define INQ_REPLY_LEN 96 /* logic assumes >= sizeof(inqCmdBlk) */
-#define INQUIRY_CMDLEN 6
-#define INQUIRY_CMD 0x12
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
-#define REASON_SZ 128
-
-#define SENSE_BUFF_SZ 64
-#define RCAP_REPLY_LEN 8
-#define LOG_SENSE_CMD 0x4d
-#define LOG_SENSE_CMDLEN 10
-#define MX_ALLOC_LEN (1024 * 17)
-#define D_ROOT_SZ 512
-#define STR_SZ 1024
-#define INOUTF_SZ 512
-#define EBUFF_SZ 512
-#define MDEV_NAME_SZ 256
-
-#define PG_CODE_ALL 0x00
-
-#define TRUE 1
-#define FALSE 0
-#define MAX_DEVICES 50
-
-#define NAME_LEN_MAX 256
-#define LEVELS 4
-
-#define SENSE_BUFF_LEN 32 /* Arbitrary, could be larger */
-#define INQ_ALLOC_LEN 255
-
-#ifndef SCSI_IOCTL_GET_PCI
-#define SCSI_IOCTL_GET_PCI 0x5387
-#endif
-
-#define READ_CAP_REPLY_LEN 8
-
-#ifndef RAW_MAJOR
-#define RAW_MAJOR 255 /*unlikey value */
-#endif
-
-#define FT_OTHER 1 /* filetype is probably normal */
-#define FT_SG 2 /* filetype is sg char device or supports
- SG_IO ioctl */
-#define FT_RAW 4 /* filetype is raw char device */
-#define FT_DEV_NULL 8 /* either "/dev/null" or "." as filename */
-#define FT_ST 16 /* filetype is st char device (tape) */
-#define FT_BLOCK 32 /* filetype is block device */
-
-#define DEV_NULL_MINOR_NUM 3
-
-#ifdef SG_GET_RESERVED_SIZE
-#define OPEN_FLAG O_RDONLY
-#else
-#define OPEN_FLAG O_RDWR
-#endif
-
-#ifndef SG_MAX_SENSE
-#define SG_MAX_SENSE 16
-#endif
-
-#define TEST_START 0
-#define TEST_BREAK 1
-#define TEST_STOP 2
-#define MAX_SG_DEVS 128
-#define MAX_SD_DEVS 128
-#define MAX_SR_DEVS 128
-#define MAX_ST_DEVS 128
-#define MAX_OSST_DEVS 128
-#define MAX_ERRORS 5
-
-#define LIN_DEV_TYPE_UNKNOWN 0
-#define LIN_DEV_TYPE_SD 1
-#define LIN_DEV_TYPE_SR 2
-#define LIN_DEV_TYPE_ST 3
-#define LIN_DEV_TYPE_SCD 4
-#define LIN_DEV_TYPE_OSST 5
-
-#define MODE_SENSE6_CMD 0x1a
-#define MODE_SENSE6_CMDLEN 6
-#define MODE_SENSE10_CMD 0x5a
-#define MODE_SENSE10_CMDLEN 10
-#define INQUIRY_CMD 0x12
-#define INQUIRY_CMDLEN 6
-#define MODE_ALLOC_LEN (1024 * 4)
-
-#define MODE_CODE_ALL 0x3f
-
-#define RB_MODE_DESC 3
-#define RB_MODE_DATA 2
-#define RB_DESC_LEN 4
-#define RB_MB_TO_READ 200
-#define RB_OPCODE 0x3C
-#define RB_CMD_LEN 10
-
-/* #define SG_DEBUG */
-
-#ifndef SG_FLAG_MMAP_IO
-#define SG_FLAG_MMAP_IO 4
-#endif
-#ifndef SG_SCSI_RESET
-#define SG_SCSI_RESET 0x2284
-#endif
-
-#ifndef SG_SCSI_RESET_NOTHING
-#define SG_SCSI_RESET_NOTHING 0
-#define SG_SCSI_RESET_DEVICE 1
-#define SG_SCSI_RESET_BUS 2
-#define SG_SCSI_RESET_HOST 3
-#endif
-#define LONG_TIMEOUT 2400000 /* 2,400,000 millisecs == 40 minutes */
-
-#define SEND_DIAGNOSTIC_CMD 0x1d
-#define SEND_DIAGNOSTIC_CMDLEN 6
-#define RECEIVE_DIAGNOSTIC_CMD 0x1c
-#define RECEIVE_DIAGNOSTIC_CMDLEN 6
-
-#define START_STOP 0x1b
-#define SYNCHRONIZE_CACHE 0x35
-
-#define DEF_START_TIMEOUT 120000 /* 120,000 millisecs == 2 minutes */
-
-#define DEVICE_RESET 0
-#define HOST_RESET 1
-#define BUS_RESET 2
-#define SG_HSZ sizeof(struct sg_header)
-#define OFFSET_HEADER (SG_HSZ - (2 * sizeof(int)))
-#define SIZEOF_BUFFER (256*1024)
-#define SIZEOF_BUFFER1 (16*1024)
-#define MAXPARM 32
-
-#define SETUP_MODE_PAGE(NPAGE, NPARAM) \
- status = get_mode_page(NPAGE, page_code); \
- if (status) { printf("\n"); return status; } \
- bdlen = buffer[11]; \
- pagestart = buffer + 12 + bdlen;
-
-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 in_stop; /* | */
- pthread_mutex_t in_mutex; /* -/ */
- 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 out_stop; /* | */
- pthread_mutex_t out_mutex; /* | */
- pthread_cond_t out_sync_cv; /* -/ hold writes until "in order" */
- int bs;
- int bpt;
- int fua_mode;
- int dio;
- int dio_incomplete; /* -\ */
- int sum_of_resids; /* | */
- pthread_mutex_t aux_mutex; /* -/ (also serializes some printf()s */
- int coe;
- int cdbsz;
- int debug;
-} Rq_coll;
-
-typedef struct request_element { /* one instance per worker thread */
- 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[MAX_SCSI_CDBSZ];
- unsigned char sb[SENSE_BUFF_LEN];
- int bs;
- int fua_mode;
- int dio;
- int dio_incomplete;
- int resid;
- int in_scsi_type;
- int out_scsi_type;
- int cdbsz;
- int debug;
-} Rq_elem;
-
-typedef struct my_map_info {
- int active;
- int lin_dev_type;
- int oth_dev_num;
- struct sg_scsi_id sg_dat;
- char vendor[8];
- char product[16];
- char revision[4];
-} my_map_info_t;
-
-typedef struct sg_map {
- int bus;
- int channel;
- int target_id;
- int lun;
- char *dev_name;
-} Sg_map;
-
-typedef struct my_scsi_idlun {
-/* why can't userland see this structure ??? */
- int dev_id;
- int host_unique_id;
-} My_scsi_idlun;
-
-struct page_code_desc {
- int page_code;
- const char *desc;
-};
-
-static const char *pg_control_str_arr[] = {
- "current",
- "changeable",
- "default",
- "saved"
-};
-
-char *devices[] =
- { "/dev/sda", "/dev/sdb", "/dev/sdc", "/dev/sdd", "/dev/sde", "/dev/sdf",
- "/dev/sdg", "/dev/sdh", "/dev/sdi", "/dev/sdj", "/dev/sdk", "/dev/sdl",
- "/dev/sdm", "/dev/sdn", "/dev/sdo", "/dev/sdp", "/dev/sdq", "/dev/sdr",
- "/dev/sds", "/dev/sdt", "/dev/sdu", "/dev/sdv", "/dev/sdw", "/dev/sdx",
- "/dev/sdy", "/dev/sdz", "/dev/sdaa", "/dev/sdab", "/dev/sdac",
- "/dev/sdad",
- "/dev/scd0", "/dev/scd1", "/dev/scd2", "/dev/scd3", "/dev/scd4",
- "/dev/scd5",
- "/dev/scd6", "/dev/scd7", "/dev/scd8", "/dev/scd9", "/dev/scd10",
- "/dev/scd11",
- "/dev/sr0", "/dev/sr1", "/dev/sr2", "/dev/sr3", "/dev/sr4", "/dev/sr5",
- "/dev/sr6", "/dev/sr7", "/dev/sr8", "/dev/sr9", "/dev/sr10",
- "/dev/sr11",
- "/dev/nst0", "/dev/nst1", "/dev/nst2", "/dev/nst3", "/dev/nst4",
- "/dev/nst5",
- "/dev/nosst0", "/dev/nosst1", "/dev/nosst2", "/dev/nosst3",
- "/dev/nosst4"
-};
-
-static char *page_names[] = {
- NULL,
- "Read-Write Error Recovery",
- "Disconnect-Reconnect",
- "Format Device",
- "Rigid Disk Geometry",
- /* "Flexible Disk" */ NULL,
- NULL,
- "Verify Error Recovery",
- "Caching",
- "Peripheral Device",
- "Control Mode",
- /* "Medium Types Supported" */ NULL,
- "Notch and Partition",
- /* "CD-ROM" */ NULL,
- /* "CD-ROM Audio Control" */ NULL,
- NULL,
- /* "Medium Partition (1)" */ NULL,
- /* "Medium Partition (2)" */ NULL,
- /* "Medium Partition (3)" */ NULL,
- /* "Medium Partition (4)" */ NULL
-};
-
-#define MAX_PAGENO (sizeof(page_names)/sizeof(char *))
-
-/* Following 2 macros from D.R. Butenhof's POSIX threads book:
- ISBN 0-201-63392-2 . [Highly recommended book.] */
-#define err_exit(code,text) do { \
- fprintf(stderr, "%s at \"%s\":%d: %s\n", \
- text, __FILE__, __LINE__, strerror(code)); \
- exit(1); \
- } while (0)
-
-static Sg_map sg_map_arr[(sizeof(devices) / sizeof(char *)) + 1];
-
-static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
- 12, 12, 10, 10
-};
-const unsigned char rbCmdBlk[10] = { READ_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static const char *level_arr[LEVELS] = { "host", "bus", "target", "lun" };
-
-static const char *proc_allow_dio = "/proc/scsi/sg/allow_dio";
-static const char *devfs_id = "/dev/.devfsd";
-static my_map_info_t map_arr[MAX_SG_DEVS];
-static char ebuff[EBUFF_SZ];
-static int glob_fd;
-static char defectformat = 0x4;
-static sigset_t signal_set;
-static pthread_t sig_listen_thread_id;
-
-static int do_ide = 0;
-static int do_inq = 1;
-static int do_leaf = 1;
-static int do_extra = 1;
-static int do_quiet = 0;
-static int checked_sg = 1;
-static int sum_of_resids = 0;
-
-static int dd_count = -1;
-static int in_full = 0;
-static int in_partial = 0;
-static int out_full = 0;
-static int out_partial = 0;
-static int do_coe = 0;
-int base = READWRITE_BASE_NUM;
-unsigned char *cmpbuf = 0;
-static unsigned char buff_a[SIZEOF_BUFFER + SG_HSZ + 12];
-static unsigned char *buffer = buff_a + OFFSET_HEADER;
-
-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;
-
-// Prototypes
-int do_scsi_sgp_read_write(char *device);
-int do_scsi_sgm_read_write(char *device);
-void sg_in_operation(Rq_coll * clp, Rq_elem * rep);
-void sg_out_operation(Rq_coll * clp, Rq_elem * rep);
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
-void 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, pthread_mutex_t * a_mutp);
-int run_sg_scan_tests(void);
-int show_scsi_logs(char *device);
-int validate_device(char *device);
-int show_devfs_devices(void);
-void usage(void);
-int do_scsi_device_read_write(char *device);
-int do_scsi_inquiry(char *device, int hex_flag);
-int show_scsi_maps(void);
-int show_scsi_modes(char *device);
-int do_scsi_read_buffer(char *device);
-int show_scsi_read_capacity(char *device);
-int do_scsi_reset_devices(char *device, int reset_opts);
-int do_scsi_send_diagnostics(char *device);
-int do_scsi_start_stop(char *device, int startstop);
-int do_scsi_read_write_buffer(char *device);
-int do_scsi_test_unit_ready(char *device);
-int show_scsi_info(char *device);
-void print_msg(int msg_num, const char *msg);
-static void scan_dev_type(const char *leadin, int max_dev, int do_numeric,
- int lin_dev_type, int last_sg_ind);
-
-#ifdef SG_IO
-int sg3_inq(int sg_fd, unsigned char *inqBuff, int do_extra);
-#endif
-
-static unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
- { 0x12, 0, 0, 0, INQ_REPLY_LEN, 0 };
-
-void print_msg(int msg_num, const char *msg)
-{
- switch (msg_num) {
- case TEST_START:
- printf
- ("\n****************** Starting Tests ***************************\n");
- break;
- case TEST_STOP:
- printf
- ("\n****************** Tests Complete ***************************\n");
- break;
- case TEST_BREAK:
- printf("\n------------------ %s Test ------------------\n\n",
- msg);
- break;
- }
-}
-
-int main(int argc, char *argv[])
-{
- int rc = 0;
-
- if (argc < 2) {
- printf("\n\nERROR:No device passed to test\n\n");
- usage();
- return 1;
- }
-
- rc = validate_device(argv[1]);
- if (rc == 0) {
-
- print_msg(TEST_START, NULL);
-
- rc = run_sg_scan_tests();
- if (rc != 0) {
- printf("ERROR: run_sg_scan_tests failed %d\n", rc);
- }
-
- rc = show_scsi_logs(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_logs failed %d\n", rc);
- }
-
- rc = show_devfs_devices();
- if (rc != 0) {
- printf("ERROR: show_devfs_devices failed %d\n", rc);
- }
-
- rc = do_scsi_device_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_devices_read_write failed %d\n",
- rc);
- }
-
- rc = do_scsi_inquiry(argv[1], TRUE);
- if (rc != 0) {
- printf("ERROR: do_scsi_inquiry HEX failed %d\n", rc);
- } else {
- rc = do_scsi_inquiry(argv[1], FALSE);
- if (rc != 0) {
- printf("ERROR: do_scsi_inquiry PCI failed %d\n",
- rc);
- }
- }
-
- rc = show_scsi_maps();
- if (rc != 0) {
- printf("ERROR: show_scsi_maps failed %d\n", rc);
- }
-
- rc = show_scsi_modes(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_modes failed %d\n", rc);
- }
-
- rc = do_scsi_read_buffer(argv[1]);
- if (rc != 0 && rc != 1) {
- printf("ERROR: do_scsi_read_buffer failed %d\n", rc);
- }
-
- rc = show_scsi_read_capacity(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_read_capacity failed %d\n",
- rc);
- }
-
- rc |= do_scsi_reset_devices(argv[1], DEVICE_RESET);
- rc |= do_scsi_reset_devices(argv[1], BUS_RESET);
- rc |= do_scsi_reset_devices(argv[1], HOST_RESET);
- if (rc != 0) {
- printf("ERROR: do_scsi_reset_devices failed %d\n", rc);
- }
-
- rc = do_scsi_send_diagnostics(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_send_diagnostics failed %d\n",
- rc);
- }
-
- rc |= do_scsi_start_stop(argv[1], FALSE);
- rc |= do_scsi_start_stop(argv[1], TRUE);
- if (rc != 0) {
- printf("ERROR: do_scsi_start_top failed %d\n", rc);
- }
-
- rc = do_scsi_read_write_buffer(argv[1]);
- if (rc != 0 && rc != 1) {
- printf("ERROR: do_scsi_read_write_buffer failed %d\n",
- rc);
- }
-
- rc = do_scsi_test_unit_ready(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_test_unit_ready failed %d\n",
- rc);
- }
-
- rc = show_scsi_info(argv[1]);
- if (rc != 0) {
- printf("ERROR: show_scsi_info failed %d\n", rc);
- }
-
- rc = do_scsi_sgp_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_sgp_read_write failed %d\n", rc);
- }
-
- rc = do_scsi_sgm_read_write(argv[1]);
- if (rc != 0) {
- printf("ERROR: do_scsi_sgm_read_write failed %d\n", rc);
- }
-
- print_msg(TEST_STOP, NULL);
- } else {
- printf("\nERROR: Invalid device passed to test\n\n\n");
- usage();
-
- }
-
- return 0;
-}
-
-int validate_device(char *device)
-{
- int rc = 0;
- int i, found = FALSE;
- char device_string[25];
-
- for (i = 0; i < MAX_DEVICES && !found; i++) {
- sprintf(device_string, "/dev/sg%d", i);
- //printf("checking %s \n", device_string);
- if (strcmp(device, device_string) == 0) {
- found = TRUE;
- }
- }
-
- return rc;
-}
-
-void usage()
-{
- printf("Usage: 'sg_scan [-a] [-n] [-w] [-i] [-x]'\n");
- printf(" where: -a do alpha scan (ie sga, sgb, sgc)\n");
- printf(" -n do numeric scan (ie sg0, sg1...) [default]\n");
- printf(" -w force open with read/write flag\n");
- printf(" -i do SCSI INQUIRY, output results\n");
- printf(" -x extra information output about queuing\n\n\n");
-}
-
-void make_dev_name(char *fname, const char *leadin, int k, int do_numeric)
-{
- char buff[64];
- int big, little;
-
- strcpy(fname, leadin ? leadin : "/dev/sg");
- if (do_numeric) {
- sprintf(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 run_sg_scan_tests()
-{
- int sg_fd, res, k, f;
- unsigned char inqBuff[OFF + INQ_REPLY_LEN];
- int inqInLen = OFF + sizeof(inqCmdBlk);
- int inqOutLen = OFF + INQ_REPLY_LEN;
- unsigned char *buffp = inqBuff + OFF;
- struct sg_header *isghp = (struct sg_header *)inqBuff;
- int do_numeric = NUMERIC_SCAN_DEF;
- int do_inquiry = 0;
- int do_extra = 1;
- int writeable = 0;
- int num_errors = 0;
- int num_silent = 0;
- int eacces_err = 0;
- char fname[64];
- My_scsi_idlun my_idlun;
- int host_no;
- int flags;
- int emul;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- flags = writeable ? O_RDWR : OPEN_FLAG;
-
- do_numeric = 1;
- writeable = O_RDONLY;
- do_inquiry = 1;
- do_extra = 1;
-
- for (k = 0, res = 0; (k < 1000) && (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(ME "close error");
- return 1;
- }
- make_dev_name(fname, NULL, k, do_numeric);
-
- sg_fd = open(fname, flags | O_NONBLOCK);
- if (sg_fd < 0) {
- if (EBUSY == errno) {
- printf
- ("%s: device busy (O_EXCL lock), skipping\n",
- fname);
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- continue;
- } else {
- if (EACCES == errno)
- eacces_err = 1;
- snprintf(ebuff, EBUFF_SZ,
- ME "Error opening %s ", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "device %s failed on scsi ioctl, skip",
- fname);
- 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", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#ifdef SG_EMULATED_HOST
- res = ioctl(sg_fd, SG_EMULATED_HOST, &emul);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "device %s failed on sg ioctl(3), skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#else
- emul = 0;
-#endif
- printf("%s: scsi%d channel=%d id=%d lun=%d", fname, host_no,
- (my_idlun.dev_id >> 16) & 0xff, my_idlun.dev_id & 0xff,
- (my_idlun.dev_id >> 8) & 0xff);
- if (emul)
- printf(" [em]");
-#if 0
- printf(", huid=%d", my_idlun.host_unique_id);
-#endif
-#ifdef SG_GET_RESERVED_SIZE
- {
- 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 ioctls(4), skip", fname);
- 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");
-#endif
- if (!do_inquiry)
- continue;
-
-#ifdef SG_IO
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &f) >= 0) && (f >= 30000)) {
- res = sg3_inq(sg_fd, inqBuff, do_extra);
- continue;
- }
-#endif
- memset(isghp, 0, sizeof(struct sg_header));
- isghp->reply_len = inqOutLen;
- memcpy(inqBuff + OFF, inqCmdBlk, INQUIRY_CMDLEN);
-
- if (O_RDWR == (flags & O_ACCMODE)) { /* turn on blocking */
- f = fcntl(sg_fd, F_GETFL);
- fcntl(sg_fd, F_SETFL, f & (~O_NONBLOCK));
- } else {
- close(sg_fd);
- sg_fd = open(fname, O_RDWR);
- }
-
- res = write(sg_fd, inqBuff, inqInLen);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s writing, skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- res = read(sg_fd, inqBuff, inqOutLen);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "device %s reading, skip",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
-#ifdef SG_GET_RESERVED_SIZE
- if (!sg_chk_n_print("Error from Inquiry", isghp->target_status,
- isghp->host_status, isghp->driver_status,
- isghp->sense_buffer, SG_MAX_SENSE))
- continue;
-#else
- if ((isghp->result != 0) || (0 != isghp->sense_buffer[0])) {
- printf("Error from Inquiry: result=%d\n",
- isghp->result);
- if (0 != isghp->sense_buffer[0])
- sg_print_sense("Error from Inquiry",
- isghp->sense_buffer,
- SG_MAX_SENSE);
- continue;
- }
-#endif
- f = (int)*(buffp + 7);
- printf(" %.8s %.16s %.4s ", buffp + 8, buffp + 16,
- buffp + 32);
- printf("[wide=%d sync=%d cmdq=%d sftre=%d pq=0x%x]\n",
- ! !(f & 0x20), ! !(f & 0x10), ! !(f & 2), ! !(f & 1),
- (*buffp & 0xe0) >> 5);
- }
- if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
- printf("Stopping because there are too many error\n");
- if (eacces_err)
- printf(" root access may be required\n");
- }
- return 0;
-}
-
-#ifdef SG_IO
-int sg3_inq(int sg_fd, unsigned char *inqBuff, int do_extra)
-{
- sg_io_hdr_t io_hdr;
- unsigned char sense_buffer[32];
- int ok;
-
- 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_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 */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror(ME "Inquiry SG_IO ioctl error");
- return 1;
- }
-
- /* now for the error processing */
- ok = 0;
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- ok = 1;
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("INQUIRY command error", &io_hdr);
- break;
- }
-
- if (ok) { /* output result if it is available */
- char *p = (char *)inqBuff;
- int f = (int)*(p + 7);
- printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32);
- printf("[wide=%d sync=%d cmdq=%d sftre=%d pq=0x%x] ",
- ! !(f & 0x20), ! !(f & 0x10), ! !(f & 2), ! !(f & 1),
- (*p & 0xe0) >> 5);
- if (do_extra)
- printf("dur=%ums\n", io_hdr.duration);
- else
- printf("\n");
- }
- return 0;
-}
-#endif
-
-static int do_logs(int sg_fd, int ppc, int sp, int pc, int pg_code,
- int paramp, void *resp, int mx_resp_len, int noisy)
-{
- int res;
- unsigned char logsCmdBlk[LOG_SENSE_CMDLEN] =
- { LOG_SENSE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- logsCmdBlk[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0));
- logsCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- logsCmdBlk[5] = (unsigned char)((paramp >> 8) & 0xff);
- logsCmdBlk[6] = (unsigned char)(paramp & 0xff);
- if (mx_resp_len > 0xffff) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- logsCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- logsCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(logsCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = logsCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (log sense) error");
- return -1;
- }
-#if 0
- printf("SG_IO ioctl: status=%d, info=%d, sb_len_wr=%d\n",
- io_hdr.status, io_hdr.info, io_hdr.sb_len_wr);
-#endif
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, ME "ppc=%d, sp=%d, "
- "pc=%d, page_code=%x, paramp=%x\n ", ppc,
- sp, pc, pg_code, paramp);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static void dStrHex(const char *str, int len, int no_ascii)
-{
- 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 (no_ascii)
- buff[cpos++] = ' ';
- else {
- 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 void show_page_name(int page_no)
-{
- switch (page_no) {
- case 0x0:
- printf(" 0x00 Supported log pages\n");
- break;
- case 0x1:
- printf(" 0x01 Buffer over-run/under-run\n");
- break;
- case 0x2:
- printf(" 0x02 Error counters (write)\n");
- break;
- case 0x3:
- printf(" 0x03 Error counters (read)\n");
- break;
- case 0x4:
- printf(" 0x04 Error counters (read reverse)\n");
- break;
- case 0x5:
- printf(" 0x05 Error counters (verify)\n");
- break;
- case 0x6:
- printf(" 0x06 Non-medium errors\n");
- break;
- case 0x7:
- printf(" 0x07 Last n error events\n");
- break;
- case 0x8:
- printf(" 0x08 Format status (sbc2)\n");
- break;
- case 0xb:
- printf(" 0x0b Last n deferred errors of "
- "asynchronous events\n");
- break;
- case 0xc:
- printf(" 0x0c Sequential Access (ssc-2)\n");
- break;
- case 0xd:
- printf(" 0x0d Temperature\n");
- break;
- case 0xe:
- printf(" 0x0e Start-stop cycle counter\n");
- break;
- case 0xf:
- printf(" 0x0f Application client\n");
- break;
- case 0x10:
- printf(" 0x10 Self-test results\n");
- break;
- case 0x18:
- printf(" 0x18 Protocol specific port\n");
- break;
- case 0x2e:
- printf(" 0x2e Tape alerts (ssc-2)\n");
- break;
- case 0x2f:
- printf(" 0x2f Informational exceptions (SMART)\n");
- break;
- default:
- printf(" 0x%.2x\n", page_no);
- break;
- }
-}
-
-static void show_buffer_under_overrun_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, count_basis, cause;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- printf("Buffer over-run/under-run page\n");
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pl = ucp[3] + 4;
- count_basis = (ucp[1] >> 5) & 0x7;
- printf(" Count basis: ");
- switch (count_basis) {
- case 0:
- printf("undefined");
- break;
- case 1:
- printf("per command");
- break;
- case 2:
- printf("per failed reconnect");
- break;
- case 3:
- printf("per unit of time");
- break;
- default:
- printf("reserved [0x%x]", count_basis);
- break;
- }
- cause = (ucp[1] >> 1) & 0xf;
- printf(", Cause: ");
- switch (cause) {
- case 0:
- printf("bus busy");
- break;
- case 1:
- printf("transfer rate too slow");
- break;
- default:
- printf("reserved [0x%x]", cause);
- break;
- }
- printf(", Type: ");
- if (ucp[1] & 1)
- printf("over-run");
- else
- printf("under-run");
- printf(", count");
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-static void show_error_counter_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, pc;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- switch (resp[0]) {
- case 2:
- printf("Write error counter page\n");
- break;
- case 3:
- printf("Read error counter page\n");
- break;
- case 4:
- printf("Read Reverse error counter page\n");
- break;
- case 5:
- printf("Verify error counter page\n");
- break;
- default:
- printf("expecting error counter page, got page=0x%x\n",
- resp[0]);
- return;
- }
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pc = (ucp[0] << 8) | ucp[1];
- pl = ucp[3] + 4;
- switch (pc) {
- case 0:
- printf(" Errors corrected without substantion delay");
- break;
- case 1:
- printf(" Errors corrected with possible delays");
- break;
- case 2:
- printf(" Total operations");
- break;
- case 3:
- printf(" Total errors corrected");
- break;
- case 4:
- printf(" Total times correction algorithm processed");
- break;
- case 5:
- printf(" Total bytes processed");
- break;
- case 6:
- printf(" Total uncorrected errors");
- break;
- default:
- printf(" Reserved or vendor specific [0x%x]", pc);
- break;
- }
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-static void show_non_medium_error_page(unsigned char *resp, int len)
-{
- int k, j, num, pl, pc;
- unsigned char *ucp;
- unsigned char *xp;
- unsigned long long ull;
-
- printf("Non-medium error page\n");
- num = len - 4;
- ucp = &resp[0] + 4;
- while (num > 3) {
- pc = (ucp[0] << 8) | ucp[1];
- pl = ucp[3] + 4;
- switch (pc) {
- case 0:
- printf(" Non-medium error count");
- break;
- default:
- if (pc <= 0x7fff)
- printf(" Reserved [0x%x]", pc);
- else
- printf(" Vendor specific [0x%x]", pc);
- break;
- }
- k = pl - 4;
- xp = ucp + 4;
- if (k > sizeof(ull)) {
- xp += (k - sizeof(ull));
- k = sizeof(ull);
- }
- ull = 0;
- for (j = 0; j < k; ++j) {
- if (j > 0)
- ull <<= 8;
- ull |= xp[j];
- }
- printf(" = %llu\n", ull);
- num -= pl;
- ucp += pl;
- }
-}
-
-const char *self_test_code[] = {
- "default", "background short", "background extended", "reserved",
- "aborted background", "foreground short", "foreground extended",
- "reserved"
-};
-
-const char *self_test_result[] = {
- "completed without error",
- "aborted by SEND DIAGNOSTIC",
- "aborted other than by SEND DIAGNOSTIC",
- "unknown error, unable to complete",
- "self test completed with failure in test segment (which one unkown)",
- "first segment in self test failed",
- "second segment in self test failed",
- "another segment in self test failed",
- "reserved", "reserved", "reserved", "reserved", "reserved", "reserved",
- "reserved",
- "self test in progress"
-};
-
-static void show_self_test_page(unsigned char *resp, int len)
-{
- int k, num, n, res;
- unsigned char *ucp;
- unsigned long long ull;
-
- num = len - 4;
- if (num < 0x190) {
- printf("badly formed self-test results page\n");
- return;
- }
- printf("Self-test results page\n");
- for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20) {
- n = (ucp[6] << 8) | ucp[7];
- if ((0 == n) && (0 == ucp[4]))
- break;
- printf(" Parameter code=%d, accumulated power-on hours=%d\n",
- (ucp[0] << 8) | ucp[1], n);
- printf(" self test code: %s [%d]\n",
- self_test_code[(ucp[4] >> 5) & 0x7],
- (ucp[4] >> 5) & 0x7);
- res = ucp[4] & 0xf;
- printf(" self test result: %s [%d]\n",
- self_test_result[res], res);
- if (ucp[5])
- printf(" self-test number=%d\n", (int)ucp[5]);
- ull = ucp[8];
- ull <<= 8;
- ull |= ucp[9];
- ull <<= 8;
- ull |= ucp[10];
- ull <<= 8;
- ull |= ucp[11];
- ull <<= 8;
- ull |= ucp[12];
- ull <<= 8;
- ull |= ucp[13];
- ull <<= 8;
- ull |= ucp[14];
- ull <<= 8;
- ull |= ucp[14];
- ull <<= 8;
- ull |= ucp[15];
- if ((0xffffffffffffffffULL != ull) && (res > 0) && (res < 0xf))
- printf(" address of first error=0x%llx\n", ull);
- if (ucp[16] & 0xf)
- printf(" sense key=0x%x, asc=0x%x, asq=0x%x\n",
- ucp[16] & 0xf, ucp[17], ucp[18]);
- }
-}
-
-static void show_Temperature_page(unsigned char *resp, int len, int hdr)
-{
- int k, num, extra, pc;
- unsigned char *ucp;
-
- num = len - 4;
- ucp = &resp[0] + 4;
- if (num < 4) {
- printf("badly formed Temperature log page\n");
- return;
- }
- if (hdr)
- printf("Temperature log page\n");
- for (k = num; k > 0; k -= extra, ucp += extra) {
- if (k < 3) {
- printf("short Temperature log page\n");
- return;
- }
- extra = ucp[3] + 4;
- pc = ((ucp[0] << 8) & 0xff) + ucp[1];
- if (0 == pc) {
- if (extra > 5) {
- if (ucp[5] < 0xff)
- printf(" Current temperature= %d C\n",
- ucp[5]);
- else
- printf
- (" Current temperature=<not available>\n");
- }
- } else if (1 == pc) {
- if (extra > 5) {
- if (ucp[5] < 0xff)
- printf
- (" Reference temperature= %d C\n",
- ucp[5]);
- else
- printf
- (" Reference temperature=<not available>\n");
- }
-
- } else {
- printf(" parameter code=0x%x, contents in hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
- }
- }
-}
-
-static void show_IE_page(unsigned char *resp, int len, int full)
-{
- int k, num, extra, pc;
- unsigned char *ucp;
-
- num = len - 4;
- ucp = &resp[0] + 4;
- if (num < 4) {
- printf("badly formed Informational Exceptions log page\n");
- return;
- }
- if (full)
- printf("Informational Exceptions log page\n");
- for (k = num; k > 0; k -= extra, ucp += extra) {
- if (k < 3) {
- printf("short Informational Exceptions log page\n");
- return;
- }
- extra = ucp[3] + 4;
- pc = ((ucp[0] << 8) & 0xff) + ucp[1];
- if (0 == pc) {
- if (extra > 5) {
- if (full)
- printf(" IE asc=0x%x, ascq=0x%x",
- ucp[4], ucp[5]);
- if (extra > 6) {
- if (full)
- printf(",");
- if (ucp[6] < 0xff)
- printf
- (" Current temperature=%d C",
- ucp[6]);
- else
- printf
- (" Current temperature=<not available>");
- }
- printf("\n");
- }
- } else if (full) {
- printf(" parameter code=0x%x, contents in hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
- }
- }
-}
-
-static void show_ascii_page(unsigned char *resp, int len)
-{
- int k, n, num;
-
- if (len < 0) {
- printf("response has bad length\n");
- return;
- }
- num = len - 4;
- switch (resp[0]) {
- case 0:
- printf("Supported pages:\n");
- for (k = 0; k < num; ++k)
- show_page_name((int)resp[4 + k]);
- break;
- case 0x1:
- show_buffer_under_overrun_page(resp, len);
- break;
- case 0x2:
- case 0x3:
- case 0x4:
- case 0x5:
- show_error_counter_page(resp, len);
- break;
- case 0x6:
- show_non_medium_error_page(resp, len);
- break;
- case 0xd:
- show_Temperature_page(resp, len, 1);
- break;
- case 0xe:
- if (len < 40) {
- printf("badly formed start-stop cycle counter page\n");
- break;
- }
- printf("Start-stop cycle counter page\n");
- printf(" Date of manufacture, year: %.4s, week: %.2s\n",
- &resp[8], &resp[12]);
- printf(" Accounting date, year: %.4s, week: %.2s\n",
- &resp[18], &resp[22]);
- n = (resp[28] << 24) | (resp[29] << 16) | (resp[30] << 8) |
- resp[31];
- printf(" Specified cycle count over device lifetime=%d\n", n);
- n = (resp[36] << 24) | (resp[37] << 16) | (resp[38] << 8) |
- resp[39];
- printf(" Accumulated start-stop cycles=%d\n", n);
- break;
- case 0x10:
- show_self_test_page(resp, len);
- break;
- case 0x2f:
- show_IE_page(resp, len, 1);
- break;
- default:
- printf("No ascii information for page=0x%x, here is hex:\n",
- resp[0]);
- dStrHex((const char *)resp, len, 1);
- break;
- }
-}
-
-static int fetchTemperature(int sg_fd, int do_hex, unsigned char *resp,
- int max_len)
-{
- int res = 0;
-
- if (0 == do_logs(sg_fd, 0, 0, 1, 0xd, 0, resp, max_len, 0))
- show_Temperature_page(resp, (resp[2] << 8) + resp[3] + 4, 0);
- else if (0 == do_logs(sg_fd, 0, 0, 1, 0x2f, 0, resp, max_len, 0))
- show_IE_page(resp, (resp[2] << 8) + resp[3] + 4, 0);
- else {
- printf
- ("Unable to find temperature in either log page (temperature "
- "or IE)\n");
- res = 1;
- }
- close(sg_fd);
- return res;
-}
-
-int show_scsi_logs(char *device)
-{
- int sg_fd, k, pg_len;
- char *file_name = 0;
- unsigned char rsp_buff[MX_ALLOC_LEN];
- int pg_code = 0;
- int pc = 1; /* N.B. some disks only give data for current cumulative */
- int paramp = 0;
- int do_list = 0;
- int do_ppc = 0;
- int do_sp = 0;
- int do_hex = 0;
- int do_all = 1;
- int do_temp = 0;
- int oflags = O_RDWR | O_NONBLOCK;
-
- file_name = device;
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "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(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- if (do_list || do_all)
- pg_code = PG_CODE_ALL;
- pg_len = 0;
- if (1 == do_temp)
- return fetchTemperature(sg_fd, do_hex, rsp_buff, MX_ALLOC_LEN);
-
- if (0 == do_logs(sg_fd, do_ppc, do_sp, pc, pg_code, paramp,
- rsp_buff, MX_ALLOC_LEN, 1)) {
- pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
- if ((pg_len + 4) > MX_ALLOC_LEN) {
- printf
- ("Only fetched %d bytes of response, truncate output\n",
- MX_ALLOC_LEN);
- pg_len = MX_ALLOC_LEN - 4;
- }
- if (do_hex) {
- printf("Returned log page code=0x%x, page len=0x%x\n",
- rsp_buff[0], pg_len);
- dStrHex((const char *)rsp_buff, pg_len + 4, 1);
- } else
- show_ascii_page(rsp_buff, pg_len + 4);
- }
- if (do_all && (pg_len > 1)) {
- int my_len = pg_len - 1;
- unsigned char parr[256];
-
- memcpy(parr, rsp_buff + 5, my_len);
- for (k = 0; k < my_len; ++k) {
- printf("\n");
- pg_code = parr[k];
- if (0 ==
- do_logs(sg_fd, do_ppc, do_sp, pc, pg_code, paramp,
- rsp_buff, MX_ALLOC_LEN, 1)) {
- pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
- if ((pg_len + 4) > MX_ALLOC_LEN) {
- printf
- ("Only fetched %d bytes of response, truncate "
- "output\n", MX_ALLOC_LEN);
- pg_len = MX_ALLOC_LEN - 4;
- }
- if (do_hex) {
- printf
- ("Returned log page code=0x%x, page len=0x%x\n",
- rsp_buff[0], pg_len);
- dStrHex((const char *)rsp_buff,
- pg_len + 4, 1);
- } else
- show_ascii_page(rsp_buff, pg_len + 4);
- }
- }
- }
- close(sg_fd);
- return 0;
-}
-
-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_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- sg_chk_n_print3("Failed INQUIRY", &io_hdr);
- 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 = 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);
- dStrHex(buff, 64, 0);
- }
-}
-
-/* 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 = 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;
-}
-
-int show_devfs_devices()
-{
- int res;
- char ds_root[D_ROOT_SZ];
- char di_root[D_ROOT_SZ];
- unsigned int larr[LEVELS];
- struct stat st;
-
- print_msg(TEST_BREAK, __FUNCTION__);
- strncpy(ds_root, "/dev", D_ROOT_SZ);
-
- 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,"
- " attempting to continue ...\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_ide = TRUE;
- 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;
-}
-
-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()
-{
- if (0 != dd_count)
- fprintf(stderr, " remaining block count=%d\n", dd_count);
- fprintf(stderr, "%d+%d records in\n", in_full - in_partial, in_partial);
- fprintf(stderr, "%d+%d records out\n", out_full - out_partial,
- 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;
- size_t len = strlen(filename);
-
- if ((1 == len) && ('.' == filename[0]))
- return FT_DEV_NULL;
- if (stat(filename, &st) < 0)
- return FT_OTHER;
- if (S_ISCHR(st.st_mode)) {
- if ((MEM_MAJOR == major(st.st_rdev)) &&
- (DEV_NULL_MINOR_NUM == minor(st.st_rdev)))
- return FT_DEV_NULL;
- if (RAW_MAJOR == major(st.st_rdev))
- return FT_RAW;
- if (SCSI_GENERIC_MAJOR == major(st.st_rdev))
- return FT_SG;
- if (SCSI_TAPE_MAJOR == major(st.st_rdev))
- return FT_ST;
- } else if (S_ISBLK(st.st_mode))
- return FT_BLOCK;
- return FT_OTHER;
-}
-
-int read_capacity(int sg_fd, int *num_sect, int *sect_sz)
-{
- int res;
- unsigned char rcCmdBlk[10] =
- { READ_CAPACITY, 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_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];
- return 0;
-}
-
-/* Return of 0 -> success, -1 -> failure, 2 -> try again */
-int sync_cache(int sg_fd)
-{
- int res;
- unsigned char scCmdBlk[10] = { SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0,
- 0, 0, 0
- };
- 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(scCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = scCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("synchronize_cache (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("synchronize cache", &io_hdr);
- return -1;
- }
- return 0;
-}
-
-int sg_build_scsi_cdb(unsigned char *cdbp, int cdb_sz, unsigned int blocks,
- unsigned int start_block, int write_true, int fua,
- int dpo)
-{
- int rd_opcode[] = { 0x8, 0x28, 0xa8, 0x88 };
- int wr_opcode[] = { 0xa, 0x2a, 0xaa, 0x8a };
- int sz_ind;
-
- memset(cdbp, 0, cdb_sz);
- if (dpo)
- cdbp[1] |= 0x10;
- if (fua)
- cdbp[1] |= 0x8;
- switch (cdb_sz) {
- case 6:
- sz_ind = 0;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[1] = (unsigned char)((start_block >> 16) & 0x1f);
- cdbp[2] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[3] = (unsigned char)(start_block & 0xff);
- cdbp[4] = (256 == blocks) ? 0 : (unsigned char)blocks;
- if (blocks > 256) {
- fprintf(stderr,
- ME "for 6 byte commands, maximum number of "
- "blocks is 256\n");
- return 1;
- }
- if ((start_block + blocks - 1) & (~0x1fffff)) {
- fprintf(stderr,
- ME "for 6 byte commands, can't address blocks"
- " beyond %d\n", 0x1fffff);
- return 1;
- }
- if (dpo || fua) {
- fprintf(stderr,
- ME "for 6 byte commands, neither dpo nor fua"
- " bits supported\n");
- return 1;
- }
- break;
- case 10:
- sz_ind = 1;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[2] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[3] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[4] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[5] = (unsigned char)(start_block & 0xff);
- cdbp[7] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[8] = (unsigned char)(blocks & 0xff);
- if (blocks & (~0xffff)) {
- fprintf(stderr,
- ME "for 10 byte commands, maximum number of "
- "blocks is %d\n", 0xffff);
- return 1;
- }
- break;
- case 12:
- sz_ind = 2;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- cdbp[2] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[3] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[4] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[5] = (unsigned char)(start_block & 0xff);
- cdbp[6] = (unsigned char)((blocks >> 24) & 0xff);
- cdbp[7] = (unsigned char)((blocks >> 16) & 0xff);
- cdbp[8] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[9] = (unsigned char)(blocks & 0xff);
- break;
- case 16:
- sz_ind = 3;
- cdbp[0] = (unsigned char)(write_true ? wr_opcode[sz_ind] :
- rd_opcode[sz_ind]);
- /* can't cope with block number > 32 bits (yet) */
- cdbp[6] = (unsigned char)((start_block >> 24) & 0xff);
- cdbp[7] = (unsigned char)((start_block >> 16) & 0xff);
- cdbp[8] = (unsigned char)((start_block >> 8) & 0xff);
- cdbp[9] = (unsigned char)(start_block & 0xff);
- cdbp[10] = (unsigned char)((blocks >> 24) & 0xff);
- cdbp[11] = (unsigned char)((blocks >> 16) & 0xff);
- cdbp[12] = (unsigned char)((blocks >> 8) & 0xff);
- cdbp[13] = (unsigned char)(blocks & 0xff);
- break;
- default:
- fprintf(stderr,
- ME "expected cdb size of 6, 10, 12, or 16 but got"
- "=%d\n", cdb_sz);
- return 1;
- }
- 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 cdbsz, int fua, int *diop)
-{
- unsigned char rdCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- if (sg_build_scsi_cdb(rdCmd, cdbsz, blocks, from_block, 0, fua, 0)) {
- fprintf(stderr,
- ME "bad rd cdb build, from_block=%d, blocks=%d\n",
- from_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- 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;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr)) {
- if (ENOMEM == errno)
- return 1;
- perror("reading (SG_IO) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while reading block=%d, num=%d\n",
- from_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("reading", &io_hdr);
- if (do_coe) {
- memset(buff, 0, bs * blocks);
- fprintf(stderr, ">> unable to read at blk=%d for "
- "%d bytes, use zeros\n", from_block,
- bs * blocks);
- return 0; /* fudge success */
- } else
- 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
- fprintf(stderr, "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 cdbsz, int fua, int *diop)
-{
- unsigned char wrCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- if (sg_build_scsi_cdb(wrCmd, cdbsz, blocks, to_block, 1, fua, 0)) {
- fprintf(stderr, ME "bad wr cdb build, to_block=%d, blocks=%d\n",
- to_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- 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;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr)) {
- if (ENOMEM == errno)
- return 1;
- perror("writing (SG_IO) on sg device, error");
- return -1;
- }
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while writing block=%d, num=%d\n",
- to_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("writing", &io_hdr);
- if (do_coe) {
- fprintf(stderr, ">> ignored errors for out blk=%d for "
- "%d bytes\n", to_block, bs * blocks);
- return 0; /* fudge success */
- } else
- 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 get_num(char *buf)
-{
- int res, num;
- char c;
-
- res = sscanf(buf, "%d%c", &num, &c);
- if (0 == res)
- return -1;
- else if (1 == res)
- return num;
- else {
- switch (c) {
- case 'c':
- case 'C':
- return num;
- case 'b':
- case 'B':
- return num * 512;
- case 'k':
- return num * 1024;
- case 'K':
- return num * 1000;
- case 'm':
- return num * 1024 * 1024;
- case 'M':
- return num * 1000000;
- case 'g':
- return num * 1024 * 1024 * 1024;
- case 'G':
- return num * 1000000000;
- default:
- fprintf(stderr, "unrecognized multiplier\n");
- return -1;
- }
- }
-}
-
-int do_scsi_device_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int bs = 0;
- int ibs = 0;
- int obs = 0;
- int bpt = DEF_BLOCKS_PER_TRANSFER;
- char inf[INOUTF_SZ];
- int in_type = FT_OTHER;
- char outf[INOUTF_SZ];
- int out_type = FT_OTHER;
- int dio = 0;
- int dio_incomplete = 0;
- int do_time = 1;
- int do_odir = 1;
- int scsi_cdbsz = DEF_SCSI_CDBSZ;
- int fua_mode = 0;
- int do_sync = 1;
- int do_blk_sgio = 1;
- int do_append = 1;
- int res, 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;
- char ebuff[EBUFF_SZ];
- int blocks_per;
- int req_count;
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- if (bs <= 0) {
- bs = DEF_BLOCK_SIZE;
- fprintf(stderr,
- "Assume default 'bs' (block size) of %d bytes\n", bs);
- }
- if ((ibs && (ibs != bs)) || (obs && (obs != 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 ((do_append > 0) && (seek > 0)) {
- fprintf(stderr, "Can't use both append and seek switches\n");
- return 1;
- }
-#ifdef SG_DEBUG
- fprintf(stderr, ME "if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, dd_count);
-#endif
- install_handler(SIGINT, interrupt_handler);
- install_handler(SIGQUIT, interrupt_handler);
- install_handler(SIGPIPE, interrupt_handler);
- install_handler(SIGUSR1, siginfo_handler);
-
- infd = STDIN_FILENO;
- outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- in_type = dd_filetype(inf);
-
- if ((FT_BLOCK & in_type) && do_blk_sgio)
- in_type |= FT_SG;
-
- if (FT_ST == in_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG & in_type) {
- if ((infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading",
- inf);
- perror(ebuff);
- return 1;
- }
- t = bs * bpt;
- res = ioctl(infd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- if (FT_BLOCK & in_type)
- fprintf(stderr,
- ME
- "SG_IO unsupported on this block"
- " device\n");
- else
- fprintf(stderr,
- ME
- "sg driver prior to 3.x.y\n");
- return 1;
- }
- } else {
- if (do_odir && (FT_BLOCK == in_type))
- infd = open(inf, O_RDONLY | O_DIRECT);
- else
- infd = open(inf, O_RDONLY);
- if (infd < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading",
- inf);
- perror(ebuff);
- return 1;
- } else if (skip > 0) {
- llse_loff_t offset = skip;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't skip to required position on %s",
- inf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
-
- if (outf[0] && ('-' != outf[0])) {
- out_type = dd_filetype(outf);
-
- if ((FT_BLOCK & out_type) && do_blk_sgio)
- out_type |= FT_SG;
-
- if (FT_ST == out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG & out_type) {
- if ((outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg writing",
- outf);
- perror(ebuff);
- return 1;
- }
- t = bs * bpt;
- res = ioctl(outfd, SG_SET_RESERVED_SIZE, &t);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr,
- ME "sg driver prior to 3.x.y\n");
- return 1;
- }
- } else if (FT_DEV_NULL & out_type)
- outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != out_type) {
- int flags = O_WRONLY | O_CREAT;
-
- if (do_odir && (FT_BLOCK == out_type))
- flags |= O_DIRECT;
- else if (do_append)
- flags |= O_APPEND;
- if ((outfd = open(outf, flags, 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for raw writing",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- if (seek > 0) {
- llse_loff_t offset = seek;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "couldn't seek to required position on %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
- fprintf(stderr,
- "Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
-
- if (dd_count < 0) {
- if (FT_SG & in_type) {
- res = read_capacity(infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res =
- read_capacity(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 & out_type) {
- res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(out), continuing\n");
- res =
- read_capacity(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;
- }
- }
-#ifdef SG_DEBUG
- fprintf(stderr,
- "Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- dd_count, in_num_sect, out_num_sect);
-#endif
- 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 (dd_count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
-
- if (dio || do_odir || (FT_RAW == in_type) || (FT_RAW == out_type)) {
- size_t psz = getpagesize();
- wrkBuff = malloc(bs * bpt + psz);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory for raw\n");
- return 1;
- }
- wrkPos = (unsigned char *)(((unsigned long)wrkBuff + psz - 1) &
- (~(psz - 1)));
- } else {
- wrkBuff = malloc(bs * bpt);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory\n");
- return 1;
- }
- wrkPos = wrkBuff;
- }
-
- blocks_per = bpt;
-#ifdef SG_DEBUG
- fprintf(stderr, "Start of loop, count=%d, blocks_per=%d\n",
- dd_count, blocks_per);
-#endif
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- req_count = dd_count;
-
- while (dd_count > 0) {
- blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
- if (FT_SG & in_type) {
- int fua = fua_mode & 2;
-
- dio_tmp = dio;
- res =
- sg_read(infd, wrkPos, blocks, skip, bs, scsi_cdbsz,
- fua, &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;
- fprintf(stderr,
- "Reducing read to %d blocks per loop\n",
- blocks_per);
- res =
- sg_read(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (r)\n");
- res =
- sg_read(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, &dio_tmp);
- }
- if (0 != res) {
- fprintf(stderr, "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) {
- snprintf(ebuff, EBUFF_SZ,
- ME "reading, skip=%d ", skip);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- dd_count = 0;
- blocks = res / bs;
- if ((res % bs) > 0) {
- blocks++;
- in_partial++;
- }
- }
- in_full += blocks;
- }
-
- if (FT_SG & out_type) {
- int fua = fua_mode & 1;
-
- dio_tmp = dio;
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &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;
- fprintf(stderr,
- "Reducing write to %d blocks per loop\n",
- blocks);
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (w)\n");
- res =
- sg_write(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, &dio_tmp);
- } else if (0 != res) {
- fprintf(stderr, "sg_write failed, seek=%d\n",
- seek);
- break;
- } else {
- out_full += blocks;
- if (dio && (0 == dio_tmp))
- dio_incomplete++;
- }
- } else if (FT_DEV_NULL & out_type)
- out_full += blocks; /* act as if written out without error */
- else {
- while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "writing, seek=%d ", seek);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- fprintf(stderr,
- "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 (dd_count > 0)
- dd_count -= blocks;
- skip += blocks;
- seek += blocks;
- }
- 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)bs *(req_count - dd_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 (do_sync) {
- if (FT_SG & out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
- free(wrkBuff);
- if (STDIN_FILENO != infd)
- close(infd);
- if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
- close(outfd);
- res = 0;
- if (0 != dd_count) {
- fprintf(stderr, "Some error occurred,");
- res = 2;
- }
- print_stats();
- if (dio_incomplete) {
- int fd;
- char c;
-
- fprintf(stderr,
- ">> Direct IO requested but incomplete %d times\n",
- 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 (sum_of_resids)
- fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
- sum_of_resids);
- return res;
-}
-
-/* Returns 0 when successful, else -1 */
-static int do_scsi_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
- void *resp, int mx_resp_len, int noisy)
-{
- 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;
-
- if (cmddt)
- inqCmdBlk[1] |= 2;
- if (evpd)
- inqCmdBlk[1] |= 1;
- inqCmdBlk[2] = (unsigned char)pg_op;
- 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_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_b;
- 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_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Inquiry error, CmdDt=%d, "
- "EVPD=%d, page_opcode=%x ", cmddt, evpd,
- pg_op);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-int do_scsi_inquiry(char *device, int hex_flag)
-{
- int sg_fd, k, j, num, len, act_len;
- int support_num;
- char *file_name = 0;
- char buff[MX_ALLOC_LEN + 1];
- unsigned char rsp_buff[MX_ALLOC_LEN + 1];
- unsigned int num_opcode = 0;
- int do_evpd = 0;
- int do_cmddt = 0;
- int do_cmdlst = 0;
- int do_hex = 0;
- int do_raw = 0;
- int do_pci = 0;
- int do_36 = 0;
- int oflags = O_RDONLY | O_NONBLOCK;
- int ansi_version = 0;
- int ret = 0;
-
- file_name = device;
-
- if (hex_flag) {
- do_hex = TRUE;
- print_msg(TEST_BREAK, __FUNCTION__);
- } else {
- do_pci = TRUE;
- }
-
- if (do_pci)
- oflags = O_RDWR | O_NONBLOCK;
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, "sg_inq: 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)) {
- fprintf(stderr,
- "sg_inq: %s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- memset(rsp_buff, 0, MX_ALLOC_LEN + 1);
-
- if (!(do_cmddt || do_evpd)) {
- if (!do_raw)
- printf("standard INQUIRY:\n");
- if (num_opcode > 0)
- printf
- (" <<given opcode or page_code is being ignored>>\n");
-
- if (0 == do_scsi_inq(sg_fd, 0, 0, 0, rsp_buff, 36, 1)) {
- len = rsp_buff[4] + 5;
- ansi_version = rsp_buff[2] & 0x7;
- if ((len > 36) && (len < 256) && (!do_36)) {
- if (do_scsi_inq
- (sg_fd, 0, 0, 0, rsp_buff, len, 1)) {
- fprintf(stderr,
- "second INQUIRY (%d byte) failed\n",
- len);
- return 1;
- }
- if (len != (rsp_buff[4] + 5)) {
- fprintf(stderr,
- "strange, twin INQUIRYs yield different "
- "'additional length'\n");
- ret = 2;
- }
- }
- if (do_36) {
- act_len = len;
- len = 36;
- } else
- act_len = len;
- if (do_hex)
- dStrHex((const char *)rsp_buff, len, 0);
- else {
- printf
- (" PQual=%d, Device type=%d, RMB=%d, ANSI version=%d, ",
- (rsp_buff[0] & 0xe0) >> 5,
- rsp_buff[0] & 0x1f,
- ! !(rsp_buff[1] & 0x80), ansi_version);
- printf("[full version=0x%02x]\n",
- (unsigned int)rsp_buff[2]);
- printf
- (" AERC=%d, TrmTsk=%d, NormACA=%d, HiSUP=%d, "
- "Resp data format=%d, SCCS=%d\n",
- ! !(rsp_buff[3] & 0x80),
- ! !(rsp_buff[3] & 0x40),
- ! !(rsp_buff[3] & 0x20),
- ! !(rsp_buff[3] & 0x10),
- rsp_buff[3] & 0x0f,
- ! !(rsp_buff[5] & 0x80));
- printf
- (" BQue=%d, EncServ=%d, MultiP=%d, MChngr=%d, "
- "ACKREQQ=%d, ", ! !(rsp_buff[6] & 0x80),
- ! !(rsp_buff[6] & 0x40),
- ! !(rsp_buff[6] & 0x10),
- ! !(rsp_buff[6] & 0x08),
- ! !(rsp_buff[6] & 0x04));
- printf("Addr16=%d\n RelAdr=%d, ",
- ! !(rsp_buff[6] & 0x01),
- ! !(rsp_buff[7] & 0x80));
- printf
- ("WBus16=%d, Sync=%d, Linked=%d, TranDis=%d, ",
- ! !(rsp_buff[7] & 0x20),
- ! !(rsp_buff[7] & 0x10),
- ! !(rsp_buff[7] & 0x08),
- ! !(rsp_buff[7] & 0x04));
- printf("CmdQue=%d\n", ! !(rsp_buff[7] & 0x02));
- if (len > 56)
- printf
- (" Clocking=0x%x, QAS=%d, IUS=%d\n",
- (rsp_buff[56] & 0x0c) >> 2,
- ! !(rsp_buff[56] & 0x2),
- ! !(rsp_buff[56] & 0x1));
- if (act_len == len)
- printf(" length=%d (0x%x)", len,
- len);
- else
- printf
- (" length=%d (0x%x), but only read 36 bytes",
- len, len);
- if ((ansi_version >= 2) && (len < 36))
- printf
- (" [for SCSI>=2, len>=36 is expected]\n");
- else
- printf("\n");
-
- if (len <= 8)
- printf
- (" Inquiry response length=%d\n, no vendor, "
- "product or revision data\n", len);
- else {
- if (len < 36)
- rsp_buff[len] = '\0';
- memcpy(buff, &rsp_buff[8], 8);
- buff[8] = '\0';
- printf(" Vendor identification: %s\n",
- buff);
- if (len <= 16)
- printf
- (" Product identification: <none>\n");
- else {
- memcpy(buff, &rsp_buff[16], 16);
- buff[16] = '\0';
- printf
- (" Product identification: %s\n",
- buff);
- }
- if (len <= 32)
- printf
- (" Product revision level: <none>\n");
- else {
- memcpy(buff, &rsp_buff[32], 4);
- buff[4] = '\0';
- printf
- (" Product revision level: %s\n",
- buff);
- }
- }
- }
- if (!do_raw &&
- (0 ==
- do_scsi_inq(sg_fd, 0, 1, 0x80, rsp_buff,
- MX_ALLOC_LEN, 0))) {
- len = rsp_buff[3];
- if (len > 0) {
- memcpy(buff, rsp_buff + 4, len);
- buff[len] = '\0';
- printf(" Product serial number: %s\n",
- buff);
- }
- }
- } else {
- printf("36 byte INQUIRY failed\n");
- return 1;
- }
- } else if (do_cmddt) {
- int reserved_cmddt;
- char op_name[128];
-
- if (do_cmdlst) {
- printf("Supported command list:\n");
- for (k = 0; k < 256; ++k) {
- if (0 ==
- do_scsi_inq(sg_fd, 1, 0, k, rsp_buff,
- MX_ALLOC_LEN, 1)) {
- support_num = rsp_buff[1] & 7;
- reserved_cmddt = rsp_buff[4];
- if ((3 == support_num)
- || (5 == support_num)) {
- num = rsp_buff[5];
- for (j = 0; j < num; ++j)
- printf(" %.2x",
- (int)rsp_buff[6 +
- j]);
- if (5 == support_num)
- printf
- (" [vendor specific manner (5)]");
- sg_get_command_name((unsigned
- char)k,
- sizeof
- (op_name) -
- 1, op_name);
- op_name[sizeof(op_name) - 1] =
- '\0';
- printf(" %s\n", op_name);
- } else if ((4 == support_num)
- || (6 == support_num))
- printf
- (" opcode=0x%.2x vendor specific (%d)\n",
- k, support_num);
- else if ((0 == support_num)
- && (reserved_cmddt > 0)) {
- printf
- (" opcode=0x%.2x ignored cmddt bit, "
- "given standard INQUIRY response, stop\n",
- k);
- break;
- }
- } else {
- fprintf(stderr,
- "CmdDt INQUIRY on opcode=0x%.2x: failed\n",
- k);
- break;
- }
- }
- } else {
- if (!do_raw) {
- printf("CmdDt INQUIRY, opcode=0x%.2x: [",
- num_opcode);
- sg_get_command_name((unsigned char)num_opcode,
- sizeof(op_name) - 1,
- op_name);
- op_name[sizeof(op_name) - 1] = '\0';
- printf("%s]\n", op_name);
- }
- if (0 == do_scsi_inq(sg_fd, 1, 0, num_opcode, rsp_buff,
- MX_ALLOC_LEN, 1)) {
- len = rsp_buff[5] + 6;
- reserved_cmddt = rsp_buff[4];
- if (do_hex)
- dStrHex((const char *)rsp_buff, len, 0);
- else {
- const char *desc_p;
- int prnt_cmd = 0;
-
- support_num = rsp_buff[1] & 7;
- num = rsp_buff[5];
- switch (support_num) {
- case 0:
- if (0 == reserved_cmddt)
- desc_p =
- "no data available";
- else
- desc_p =
- "ignored cmddt bit, standard INQUIRY "
- "response";
- break;
- case 1:
- desc_p = "not supported";
- break;
- case 2:
- desc_p = "reserved (2)";
- break;
- case 3:
- desc_p =
- "supported as per standard";
- prnt_cmd = 1;
- break;
- case 4:
- desc_p = "vendor specific (4)";
- break;
- case 5:
- desc_p =
- "supported in vendor specific way";
- prnt_cmd = 1;
- break;
- case 6:
- desc_p = "vendor specific (6)";
- break;
- case 7:
- desc_p = "reserved (7)";
- break;
- default:
- desc_p = "impossible value > 7";
- break;
- }
- if (prnt_cmd) {
- printf(" Support field: %s [",
- desc_p);
- for (j = 0; j < num; ++j)
- printf(" %.2x",
- (int)rsp_buff[6 +
- j]);
- printf(" ]\n");
- } else
- printf(" Support field: %s\n",
- desc_p);
- }
- } else {
- fprintf(stderr,
- "CmdDt INQUIRY on opcode=0x%.2x: failed\n",
- num_opcode);
- return 1;
- }
-
- }
- } else if (do_evpd) {
- if (!do_raw)
- printf("EVPD INQUIRY, page code=0x%.2x:\n", num_opcode);
- if (0 ==
- do_scsi_inq(sg_fd, 0, 1, num_opcode, rsp_buff, MX_ALLOC_LEN,
- 1)) {
- len = rsp_buff[3] + 4;
- if (num_opcode != rsp_buff[1])
- printf
- ("non evpd respone; probably a STANDARD INQUIRY "
- "response\n");
- else {
- if (!do_hex)
- printf(" Only hex output supported\n");
- dStrHex((const char *)rsp_buff, len, 0);
- }
- } else {
- fprintf(stderr,
- "EVPD INQUIRY, page code=0x%.2x: failed\n",
- num_opcode);
- return 1;
- }
- }
-
- if (do_pci) {
- unsigned char slot_name[16];
-
- printf("\n");
- memset(slot_name, '\0', sizeof(slot_name));
- if (ioctl(sg_fd, SCSI_IOCTL_GET_PCI, slot_name) < 0) {
- if (EINVAL == errno)
- printf
- ("ioctl(SCSI_IOCTL_GET_PCI) not supported by this "
- "kernel\n");
- else if (ENXIO == errno)
- printf
- ("associated adapter not a PCI device?\n");
- else
- perror("ioctl(SCSI_IOCTL_GET_PCI) failed");
- } else
- printf("PCI:slot_name: %s\n", slot_name);
- }
-
- close(sg_fd);
- return ret;
-}
-
-int show_scsi_maps()
-{
- int sg_fd, res, k;
- int do_numeric = NUMERIC_SCAN_DEF;
- int do_all_s = 1;
- int do_sd = 0;
- int do_st = 0;
- int do_osst = 0;
- int do_sr = 0;
- int do_scd = 0;
- int do_extra = 1;
- int do_inquiry = 0;
- char fname[64];
- int num_errors = 0;
- int num_silent = 0;
- int eacces_err = 0;
- int last_sg_ind = -1;
- struct stat stat_buf;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if (stat(devfs_id, &stat_buf) == 0)
- printf("# Note: the devfs pseudo file system is present\n");
-
- for (k = 0, res = 0; (k < MAX_SG_DEVS) && (num_errors < MAX_ERRORS);
- ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
- perror("sg_map: close error");
- return 1;
- }
- make_dev_name(fname, "/dev/sg", k, do_numeric);
-
- sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
- if (sg_fd < 0) {
- if (EBUSY == errno) {
- map_arr[k].active = -2;
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- map_arr[k].active = -1;
- continue;
- } else {
- if (EACCES == errno)
- eacces_err = 1;
- snprintf(ebuff, EBUFF_SZ, "Error opening %s ",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
- res = ioctl(sg_fd, SG_GET_SCSI_ID, &map_arr[k].sg_dat);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on sg ioctl, skip", fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- if (do_inquiry) {
- char buff[36];
-
- if (0 ==
- do_scsi_inq(sg_fd, 0, 0, 0, buff, sizeof(buff),
- 1)) {
- memcpy(map_arr[k].vendor, &buff[8], 8);
- memcpy(map_arr[k].product, &buff[16], 16);
- memcpy(map_arr[k].revision, &buff[32], 4);
- }
- }
- map_arr[k].active = 1;
- map_arr[k].oth_dev_num = -1;
- last_sg_ind = k;
- }
- if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
- printf("Stopping because there are too many error\n");
- if (eacces_err)
- printf(" root access may be required\n");
- return 1;
- }
- if (last_sg_ind < 0) {
- printf("Stopping because no sg devices found\n");
- }
-
- if (do_all_s || do_sd)
- scan_dev_type("/dev/sd", MAX_SD_DEVS, 0, LIN_DEV_TYPE_SD,
- last_sg_ind);
- if (do_all_s || do_sr)
- scan_dev_type("/dev/sr", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SR,
- last_sg_ind);
- if (do_all_s || do_scd)
- scan_dev_type("/dev/scd", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SCD,
- last_sg_ind);
- if (do_all_s || do_st)
- scan_dev_type("/dev/st", MAX_ST_DEVS, 1, LIN_DEV_TYPE_ST,
- last_sg_ind);
- if (do_all_s || do_osst)
- scan_dev_type("/dev/osst", MAX_OSST_DEVS, 1, LIN_DEV_TYPE_OSST,
- last_sg_ind);
-
- for (k = 0; k <= last_sg_ind; ++k) {
- make_dev_name(fname, "/dev/sg", k, do_numeric);
- printf("%s", fname);
- switch (map_arr[k].active) {
- case -2:
- printf(do_extra ? " -2 -2 -2 -2 -2" : " busy");
- break;
- case -1:
- printf(do_extra ? " -1 -1 -1 -1 -1" :
- " not present");
- break;
- case 0:
- printf(do_extra ? " -3 -3 -3 -3 -3" :
- " some error\n");
- break;
- case 1:
- if (do_extra)
- printf(" %d %d %d %d %d",
- map_arr[k].sg_dat.host_no,
- map_arr[k].sg_dat.channel,
- map_arr[k].sg_dat.scsi_id,
- map_arr[k].sg_dat.lun,
- map_arr[k].sg_dat.scsi_type);
- switch (map_arr[k].lin_dev_type) {
- case LIN_DEV_TYPE_SD:
- make_dev_name(fname, "/dev/sd",
- map_arr[k].oth_dev_num, 0);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_ST:
- make_dev_name(fname, "/dev/st",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_OSST:
- make_dev_name(fname, "/dev/osst",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_SR:
- make_dev_name(fname, "/dev/sr",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- case LIN_DEV_TYPE_SCD:
- make_dev_name(fname, "/dev/scd",
- map_arr[k].oth_dev_num, 1);
- printf(" %s", fname);
- break;
- default:
- break;
- }
- if (do_inquiry)
- printf(" %.8s %.16s %.4s", map_arr[k].vendor,
- map_arr[k].product, map_arr[k].revision);
- break;
- default:
- printf(" bad logic\n");
- break;
- }
- printf("\n");
- }
- return 0;
-}
-
-static int find_dev_in_sg_arr(My_scsi_idlun * my_idlun, int host_no,
- int last_sg_ind)
-{
- int k;
- struct sg_scsi_id *sidp;
-
- for (k = 0; k <= last_sg_ind; ++k) {
- sidp = &(map_arr[k].sg_dat);
- if ((host_no == sidp->host_no) &&
- ((my_idlun->dev_id & 0xff) == sidp->scsi_id) &&
- (((my_idlun->dev_id >> 8) & 0xff) == sidp->lun) &&
- (((my_idlun->dev_id >> 16) & 0xff) == sidp->channel))
- return k;
- }
- return -1;
-}
-
-static void scan_dev_type(const char *leadin, int max_dev, int do_numeric,
- int lin_dev_type, int last_sg_ind)
-{
- int k, res, ind, sg_fd = 0;
- int num_errors = 0;
- int num_silent = 0;
- int host_no = -1;
- int nonMappedDevicesPresent = FALSE;
- My_scsi_idlun my_idlun;
- char fname[64];
-
- for (k = 0, res = 0; (k < max_dev) && (num_errors < MAX_ERRORS);
- ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
-
-/* ignore close() errors */
-#if 0
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
- perror("sg_map: close error");
-#ifndef IGN_CLOSE_ERR
- return;
-#else
- ++num_errors;
- sg_fd = 0;
-#endif
- }
-#endif
- make_dev_name(fname, leadin, k, do_numeric);
-#ifdef DEBUG
- printf("Trying %s: ", fname);
-#endif
-
- sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
- if (sg_fd < 0) {
-#ifdef DEBUG
- printf("ERROR %i\n", errno);
-#endif
- if (EBUSY == errno) {
- printf("Device %s is busy\n", fname);
- ++num_errors;
- continue;
- } else if ((ENODEV == errno) || (ENOENT == errno) ||
- (ENXIO == errno)) {
- ++num_errors;
- ++num_silent;
- continue;
- } else {
- snprintf(ebuff, EBUFF_SZ, "Error opening %s ",
- fname);
- perror(ebuff);
- ++num_errors;
- continue;
- }
- }
-
- res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on scsi ioctl(idlun), skip",
- fname);
- perror(ebuff);
- ++num_errors;
-#ifdef DEBUG
- printf("Couldn't get IDLUN!\n");
-#endif
- continue;
- }
- res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "device %s failed on scsi ioctl(bus_number), skip",
- fname);
- perror(ebuff);
- ++num_errors;
-#ifdef DEBUG
- printf("Couldn't get BUS!\n");
-#endif
- continue;
- }
-#ifdef DEBUG
- printf("%i(%x) %i %i %i %i\n", host_no, my_idlun.host_unique_id,
- (my_idlun.dev_id >> 24) & 0xff,
- (my_idlun.dev_id >> 16) & 0xff,
- (my_idlun.dev_id >> 8) & 0xff, my_idlun.dev_id & 0xff);
-#endif
- ind = find_dev_in_sg_arr(&my_idlun, host_no, last_sg_ind);
- if (ind >= 0) {
- map_arr[ind].oth_dev_num = k;
- map_arr[ind].lin_dev_type = lin_dev_type;
- } else if (ind != -1) {
- printf
- ("Strange, could not find device %s mapped to sg device error %d??\n",
- fname, ind);
- } else {
- nonMappedDevicesPresent = TRUE;
- }
- }
- if (nonMappedDevicesPresent) {
- printf("Unmapped Devices found...\n\n");
- }
-}
-
-/* Returns 0 when successful, else -1 */
-static int do_simple_inq(int sg_fd, void *resp, int mx_resp_len, int noisy)
-{
- 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_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = inqCmdBlk;
- io_hdr.sbp = sense_b;
- 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_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Inquiry error ");
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static int do_modes(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
- void *resp, int mx_resp_len, int noisy, int mode6)
-{
- int res;
- unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] =
- { MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0);
- modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- modesCmdBlk[3] = (unsigned char)(sub_pg_code & 0xff);
- if (mx_resp_len > (mode6 ? 0xff : 0xffff)) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- if (mode6) {
- modesCmdBlk[0] = MODE_SENSE6_CMD;
- modesCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
- } else {
- modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- memset(sense_b, 0, sizeof(sense_b));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = mode6 ? MODE_SENSE6_CMDLEN : MODE_SENSE10_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = modesCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (mode sense) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Mode sense error, dbd=%d "
- "pc=%d page_code=%x sub_page_code=%x\n ",
- dbd, pc, pg_code, sub_pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- if ((0x70 == (0x7f & sense_b[0])) && (0x20 == sense_b[12]) &&
- (0x0 == sense_b[13])) {
- if (mode6)
- fprintf(stderr,
- ">>>>>> drop '-6' switch and try again with "
- "a 10 byte MODE SENSE\n");
- else
- fprintf(stderr,
- ">>>>>> add '-6' switch and try again with "
- "a 6 byte MODE SENSE\n");
- }
- return -1;
- }
-}
-
-const char *scsi_ptype_strs[] = {
- "disk",
- "tape",
- "printer",
- "processor",
- "write once optical disk",
- "cd/dvd",
- "scanner",
- "optical memory device",
- "medium changer",
- "communications",
- "graphics",
- "graphics",
- "storage array controller",
- "enclosure services device",
- "simplified direct access device",
- "optical card reader/writer device",
-};
-
-const char *get_ptype_str(int scsi_ptype)
-{
- int num = sizeof(scsi_ptype_strs) / sizeof(scsi_ptype_strs[0]);
-
- return (scsi_ptype < num) ? scsi_ptype_strs[scsi_ptype] : "";
-}
-
-static struct page_code_desc pc_desc_all[] = {
- {0x0, "Unit Attention condition [vendor: page format not required]"},
- {0x2, "Disconnect-Reconnect"},
- {0xa, "Control"},
- {0x15, "Extended"},
- {0x16, "Extended device-type specific"},
- {0x18, "Protocol specific LUN"},
- {0x19, "Protocol specific port"},
- {0x1a, "Power condition"},
- {0x1c, "Informational exceptions control"},
- {0x3f, "[yields all supported pages]"},
-};
-
-static struct page_code_desc pc_desc_disk[] = {
- {0x1, "Read-Write error recovery"},
- {0x3, "Format"},
- {0x4, "Rigid disk geometry"},
- {0x5, "Flexible geometry"},
- {0x7, "Verify error recovery"},
- {0x8, "Caching"},
- {0x9, "Peripheral device (spc-2 ?)"},
- {0xb, "Medium types supported"},
- {0xc, "Notch and partition"},
- {0xd, "Power condition (obsolete)"},
- {0x10, "XOR control"},
-};
-
-static struct page_code_desc pc_desc_tape[] = {
- {0xf, "Data Compression"},
- {0x10, "Device config"},
- {0x11, "Medium Partition [1]"},
- {0x12, "Medium Partition [2]"},
- {0x13, "Medium Partition [3]"},
- {0x14, "Medium Partition [4]"},
- {0x1c, "Informational exceptions control (tape version)"},
-};
-
-static struct page_code_desc pc_desc_cddvd[] = {
- {0x1, "Read-Write error recovery"},
- {0x3, "MRW"},
- {0x5, "Write parameters"},
- {0xd, "CD device parameters (obsolete)"},
- {0xe, "CD audio"},
- {0x1a, "Power condition"},
- {0x1c, "Fault/failure reporting control"},
- {0x1d, "Timeout and protect"},
- {0x2a, "MM capabilities and mechanical status (obsolete)"},
-};
-
-static struct page_code_desc pc_desc_smc[] = {
- {0x1d, "Element address assignment"},
- {0x1e, "Transport geometry parameters"},
- {0x1f, "Device capabilities"},
-};
-
-static struct page_code_desc pc_desc_scc[] = {
- {0x1b, "LUN mapping"},
-};
-
-static struct page_code_desc pc_desc_ses[] = {
- {0x14, "Enclosure services management"},
-};
-
-struct page_code_desc *find_mode_page_table(int scsi_ptype, int *size)
-{
- switch (scsi_ptype) {
- case 0: /* disk (direct access) type devices */
- case 4:
- case 7:
- case 0xe:
- *size = sizeof(pc_desc_disk) / sizeof(pc_desc_disk[0]);
- return &pc_desc_disk[0];
- case 1: /* tape devices */
- case 2:
- *size = sizeof(pc_desc_tape) / sizeof(pc_desc_tape[0]);
- return &pc_desc_tape[0];
- case 5: /* cd/dvd devices */
- *size = sizeof(pc_desc_cddvd) / sizeof(pc_desc_cddvd[0]);
- return &pc_desc_cddvd[0];
- case 8: /* medium changer devices */
- *size = sizeof(pc_desc_smc) / sizeof(pc_desc_smc[0]);
- return &pc_desc_smc[0];
- case 0xc: /* storage array devices */
- *size = sizeof(pc_desc_scc) / sizeof(pc_desc_scc[0]);
- return &pc_desc_scc[0];
- case 0xd: /* enclosure services devices */
- *size = sizeof(pc_desc_ses) / sizeof(pc_desc_ses[0]);
- return &pc_desc_ses[0];
- }
- *size = 0;
- return NULL;
-}
-
-const char *find_page_code_desc(int page_num, int scsi_ptype)
-{
- int k;
- int num;
- const struct page_code_desc *pcdp;
-
- pcdp = find_mode_page_table(scsi_ptype, &num);
- if (pcdp) {
- for (k = 0; k < num; ++k, ++pcdp) {
- if (page_num == pcdp->page_code)
- return pcdp->desc;
- else if (page_num < pcdp->page_code)
- break;
- }
- }
- pcdp = &pc_desc_all[0];
- num = sizeof(pc_desc_all) / sizeof(pc_desc_all[0]);
- for (k = 0; k < num; ++k, ++pcdp) {
- if (page_num == pcdp->page_code)
- return pcdp->desc;
- else if (page_num < pcdp->page_code)
- break;
- }
- return NULL;
-}
-
-static void list_page_codes(int scsi_ptype)
-{
- int k;
- int num = sizeof(pc_desc_all) / sizeof(pc_desc_all[0]);
- const struct page_code_desc *pcdp = &pc_desc_all[0];
- int num_ptype;
- const struct page_code_desc *pcd_ptypep;
-
- pcd_ptypep = find_mode_page_table(scsi_ptype, &num_ptype);
- printf("Page_Code Description\n");
- for (k = 0; k < 0x3f; ++k) {
- if (pcd_ptypep && (num_ptype > 0)) {
- if (k == pcd_ptypep->page_code) {
- printf(" 0x%02x %s\n",
- pcd_ptypep->page_code, pcd_ptypep->desc);
- ++pcd_ptypep;
- --num_ptype;
- continue;
- } else if (k > pcd_ptypep->page_code) {
- pcd_ptypep++;
- --num_ptype;
- }
- }
- if (pcdp && (num > 0)) {
- if (k == pcdp->page_code) {
- printf(" 0x%02x %s\n", pcdp->page_code,
- pcdp->desc);
- ++pcdp;
- --num;
- continue;
- } else if (k > pcdp->page_code) {
- pcdp++;
- --num;
- }
- }
- }
-}
-
-int show_scsi_modes(char *device)
-{
- int sg_fd, k, num, len, md_len, bd_len, longlba, page_num;
- char *file_name = 0;
- char ebuff[EBUFF_SZ];
- const char *descp;
- unsigned char rsp_buff[MODE_ALLOC_LEN];
- int rsp_buff_size = MODE_ALLOC_LEN;
- int pg_code = 0;
- int sub_pg_code = 0;
- int pc = 0;
- int do_all = 1;
- int do_dbd = 0;
- int do_hex = 0;
- int do_mode6 = 0; /* Use MODE SENSE(6) instead of MODE SENSE(10) */
- int oflags = O_RDONLY | O_NONBLOCK;
- struct sg_scsi_id a_sid;
- int scsi_ptype, density_code_off;
- unsigned char *ucp;
- unsigned char uc;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- list_page_codes(0);
-
- /* The 6 bytes command only allows up to 255 bytes of response data */
- if (do_mode6)
- rsp_buff_size = 255;
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "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(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- if (ioctl(sg_fd, SG_GET_SCSI_ID, &a_sid) < 0) {
- unsigned char inqBuff[36];
-
- if (do_simple_inq(sg_fd, inqBuff, sizeof(inqBuff), 1)) {
- printf(ME "%s doesn't respond to a SCSI INQUIRY\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- scsi_ptype = inqBuff[0] & 0x1f; /* fetch peripheral device type */
- } else
- scsi_ptype = a_sid.scsi_type;
- printf(" SCSI peripheral type: %s [0x%x] (from INQUIRY)\n",
- get_ptype_str(scsi_ptype), scsi_ptype);
-
- if (do_all)
- pg_code = MODE_CODE_ALL;
-
- if (0 == do_modes(sg_fd, do_dbd, pc, pg_code, sub_pg_code,
- rsp_buff, rsp_buff_size, 1, do_mode6)) {
- int medium_type, specific, headerlen;
-
- printf("Mode parameter header from %s byte MODE SENSE:\n",
- (do_mode6 ? "6" : "10"));
- if (do_mode6) {
- headerlen = 4;
- if (do_hex)
- dStrHex((const char *)rsp_buff, headerlen, 1);
- md_len = rsp_buff[0] + 1;
- bd_len = rsp_buff[3];
- medium_type = rsp_buff[1];
- specific = rsp_buff[2];
- longlba = 0; /* what is this field? */
- } else {
- headerlen = 8;
- md_len = (rsp_buff[0] << 8) + rsp_buff[1] + 2;
- bd_len = (rsp_buff[6] << 8) + rsp_buff[7];
- medium_type = rsp_buff[2];
- specific = rsp_buff[3];
- longlba = rsp_buff[4] & 1;
- }
- if (do_hex)
- dStrHex((const char *)rsp_buff, headerlen, 1);
- printf(" Mode data length=%d, medium type=0x%.2x, specific"
- " param=0x%.2x, longlba=%d\n", md_len, medium_type,
- specific, longlba);
- if (md_len > rsp_buff_size) {
- printf
- ("Only fetched %d bytes of response, truncate output\n",
- rsp_buff_size);
- md_len = rsp_buff_size;
- if (bd_len + headerlen > rsp_buff_size)
- bd_len = rsp_buff_size - headerlen;
- }
- printf(" Block descriptor length=%d\n", bd_len);
- if (bd_len > 0) {
- len = 8;
- density_code_off = 0;
- num = bd_len;
- if (longlba) {
- printf("> longlba block descriptors:\n");
- len = 16;
- density_code_off = 8;
- } else if (0 == scsi_ptype) {
- printf
- ("> Direct access device block descriptors:\n");
- density_code_off = 4;
- } else
- printf
- ("> General mode parameter block descriptors:\n");
-
- ucp = rsp_buff + headerlen;
- while (num > 0) {
- printf(" Density code=0x%x\n",
- *(ucp + density_code_off));
- dStrHex((const char *)ucp, len, 1);
- ucp += len;
- num -= len;
- }
- printf("\n");
- }
- ucp = rsp_buff + bd_len + headerlen; /* start of mode page(s) */
- md_len -= bd_len + headerlen; /* length of mode page(s) */
- while (md_len > 0) { /* got mode page(s) */
- uc = *ucp;
- page_num = ucp[0] & 0x3f;
- if (do_hex)
- descp = NULL;
- else {
- descp =
- find_page_code_desc(page_num, scsi_ptype);
- if (NULL == descp)
- snprintf(ebuff, EBUFF_SZ,
- "vendor[0x%x]", page_num);
- }
- if (uc & 0x40) {
- len = (ucp[2] << 8) + ucp[3] + 4;
- if (do_hex)
- printf
- (">> page_code=0x%x, subpage_code=0x%x, "
- "page_control=%d\n", page_num,
- ucp[1], pc);
- else
- printf
- (">> page_code: %s, subpage_code=0x%x, "
- "page_control: %s\n",
- (descp ? descp : ebuff), ucp[1],
- pg_control_str_arr[pc]);
- } else {
- len = ucp[1] + 2;
- if (do_hex)
- printf
- (">> page_code=0x%x, page_control=%d\n",
- page_num, pc);
- else
- printf
- (">> page_code: %s, page_control: %s\n",
- (descp ? descp : ebuff),
- pg_control_str_arr[pc]);
- }
- dStrHex((const char *)ucp, len, 1);
- ucp += len;
- md_len -= len;
- }
- }
-
- close(sg_fd);
- return 0;
-}
-
-int do_scsi_read_buffer(char *device)
-{
- int sg_fd, res;
- unsigned int k, num;
- unsigned char rbCmdBlk[RB_CMD_LEN];
- unsigned char *rbBuff = NULL;
- void *rawp = NULL;
- unsigned char sense_buffer[32];
- int buf_capacity = 0;
- int do_quick = 0;
- int do_dio = 0;
- int do_mmap = 1;
- int do_time = 0;
- int buf_size = 0;
- unsigned int total_size_mb = RB_MB_TO_READ;
- char *file_name = 0;
- size_t psz = getpagesize();
- int dio_incomplete = 0;
- sg_io_hdr_t io_hdr;
- struct timeval start_tm, end_tm;
-#ifdef SG_DEBUG
- int clear = 1;
-#endif
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- sg_fd = open(file_name, O_RDONLY);
- if (sg_fd < 0) {
- perror(ME "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(ME "not a sg device, or driver prior to 3.x\n");
- return 1;
- }
- if (do_mmap) {
- do_dio = 0;
- do_quick = 0;
- }
- if (NULL == (rawp = malloc(512))) {
- printf(ME "out of memory (query)\n");
- return 1;
- }
- rbBuff = rawp;
-
- memset(rbCmdBlk, 0, RB_CMD_LEN);
- rbCmdBlk[0] = RB_OPCODE;
- rbCmdBlk[1] = RB_MODE_DESC;
- rbCmdBlk[8] = RB_DESC_LEN;
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rbCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = RB_DESC_LEN;
- io_hdr.dxferp = rbBuff;
- io_hdr.cmdp = rbCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 60000; /* 60000 millisecs == 60 seconds */
- /* do normal IO to find RB size (not dio or mmap-ed at this stage) */
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror(ME "SG_IO READ BUFFER descriptor error");
- if (rawp)
- free(rawp);
- return 1;
- }
-
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- printf
- ("Recovered error on READ BUFFER descriptor, continuing\n");
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER descriptor error", &io_hdr);
- if (rawp)
- free(rawp);
- return 1;
- }
-
- buf_capacity = ((rbBuff[1] << 16) | (rbBuff[2] << 8) | rbBuff[3]);
- printf("READ BUFFER reports: buffer capacity=%d, offset boundary=%d\n",
- buf_capacity, (int)rbBuff[0]);
-
- if (0 == buf_size)
- buf_size = buf_capacity;
- else if (buf_size > buf_capacity) {
- printf
- ("Requested buffer size=%d exceeds reported capacity=%d\n",
- buf_size, buf_capacity);
- if (rawp)
- free(rawp);
- return 1;
- }
- if (rawp) {
- free(rawp);
- rawp = NULL;
- }
-
- if (!do_dio) {
- k = buf_size;
- if (do_mmap && (0 != (k % psz)))
- k = ((k / psz) + 1) * psz; /* round up to page size */
- res = ioctl(sg_fd, SG_SET_RESERVED_SIZE, &k);
- if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
- }
-
- if (do_mmap) {
- rbBuff = mmap(NULL, buf_size, PROT_READ, MAP_SHARED, sg_fd, 0);
- if (MAP_FAILED == rbBuff) {
- if (ENOMEM == errno)
- printf(ME "mmap() out of memory, try a smaller "
- "buffer size than %d KB\n",
- buf_size / 1024);
- else
- perror(ME "error using mmap()");
- return 1;
- }
- } else { /* non mmap-ed IO */
- rawp = malloc(buf_size + (do_dio ? psz : 0));
- if (NULL == rawp) {
- printf(ME "out of memory (data)\n");
- return 1;
- }
- if (do_dio) /* align to page boundary */
- rbBuff =
- (unsigned char *)(((unsigned long)rawp + psz - 1) &
- (~(psz - 1)));
- else
- rbBuff = rawp;
- }
-
- num = (total_size_mb * 1024U * 1024U) / (unsigned int)buf_size;
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- /* main data reading loop */
- for (k = 0; k < num; ++k) {
- memset(rbCmdBlk, 0, RB_CMD_LEN);
- rbCmdBlk[0] = RB_OPCODE;
- rbCmdBlk[1] = RB_MODE_DATA;
- rbCmdBlk[6] = 0xff & (buf_size >> 16);
- rbCmdBlk[7] = 0xff & (buf_size >> 8);
- rbCmdBlk[8] = 0xff & buf_size;
-#ifdef SG_DEBUG
- memset(rbBuff, 0, buf_size);
-#endif
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(rbCmdBlk);
- io_hdr.mx_sb_len = sizeof(sense_buffer);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = buf_size;
- if (!do_mmap)
- io_hdr.dxferp = rbBuff;
- io_hdr.cmdp = rbCmdBlk;
- io_hdr.sbp = sense_buffer;
- io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
- io_hdr.pack_id = k;
- if (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_IO;
- else if (do_dio)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
- else if (do_quick)
- io_hdr.flags |= SG_FLAG_NO_DXFER;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- if (ENOMEM == errno)
- printf(ME
- "SG_IO data; out of memory, try a smaller "
- "buffer size than %d KB\n",
- buf_size / 1024);
- else
- perror(ME "SG_IO READ BUFFER data error");
- if (rawp)
- free(rawp);
- return 1;
- }
-
- /* now for the error processing */
- switch (sg_err_category3(&io_hdr)) {
- case SG_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- printf
- ("Recovered error on READ BUFFER data, continuing\n");
- break;
- default: /* won't bother decoding other categories */
- sg_chk_n_print3("READ BUFFER data error", &io_hdr);
- if (rawp)
- free(rawp);
- return 1;
- }
- if (do_dio &&
- ((io_hdr.info & SG_INFO_DIRECT_IO_MASK) !=
- SG_INFO_DIRECT_IO))
- dio_incomplete = 1; /* flag that dio not done (completely) */
-
-#ifdef SG_DEBUG
- if (clear) {
- for (j = 0; j < buf_size; ++j) {
- if (rbBuff[j] != 0) {
- clear = 0;
- break;
- }
- }
- }
-#endif
- }
- 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)buf_size *num;
- printf("time to read data from buffer 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 (dio_incomplete)
- printf(">> direct IO requested but not done\n");
- printf
- ("Read %u MBytes (actual %u MB, %u bytes), buffer size=%d KBytes\n",
- total_size_mb, (num * buf_size) / 1048576, num * buf_size,
- buf_size / 1024);
-
- if (rawp)
- free(rawp);
- res = close(sg_fd);
- if (res < 0) {
- perror(ME "close error");
- return 0;
- }
-#ifdef SG_DEBUG
- if (clear)
- printf("read buffer always zero\n");
- else
- printf("read buffer non-zero\n");
-#endif
- return 0;
-}
-
-/* Performs a 10 byte READ CAPACITY command and fetches response. There is
- * evidently a 16 byte READ CAPACITY command coming.
- * Return of 0 -> success, -1 -> failure */
-int do_readcap_10(int sg_fd, int pmi, unsigned int lba,
- unsigned int *last_sect, unsigned int *sect_sz)
-{
- int res;
- unsigned char rcCmdBlk[10] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char rcBuff[RCAP_REPLY_LEN];
- unsigned char sense_b[SENSE_BUFF_SZ];
- sg_io_hdr_t io_hdr;
-
- if (pmi) { /* lbs only valid when pmi set */
- rcCmdBlk[8] |= 1;
- rcCmdBlk[2] = (lba >> 24) & 0xff;
- rcCmdBlk[3] = (lba >> 16) & 0xff;
- rcCmdBlk[4] = (lba >> 8) & 0xff;
- rcCmdBlk[5] = lba & 0xff;
- }
- 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 = 60000;
-
- while (1) {
- 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)
- continue;
- else if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("READ CAPACITY command error", &io_hdr);
- return -1;
- } else
- break;
- }
- *last_sect = ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
- (rcBuff[2] << 8) | rcBuff[3]);
- *sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) |
- (rcBuff[6] << 8) | rcBuff[7];
- return 0;
-}
-
-int show_scsi_read_capacity(char *device)
-{
- int sg_fd, k, res;
- unsigned int lba = 0;
- int pmi = 1;
- unsigned int last_blk_addr, block_size;
- char ebuff[EBUFF_SZ];
- const char *file_name = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- if ((0 == pmi) && (lba > 0)) {
- fprintf(stderr,
- ME "lba can only be non-zero when pmi is set\n");
- usage();
- return 1;
- }
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "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(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- res = do_readcap_10(sg_fd, pmi, lba, &last_blk_addr, &block_size);
-
- if (0 == res) {
- printf("Read Capacity results:\n");
- if (pmi)
- printf(" PMI mode: given lba=0x%x, last block before "
- "delay=0x%x\n", lba, last_blk_addr);
- else
- printf
- (" Last block address=%u (0x%x), Number of blocks=%u\n",
- last_blk_addr, last_blk_addr, last_blk_addr + 1);
- printf(" Block size = %u bytes\n", block_size);
- }
- close(sg_fd);
- return 0;
-}
-
-int do_scsi_reset_devices(char *device, int reset_opt)
-{
- int sg_fd, res, k;
- int do_device_reset = 0;
- int do_bus_reset = 0;
- int do_host_reset = 0;
- char *file_name = 0;
-
- switch (reset_opt) {
- case DEVICE_RESET:
- print_msg(TEST_BREAK, __FUNCTION__);
- do_device_reset = 1;
- break;
- case HOST_RESET:
- do_host_reset = 1;
- break;
- case BUS_RESET:
- do_bus_reset = 1;
- break;
- }
-
- file_name = device;
-
- sg_fd = open(file_name, O_RDWR | O_NONBLOCK);
- if (sg_fd < 0) {
- perror("sg_reset: open error");
- return 1;
- }
-
- k = SG_SCSI_RESET_NOTHING;
- if (do_device_reset) {
- printf("sg_reset: starting device reset\n");
- k = SG_SCSI_RESET_DEVICE;
- } else if (do_bus_reset) {
- printf("sg_reset: starting bus reset\n");
- k = SG_SCSI_RESET_BUS;
- } else if (do_host_reset) {
- printf("sg_reset: starting host reset\n");
- k = SG_SCSI_RESET_HOST;
- }
-
- res = ioctl(sg_fd, SG_SCSI_RESET, &k);
- if (res < 0) {
- if (EBUSY == errno)
- printf("sg_reset: BUSY, may be resetting now\n");
- else if (EIO == errno)
- printf
- ("sg_reset: requested type of reset may not be available\n");
- else if (EACCES == errno)
- printf("sg_reset: reset requires CAP_SYS_ADMIN (root) "
- "permission\n");
- else if (EINVAL == errno)
- printf("sg_reset: SG_SCSI_RESET not supported\n");
- else if (EIO == errno)
- printf("sg_reset: scsi_reset_provider() call failed\n");
- else
- perror("sg_reset: SG_SCSI_RESET failed");
- return 1;
- }
- if (SG_SCSI_RESET_NOTHING == k)
- printf("sg_reset: did nothing, device is normal mode\n");
- else if (SG_SCSI_RESET_DEVICE == k)
- printf("sg_reset: completed device reset\n");
- else if (SG_SCSI_RESET_BUS == k)
- printf("sg_reset: completed bus reset\n");
- else if (SG_SCSI_RESET_HOST == k)
- printf("sg_reset: completed host reset\n");
-
- if (close(sg_fd) < 0) {
- perror("sg_reset: close error");
- return 1;
- }
- return 0;
-}
-
-static int do_senddiag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
- int devofl_bit, int unitofl_bit, void *outgoing_pg,
- int outgoing_len, int noisy)
-{
- int res;
- unsigned char senddiagCmdBlk[SEND_DIAGNOSTIC_CMDLEN] =
- { SEND_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- senddiagCmdBlk[1] = (unsigned char)((sf_code << 5) | (pf_bit << 4) |
- (sf_bit << 2) | (devofl_bit << 1) |
- unitofl_bit);
- senddiagCmdBlk[3] = (unsigned char)((outgoing_len >> 8) & 0xff);
- senddiagCmdBlk[4] = (unsigned char)(outgoing_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = SEND_DIAGNOSTIC_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = outgoing_len ? SG_DXFER_TO_DEV : SG_DXFER_NONE;
- io_hdr.dxfer_len = outgoing_len;
- io_hdr.dxferp = outgoing_pg;
- io_hdr.cmdp = senddiagCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = LONG_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (send diagnostic) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ,
- "Send diagnostic error, sf_code=0x%x, "
- "pf_bit=%d, sf_bit=%d ", sf_code, pf_bit,
- sf_bit);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-static int do_rcvdiag(int sg_fd, int pcv, int pg_code, void *resp,
- int mx_resp_len, int noisy)
-{
- int res;
- unsigned char rcvdiagCmdBlk[RECEIVE_DIAGNOSTIC_CMDLEN] =
- { RECEIVE_DIAGNOSTIC_CMD, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
-
- rcvdiagCmdBlk[1] = (unsigned char)(pcv ? 0x1 : 0);
- rcvdiagCmdBlk[2] = (unsigned char)(pg_code);
- rcvdiagCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- rcvdiagCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = RECEIVE_DIAGNOSTIC_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = rcvdiagCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (receive diagnostic) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ,
- "Receive diagnostic error, pcv=%d, "
- "page_code=%x ", pcv, pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-/* Get last extended self-test time from mode page 0xa (for '-e' option) */
-static int do_modes_0a(int sg_fd, void *resp, int mx_resp_len, int noisy,
- int mode6)
-{
- int res;
- unsigned char modesCmdBlk[MODE_SENSE10_CMDLEN] =
- { MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned char sense_b[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int dbd = 1;
- int pc = 0;
- int pg_code = 0xa;
-
- modesCmdBlk[1] = (unsigned char)(dbd ? 0x8 : 0);
- modesCmdBlk[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
- if (mx_resp_len > (mode6 ? 0xff : 0xffff)) {
- printf(ME "mx_resp_len too big\n");
- return -1;
- }
- if (mode6) {
- modesCmdBlk[0] = MODE_SENSE6_CMD;
- modesCmdBlk[4] = (unsigned char)(mx_resp_len & 0xff);
- } else {
- modesCmdBlk[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- modesCmdBlk[8] = (unsigned char)(mx_resp_len & 0xff);
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = mode6 ? MODE_SENSE6_CMDLEN : MODE_SENSE10_CMDLEN;
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = mx_resp_len;
- io_hdr.dxferp = resp;
- io_hdr.cmdp = modesCmdBlk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_TIMEOUT;
-
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("SG_IO (mode sense) error");
- return -1;
- }
- res = sg_err_category3(&io_hdr);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
- return 0;
- default:
- if (noisy) {
- char ebuff[EBUFF_SZ];
- snprintf(ebuff, EBUFF_SZ, "Mode sense error, dbd=%d, "
- "pc=%d, page_code=%x ", dbd, pc, pg_code);
- sg_chk_n_print3(ebuff, &io_hdr);
- }
- return -1;
- }
-}
-
-int do_scsi_send_diagnostics(char *device)
-{
- int sg_fd, k, num, rsp_len;
- char *file_name = 0;
- unsigned char rsp_buff[MODE_ALLOC_LEN];
- int rsp_buff_size = MODE_ALLOC_LEN;
- int self_test_code = 6;
- int do_pf = 0;
- int do_doff = 0;
- int do_def_test = 0;
- int do_uoff = 0;
- int oflags = O_RDWR;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- if ((sg_fd = open(file_name, oflags)) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "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(ME "%s doesn't seem to be a version 3 sg device\n",
- file_name);
- close(sg_fd);
- return 1;
- }
-
- if (0 == do_modes_0a(sg_fd, rsp_buff, 32, 1, 0)) {
- /* Assume mode sense(10) response without block descriptors */
- num = (rsp_buff[0] << 8) + rsp_buff[1] - 6;
- if (num >= 0xc) {
- int secs;
-
- secs = (rsp_buff[18] << 8) + rsp_buff[19];
- printf
- ("Previous extended self-test duration=%d seconds "
- "(%.2f minutes)\n", secs, secs / 60.0);
- } else
- printf("Extended self-test duration not available\n");
- } else
- printf("Extended self-test duration (mode page 0xa) failed\n");
-
- memset(rsp_buff, 0, sizeof(rsp_buff));
- if (0 == do_senddiag(sg_fd, 0, do_pf, 0, 0, 0, rsp_buff, 4, 1)) {
- if (0 == do_rcvdiag(sg_fd, 0, 0, rsp_buff, rsp_buff_size, 1)) {
- printf("Supported diagnostic pages response:\n");
- rsp_len = (rsp_buff[2] << 8) + rsp_buff[3] + 4;
- for (k = 0; k < (rsp_len - 4); ++k)
- printf(" %s\n",
- find_page_code_desc(rsp_buff[k + 4], 0));
- }
- }
-
- if (0 == do_senddiag(sg_fd, self_test_code, do_pf, do_def_test,
- do_doff, do_uoff, NULL, 0, 1)) {
- if ((5 == self_test_code) || (6 == self_test_code))
- printf("Foreground self test returned GOOD status\n");
- else if (do_def_test && (!do_doff) && (!do_uoff))
- printf("Default self test returned GOOD status\n");
- }
- close(sg_fd);
- return 0;
-}
-
-static void do_start_stop(int fd, int start, int immed, int loej,
- int power_conditions)
-{
- unsigned char cmdblk[6] = {
- START_STOP, /* Command */
- 0, /* Resvd/Immed */
- 0, /* Reserved */
- 0, /* Reserved */
- 0, /* PowCond/Resvd/LoEj/Start */
- 0
- }; /* Reserved/Flag/Link */
- unsigned char sense_b[32];
- sg_io_hdr_t io_hdr;
- int k, res, debug = 1;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- cmdblk[1] = immed & 1;
- cmdblk[4] = ((power_conditions & 0xf) << 4) |
- ((loej & 1) << 1) | (start & 1);
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(cmdblk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = cmdblk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_START_TIMEOUT;
-
- if (debug) {
- printf(" Start/Stop command:");
- for (k = 0; k < 6; ++k)
- printf(" %02x", cmdblk[k]);
- printf("\n");
- }
-
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res) {
- fprintf(stderr, "media change report, try start_stop again\n");
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("start_stop (SG_IO) error");
- return;
- }
- }
- if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("start_stop", &io_hdr);
- return;
- }
- if (debug)
- fprintf(stderr, "start_stop [%s] successful\n",
- start ? "start" : "stop");
-}
-
-static void do_sync_cache(int fd)
-{
- unsigned char cmdblk[10] = {
- SYNCHRONIZE_CACHE, /* Command */
- 0, /* Immed (2) */
- 0, 0, 0, 0, /* LBA */
- 0, /* Reserved */
- 0, 0, /* No of blocks */
- 0
- }; /* Reserved/Flag/Link */
- unsigned char sense_b[32];
- sg_io_hdr_t io_hdr;
- int res, debug = 1;
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(cmdblk);
- io_hdr.mx_sb_len = sizeof(sense_b);
- io_hdr.dxfer_direction = SG_DXFER_NONE;
- io_hdr.dxfer_len = 0;
- io_hdr.dxferp = NULL;
- io_hdr.cmdp = cmdblk;
- io_hdr.sbp = sense_b;
- io_hdr.timeout = DEF_START_TIMEOUT;
-
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("sync_cache (SG_IO) error");
- return;
- }
- res = sg_err_category3(&io_hdr);
- if (SG_ERR_CAT_MEDIA_CHANGED == res) {
- fprintf(stderr, "media change report, try sync_cache again\n");
- if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- perror("sync_cache (SG_IO) error");
- return;
- }
- }
- if (SG_ERR_CAT_CLEAN != res) {
- sg_chk_n_print3("sync_cache", &io_hdr);
- return;
- }
- if (debug)
- fprintf(stderr, "synchronize cache successful\n");
-}
-
-int do_scsi_start_stop(char *device, int startstop)
-{
- int synccache = 1;
- char *file_name = 0;
- int fd;
- int immed = 1;
- int loej = 0;
- int power_conds = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- file_name = device;
-
- fd = open(file_name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- fprintf(stderr, "Error trying to open %s\n", file_name);
- perror("");
- usage();
- return 2;
- }
- if (ioctl(fd, SG_GET_TIMEOUT, 0) < 0) {
- fprintf(stderr, "Given file not block or SCSI "
- "generic device\n");
- close(fd);
- return 3;
- }
-
- if (synccache)
- do_sync_cache(fd);
-
- if (power_conds > 0)
- do_start_stop(fd, 0, immed, 0, power_conds);
- else if (startstop != -1)
- do_start_stop(fd, startstop, immed, loej, 0);
-
- close(fd);
- return 0;
-}
-
-int find_out_about_buffer(int sg_fd, int *buf_capacity, char *file_name)
-{
- int res, buf_granul = 255;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + 512);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
- int rbInLen = OFF + RB_DESC_LEN;
- int rbOutLen = OFF + sizeof(rbCmdBlk);
- unsigned char *buffp = rbBuff + OFF;
- rsghp->pack_len = 0; /* don't care */
- rsghp->pack_id = 0;
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
-#ifndef SG_GET_RESERVED_SIZE
- rsghp->sense_buffer[0] = 0;
-#endif
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 1] = RB_MODE_DESC;
- rbBuff[OFF + 8] = RB_DESC_LEN;
-
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (desc) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (desc), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- memset(rbBuff + OFF, 0, RB_DESC_LEN);
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (desc) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbInLen) {
- printf("sg_test_rwbuf: read less (desc), ask=%d, got=%d\n",
- rbInLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#ifdef SG_GET_RESERVED_SIZE
- if (!sg_chk_n_print("sg_test_rwbuf: desc", rsghp->target_status,
- rsghp->host_status, rsghp->driver_status,
- rsghp->sense_buffer, SG_MAX_SENSE)) {
- printf
- ("sg_test_rwbuf: perhaps %s doesn't support READ BUFFER\n",
- file_name);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#else
- if ((rsghp->result != 0) || (0 != rsghp->sense_buffer[0])) {
- printf("sg_test_rwbuf: read(desc) result=%d\n", rsghp->result);
- if (0 != rsghp->sense_buffer[0])
- sg_print_sense("sg_test_rwbuf: desc",
- rsghp->sense_buffer, SG_MAX_SENSE);
- printf
- ("sg_test_rwbuf: perhaps %s doesn't support READ BUFFER\n",
- file_name);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-#endif
- *(buf_capacity) = ((buffp[1] << 16) | (buffp[2] << 8) | buffp[3]);
- buf_granul = (unsigned char)buffp[0];
-
- printf("READ BUFFER reports: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffp[0], buffp[1], buffp[2], buffp[3],
- buffp[4], buffp[5], buffp[6], buffp[7]);
-
- printf("READ BUFFER reports: buffer capacity=%d, offset boundary=%d\n",
- *(buf_capacity), buf_granul);
-#ifdef SG_DEF_RESERVED_SIZE
- res = ioctl(sg_fd, SG_SET_RESERVED_SIZE, buf_capacity);
- if (res < 0)
- perror("sg_test_rwbuf: SG_SET_RESERVED_SIZE error");
-#endif
- return 0;
-}
-
-int mymemcmp(unsigned char *bf1, unsigned char *bf2, int len)
-{
- int df;
- for (df = 0; df < len; df++)
- if (bf1[df] != bf2[df])
- return df;
- return 0;
-}
-
-int do_checksum(int *buf, int len, int quiet)
-{
- int sum = base;
- int i;
- int rln = len;
- for (i = 0; i < len / BPI; i++)
- sum += buf[i];
- while (rln % BPI)
- sum += ((char *)buf)[--rln];
- if (sum != READWRITE_BASE_NUM) {
- if (!quiet)
- printf("sg_test_rwbuf: Checksum error (sz=%i): %08x\n",
- len, sum);
- if (cmpbuf && !quiet) {
- int diff = mymemcmp(cmpbuf, (unsigned char *)buf, len);
- printf("Differ at pos %i/%i:\n", diff, len);
- for (i = 0; i < 24 && i + diff < len; i++)
- printf(" %02x", cmpbuf[i + diff]);
- printf("\n");
- for (i = 0; i < 24 && i + diff < len; i++)
- printf(" %02x",
- ((unsigned char *)buf)[i + diff]);
- printf("\n");
- }
- return 2;
- } else
- return 0;
-}
-
-void do_fill_buffer(int *buf, int len)
-{
- int sum;
- int i;
- int rln = len;
- srand(time(0));
-retry:
- if (len >= BPI)
- base = READWRITE_BASE_NUM + rand();
- else
- base = READWRITE_BASE_NUM + (char)rand();
- sum = base;
- for (i = 0; i < len / BPI - 1; i++) {
- /* we rely on rand() giving full range of int */
- buf[i] = rand();
- sum += buf[i];
- }
- while (rln % BPI) {
- ((char *)buf)[--rln] = rand();
- sum += ((char *)buf)[rln];
- }
- if (len >= BPI)
- buf[len / BPI - 1] = READWRITE_BASE_NUM - sum;
- else
- ((char *)buf)[0] = READWRITE_BASE_NUM + ((char *)buf)[0] - sum;
- if (do_checksum(buf, len, 1)) {
- if (len < BPI)
- goto retry;
- printf("sg_test_rwbuf: Memory corruption?\n");
- exit(1);
- }
- if (cmpbuf)
- memcpy(cmpbuf, (char *)buf, len);
-}
-
-int read_buffer(int sg_fd, unsigned size)
-{
- int res;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + size);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
-
- int rbInLen = OFF + size;
- int rbOutLen = OFF + sizeof(rbCmdBlk);
- memset(rbBuff, 0, OFF + sizeof(rbCmdBlk) + size);
- rsghp->pack_len = 0; /* don't care */
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 1] = RB_MODE_DATA;
- rbBuff[OFF + 6] = 0xff & ((size) >> 16);
- rbBuff[OFF + 7] = 0xff & ((size) >> 8);
- rbBuff[OFF + 8] = 0xff & (size);
-
- rsghp->pack_id = 2;
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (data), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbInLen) {
- printf("sg_test_rwbuf: read less (data), ask=%d, got=%d\n",
- rbInLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- res = do_checksum((int *)(rbBuff + OFF), size, 0);
- if (rbBuff)
- free(rbBuff);
- return res;
-}
-
-int write_buffer(int sg_fd, unsigned size)
-{
- int res;
- unsigned char *rbBuff = malloc(OFF + sizeof(rbCmdBlk) + size);
- struct sg_header *rsghp = (struct sg_header *)rbBuff;
- //unsigned char * buffp = rbBuff + OFF;
-
- int rbInLen = OFF;
- int rbOutLen = OFF + sizeof(rbCmdBlk) + size;
-
- do_fill_buffer((int *)(rbBuff + OFF + sizeof(rbCmdBlk)), size);
- rsghp->pack_len = 0; /* don't care */
- rsghp->reply_len = rbInLen;
- rsghp->twelve_byte = 0;
- rsghp->result = 0;
- memcpy(rbBuff + OFF, rbCmdBlk, sizeof(rbCmdBlk));
- rbBuff[OFF + 0] = WRITE_BUFFER;
- rbBuff[OFF + 1] = RB_MODE_DATA;
- rbBuff[OFF + 6] = 0xff & ((size) >> 16);
- rbBuff[OFF + 7] = 0xff & ((size) >> 8);
- rbBuff[OFF + 8] = 0xff & (size);
-
- rsghp->pack_id = 1;
- res = write(sg_fd, rbBuff, rbOutLen);
- if (res < 0) {
- perror("sg_test_rwbuf: write (data) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (res < rbOutLen) {
- printf("sg_test_rwbuf: wrote less (data), ask=%d, got=%d\n",
- rbOutLen, res);
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
-
- res = read(sg_fd, rbBuff, rbInLen);
- if (res < 0) {
- perror("sg_test_rwbuf: read (status) error");
- if (rbBuff)
- free(rbBuff);
- return 1;
- }
- if (rbBuff)
- free(rbBuff);
- return 0;
-}
-
-int do_scsi_read_write_buffer(char *device)
-{
- int sg_fd;
- int res, buf_capacity;
- char *file_name = device;
- struct stat a_st;
- int block_dev = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- sg_fd = open(file_name, O_RDWR);
- if (sg_fd < 0) {
- perror("sg_test_rwbuf: open error");
- return 1;
- }
- if (fstat(sg_fd, &a_st) < 0) {
- fprintf(stderr, "could do fstat() on fd ??\n");
- close(sg_fd);
- return 1;
- }
- if (S_ISBLK(a_st.st_mode))
- block_dev = 1;
- /* Don't worry, being very careful not to write to a none-sg file ... */
- if (block_dev || (ioctl(sg_fd, SG_GET_TIMEOUT, 0) < 0)) {
- /* perror("ioctl on generic device, error"); */
- printf("sg_test_rwbuf: not a sg device, or wrong driver\n");
- return 1;
- }
- if (find_out_about_buffer(sg_fd, &buf_capacity, file_name))
- return 1;
-
- cmpbuf = malloc(buf_capacity);
- if (write_buffer(sg_fd, buf_capacity))
- return 3;
- res = read_buffer(sg_fd, buf_capacity);
- if (res)
- return (res + 4);
-
- res = close(sg_fd);
- if (res < 0) {
- perror("sg_test_rwbuf: close error");
- return 6;
- }
- printf("Success\n");
- return 0;
-}
-
-int do_scsi_test_unit_ready(char *device)
-{
- int sg_fd, k;
- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
- sg_io_hdr_t io_hdr;
- char *file_name = device;
- char ebuff[EBUFF_SZ];
- unsigned char sense_buffer[32];
- int num_turs = 10240;
- int num_errs = 0;
- int do_time = 1;
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "sg_turs: error opening file: %s", file_name);
- perror(ebuff);
- return 1;
- }
- /* Just to be safe, check we have a new sg driver by trying an ioctl */
- if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
- printf
- ("sg_turs: %s isn't an sg device (or the sg driver is old)\n",
- file_name);
- close(sg_fd);
- return 1;
- }
- /* 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 */
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- for (k = 0; k < num_turs; ++k) {
- io_hdr.pack_id = k;
- if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
- perror("sg_turs: Test Unit Ready SG_IO ioctl error");
- close(sg_fd);
- return 1;
- }
- if (io_hdr.info & SG_INFO_OK_MASK) {
- ++num_errs;
- if (1 == num_turs) { /* then print out the error message */
- if (SG_ERR_CAT_CLEAN !=
- sg_err_category3(&io_hdr))
- sg_chk_n_print3("tur", &io_hdr);
- }
- }
- }
- 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)num_turs;
- printf("time to perform commands was %d.%06d secs",
- (int)res_tm.tv_sec, (int)res_tm.tv_usec);
- if (a > 0.00001)
- printf("; %.2f operations/sec\n", b / a);
- else
- printf("\n");
- }
-
- printf("Completed %d Test Unit Ready commands with %d errors\n",
- num_turs, num_errs);
- close(sg_fd);
- return 0;
-}
-
-/* Returns 0 -> ok, 1 -> err, 2 -> recovered error */
-static int do_sg_io(int sg_fd, unsigned char *buff)
-{
-/* N.B. Assuming buff contains pointer 'buffer' or 'buffer1' */
- struct sg_header *sghp = (struct sg_header *)(buff - OFF);
- int res;
-
- sghp->pack_len = 0;
- sghp->reply_len = SG_HSZ + *(((int *)buff) + 1);
- sghp->pack_id = 0;
- sghp->twelve_byte = 0;
- sghp->other_flags = 0;
-#ifndef SG_GET_RESERVED_SIZE
- sghp->sense_buffer[0] = 0;
-#endif
-#if 0
- sg_print_command(buff + 8);
- printf(" write_len=%d, read_len=%d\n",
- SG_HSZ + sg_get_command_size(buff[8]) + *((int *)buff),
- sghp->reply_len);
-#endif
- res = write(sg_fd, (const void *)sghp,
- SG_HSZ + sg_get_command_size(buff[8]) + *((int *)buff));
- if (res < 0) {
-#ifdef SG_IO_DEBUG
- perror("write to sg failed");
-#endif
- return 1;
- }
- res = read(sg_fd, (void *)sghp, sghp->reply_len);
- if (res < 0) {
-#ifdef SG_IO_DEBUG
- perror("read from sg failed");
-#endif
- return 1;
- }
-#ifdef SG_GET_RESERVED_SIZE
- res = sg_err_category(sghp->target_status, sghp->host_status,
- sghp->driver_status, sghp->sense_buffer,
- SG_MAX_SENSE);
- switch (res) {
- case SG_ERR_CAT_CLEAN:
- return 0;
- case SG_ERR_CAT_RECOVERED:
- return 2;
- default:
-#ifdef SG_IO_DEBUG
- sg_chk_n_print("read from sg", sghp->target_status,
- sghp->host_status, sghp->driver_status,
- sghp->sense_buffer, SG_MAX_SENSE);
-#endif
- return 1;
- }
-#else
- if (0 != sghp->sense_buffer[0]) {
-#ifdef SG_IO_DEBUG
- int k;
- printf("read from sg, sense buffer (in hex):\n ");
- for (k = 0; k < 16; ++k)
- printf("%02x ", (int)sghp->sense_buffer[k]);
- printf("\n");
-#endif
- return 1;
- } else if (0 != sghp->result) {
-#ifdef SG_IO_DEBUG
- printf("read from sg, bad result=%d\n", sghp->result);
-#endif
- return 1;
- } else
- return 0;
-#endif
-}
-
-static char *get_page_name(int pageno)
-{
- if ((pageno <= 0) || (pageno >= MAX_PAGENO) || (!page_names[pageno]))
- return "Mode";
- return page_names[pageno];
-}
-
-static int getnbyte(unsigned char *pnt, int nbyte)
-{
- unsigned int result;
- int i;
- result = 0;
- for (i = 0; i < nbyte; i++)
- result = (result << 8) | (pnt[i] & 0xff);
- return result;
-}
-
-static void bitfield(unsigned char *pageaddr, char *text, int mask, int shift)
-{
- printf("%-35s%d\n", text, (*pageaddr >> shift) & mask);
-}
-
-static void notbitfield(unsigned char *pageaddr, char *text, int mask,
- int shift)
-{
- printf("%-35s%d\n", text, !((*pageaddr >> shift) & mask));
-}
-
-static void intfield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s%d\n", text, getnbyte(pageaddr, nbytes));
-}
-
-static void hexfield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s0x%x\n", text, getnbyte(pageaddr, nbytes));
-}
-
-static void hexdatafield(unsigned char *pageaddr, int nbytes, char *text)
-{
- printf("%-35s0x", text);
- while (nbytes-- > 0)
- printf("%02x", *pageaddr++);
- putchar('\n');
-}
-
-static int get_mode_page(int page, int page_code)
-{
- int status, quiet;
- unsigned char *cmd;
-
- memset(buffer, 0, SIZEOF_BUFFER);
-
- quiet = page_code & ~3;
- page_code &= 3;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 0xff; /* length of output data */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = MODE_SENSE; /* MODE SENSE (6) */
- cmd[1] = 0x00; /* lun = 0, inhibitting BD makes this fail
- for me */
- cmd[2] = (page_code << 6) | page;
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = (unsigned char)0xff; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status && (!quiet))
- fprintf(stdout, ">>> Unable to read %s Page %02xh\n",
- get_page_name(page), page);
- //dump (buffer+2, 46);
- return status;
-}
-
-/* Same as above, but this time with MODE_SENSE_10 */
-static int get_mode_page10(int page, int page_code)
-{
- int status, quiet;
- unsigned char *cmd;
-
- memset(buffer, 0, SIZEOF_BUFFER);
-
- quiet = page_code & ~3;
- page_code &= 3;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 0xffff; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = MODE_SENSE_10; /* MODE SENSE (10) */
- cmd[1] = 0x00; /* lun = 0, inhibitting BD makes this fail
- for me */
- cmd[2] = (page_code << 6) | page;
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = 0xff; /* allocation length hi */
- cmd[8] = 0xff; /* allocation length lo */
- cmd[9] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status && (!quiet))
- fprintf(stdout,
- ">>> Unable to read %s Page %02xh with MODESENSE(10)\n",
- get_page_name(page), page);
- return status;
-}
-
-/* Contents should point to the mode parameter header that we obtained
- in a prior read operation. This way we do not have to work out the
- format of the beast */
-
-static int read_geometry(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(4, 9);
-
- printf("Data from Rigid Disk Drive Geometry Page\n");
- printf("----------------------------------------\n");
- intfield(pagestart + 2, 3, "Number of cylinders");
- intfield(pagestart + 5, 1, "Number of heads");
- intfield(pagestart + 6, 3, "Starting write precomp");
- intfield(pagestart + 9, 3, "Starting reduced current");
- intfield(pagestart + 12, 2, "Drive step rate");
- intfield(pagestart + 14, 3, "Landing Zone Cylinder");
- bitfield(pagestart + 17, "RPL", 3, 0);
- intfield(pagestart + 18, 1, "Rotational Offset");
- intfield(pagestart + 20, 2, "Rotational Rate");
- printf("\n");
- return 0;
-
-}
-
-static int read_disconnect_reconnect_data(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(2, 7);
-
- printf("Data from Disconnect-Reconnect Page\n");
- printf("-----------------------------------\n");
- intfield(pagestart + 2, 1, "Buffer full ratio");
- intfield(pagestart + 3, 1, "Buffer empty ratio");
- intfield(pagestart + 4, 2, "Bus Inactivity Limit");
- intfield(pagestart + 6, 2, "Disconnect Time Limit");
- intfield(pagestart + 8, 2, "Connect Time Limit");
- intfield(pagestart + 10, 2, "Maximum Burst Size");
- hexfield(pagestart + 12, 1, "DTDC");
- printf("\n");
- return 0;
-
-}
-
-static int read_control_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(10, 9);
-
- printf("Data from Control Page\n");
- printf("----------------------\n");
- bitfield(pagestart + 2, "RLEC", 1, 0);
- bitfield(pagestart + 3, "QErr", 1, 1);
- bitfield(pagestart + 3, "DQue", 1, 0);
- bitfield(pagestart + 4, "EECA", 1, 7);
- bitfield(pagestart + 4, "RAENP", 1, 2);
- bitfield(pagestart + 4, "UUAENP", 1, 1);
- bitfield(pagestart + 4, "EAENP", 1, 0);
- bitfield(pagestart + 3, "Queue Algorithm Modifier", 0xf, 4);
- intfield(pagestart + 6, 2, "Ready AEN Holdoff Period");
- printf("\n");
- return 0;
-
-}
-
-static int error_recovery_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(1, 14);
- printf("Data from Error Recovery Page\n");
- printf("-----------------------------\n");
- bitfield(pagestart + 2, "AWRE", 1, 7);
- bitfield(pagestart + 2, "ARRE", 1, 6);
- bitfield(pagestart + 2, "TB", 1, 5);
- bitfield(pagestart + 2, "RC", 1, 4);
- bitfield(pagestart + 2, "EER", 1, 3);
- bitfield(pagestart + 2, "PER", 1, 2);
- bitfield(pagestart + 2, "DTE", 1, 1);
- bitfield(pagestart + 2, "DCR", 1, 0);
- intfield(pagestart + 3, 1, "Read Retry Count");
- intfield(pagestart + 4, 1, "Correction Span");
- intfield(pagestart + 5, 1, "Head Offset Count");
- intfield(pagestart + 6, 1, "Data Strobe Offset Count");
- intfield(pagestart + 8, 1, "Write Retry Count");
- intfield(pagestart + 10, 2, "Recovery Time Limit");
- printf("\n");
- return 0;
-}
-
-static int notch_parameters_page(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(0xc, 7);
-
- printf("Data from Notch Parameters Page\n");
- printf("-------------------------------\n");
- bitfield(pagestart + 2, "Notched Drive", 1, 7);
- bitfield(pagestart + 2, "Logical or Physical Notch", 1, 6);
- intfield(pagestart + 4, 2, "Max # of notches");
- intfield(pagestart + 6, 2, "Active Notch");
- if (pagestart[2] & 0x40) {
- intfield(pagestart + 8, 4, "Starting Boundary");
- intfield(pagestart + 12, 4, "Ending Boundary");
- } else { /* Hex is more meaningful for physical notches */
- hexfield(pagestart + 8, 4, "Starting Boundary");
- hexfield(pagestart + 12, 4, "Ending Boundary");
- }
-
- printf("0x%8.8x%8.8x", getnbyte(pagestart + 16, 4),
- getnbyte(pagestart + 20, 4));
-
- printf("\n");
- return 0;
-}
-
-static char *formatname(int format)
-{
- switch (format) {
- case 0x0:
- return "logical blocks";
- case 0x4:
- return "bytes from index [Cyl:Head:Off]\n"
- "Offset -1 marks whole track as bad.\n";
- case 0x5:
- return "physical blocks [Cyl:Head:Sect]\n"
- "Sector -1 marks whole track as bad.\n";
- }
- return "Weird, unknown format";
-}
-
-static int read_defect_list(int page_code)
-{
- int status = 0, i, len, reallen, table, k;
- unsigned char *cmd, *df = 0;
- int trunc;
-
- printf("Data from Defect Lists\n" "----------------------\n");
- for (table = 0; table < 2; table++) {
- memset(buffer, 0, SIZEOF_BUFFER);
- trunc = 0;
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 4; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x37; /* READ DEFECT DATA */
- cmd[1] = 0x00; /* lun=0 */
- cmd[2] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = 0x00; /* Alloc len */
- cmd[8] = 0x04; /* Alloc len */
- cmd[9] = 0x00; /* control */
-
- i = do_sg_io(glob_fd, buffer);
- if (2 == i)
- i = 0; /* Recovered error, probably returned a different
- format */
- if (i) {
- fprintf(stdout, ">>> Unable to read %s defect data.\n",
- (table ? "grown" : "manufacturer"));
- status |= i;
- continue;
- }
- len = (buffer[10] << 8) | buffer[11];
- reallen = len;
- if (len > 0) {
- if (len >= 0xfff8) {
- len = SIZEOF_BUFFER - 8;
- k = len + 8; /* length of defect list */
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = k; /* length of output buffer */
- ((struct sg_header *)buffer)->twelve_byte = 1;
- cmd[0] = 0xB7; /* READ DEFECT DATA */
- cmd[1] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[2] = 0x00; /* (reserved) */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* Alloc len */
- cmd[7] = (k >> 16); /* Alloc len */
- cmd[8] = (k >> 8); /* Alloc len */
- cmd[9] = (k & 0xff); /* Alloc len */
- cmd[10] = 0x00; /* reserved */
- cmd[11] = 0x00; /* control */
- i = do_sg_io(glob_fd, buffer);
- if (i == 2)
- i = 0;
- if (i)
- goto trytenbyte;
- reallen =
- (buffer[12] << 24 | buffer[13] << 16 |
- buffer[14] << 8 | buffer[15]);
- len = reallen;
- if (len > SIZEOF_BUFFER - 8) {
- len = SIZEOF_BUFFER - 8;
- trunc = 1;
- }
- df = (unsigned char *)(buffer + 16);
- } else {
-trytenbyte:
- if (len > 0xfff8) {
- len = 0xfff8;
- trunc = 1;
- }
- k = len + 4; /* length of defect list */
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = k; /* length of output buffer */
- cmd[0] = 0x37; /* READ DEFECT DATA */
- cmd[1] = 0x00; /* lun=0 */
- cmd[2] = (table ? 0x08 : 0x10) | defectformat; /* List, Format */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x00; /* (reserved) */
- cmd[5] = 0x00; /* (reserved) */
- cmd[6] = 0x00; /* (reserved) */
- cmd[7] = (k >> 8); /* Alloc len */
- cmd[8] = (k & 0xff); /* Alloc len */
- cmd[9] = 0x00; /* control */
- i = do_sg_io(glob_fd, buffer);
- df = (unsigned char *)(buffer + 12);
- }
- }
- if (2 == i)
- i = 0; /* Recovered error, probably returned a different
- format */
- if (i) {
- fprintf(stdout, ">>> Unable to read %s defect data.\n",
- (table ? "grown" : "manufacturer"));
- status |= i;
- continue;
- } else {
- if (table && !status)
- printf("\n");
- printf("%d entries (%d bytes) in %s table.\n"
- "Format (%x) is: %s\n",
- reallen / ((buffer[9] & 7) ? 8 : 4), reallen,
- (table ? "grown" : "manufacturer"),
- buffer[9] & 7, formatname(buffer[9] & 7));
- i = 0;
- if ((buffer[9] & 7) == 4) {
- while (len > 0) {
- snprintf((char *)buffer, 40,
- "%6d:%3u:%8d", getnbyte(df, 3),
- df[3], getnbyte(df + 4, 4));
- printf("%19s", (char *)buffer);
- len -= 8;
- df += 8;
- i++;
- if (i >= 4) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- } else if ((buffer[9] & 7) == 5) {
- while (len > 0) {
- snprintf((char *)buffer, 40,
- "%6d:%2u:%5d", getnbyte(df, 3),
- df[3], getnbyte(df + 4, 4));
- printf("%15s", (char *)buffer);
- len -= 8;
- df += 8;
- i++;
- if (i >= 5) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- } else {
- while (len > 0) {
- printf("%10d", getnbyte(df, 4));
- len -= 4;
- df += 4;
- i++;
- if (i >= 7) {
- printf("\n");
- i = 0;
- } else
- printf("|");
- }
- }
- if (i)
- printf("\n");
- }
- if (trunc)
- printf("[truncated]\n");
- }
- printf("\n");
- return status;
-}
-
-static int read_cache(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(8, 9);
-
- printf("Data from Caching Page\n");
- printf("----------------------\n");
- bitfield(pagestart + 2, "Write Cache", 1, 2);
- notbitfield(pagestart + 2, "Read Cache", 1, 0);
- bitfield(pagestart + 2, "Prefetch units", 1, 1);
- bitfield(pagestart + 3, "Demand Read Retention Priority", 0xf, 4);
- bitfield(pagestart + 3, "Demand Write Retention Priority", 0xf, 0);
- intfield(pagestart + 4, 2, "Disable Pre-fetch Transfer Length");
- intfield(pagestart + 6, 2, "Minimum Pre-fetch");
- intfield(pagestart + 8, 2, "Maximum Pre-fetch");
- intfield(pagestart + 10, 2, "Maximum Pre-fetch Ceiling");
- printf("\n");
- return 0;
-}
-
-static int read_format_info(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(3, 13);
-
- printf("Data from Format Device Page\n");
- printf("----------------------------\n");
- bitfield(pagestart + 20, "Removable Medium", 1, 5);
- bitfield(pagestart + 20, "Supports Hard Sectoring", 1, 6);
- bitfield(pagestart + 20, "Supports Soft Sectoring", 1, 7);
- bitfield(pagestart + 20, "Addresses assigned by surface", 1, 4);
- intfield(pagestart + 2, 2, "Tracks per Zone");
- intfield(pagestart + 4, 2, "Alternate sectors per zone");
- intfield(pagestart + 6, 2, "Alternate tracks per zone");
- intfield(pagestart + 8, 2, "Alternate tracks per lun");
- intfield(pagestart + 10, 2, "Sectors per track");
- intfield(pagestart + 12, 2, "Bytes per sector");
- intfield(pagestart + 14, 2, "Interleave");
- intfield(pagestart + 16, 2, "Track skew factor");
- intfield(pagestart + 18, 2, "Cylinder skew factor");
- printf("\n");
- return 0;
-
-}
-
-static int verify_error_recovery(int page_code)
-{
- int status;
- int bdlen;
- unsigned char *pagestart;
-
- SETUP_MODE_PAGE(7, 7);
-
- printf("Data from Verify Error Recovery Page\n");
- printf("------------------------------------\n");
- bitfield(pagestart + 2, "EER", 1, 3);
- bitfield(pagestart + 2, "PER", 1, 2);
- bitfield(pagestart + 2, "DTE", 1, 1);
- bitfield(pagestart + 2, "DCR", 1, 0);
- intfield(pagestart + 3, 1, "Verify Retry Count");
- intfield(pagestart + 4, 1, "Verify Correction Span (bits)");
- intfield(pagestart + 10, 2, "Verify Recovery Time Limit (ms)");
-
- printf("\n");
- return 0;
-}
-
-static int peripheral_device_page(int page_code)
-{
- static char *idents[] = {
- "X3.131: Small Computer System Interface",
- "X3.91M-1987: Storage Module Interface",
- "X3.170: Enhanced Small Device Interface",
- "X3.130-1986; X3T9.3/87-002: IPI-2",
- "X3.132-1987; X3.147-1988: IPI-3"
- };
- int status;
- int bdlen;
- unsigned ident;
- unsigned char *pagestart;
- char *name;
-
- SETUP_MODE_PAGE(9, 2);
-
- printf("Data from Peripheral Device Page\n");
- printf("--------------------------------\n");
-
- ident = getnbyte(pagestart + 2, 2);
- if (ident < (sizeof(idents) / sizeof(char *)))
- name = idents[ident];
- else if (ident < 0x8000)
- name = "Reserved";
- else
- name = "Vendor Specific";
-
- bdlen = pagestart[1] - 6;
- if (bdlen < 0)
- bdlen = 0;
- else
- SETUP_MODE_PAGE(9, 2);
-
- hexfield(pagestart + 2, 2, "Interface Identifier");
- for (ident = 0; ident < 35; ident++)
- putchar(' ');
- puts(name);
-
- hexdatafield(pagestart + 8, bdlen, "Vendor Specific Data");
-
- printf("\n");
- return 0;
-}
-
-/* end */
-
-static int do_user_page(int page_code, int page_no)
-{
- int status;
- int bdlen;
- int i;
- //unsigned ident;
- unsigned char *pagestart;
- char *name;
-
- SETUP_MODE_PAGE(page_no, 0);
- //printf ("Page 0x%02x len: %i\n", page_code, pagestart[1]);
-
- name = "Vendor specific";
- for (i = 2; i < pagestart[1] + 2; i++) {
- char nm[8];
- snprintf(nm, 8, "%02x", i);
- hexdatafield(pagestart + i, 1, nm);
- }
-
- printf("\n");
- puts(name);
- return 0;
-}
-
-/* end */
-
-static int do_scsi_info_inquiry(int page_code)
-{
- int status, i, x_interface = 0;
- unsigned char *cmd;
- unsigned char *pagestart;
- unsigned char tmp;
-
- for (i = 0; i < 1024; i++) {
- buffer[i] = 0;
- }
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 36; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x00; /* lun=0, evpd=0 */
- cmd[2] = 0x00; /* page code = 0 */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x24; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (1)");
- return status;
- }
-
- pagestart = buffer + 8;
-
- printf("Inquiry command\n");
- printf("---------------\n");
- bitfield(pagestart + 7, "Relative Address", 1, 7);
- bitfield(pagestart + 7, "Wide bus 32", 1, 6);
- bitfield(pagestart + 7, "Wide bus 16", 1, 5);
- bitfield(pagestart + 7, "Synchronous neg.", 1, 4);
- bitfield(pagestart + 7, "Linked Commands", 1, 3);
- bitfield(pagestart + 7, "Command Queueing", 1, 1);
- bitfield(pagestart + 7, "SftRe", 1, 0);
- bitfield(pagestart + 0, "Device Type", 0x1f, 0);
- bitfield(pagestart + 0, "Peripheral Qualifier", 0x7, 5);
- bitfield(pagestart + 1, "Removable?", 1, 7);
- bitfield(pagestart + 1, "Device Type Modifier", 0x7f, 0);
- bitfield(pagestart + 2, "ISO Version", 3, 6);
- bitfield(pagestart + 2, "ECMA Version", 7, 3);
- bitfield(pagestart + 2, "ANSI Version", 7, 0);
- bitfield(pagestart + 3, "AENC", 1, 7);
- bitfield(pagestart + 3, "TrmIOP", 1, 6);
- bitfield(pagestart + 3, "Response Data Format", 0xf, 0);
- tmp = pagestart[16];
- pagestart[16] = 0;
- printf("%s%s\n", (!x_interface ? "Vendor: " : ""),
- pagestart + 8);
- pagestart[16] = tmp;
-
- tmp = pagestart[32];
- pagestart[32] = 0;
- printf("%s%s\n", (!x_interface ? "Product: " : ""),
- pagestart + 16);
- pagestart[32] = tmp;
-
- printf("%s%s\n", (!x_interface ? "Revision level: " : ""),
- pagestart + 32);
-
- printf("\n");
- return status;
-
-}
-
-static int do_serial_number(int page_code)
-{
- int status, i, pagelen;
- unsigned char *cmd;
- unsigned char *pagestart;
-
- for (i = 0; i < 1024; i++) {
- buffer[i] = 0;
- }
-
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = 4; /* length of output buffer */
-
- cmd = (unsigned char *)(((int *)buffer) + 2);
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x01; /* lun=0, evpd=1 */
- cmd[2] = 0x80; /* page code = 0x80, serial number */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = 0x04; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (evpd=1, serial number)\n");
- return status;
- }
-
- pagestart = buffer + 8;
-
- pagelen = 4 + pagestart[3];
- *((int *)buffer) = 0; /* length of input data */
- *(((int *)buffer) + 1) = pagelen; /* length of output buffer */
-
- cmd[0] = 0x12; /* INQUIRY */
- cmd[1] = 0x01; /* lun=0, evpd=1 */
- cmd[2] = 0x80; /* page code = 0x80, serial number */
- cmd[3] = 0x00; /* (reserved) */
- cmd[4] = (unsigned char)pagelen; /* allocation length */
- cmd[5] = 0x00; /* control */
-
- status = do_sg_io(glob_fd, buffer);
- if (status) {
- printf("Error doing INQUIRY (evpd=1, serial number, len)\n");
- return status;
- }
-
- printf("Serial Number '");
- for (i = 0; i < pagestart[3]; i++)
- printf("%c", pagestart[4 + i]);
- printf("'\n");
- printf("\n");
-
- return status;
-}
-
-/* Print out a list of the known devices on the system */
-static void show_devices()
-{
- int k, j, fd, err, bus;
- My_scsi_idlun m_idlun;
- char name[MDEV_NAME_SZ];
- char ebuff[EBUFF_SZ];
- int do_numeric = 1;
- int max_holes = MAX_HOLES;
-
- for (k = 0, j = 0; k < sizeof(devices) / sizeof(char *); k++) {
- fd = open(devices[k], O_RDONLY | O_NONBLOCK);
- if (fd < 0)
- continue;
- err =
- ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &(sg_map_arr[j].bus));
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "SCSI(1) ioctl on %s failed", devices[k]);
- perror(ebuff);
- close(fd);
- continue;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ,
- "SCSI(2) ioctl on %s failed", devices[k]);
- perror(ebuff);
- close(fd);
- continue;
- }
- sg_map_arr[j].channel = (m_idlun.dev_id >> 16) & 0xff;
- sg_map_arr[j].lun = (m_idlun.dev_id >> 8) & 0xff;
- sg_map_arr[j].target_id = m_idlun.dev_id & 0xff;
- sg_map_arr[j].dev_name = devices[k];
-
- printf("[scsi%d ch=%d id=%d lun=%d %s] ", sg_map_arr[j].bus,
- sg_map_arr[j].channel, sg_map_arr[j].target_id,
- sg_map_arr[j].lun, sg_map_arr[j].dev_name);
-
- ++j;
- printf("%s ", devices[k]);
- close(fd);
- };
- printf("\n");
- for (k = 0; k < MAX_SG_DEVS; k++) {
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- if ((ENOENT == errno) && (0 == k)) {
- do_numeric = 0;
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- }
- if (fd < 0) {
- if (EBUSY == errno)
- continue; /* step over if O_EXCL already on it */
- else {
-#if 0
- snprintf(ebuff, EBUFF_SZ,
- "open on %s failed (%d)", name,
- errno);
- perror(ebuff);
-#endif
- if (max_holes-- > 0)
- continue;
- else
- break;
- }
- }
- }
- max_holes = MAX_HOLES;
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed",
- name);
- perror(ebuff);
- close(fd);
- continue;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- snprintf(ebuff, EBUFF_SZ, "SCSI(3) ioctl on %s failed",
- name);
- perror(ebuff);
- close(fd);
- continue;
- }
-
- printf("[scsi%d ch=%d id=%d lun=%d %s]", bus,
- (m_idlun.dev_id >> 16) & 0xff, m_idlun.dev_id & 0xff,
- (m_idlun.dev_id >> 8) & 0xff, name);
-
- for (j = 0; sg_map_arr[j].dev_name; ++j) {
- if ((bus == sg_map_arr[j].bus) &&
- ((m_idlun.dev_id & 0xff) == sg_map_arr[j].target_id)
- && (((m_idlun.dev_id >> 16) & 0xff) ==
- sg_map_arr[j].channel)
- && (((m_idlun.dev_id >> 8) & 0xff) ==
- sg_map_arr[j].lun)) {
- printf("%s [=%s scsi%d ch=%d id=%d lun=%d]\n",
- name, sg_map_arr[j].dev_name, bus,
- ((m_idlun.dev_id >> 16) & 0xff),
- m_idlun.dev_id & 0xff,
- ((m_idlun.dev_id >> 8) & 0xff));
- break;
- }
- }
- if (NULL == sg_map_arr[j].dev_name)
- printf("%s [scsi%d ch=%d id=%d lun=%d]\n", name, bus,
- ((m_idlun.dev_id >> 16) & 0xff),
- m_idlun.dev_id & 0xff,
- ((m_idlun.dev_id >> 8) & 0xff));
- close(fd);
- }
- printf("\n");
-}
-
-static int show_pages(int page_code)
-{
- int offset;
- int length;
- int i;
- unsigned long long pages_sup = 0;
- unsigned long long pages_mask = 0;
-
- if (!get_mode_page10(0x3f, page_code | 0x10)) {
- length = 9 + getnbyte(buffer + 8, 2);
- offset = 16 + getnbyte(buffer + 14, 2);
- } else if (!get_mode_page(0x3f, page_code | 0x10)) {
- length = 9 + buffer[8];
- offset = 12 + buffer[11];
- } else { /* Assume SCSI-1 and fake settings to report NO pages */
- offset = 10;
- length = 0;
- }
-
- /* Get mask of pages supported by prog: */
- for (i = 0; i < MAX_PAGENO; i++)
- if (page_names[i])
- pages_mask |= (1LL << i);
-
- /* Get pages listed in mode_pages */
- while (offset < length) {
- pages_sup |= (1LL << (buffer[offset] & 0x3f));
- offset += 2 + buffer[offset + 1];
- }
-
- /* Mask out pages unsupported by this binary */
- pages_sup &= pages_mask;
-
- /* Notch page supported? */
- if (pages_sup & (1LL << 12)) {
- if (get_mode_page(12, 0))
- return 2;
- offset = 12 + buffer[11];
- } else { /* Fake empty notch page */
- memset(buffer, 0, SIZEOF_BUFFER);
- offset = 0;
- }
-
- pages_mask = getnbyte(buffer + offset + 16, 4);
- pages_mask <<= 32;
- pages_mask += getnbyte(buffer + offset + 20, 4);
-
- puts("Mode Pages supported by this binary and target:");
- puts("-----------------------------------------------");
- for (i = 0; i < MAX_PAGENO; i++)
- if (pages_sup & (1LL << i))
- printf("%02xh: %s Page%s\n", i, get_page_name(i),
- (pages_mask & (1LL << i)) ? " (notched)" : "");
- if (pages_sup & (1LL << 12)) {
- printf("\nCurrent notch is %d.\n",
- getnbyte(buffer + offset + 6, 2));
- }
- if (!pages_sup)
- puts("No mode pages supported (SCSI-1?).");
-
- return 0;
-}
-
-static int open_sg_dev(char *devname)
-{
- int fd, err, bus, bbus, k;
- My_scsi_idlun m_idlun, mm_idlun;
- int do_numeric = 1;
- char name[DEVNAME_SZ];
- struct stat a_st;
- int block_dev = 0;
-
- strncpy(name, devname, DEVNAME_SZ);
- name[DEVNAME_SZ - 1] = '\0';
- fd = open(name, O_RDONLY);
- if (fd < 0)
- return fd;
- if (fstat(fd, &a_st) < 0) {
- fprintf(stderr, "could do fstat() on fd ??\n");
- close(fd);
- return -9999;
- }
- if (S_ISBLK(a_st.st_mode))
- block_dev = 1;
- if (block_dev || (ioctl(fd, SG_GET_TIMEOUT, 0) < 0)) {
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus);
- if (err < 0) {
- perror("A SCSI device name is required\n");
- close(fd);
- return -9999;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &m_idlun);
- if (err < 0) {
- perror("A SCSI device name is required\n");
- close(fd);
- return -9999;
- }
- close(fd);
-
- for (k = 0; k < MAX_SG_DEVS; k++) {
- make_dev_name(name, NULL, k, do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- if ((ENOENT == errno) && (0 == k)) {
- do_numeric = 0;
- make_dev_name(name, NULL, k,
- do_numeric);
- fd = open(name, O_RDWR | O_NONBLOCK);
- }
- if (fd < 0) {
- if (EBUSY == errno)
- continue; /* step over if O_EXCL already on it */
- else
- break;
- }
- }
- err = ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bbus);
- if (err < 0) {
- perror("sg ioctl failed");
- close(fd);
- fd = -9999;
- }
- err = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &mm_idlun);
- if (err < 0) {
- perror("sg ioctl failed");
- close(fd);
- fd = -9999;
- }
- if ((bus == bbus) &&
- ((m_idlun.dev_id & 0xff) ==
- (mm_idlun.dev_id & 0xff))
- && (((m_idlun.dev_id >> 8) & 0xff) ==
- ((mm_idlun.dev_id >> 8) & 0xff))
- && (((m_idlun.dev_id >> 16) & 0xff) ==
- ((mm_idlun.dev_id >> 16) & 0xff)))
- break;
- else {
- close(fd);
- fd = -9999;
- }
- }
- }
- if (fd >= 0) {
-#ifdef SG_GET_RESERVED_SIZE
- int size;
-
- if (ioctl(fd, SG_GET_RESERVED_SIZE, &size) < 0) {
- fprintf(stderr,
- "Compiled with new driver, running on old!!\n");
- close(fd);
- return -9999;
- }
-#endif
- close(fd);
- return open(name, O_RDWR);
- } else
- return fd;
-}
-
-int show_scsi_info(char *device)
-{
- int page_code = 0;
- int status = 0;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- show_devices();
-
- glob_fd = open_sg_dev(device);
- if (glob_fd < 0) {
- if (-9999 == glob_fd)
- fprintf(stderr,
- "Couldn't find sg device corresponding to %s\n",
- device);
- else {
- perror("sginfo(open)");
- fprintf(stderr,
- "file=%s, or no corresponding sg device found\n",
- device);
- fprintf(stderr, "Is sg driver loaded?\n");
- }
- return 1;
- }
-
- status |= do_scsi_info_inquiry(page_code);
-
- status |= do_serial_number(page_code);
-
- status |= read_geometry(page_code);
-
- status |= read_cache(page_code);
-
- status |= read_format_info(page_code);
-
- status |= error_recovery_page(page_code);
-
- status |= read_control_page(page_code);
-
- status |= read_disconnect_reconnect_data(page_code);
-
- status |= read_defect_list(page_code);
-
- status |= notch_parameters_page(page_code);
-
- status |= verify_error_recovery(page_code);
-
- status |= peripheral_device_page(page_code);
-
- status |= do_user_page(page_code, 0);
-
- status |= show_pages(page_code);
-
- return status;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_read2(int sg_fd, unsigned char *buff, int blocks, int from_block,
- int bs, int cdbsz, int fua, int do_mmap)
-{
- unsigned char rdCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int res;
-
- if (sg_build_scsi_cdb(rdCmd, cdbsz, blocks, from_block, 0, fua, 0)) {
- fprintf(stderr,
- ME "bad rd cdb build, from_block=%d, blocks=%d\n",
- from_block, blocks);
- return -1;
- }
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = rdCmd;
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.dxfer_len = bs * blocks;
- if (!do_mmap)
- 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 (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_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_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while reading block=%d, num=%d\n",
- from_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- return 2;
- default:
- sg_chk_n_print3("reading", &io_hdr);
- return -1;
- }
- sum_of_resids += io_hdr.resid;
-#if SG_DEBUG
- fprintf(stderr, "duration=%u ms\n", io_hdr.duration);
-#endif
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> recoverable (ENOMEM),
- 2 -> try again */
-int sg_write2(int sg_fd, unsigned char *buff, int blocks, int to_block,
- int bs, int cdbsz, int fua, int do_mmap, int *diop)
-{
- unsigned char wrCmd[MAX_SCSI_CDBSZ];
- unsigned char senseBuff[SENSE_BUFF_LEN];
- sg_io_hdr_t io_hdr;
- int res;
-
- if (sg_build_scsi_cdb(wrCmd, cdbsz, blocks, to_block, 1, fua, 0)) {
- fprintf(stderr, ME "bad wr cdb build, to_block=%d, blocks=%d\n",
- to_block, blocks);
- return -1;
- }
-
- memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
- io_hdr.interface_id = 'S';
- io_hdr.cmd_len = cdbsz;
- io_hdr.cmdp = wrCmd;
- io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
- io_hdr.dxfer_len = bs * blocks;
- if (!do_mmap)
- 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 (do_mmap)
- io_hdr.flags |= SG_FLAG_MMAP_IO;
- 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_ERR_CAT_CLEAN:
- break;
- case SG_ERR_CAT_RECOVERED:
- fprintf(stderr,
- "Recovered error while writing block=%d, num=%d\n",
- to_block, blocks);
- break;
- case SG_ERR_CAT_MEDIA_CHANGED:
- 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 do_scsi_sgm_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int bs = 0;
- int bpt = DEF_BLOCKS_PER_TRANSFER;
- char inf[INOUTF_SZ];
- int in_type = FT_OTHER;
- char outf[INOUTF_SZ];
- int out_type = FT_OTHER;
- int res, t;
- int infd, outfd, blocks;
- unsigned char *wrkPos;
- unsigned char *wrkBuff = NULL;
- unsigned char *wrkMmap = NULL;
- int in_num_sect = 0;
- int in_res_sz = 0;
- int out_num_sect = 0;
- int out_res_sz = 0;
- int do_time = 1;
- int scsi_cdbsz = DEF_SCSI_CDBSZ;
- int do_sync = 1;
- int do_dio = 0;
- int num_dio_not_done = 0;
- int fua_mode = 0;
- int in_sect_sz, out_sect_sz;
- char ebuff[EBUFF_SZ];
- int blocks_per;
- int req_count;
- size_t psz = getpagesize();
- struct timeval start_tm, end_tm;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- install_handler(SIGINT, interrupt_handler);
- install_handler(SIGQUIT, interrupt_handler);
- install_handler(SIGPIPE, interrupt_handler);
- install_handler(SIGUSR1, siginfo_handler);
-
- infd = STDIN_FILENO;
- outfd = STDOUT_FILENO;
-
- in_type = dd_filetype(inf);
-
- if (FT_ST == in_type) {
- fprintf(stderr, ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG == in_type) {
- if ((infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading", inf);
- perror(ebuff);
- return 1;
- }
- res = ioctl(infd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30122)) {
- fprintf(stderr, ME "sg driver prior to 3.1.22\n");
- return 1;
- }
- in_res_sz = bs * bpt;
- if (0 != (in_res_sz % psz)) /* round up to next page */
- in_res_sz = ((in_res_sz / psz) + 1) * psz;
- if (ioctl(infd, SG_GET_RESERVED_SIZE, &t) < 0) {
- perror(ME "SG_GET_RESERVED_SIZE error");
- return 1;
- }
- if (in_res_sz > t) {
- if (ioctl(infd, SG_SET_RESERVED_SIZE, &in_res_sz) < 0) {
- perror(ME "SG_SET_RESERVED_SIZE error");
- return 1;
- }
- }
- wrkMmap = mmap(NULL, in_res_sz, PROT_READ | PROT_WRITE,
- MAP_SHARED, infd, 0);
- if (MAP_FAILED == wrkMmap) {
- snprintf(ebuff, EBUFF_SZ,
- ME "error using mmap() on file: %s", inf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((infd = open(inf, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading", inf);
- perror(ebuff);
- return 1;
- } else if (skip > 0) {
- llse_loff_t offset = skip;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to "
- "required position on %s", inf);
- perror(ebuff);
- return 1;
- }
- }
- }
-
- if (outf[0] && ('-' != outf[0])) {
- out_type = dd_filetype(outf);
-
- if (FT_ST == out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG == out_type) {
- if ((outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for "
- "sg writing", outf);
- perror(ebuff);
- return 1;
- }
- res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30122)) {
- fprintf(stderr,
- ME "sg driver prior to 3.1.22\n");
- return 1;
- }
- if (ioctl(outfd, SG_GET_RESERVED_SIZE, &t) < 0) {
- perror(ME "SG_GET_RESERVED_SIZE error");
- return 1;
- }
- out_res_sz = bs * bpt;
- if (out_res_sz > t) {
- if (ioctl
- (outfd, SG_SET_RESERVED_SIZE,
- &out_res_sz) < 0) {
- perror(ME "SG_SET_RESERVED_SIZE error");
- return 1;
- }
- }
- if (NULL == wrkMmap) {
- wrkMmap =
- mmap(NULL, out_res_sz,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- outfd, 0);
- if (MAP_FAILED == wrkMmap) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "error using mmap() on file: %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- } else if (FT_DEV_NULL == out_type)
- outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != out_type) {
- if ((outfd =
- open(outf, O_WRONLY | O_CREAT,
- 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s "
- "for raw writing", outf);
- perror(ebuff);
- return 1;
- }
- }
- if (seek > 0) {
- llse_loff_t offset = seek;
-
- offset *= bs; /* could exceed 32 bits here! */
- if (llse_llseek(outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "couldn't seek to "
- "required position on %s",
- outf);
- perror(ebuff);
- return 1;
- }
- }
- }
- }
- if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
- fprintf(stderr,
- "Can't have both 'if' as stdin _and_ 'of' as stdout\n");
- return 1;
- }
-#if 0
- if ((FT_OTHER == in_type) && (FT_OTHER == out_type)) {
- fprintf(stderr, "Both 'if' and 'of' can't be ordinary files\n");
- return 1;
- }
-#endif
- if (dd_count < 0) {
- if (FT_SG == in_type) {
- res = read_capacity(infd, &in_num_sect, &in_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res =
- read_capacity(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 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 (FT_SG == out_type) {
- res = read_capacity(outfd, &out_num_sect, &out_sect_sz);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(out), continuing\n");
- res =
- read_capacity(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;
- }
- }
-#ifdef SG_DEBUG
- fprintf(stderr,
- "Start of loop, count=%d, in_num_sect=%d, out_num_sect=%d\n",
- dd_count, in_num_sect, out_num_sect);
-#endif
- 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 (dd_count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
- if (do_dio && (FT_SG != in_type)) {
- do_dio = 0;
- fprintf(stderr,
- ">>> dio only performed on 'of' side when 'if' is"
- " an sg device\n");
- }
- if (do_dio) {
- int fd;
- char c;
-
- 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 (wrkMmap)
- wrkPos = wrkMmap;
- else {
- if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
- wrkBuff = malloc(bs * bpt + psz);
- if (0 == wrkBuff) {
- fprintf(stderr,
- "Not enough user memory for raw\n");
- return 1;
- }
- wrkPos =
- (unsigned char *)(((unsigned long)wrkBuff + psz - 1)
- & (~(psz - 1)));
- } else {
- wrkBuff = malloc(bs * bpt);
- if (0 == wrkBuff) {
- fprintf(stderr, "Not enough user memory\n");
- return 1;
- }
- wrkPos = wrkBuff;
- }
- }
-
- blocks_per = bpt;
-#ifdef SG_DEBUG
- fprintf(stderr, "Start of loop, count=%d, blocks_per=%d\n",
- dd_count, blocks_per);
-#endif
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
- req_count = dd_count;
-
- while (dd_count > 0) {
- blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
- if (FT_SG == in_type) {
- int fua = fua_mode & 2;
-
- res =
- sg_read2(infd, wrkPos, blocks, skip, bs, scsi_cdbsz,
- fua, 1);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (r)\n");
- res =
- sg_read2(infd, wrkPos, blocks, skip, bs,
- scsi_cdbsz, fua, 1);
- }
- if (0 != res) {
- fprintf(stderr, "sg_read2 failed, skip=%d\n",
- skip);
- break;
- } else
- in_full += blocks;
- } else {
- while (((res = read(infd, wrkPos, blocks * bs)) < 0) &&
- (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "reading, skip=%d ", skip);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- dd_count = 0;
- blocks = res / bs;
- if ((res % bs) > 0) {
- blocks++;
- in_partial++;
- }
- }
- in_full += blocks;
- }
-
- if (FT_SG == out_type) {
- int do_mmap = (FT_SG == in_type) ? 0 : 1;
- int fua = fua_mode & 1;
- int dio_res = do_dio;
-
- res =
- sg_write2(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, do_mmap, &dio_res);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed, continuing (w)\n");
- res =
- sg_write2(outfd, wrkPos, blocks, seek, bs,
- scsi_cdbsz, fua, do_mmap,
- &dio_res);
- } else if (0 != res) {
- fprintf(stderr, "sg_write2 failed, seek=%d\n",
- seek);
- break;
- } else {
- out_full += blocks;
- if (do_dio && (0 == dio_res))
- num_dio_not_done++;
- }
- } else if (FT_DEV_NULL == out_type)
- out_full += blocks; /* act as if written out without error */
- else {
- while (((res = write(outfd, wrkPos, blocks * bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "writing, seek=%d ", seek);
- perror(ebuff);
- break;
- } else if (res < blocks * bs) {
- fprintf(stderr,
- "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 (dd_count > 0)
- dd_count -= blocks;
- skip += blocks;
- seek += blocks;
- }
- 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)bs *(req_count - dd_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 (do_sync) {
- if (FT_SG == out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
-
- if (wrkBuff)
- free(wrkBuff);
- if (STDIN_FILENO != infd)
- close(infd);
- if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
- close(outfd);
- res = 0;
- if (0 != dd_count) {
- fprintf(stderr, "Some error occurred,");
- res = 2;
- }
- print_stats();
- if (sum_of_resids)
- fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
- sum_of_resids);
- if (num_dio_not_done)
- fprintf(stderr, ">> dio requested but _not done %d times\n",
- num_dio_not_done);
- return res;
-}
-
-static void guarded_stop_in(Rq_coll * clp)
-{
- pthread_mutex_lock(&clp->in_mutex);
- clp->in_stop = 1;
- pthread_mutex_unlock(&clp->in_mutex);
-}
-
-static void guarded_stop_out(Rq_coll * clp)
-{
- pthread_mutex_lock(&clp->out_mutex);
- clp->out_stop = 1;
- pthread_mutex_unlock(&clp->out_mutex);
-}
-
-static void guarded_stop_both(Rq_coll * clp)
-{
- guarded_stop_in(clp);
- guarded_stop_out(clp);
-}
-
-void *sig_listen_thread(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
- int sig_number;
-
- while (1) {
- sigwait(&signal_set, &sig_number);
- if (SIGINT == sig_number) {
- fprintf(stderr, ME "interrupted by SIGINT\n");
- guarded_stop_both(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
- }
- }
- return NULL;
-}
-
-void cleanup_in(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
-
- fprintf(stderr, "thread cancelled while in mutex held\n");
- clp->in_stop = 1;
- pthread_mutex_unlock(&clp->in_mutex);
- guarded_stop_out(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
-}
-
-void cleanup_out(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
-
- fprintf(stderr, "thread cancelled while out mutex held\n");
- clp->out_stop = 1;
- pthread_mutex_unlock(&clp->out_mutex);
- guarded_stop_in(clp);
- pthread_cond_broadcast(&clp->out_sync_cv);
-}
-
-void *read_write_thread(void *v_clp)
-{
- Rq_coll *clp = (Rq_coll *) v_clp;
- Rq_elem rel;
- Rq_elem *rep = &rel;
- size_t psz = 0;
- int sz = clp->bpt * clp->bs;
- int stop_after_write = 0;
- int seek_skip = clp->seek - clp->skip;
- int blocks, status;
-
- memset(rep, 0, sizeof(Rq_elem));
- psz = getpagesize();
- if (NULL == (rep->alloc_bp = malloc(sz + psz)))
- err_exit(ENOMEM, "out of memory creating user buffers\n");
- rep->buffp =
- (unsigned char *)(((unsigned long)rep->alloc_bp + psz - 1) &
- (~(psz - 1)));
- /* Follow clp members are constant during lifetime of thread */
- rep->bs = clp->bs;
- rep->fua_mode = clp->fua_mode;
- rep->dio = clp->dio;
- rep->infd = clp->infd;
- rep->outfd = clp->outfd;
- rep->debug = clp->debug;
- rep->in_scsi_type = clp->in_scsi_type;
- rep->out_scsi_type = clp->out_scsi_type;
- rep->cdbsz = clp->cdbsz;
-
- while (1) {
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- if (clp->in_stop || (clp->in_count <= 0)) {
- /* no more to do, exit loop then thread */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- break;
- }
- blocks = (clp->in_count > clp->bpt) ? clp->bpt : clp->in_count;
- rep->wr = 0;
- rep->blk = clp->in_blk;
- rep->num_blks = blocks;
- clp->in_blk += blocks;
- clp->in_count -= blocks;
-
- pthread_cleanup_push(cleanup_in, (void *)clp);
- if (FT_SG == clp->in_type)
- sg_in_operation(clp, rep); /* lets go of in_mutex mid operation */
- else {
- stop_after_write =
- normal_in_operation(clp, rep, blocks);
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- }
- pthread_cleanup_pop(0);
-
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- if (FT_DEV_NULL != clp->out_type) {
- while ((!clp->out_stop) &&
- ((rep->blk + seek_skip) != clp->out_blk)) {
- /* if write would be out of sequence then wait */
- pthread_cleanup_push(cleanup_out, (void *)clp);
- status =
- pthread_cond_wait(&clp->out_sync_cv,
- &clp->out_mutex);
- if (0 != status)
- err_exit(status, "cond out_sync_cv");
- pthread_cleanup_pop(0);
- }
- }
-
- if (clp->out_stop || (clp->out_count <= 0)) {
- if (!clp->out_stop)
- clp->out_stop = 1;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- break;
- }
- if (stop_after_write)
- clp->out_stop = 1;
- rep->wr = 1;
- rep->blk = clp->out_blk;
- /* rep->num_blks = blocks; */
- clp->out_blk += blocks;
- clp->out_count -= blocks;
-
- pthread_cleanup_push(cleanup_out, (void *)clp);
- if (FT_SG == clp->out_type)
- sg_out_operation(clp, rep); /* releases out_mutex mid operation */
- else if (FT_DEV_NULL == clp->out_type) {
- /* skip actual write operation */
- clp->out_done_count -= blocks;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- } else {
- normal_out_operation(clp, rep, blocks);
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- }
- pthread_cleanup_pop(0);
-
- if (stop_after_write)
- break;
- pthread_cond_broadcast(&clp->out_sync_cv);
- } /* end of while loop */
- if (rep->alloc_bp)
- free(rep->alloc_bp);
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- if (!clp->in_stop)
- clp->in_stop = 1; /* flag other workers to stop */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- pthread_cond_broadcast(&clp->out_sync_cv);
- return stop_after_write ? NULL : v_clp;
-}
-
-int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
- int stop_after_write = 0;
-
- /* enters holding in_mutex */
- while (((res = read(clp->infd, rep->buffp,
- blocks * clp->bs)) < 0) && (EINTR == errno)) ;
- 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, %s\n", rep->blk,
- rep->num_blks * rep->bs, strerror(errno));
- res = rep->num_blks * clp->bs;
- } else {
- fprintf(stderr, "error in normal read, %s\n",
- strerror(errno));
- clp->in_stop = 1;
- guarded_stop_out(clp);
- return 1;
- }
- }
- if (res < blocks * clp->bs) {
- int o_blocks = blocks;
- stop_after_write = 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;
- return stop_after_write;
-}
-
-void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
-{
- int res;
-
- /* enters holding out_mutex */
- while (((res = write(clp->outfd, rep->buffp,
- rep->num_blks * clp->bs)) < 0)
- && (EINTR == errno)) ;
- if (res < 0) {
- if (clp->coe) {
- fprintf(stderr, ">> ignored error for out blk=%d for "
- "%d bytes, %s\n", rep->blk,
- rep->num_blks * rep->bs, strerror(errno));
- res = rep->num_blks * clp->bs;
- } else {
- fprintf(stderr, "error normal write, %s\n",
- strerror(errno));
- guarded_stop_in(clp);
- clp->out_stop = 1;
- return;
- }
- }
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
- blocks++;
- clp->out_partial++;
- }
- rep->num_blks = blocks;
- }
- clp->out_done_count -= blocks;
-}
-
-void sg_in_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
- int status;
-
- /* enters holding in_mutex */
- while (1) {
- res = sg_start_io(rep);
- if (1 == res)
- err_exit(ENOMEM, "sg starting in command");
- else if (res < 0) {
- fprintf(stderr, ME "inputting to sg failed, blk=%d\n",
- rep->blk);
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- guarded_stop_both(clp);
- return;
- }
- /* Now release in mutex to let other reads run in parallel */
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
-
- res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
- 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);
- } else {
- fprintf(stderr,
- "error finishing sg in command\n");
- guarded_stop_both(clp);
- return;
- }
- }
- if (res <= 0) { /* looks good, going to return */
- if (rep->dio_incomplete || rep->resid) {
- status = pthread_mutex_lock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- status = pthread_mutex_unlock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- }
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- clp->in_done_count -= rep->num_blks;
- status = pthread_mutex_unlock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "unlock in_mutex");
- return;
- }
- /* else assume 1 == res so try again with same addr, count info */
- /* now re-acquire read mutex for balance */
- /* N.B. This re-read could now be out of read sequence */
- status = pthread_mutex_lock(&clp->in_mutex);
- if (0 != status)
- err_exit(status, "lock in_mutex");
- }
-}
-
-void sg_out_operation(Rq_coll * clp, Rq_elem * rep)
-{
- int res;
- int status;
-
- /* enters holding out_mutex */
- while (1) {
- res = sg_start_io(rep);
- if (1 == res)
- err_exit(ENOMEM, "sg starting out command");
- else if (res < 0) {
- fprintf(stderr,
- ME "outputting from sg failed, blk=%d\n",
- rep->blk);
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- guarded_stop_both(clp);
- return;
- }
- /* Now release in mutex to let other reads run in parallel */
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
-
- res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
- 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);
- else {
- fprintf(stderr,
- "error finishing sg out command\n");
- guarded_stop_both(clp);
- return;
- }
- }
- if (res <= 0) {
- if (rep->dio_incomplete || rep->resid) {
- status = pthread_mutex_lock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- clp->dio_incomplete += rep->dio_incomplete;
- clp->sum_of_resids += rep->resid;
- status = pthread_mutex_unlock(&clp->aux_mutex);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- }
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- clp->out_done_count -= rep->num_blks;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
- return;
- }
- /* else assume 1 == res so try again with same addr, count info */
- /* now re-acquire out mutex for balance */
- /* N.B. This re-write could now be out of write sequence */
- status = pthread_mutex_lock(&clp->out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- }
-}
-
-int sg_start_io(Rq_elem * rep)
-{
- sg_io_hdr_t *hp = &rep->io_hdr;
- int fua = rep->wr ? (rep->fua_mode & 1) : (rep->fua_mode & 2);
- int res;
-
- if (sg_build_scsi_cdb(rep->cmd, rep->cdbsz, rep->num_blks, rep->blk,
- rep->wr, fua, 0)) {
- fprintf(stderr, ME "bad cdb build, start_blk=%d, blocks=%d\n",
- rep->blk, rep->num_blks);
- return -1;
- }
- memset(hp, 0, sizeof(sg_io_hdr_t));
- hp->interface_id = 'S';
- hp->cmd_len = rep->cdbsz;
- 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;
- perror("starting io on sg device, error");
- return -1;
- }
- return 0;
-}
-
-/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
-int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
-{
- int res, status;
- 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)
- err_exit(0,
- "sg_finish_io: bad usr_ptr, request-response mismatch\n");
- 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);
- status = pthread_mutex_lock(a_mutp);
- if (0 != status)
- err_exit(status, "lock aux_mutex");
- sg_chk_n_print3(ebuff, hp);
- status = pthread_mutex_unlock(a_mutp);
- if (0 != status)
- err_exit(status, "unlock aux_mutex");
- 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;
-}
-
-int sg_prepare(int fd, int bs, int bpt, int *scsi_typep)
-{
- int res, t;
-
- res = ioctl(fd, SG_GET_VERSION_NUM, &t);
- if ((res < 0) || (t < 30000)) {
- fprintf(stderr, ME "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(ME "SG_SET_RESERVED_SIZE error");
- t = 1;
- res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
- if (res < 0)
- perror(ME "SG_SET_FORCE_PACK_ID error");
- if (scsi_typep) {
- struct sg_scsi_id info;
-
- res = ioctl(fd, SG_GET_SCSI_ID, &info);
- if (res < 0)
- perror(ME "SG_SET_SCSI_ID error");
- *scsi_typep = info.scsi_type;
- }
- return 0;
-}
-
-int do_scsi_sgp_read_write(char *device)
-{
- int skip = 0;
- int seek = 0;
- int count = -1;
- 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;
- pthread_t threads[MAX_NUM_THREADS];
- int do_time = 1;
- int do_sync = 1;
- int in_sect_sz, out_sect_sz, status, infull, outfull;
- void *vp;
- char ebuff[EBUFF_SZ];
- struct timeval start_tm, end_tm;
- Rq_coll rcoll;
-
- print_msg(TEST_BREAK, __FUNCTION__);
-
- memset(&rcoll, 0, sizeof(Rq_coll));
- rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
- rcoll.in_type = FT_OTHER;
- rcoll.out_type = FT_OTHER;
- rcoll.cdbsz = DEF_SCSI_CDBSZ;
-
- strcpy(inf, "/dev/zero");
- strcpy(outf, device);
-
- if (rcoll.bs <= 0) {
- rcoll.bs = DEF_BLOCK_SIZE;
- fprintf(stderr,
- "Assume default 'bs' (block size) of %d bytes\n",
- rcoll.bs);
- }
-
- if (rcoll.debug)
- fprintf(stderr, ME "if=%s skip=%d of=%s seek=%d count=%d\n",
- inf, skip, outf, seek, count);
-
- rcoll.infd = STDIN_FILENO;
- rcoll.outfd = STDOUT_FILENO;
- if (inf[0] && ('-' != inf[0])) {
- rcoll.in_type = dd_filetype(inf);
-
- if (FT_ST == rcoll.in_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", inf);
- return 1;
- } else if (FT_SG == rcoll.in_type) {
- if ((rcoll.infd = open(inf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading",
- inf);
- perror(ebuff);
- return 1;
- }
- if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt,
- &rcoll.in_scsi_type))
- return 1;
- } else {
- if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "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,
- ME
- "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_ST == rcoll.out_type) {
- fprintf(stderr,
- ME "unable to use scsi tape device %s\n", outf);
- return 1;
- } else if (FT_SG == rcoll.out_type) {
- if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg writing",
- outf);
- perror(ebuff);
- return 1;
- }
-
- if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt,
- &rcoll.out_scsi_type))
- return 1;
- } else if (FT_DEV_NULL == rcoll.out_type)
- rcoll.outfd = -1; /* don't bother opening */
- else {
- if (FT_RAW != rcoll.out_type) {
- if ((rcoll.outfd =
- open(outf, O_WRONLY | O_CREAT,
- 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "could not open %s for writing",
- outf);
- perror(ebuff);
- return 1;
- }
- } else {
- if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME
- "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,
- ME
- "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 (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), continuing\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), continuing\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)
- count =
- (in_num_sect >
- out_num_sect) ? out_num_sect : in_num_sect;
- else
- count = in_num_sect;
- } else
- count = out_num_sect;
- }
- if (rcoll.debug > 1)
- fprintf(stderr, "Start of loop, count=%d, in_num_sect=%d, "
- "out_num_sect=%d\n", count, in_num_sect, out_num_sect);
- if (count < 0) {
- fprintf(stderr, "Couldn't calculate count, please give one\n");
- return 1;
- }
-
- rcoll.in_count = count;
- rcoll.in_done_count = count;
- rcoll.skip = skip;
- rcoll.in_blk = skip;
- rcoll.out_count = count;
- rcoll.out_done_count = count;
- rcoll.seek = seek;
- rcoll.out_blk = seek;
- status = pthread_mutex_init(&rcoll.in_mutex, NULL);
- if (0 != status)
- err_exit(status, "init in_mutex");
- status = pthread_mutex_init(&rcoll.out_mutex, NULL);
- if (0 != status)
- err_exit(status, "init out_mutex");
- status = pthread_mutex_init(&rcoll.aux_mutex, NULL);
- if (0 != status)
- err_exit(status, "init aux_mutex");
- status = pthread_cond_init(&rcoll.out_sync_cv, NULL);
- if (0 != status)
- err_exit(status, "init out_sync_cv");
-
- sigemptyset(&signal_set);
- sigaddset(&signal_set, SIGINT);
- status = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
- if (0 != status)
- err_exit(status, "pthread_sigmask");
- status = pthread_create(&sig_listen_thread_id, NULL,
- sig_listen_thread, (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create, sig...");
-
- if (do_time) {
- start_tm.tv_sec = 0;
- start_tm.tv_usec = 0;
- gettimeofday(&start_tm, NULL);
- }
-
-/* vvvvvvvvvvv Start worker threads vvvvvvvvvvvvvvvvvvvvvvvv */
- if ((rcoll.out_done_count > 0) && (num_threads > 0)) {
- /* Run 1 work thread to shake down infant retryable stuff */
- status = pthread_mutex_lock(&rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "lock out_mutex");
- status = pthread_create(&threads[0], NULL, read_write_thread,
- (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create");
- if (rcoll.debug)
- fprintf(stderr, "Starting worker thread k=0\n");
-
- /* wait for any broadcast */
- pthread_cleanup_push(cleanup_out, (void *)&rcoll);
- status =
- pthread_cond_wait(&rcoll.out_sync_cv, &rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "cond out_sync_cv");
- pthread_cleanup_pop(0);
- status = pthread_mutex_unlock(&rcoll.out_mutex);
- if (0 != status)
- err_exit(status, "unlock out_mutex");
-
- /* now start the rest of the threads */
- for (k = 1; k < num_threads; ++k) {
- status =
- pthread_create(&threads[k], NULL, read_write_thread,
- (void *)&rcoll);
- if (0 != status)
- err_exit(status, "pthread_create");
- if (rcoll.debug)
- fprintf(stderr, "Starting worker thread k=%d\n",
- k);
- }
-
- /* now wait for worker threads to finish */
- for (k = 0; k < num_threads; ++k) {
- status = pthread_join(threads[k], &vp);
- if (0 != status)
- err_exit(status, "pthread_join");
- if (rcoll.debug)
- fprintf(stderr,
- "Worker thread k=%d terminated\n", k);
- }
- }
-
- 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 * (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 (do_sync) {
- if (FT_SG == rcoll.out_type) {
- fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
- res = sync_cache(rcoll.outfd);
- if (2 == res) {
- fprintf(stderr,
- "Unit attention, media changed(in), continuing\n");
- res = sync_cache(rcoll.outfd);
- }
- if (0 != res)
- fprintf(stderr,
- "Unable to synchronize cache\n");
- }
- }
-
- status = pthread_cancel(sig_listen_thread_id);
- if (0 != status)
- err_exit(status, "pthread_cancel");
- if (STDIN_FILENO != rcoll.infd)
- close(rcoll.infd);
- if ((STDOUT_FILENO != rcoll.outfd) && (FT_DEV_NULL != rcoll.out_type))
- close(rcoll.outfd);
- res = 0;
- if (0 != rcoll.out_count) {
- fprintf(stderr,
- ">>>> Some error occurred, remaining blocks=%d\n",
- rcoll.out_count);
- res = 2;
- }
- infull = count - rcoll.in_done_count - rcoll.in_partial;
- fprintf(stderr, "%d+%d records in\n", infull, rcoll.in_partial);
- outfull = count - rcoll.out_done_count - rcoll.out_partial;
- fprintf(stderr, "%d+%d records out\n", outfull, rcoll.out_partial);
- 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/testcases/kernel/fs/scsi/ltpscsi/sg_err.c b/testcases/kernel/fs/scsi/ltpscsi/sg_err.c
deleted file mode 100644
index 08eba2cf3..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_err.c
+++ /dev/null
@@ -1,1379 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sg_include.h"
-#include "sg_err.h"
-
-/* This file is a huge cut, paste and hack from linux/drivers/scsi/constant.c
-* which I guess was written by:
-* Copyright (C) 1993, 1994, 1995 Eric Youngdale
-
-* The rest of this is:
-* Copyright (C) 1999 - 2003 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.
-*
-* ASCII values for a number of symbolic constants, printing functions, etc.
-*
-* Some of the tables have been updated for SCSI 2.
-* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
-*
-* Version 0.89 (20030313)
-* sense key specific field (bytes 15-17) decoding [Trent Piepho]
-*/
-
-#define OUTP stderr
-
-static const unsigned char scsi_command_size[8] = { 6, 10, 10, 12,
- 16, 12, 10, 10
-};
-
-#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
-
-static const char unknown[] = "UNKNOWN";
-
-static const char *group_0_commands[] = {
-/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
-/* 04-07 */ "Format Unit", "Read Block Limits", unknown,
- "Reasssign Blocks",
-/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown,
- unknown,
-/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space",
- "Inquiry",
-/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
-/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
-/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
-/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
-};
-
-static const char *group_1_commands[] = {
-/* 20-23 */ unknown, unknown, unknown, "Read Format capacities",
-/* 24-28 */ "Set window", "Read Capacity",
- unknown, unknown, "Read (10)",
-/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase",
- "Read updated block",
-/* 2e-31 */ "Write Verify", "Verify", "Search High", "Search Equal",
-/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
-/* 35-37 */ "Synchronize Cache", "Lock/Unlock Cache",
- "Read Defect Data",
-/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
- "Read Buffer",
-/* 3d-3f */ "Update Block", "Read Long", "Write Long",
-};
-
-static const char *group_2_commands[] = {
-/* 40-41 */ "Change Definition", "Write Same",
-/* 42-48 */ "Read sub-channel", "Read TOC", "Read header",
- "Play audio (10)", "Get configuration", "Play audio msf",
- "Play audio track/index",
-/* 49-4f */ "Play track relative (10)", "Get event status notification",
- "Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
- unknown,
-/* 50-55 */ "Xdwrite", "Xpwrite, Read disk info",
- "Xdread, Read track info",
- "Reserve track", "Send OPC onfo", "Mode Select (10)",
-/* 56-5b */ "Reserve (10)", "Release (10)", "Repair track",
- "Read master cue",
- "Mode Sense (10)", "Close track/session",
-/* 5c-5f */ "Read buffer capacity", "Send cue sheet",
- "Persistent reserve in",
- "Persistent reserve out",
-};
-
-/* The following are 16 byte commands in group 4 */
-static const char *group_4_commands[] = {
-/* 80-84 */ "Xdwrite (16)", "Rebuild (16)", "Regenerate (16)",
- "Extended copy",
- "Receive copy results",
-/* 85-89 */ "Memory Export In (16)", "Access control in",
- "Access control out",
- "Read (16)", "Memory Export Out (16)",
-/* 8a-8f */ "Write (16)", unknown, "Read attributes",
- "Write attributes",
- "Write and verify (16)", "Verify (16)",
-/* 90-94 */ "Pre-fetch (16)", "Synchronize cache (16)",
- "Lock/unlock cache (16)", "Write same (16)", unknown,
-/* 95-99 */ unknown, unknown, unknown, unknown, unknown,
-/* 9a-9f */ unknown, unknown, unknown, unknown, "Service action in",
- "Service action out",
-};
-
-/* The following are 12 byte commands in group 5 */
-static const char *group_5_commands[] = {
-/* a0-a5 */ "Report luns", "Blank", "Send event", "Maintenance (in)",
- "Maintenance (out)", "Move medium/play audio(12)",
-/* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
- "Play track relative(12)",
-/* aa-ae */ "Write(12)", unknown, "Erase(12), Get Performance",
- "Read DVD structure", "Write and verify(12)",
-/* af-b1 */ "Verify(12)", "Search data high(12)",
- "Search data equal(12)",
-/* b2-b4 */ "Search data low(12)", "Set limits(12)",
- "Read element status attached",
-/* b5-b6 */ "Request volume element address",
- "Send volume tag, set streaming",
-/* b7-b9 */ "Read defect data(12)", "Read element status",
- "Read CD msf",
-/* ba-bc */ "Redundancy group (in), Scan",
- "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
-/* bd-bf */ "Spare (out), Mechanism status", "Volume set (in), Read cd",
- "Volume set (out), Send DVD structure",
-};
-
-#define group(opcode) (((opcode) >> 5) & 7)
-
-#define RESERVED_GROUP 0
-#define VENDOR_GROUP 1
-
-static const char **commands[] = {
- group_0_commands, group_1_commands, group_2_commands,
- (const char **)RESERVED_GROUP, group_4_commands,
- group_5_commands, (const char **)VENDOR_GROUP,
- (const char **)VENDOR_GROUP
-};
-
-static const char reserved[] = "RESERVED";
-static const char vendor[] = "VENDOR SPECIFIC";
-
-static void print_opcode(int opcode)
-{
- const char **table = commands[group(opcode)];
-
- switch ((unsigned long)table) {
- case RESERVED_GROUP:
- fprintf(OUTP, "%s(0x%02x)", reserved, opcode);
- break;
- case VENDOR_GROUP:
- fprintf(OUTP, "%s(0x%02x)", vendor, opcode);
- break;
- default:
- fprintf(OUTP, "%s", table[opcode & 0x1f]);
- break;
- }
-}
-
-void sg_print_command(const unsigned char *command)
-{
- int k, s;
- print_opcode(command[0]);
- fprintf(OUTP, " [");
- for (k = 0, s = COMMAND_SIZE(command[0]); k < s; ++k)
- fprintf(OUTP, "%02x ", command[k]);
- fprintf(OUTP, "]\n");
-}
-
-void sg_print_status(int masked_status)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- sg_print_scsi_status(scsi_status);
-}
-
-void sg_print_scsi_status(int scsi_status)
-{
- const char *ccp;
-
- scsi_status &= 0x7e; /* sanitize as much as possible */
- switch (scsi_status) {
- case 0:
- ccp = "Good";
- break;
- case 0x2:
- ccp = "Check Condition";
- break;
- case 0x4:
- ccp = "Condition Met";
- break;
- case 0x8:
- ccp = "Busy";
- break;
- case 0x10:
- ccp = "Intermediate";
- break;
- case 0x14:
- ccp = "Intermediate-Condition Met";
- break;
- case 0x18:
- ccp = "Reservation Conflict";
- break;
- case 0x22:
- ccp = "Command Terminated (obsolete)";
- break;
- case 0x28:
- ccp = "Task set Full";
- break;
- case 0x30:
- ccp = "ACA Active";
- break;
- case 0x40:
- ccp = "Task Aborted";
- break;
- default:
- ccp = "Unknown status";
- break;
- }
- fprintf(OUTP, "%s ", ccp);
-}
-
-/* In brackets is the related SCSI document (see www.t10.org) with the */
-/* peripheral device type after the colon */
-/* No programmatic use is made of these flags currently */
-#define D 0x0001 /* DIRECT ACCESS DEVICE (disk) [SBC-2: 0] */
-#define T 0x0002 /* SEQUENTIAL ACCESS DEVICE (tape) [SSC: 1] */
-#define L 0x0004 /* PRINTER DEVICE [SSC: 2] */
-#define P 0x0008 /* PROCESSOR DEVICE [SPC-2: 3] */
-#define W 0x0010 /* WRITE ONCE READ MULTIPLE DEVICE [SBC-2: 4] */
-#define R 0x0020 /* CD/DVD DEVICE [MMC-2: 5] */
-#define S 0x0040 /* SCANNER DEVICE [SCSI-2 (obsolete): 6] */
-#define O 0x0080 /* OPTICAL MEMORY DEVICE [SBC-2: 7] */
-#define M 0x0100 /* MEDIA CHANGER DEVICE [SMC-2: 8] */
-#define C 0x0200 /* COMMUNICATION DEVICE [SCSI-2 (obsolete): 9] */
-#define A 0x0400 /* ARRAY STORAGE [SCC-2: 12] */
-#define E 0x0800 /* ENCLOSURE SERVICES DEVICE [SES: 13] */
-#define B 0x1000 /* SIMPLIFIED DIRECT ACCESS DEVICE [RBC: 14] */
-#define K 0x2000 /* OPTICAL CARD READER/WRITER DEVICE [OCRW: 15] */
-
-#define SC_ALL_DEVS ( D|T|L|P|W|R|S|O|M|C|A|E|B|K )
-
-/* oft used strings are encoded using ASCII codes 0x1 to 0x1f . */
-/* This is to save space. This encoding should be UTF-8 and */
-/* UTF-16 friendly. */
-#define SC_AUDIO_PLAY_OPERATION "\x1"
-#define SC_LOGICAL_UNIT "\x2"
-#define SC_NOT_READY "\x3"
-#define SC_OPERATION "\x4"
-#define SC_IN_PROGRESS "\x5"
-#define SC_HARDWARE_IF "\x6"
-#define SC_CONTROLLER_IF "\x7"
-#define SC_DATA_CHANNEL_IF "\x8"
-#define SC_SERVO_IF "\x9"
-#define SC_SPINDLE_IF "\xa"
-#define SC_FIRMWARE_IF "\xb"
-#define SC_RECOVERED_DATA "\xc"
-#define SC_ERROR_RATE_TOO_HIGH "\xd"
-#define SC_TIMES_TOO_HIGH "\xe"
-
-struct error_info {
- unsigned char code1, code2;
- unsigned short int devices;
- const char *text;
-};
-
-struct error_info2 {
- unsigned char code1, code2_min, code2_max;
- unsigned short int devices;
- const char *text;
-};
-
-static struct error_info2 additional2[] = {
- {0x40, 0x00, 0x7f, D, "Ram failure (%x)"},
- {0x40, 0x80, 0xff, D | T | L | P | W | R | S | O | M | C,
- "Diagnostic failure on component (%x)"},
- {0x41, 0x00, 0xff, D, "Data path failure (%x)"},
- {0x42, 0x00, 0xff, D, "Power-on or self-test failure (%x)"},
- {0, 0, 0, 0, NULL}
-};
-
-static struct error_info additional[] = {
- {0x00, 0x00, SC_ALL_DEVS, "No additional sense information"},
- {0x00, 0x01, T, "Filemark detected"},
- {0x00, 0x02, T | S, "End-of-partition/medium detected"},
- {0x00, 0x03, T, "Setmark detected"},
- {0x00, 0x04, T | S, "Beginning-of-partition/medium detected"},
- {0x00, 0x05, T | L | S, "End-of-data detected"},
- {0x00, 0x06, SC_ALL_DEVS, "I/O process terminated"},
- {0x00, 0x11, R, SC_AUDIO_PLAY_OPERATION SC_IN_PROGRESS},
- {0x00, 0x12, R, SC_AUDIO_PLAY_OPERATION "paused"},
- {0x00, 0x13, R, SC_AUDIO_PLAY_OPERATION "successfully completed"},
- {0x00, 0x14, R, SC_AUDIO_PLAY_OPERATION "stopped due to error"},
- {0x00, 0x15, R, "No current audio status to return"},
- {0x00, 0x16, SC_ALL_DEVS, SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x17, D | T | L | W | R | S | O | M | A | E | B | K,
- "Cleaning requested"},
- {0x00, 0x18, T, "Erase" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x19, T, "Locate" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1a, T, "Rewind" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1b, T, "Set capacity" SC_OPERATION SC_IN_PROGRESS},
- {0x00, 0x1c, T, "Verify" SC_OPERATION SC_IN_PROGRESS},
- {0x01, 0x00, D | W | O | B | K, "No index/sector signal"},
- {0x02, 0x00, D | W | R | O | M | B | K, "No seek complete"},
- {0x03, 0x00, D | T | L | W | S | O | B | K,
- "Peripheral device write fault"},
- {0x03, 0x01, T, "No write current"},
- {0x03, 0x02, T, "Excessive write errors"},
- {0x04, 0x00, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "cause not reportable"},
- {0x04, 0x01, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "is" SC_IN_PROGRESS "of becoming ready"},
- {0x04, 0x02, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "initializing cmd. required"},
- {0x04, 0x03, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "manual intervention required"},
- {0x04, 0x04, D | T | L | R | O | B,
- SC_LOGICAL_UNIT SC_NOT_READY "format" SC_IN_PROGRESS},
- {0x04, 0x05, D | T | W | O | M | C | A | B | K,
- SC_LOGICAL_UNIT SC_NOT_READY "rebuild" SC_IN_PROGRESS},
- {0x04, 0x06, D | T | W | O | M | C | A | B | K,
- SC_LOGICAL_UNIT SC_NOT_READY "recalculation" SC_IN_PROGRESS},
- {0x04, 0x07, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY SC_OPERATION SC_IN_PROGRESS},
- {0x04, 0x08, R,
- SC_LOGICAL_UNIT SC_NOT_READY "long write" SC_IN_PROGRESS},
- {0x04, 0x09, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "self-test" SC_IN_PROGRESS},
- {0x04, 0x0a, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, asymmetric access state transition"},
- {0x04, 0x0b, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, target port in standby state"},
- {0x04, 0x0c, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "not accessible, target port in unavailable state"},
- {0x04, 0x10, SC_ALL_DEVS,
- SC_LOGICAL_UNIT SC_NOT_READY "auxiliary memory not accessible"},
- {0x05, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "does not respond to selection"},
- {0x06, 0x00, D | W | R | O | M | B | K, "No reference position found"},
- {0x07, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Multiple peripheral devices selected"},
- {0x08, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication failure"},
- {0x08, 0x01, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication time-out"},
- {0x08, 0x02, D | T | L | W | R | S | O | M | C | A | E | B | K,
- SC_LOGICAL_UNIT "communication parity error"},
- {0x08, 0x03, D | T | R | O | M | B | K,
- SC_LOGICAL_UNIT "communication CRC error (Ultra-DMA/32)"},
- {0x08, 0x04, D | T | L | P | W | R | S | O | C | K,
- "Unreachable copy target"},
- {0x09, 0x00, D | T | W | R | O | B, "Track following error"},
- {0x09, 0x01, W | R | O | K, "Tracking servo failure"},
- {0x09, 0x02, W | R | O | K, "Focus servo failure"},
- {0x09, 0x03, W | R | O, "Spindle servo failure"},
- {0x09, 0x04, D | T | W | R | O | B, "Head select fault"},
- {0x0A, 0x00, SC_ALL_DEVS, "Error log overflow"},
- {0x0B, 0x00, SC_ALL_DEVS, "Warning"},
- {0x0B, 0x01, SC_ALL_DEVS, "Warning - specified temperature exceeded"},
- {0x0B, 0x02, SC_ALL_DEVS, "Warning - enclosure degraded"},
- {0x0C, 0x00, T | R | S, "Write error"},
- {0x0C, 0x01, K, "Write error - recovered with auto reallocation"},
- {0x0C, 0x02, D | W | O | B | K,
- "Write error - auto reallocation failed"},
- {0x0C, 0x03, D | W | O | B | K, "Write error - recommend reassignment"},
- {0x0C, 0x04, D | T | W | O | B, "Compression check miscompare error"},
- {0x0C, 0x05, D | T | W | O | B,
- "Data expansion occurred during compression"},
- {0x0C, 0x06, D | T | W | O | B, "Block not compressible"},
- {0x0C, 0x07, R, "Write error - recovery needed"},
- {0x0C, 0x08, R, "Write error - recovery failed"},
- {0x0C, 0x09, R, "Write error - loss of streaming"},
- {0x0C, 0x0A, R, "Write error - padding blocks added"},
- {0x0C, 0x0B, D | T | W | R | O | M | B, "Auxiliary memory write error"},
- {0x0C, 0x0C, SC_ALL_DEVS, "Write error - unexpected unsolicited data"},
- {0x0C, 0x0D, SC_ALL_DEVS, "Write error - not enough unsolicited data"},
- {0x0D, 0x00, D | T | L | P | W | R | S | O | C | A | K,
- "Error detected by third party temporary initiator"},
- {0x0D, 0x01, D | T | L | P | W | R | S | O | C | A | K,
- "Third party device failure"},
- {0x0D, 0x02, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device not reachable"},
- {0x0D, 0x03, D | T | L | P | W | R | S | O | C | A | K,
- "Incorrect copy target device"},
- {0x0D, 0x04, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device underrun"},
- {0x0D, 0x05, D | T | L | P | W | R | S | O | C | A | K,
- "Copy target device overrun"},
- {0x10, 0x00, D | W | O | B | K, "Id CRC or ECC error"},
- {0x11, 0x00, D | T | W | R | S | O | B | K, "Unrecovered read error"},
- {0x11, 0x01, D | T | W | R | S | O | B | K, "Read retries exhausted"},
- {0x11, 0x02, D | T | W | R | S | O | B | K,
- "Error too long to correct"},
- {0x11, 0x03, D | T | W | S | O | B | K, "Multiple read errors"},
- {0x11, 0x04, D | W | O | B | K,
- "Unrecovered read error - auto reallocate failed"},
- {0x11, 0x05, W | R | O | B, "L-EC uncorrectable error"},
- {0x11, 0x06, W | R | O | B, "CIRC unrecovered error"},
- {0x11, 0x07, W | O | B, "Data re-synchronization error"},
- {0x11, 0x08, T, "Incomplete block read"},
- {0x11, 0x09, T, "No gap found"},
- {0x11, 0x0A, D | T | O | B | K, "Miscorrected error"},
- {0x11, 0x0B, D | W | O | B | K,
- "Unrecovered read error - recommend reassignment"},
- {0x11, 0x0C, D | W | O | B | K,
- "Unrecovered read error - recommend rewrite the data"},
- {0x11, 0x0D, D | T | W | R | O | B, "De-compression CRC error"},
- {0x11, 0x0E, D | T | W | R | O | B,
- "Cannot decompress using declared algorithm"},
- {0x11, 0x0F, R, "Error reading UPC/EAN number"},
- {0x11, 0x10, R, "Error reading ISRC number"},
- {0x11, 0x11, R, "Read error - loss of streaming"},
- {0x11, 0x12, D | T | W | R | O | M | B, "Auxiliary memory read error"},
- {0x11, 0x13, SC_ALL_DEVS, "Read error - failed retransmission request"},
- {0x12, 0x00, D | W | O | B | K, "Address mark not found for id field"},
- {0x13, 0x00, D | W | O | B | K,
- "Address mark not found for data field"},
- {0x14, 0x00, D | T | L | W | R | S | O | B | K,
- "Recorded entity not found"},
- {0x14, 0x01, D | T | W | R | O | B | K, "Record not found"},
- {0x14, 0x02, T, "Filemark or setmark not found"},
- {0x14, 0x03, T, "End-of-data not found"},
- {0x14, 0x04, T, "Block sequence error"},
- {0x14, 0x05, D | T | W | O | B | K,
- "Record not found - recommend reassignment"},
- {0x14, 0x06, D | T | W | O | B | K,
- "Record not found - data auto-reallocated"},
- {0x14, 0x07, T, "Locate" SC_OPERATION " failure"},
- {0x15, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Random positioning error"},
- {0x15, 0x01, D | T | L | W | R | S | O | M | B | K,
- "Mechanical positioning error"},
- {0x15, 0x02, D | T | W | R | O | B | K,
- "Positioning error detected by read of medium"},
- {0x16, 0x00, D | W | O | B | K, "Data synchronization mark error"},
- {0x16, 0x01, D | W | O | B | K, "Data sync error - data rewritten"},
- {0x16, 0x02, D | W | O | B | K, "Data sync error - recommend rewrite"},
- {0x16, 0x03, D | W | O | B | K,
- "Data sync error - data auto-reallocated"},
- {0x16, 0x04, D | W | O | B | K,
- "Data sync error - recommend reassignment"},
- {0x17, 0x00, D | T | W | R | S | O | B | K,
- SC_RECOVERED_DATA "with no error correction applied"},
- {0x17, 0x01, D | T | W | R | S | O | B | K,
- SC_RECOVERED_DATA "with retries"},
- {0x17, 0x02, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with positive head offset"},
- {0x17, 0x03, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with negative head offset"},
- {0x17, 0x04, W | R | O | B,
- SC_RECOVERED_DATA "with retries and/or circ applied"},
- {0x17, 0x05, D | W | R | O | B | K,
- SC_RECOVERED_DATA "using previous sector id"},
- {0x17, 0x06, D | W | O | B | K,
- SC_RECOVERED_DATA "without ecc - data auto-reallocated"},
- {0x17, 0x07, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - recommend reassignment"},
- {0x17, 0x08, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - recommend rewrite"},
- {0x17, 0x09, D | W | R | O | B | K,
- SC_RECOVERED_DATA "without ecc - data rewritten"},
- {0x18, 0x00, D | T | W | R | O | B | K,
- SC_RECOVERED_DATA "with error correction applied"},
- {0x18, 0x01, D | W | R | O | B | K,
- SC_RECOVERED_DATA "with error corr. & retries applied"},
- {0x18, 0x02, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- data auto-reallocated"},
- {0x18, 0x03, R, SC_RECOVERED_DATA "with CIRC"},
- {0x18, 0x04, R, SC_RECOVERED_DATA "with L-EC"},
- {0x18, 0x05, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- recommend reassignment"},
- {0x18, 0x06, D | W | R | O | B | K,
- SC_RECOVERED_DATA "- recommend rewrite"},
- {0x18, 0x07, D | W | O | B | K,
- SC_RECOVERED_DATA "with ecc - data rewritten"},
- {0x18, 0x08, R, SC_RECOVERED_DATA "with linking"},
- {0x19, 0x00, D | O | K, "Defect list error"},
- {0x19, 0x01, D | O | K, "Defect list not available"},
- {0x19, 0x02, D | O | K, "Defect list error in primary list"},
- {0x19, 0x03, D | O | K, "Defect list error in grown list"},
- {0x1A, 0x00, SC_ALL_DEVS, "Parameter list length error"},
- {0x1B, 0x00, SC_ALL_DEVS, "Synchronous data transfer error"},
- {0x1C, 0x00, D | O | B | K, "Defect list not found"},
- {0x1C, 0x01, D | O | B | K, "Primary defect list not found"},
- {0x1C, 0x02, D | O | B | K, "Grown defect list not found"},
- {0x1D, 0x00, D | T | W | R | O | B | K,
- "Miscompare during verify" SC_OPERATION},
- {0x1E, 0x00, D | W | O | B | K, "Recovered id with ecc correction"},
- {0x1F, 0x00, D | O | K, "Partial defect list transfer"},
- {0x20, 0x00, SC_ALL_DEVS, "Invalid command" SC_OPERATION " code"},
- {0x20, 0x01, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - initiator pending-enrolled"},
- {0x20, 0x02, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - no access rights"},
- {0x20, 0x03, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - no mgmt id key"},
- {0x20, 0x04, T, "Illegal command while in write capable state"},
- {0x20, 0x05, T, "Obsolete"},
- {0x20, 0x06, T, "Illegal command while in explicit address mode"},
- {0x20, 0x07, T, "Illegal command while in implicit address mode"},
- {0x20, 0x08, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - enrollment conflict"},
- {0x20, 0x09, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - invalid LU identifier"},
- {0x20, 0x0A, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - invalid proxy token"},
- {0x20, 0x0B, D | T | P | W | R | O | M | A | E | B | K,
- "Access denied - ACL LUN conflict"},
- {0x21, 0x00, D | T | W | R | O | M | B | K,
- "Logical block address out of range"},
- {0x21, 0x01, D | T | W | R | O | M | B | K, "Invalid element address"},
- {0x21, 0x02, R, "Invalid address for write"},
- {0x22, 0x00, D, "Illegal function (use 20 00,24 00,or 26 00)"},
- {0x24, 0x00, SC_ALL_DEVS, "Invalid field in cdb"},
- {0x24, 0x01, SC_ALL_DEVS, "CDB decryption error"},
- {0x25, 0x00, SC_ALL_DEVS, SC_LOGICAL_UNIT "not supported"},
- {0x26, 0x00, SC_ALL_DEVS, "Invalid field in parameter list"},
- {0x26, 0x01, SC_ALL_DEVS, "Parameter not supported"},
- {0x26, 0x02, SC_ALL_DEVS, "Parameter value invalid"},
- {0x26, 0x03, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Threshold parameters not supported"},
- {0x26, 0x04, SC_ALL_DEVS, "Invalid release of persistent reservation"},
- {0x26, 0x05, D | T | L | P | W | R | S | O | M | C | A | B | K,
- "Data decryption error"},
- {0x26, 0x06, D | T | L | P | W | R | S | O | C | K,
- "Too many target descriptors"},
- {0x26, 0x07, D | T | L | P | W | R | S | O | C | K,
- "Unsupported target descriptor type code"},
- {0x26, 0x08, D | T | L | P | W | R | S | O | C | K,
- "Too many segment descriptors"},
- {0x26, 0x09, D | T | L | P | W | R | S | O | C | K,
- "Unsupported segment descriptor type code"},
- {0x26, 0x0A, D | T | L | P | W | R | S | O | C | K,
- "Unexpected inexact segment"},
- {0x26, 0x0B, D | T | L | P | W | R | S | O | C | K,
- "Inline data length exceeded"},
- {0x26, 0x0C, D | T | L | P | W | R | S | O | C | K,
- "Invalid" SC_OPERATION " for copy source or destination"},
- {0x26, 0x0D, D | T | L | P | W | R | S | O | C | K,
- "Copy segment granularity violation"},
- {0x27, 0x00, D | T | W | R | O | B | K, "Write protected"},
- {0x27, 0x01, D | T | W | R | O | B | K, "Hardware write protected"},
- {0x27, 0x02, D | T | W | R | O | B | K,
- SC_LOGICAL_UNIT "software write protected"},
- {0x27, 0x03, T | R, "Associated write protect"},
- {0x27, 0x04, T | R, "Persistent write protect"},
- {0x27, 0x05, T | R, "Permanent write protect"},
- {0x27, 0x06, R, "Conditional write protect"},
- {0x28, 0x00, SC_ALL_DEVS,
- "Not ready to ready change, medium may have changed"},
- {0x28, 0x01, D | T | W | R | O | M | B,
- "Import or export element accessed"},
- {0x29, 0x00, SC_ALL_DEVS,
- "Power on,reset,or bus device reset occurred"},
- {0x29, 0x01, SC_ALL_DEVS, "Power on occurred"},
- {0x29, 0x02, SC_ALL_DEVS, "Scsi bus reset occurred"},
- {0x29, 0x03, SC_ALL_DEVS, "Bus device reset function occurred"},
- {0x29, 0x04, SC_ALL_DEVS, "Device internal reset"},
- {0x29, 0x05, SC_ALL_DEVS, "Transceiver mode changed to single-ended"},
- {0x29, 0x06, SC_ALL_DEVS, "Transceiver mode changed to lvd"},
- {0x29, 0x07, SC_ALL_DEVS, "I_T nexus loss occurred"},
- {0x2A, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Parameters changed"},
- {0x2A, 0x01, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Mode parameters changed"},
- {0x2A, 0x02, D | T | L | W | R | S | O | M | C | A | E | K,
- "Log parameters changed"},
- {0x2A, 0x03, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Reservations preempted"},
- {0x2A, 0x04, D | T | L | P | W | R | S | O | M | C | A | E,
- "Reservations released"},
- {0x2A, 0x05, D | T | L | P | W | R | S | O | M | C | A | E,
- "Registrations preempted"},
- {0x2A, 0x06, SC_ALL_DEVS, "Asymmetric access state changed"},
- {0x2A, 0x07, SC_ALL_DEVS,
- "Implicit asymmetric access state transition failed"},
- {0x2B, 0x00, D | T | L | P | W | R | S | O | C | K,
- "Copy cannot execute since host cannot disconnect"},
- {0x2C, 0x00, SC_ALL_DEVS, "Command sequence error"},
- {0x2C, 0x01, S, "Too many windows specified"},
- {0x2C, 0x02, S, "Invalid combination of windows specified"},
- {0x2C, 0x03, R, "Current program area is not empty"},
- {0x2C, 0x04, R, "Current program area is empty"},
- {0x2C, 0x05, B, "Illegal power condition request"},
- {0x2C, 0x06, R, "Persistent prevent conflict"},
- {0x2C, 0x07, SC_ALL_DEVS, "Previous busy status"},
- {0x2C, 0x08, SC_ALL_DEVS, "Previous task set full status"},
- {0x2C, 0x09, D | T | L | P | W | R | S | O | M | E | B | K,
- "Previous reservation conflict status"},
- {0x2D, 0x00, T, "Overwrite error on update in place"},
- {0x2F, 0x00, SC_ALL_DEVS, "Commands cleared by another initiator"},
- {0x30, 0x00, D | T | W | R | O | M | B | K,
- "Incompatible medium installed"},
- {0x30, 0x01, D | T | W | R | O | B | K,
- "Cannot read medium - unknown format"},
- {0x30, 0x02, D | T | W | R | O | B | K,
- "Cannot read medium - incompatible format"},
- {0x30, 0x03, D | T | R | K, "Cleaning cartridge installed"},
- {0x30, 0x04, D | T | W | R | O | B | K,
- "Cannot write medium - unknown format"},
- {0x30, 0x05, D | T | W | R | O | B | K,
- "Cannot write medium - incompatible format"},
- {0x30, 0x06, D | T | W | R | O | B,
- "Cannot format medium - incompatible medium"},
- {0x30, 0x07, D | T | L | W | R | S | O | M | A | E | B | K,
- "Cleaning failure"},
- {0x30, 0x08, R, "Cannot write - application code mismatch"},
- {0x30, 0x09, R, "Current session not fixated for append"},
- {0x30, 0x10, R, "Medium not formatted"}, /* should ascq be 0xa ?? */
- {0x31, 0x00, D | T | W | R | O | B | K, "Medium format corrupted"},
- {0x31, 0x01, D | L | R | O | B, "Format command failed"},
- {0x31, 0x02, R, "Zoned formatting failed due to spare linking"},
- {0x32, 0x00, D | W | O | B | K, "No defect spare location available"},
- {0x32, 0x01, D | W | O | B | K, "Defect list update failure"},
- {0x33, 0x00, T, "Tape length error"},
- {0x34, 0x00, SC_ALL_DEVS, "Enclosure failure"},
- {0x35, 0x00, SC_ALL_DEVS, "Enclosure services failure"},
- {0x35, 0x01, SC_ALL_DEVS, "Unsupported enclosure function"},
- {0x35, 0x02, SC_ALL_DEVS, "Enclosure services unavailable"},
- {0x35, 0x03, SC_ALL_DEVS, "Enclosure services transfer failure"},
- {0x35, 0x04, SC_ALL_DEVS, "Enclosure services transfer refused"},
- {0x36, 0x00, L, "Ribbon,ink,or toner failure"},
- {0x37, 0x00, D | T | L | W | R | S | O | M | C | A | E | B | K,
- "Rounded parameter"},
- {0x38, 0x00, B, "Event status notification"},
- {0x38, 0x02, B, "Esn - power management class event"},
- {0x38, 0x04, B, "Esn - media class event"},
- {0x38, 0x06, B, "Esn - device busy class event"},
- {0x39, 0x00, D | T | L | W | R | S | O | M | C | A | E | K,
- "Saving parameters not supported"},
- {0x3A, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Medium not present"},
- {0x3A, 0x01, D | T | W | R | O | M | B | K,
- "Medium not present - tray closed"},
- {0x3A, 0x02, D | T | W | R | O | M | B | K,
- "Medium not present - tray open"},
- {0x3A, 0x03, D | T | W | R | O | M | B,
- "Medium not present - loadable"},
- {0x3A, 0x04, D | T | W | R | O | M | B,
- "Medium not present - medium auxiliary memory accessible"},
- {0x3B, 0x00, T | L, "Sequential positioning error"},
- {0x3B, 0x01, T, "Tape position error at beginning-of-medium"},
- {0x3B, 0x02, T, "Tape position error at end-of-medium"},
- {0x3B, 0x03, L, "Tape or electronic vertical forms unit " SC_NOT_READY},
- {0x3B, 0x04, L, "Slew failure"},
- {0x3B, 0x05, L, "Paper jam"},
- {0x3B, 0x06, L, "Failed to sense top-of-form"},
- {0x3B, 0x07, L, "Failed to sense bottom-of-form"},
- {0x3B, 0x08, T, "Reposition error"},
- {0x3B, 0x09, S, "Read past end of medium"},
- {0x3B, 0x0A, S, "Read past beginning of medium"},
- {0x3B, 0x0B, S, "Position past end of medium"},
- {0x3B, 0x0C, T | S, "Position past beginning of medium"},
- {0x3B, 0x0D, D | T | W | R | O | M | B | K,
- "Medium destination element full"},
- {0x3B, 0x0E, D | T | W | R | O | M | B | K,
- "Medium source element empty"},
- {0x3B, 0x0F, R, "End of medium reached"},
- {0x3B, 0x11, D | T | W | R | O | M | B | K,
- "Medium magazine not accessible"},
- {0x3B, 0x12, D | T | W | R | O | M | B | K, "Medium magazine removed"},
- {0x3B, 0x13, D | T | W | R | O | M | B | K, "Medium magazine inserted"},
- {0x3B, 0x14, D | T | W | R | O | M | B | K, "Medium magazine locked"},
- {0x3B, 0x15, D | T | W | R | O | M | B | K, "Medium magazine unlocked"},
- {0x3B, 0x16, R, "Mechanical positioning or changer error"},
- {0x3D, 0x00, D | T | L | P | W | R | S | O | M | C | A | E | K,
- "Invalid bits in identify message"},
- {0x3E, 0x00, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "has not self-configured yet"},
- {0x3E, 0x01, SC_ALL_DEVS, SC_LOGICAL_UNIT "failure"},
- {0x3E, 0x02, SC_ALL_DEVS, "Timeout on logical unit"},
- {0x3E, 0x03, SC_ALL_DEVS, SC_LOGICAL_UNIT "failed self-test"},
- {0x3E, 0x04, SC_ALL_DEVS,
- SC_LOGICAL_UNIT "unable to update self-test log"},
- {0x3F, 0x00, SC_ALL_DEVS, "Target operating conditions have changed"},
- {0x3F, 0x01, SC_ALL_DEVS, "Microcode has been changed"},
- {0x3F, 0x02, D | T | L | P | W | R | S | O | M | C | B | K,
- "Changed operating definition"},
- {0x3F, 0x03, SC_ALL_DEVS, "Inquiry data has changed"},
- {0x3F, 0x04, D | T | W | R | O | M | C | A | E | B | K,
- "Component device attached"},
- {0x3F, 0x05, D | T | W | R | O | M | C | A | E | B | K,
- "Device identifier changed"},
- {0x3F, 0x06, D | T | W | R | O | M | C | A | E | B,
- "Redundancy group created or modified"},
- {0x3F, 0x07, D | T | W | R | O | M | C | A | E | B,
- "Redundancy group deleted"},
- {0x3F, 0x08, D | T | W | R | O | M | C | A | E | B,
- "Spare created or modified"},
- {0x3F, 0x09, D | T | W | R | O | M | C | A | E | B, "Spare deleted"},
- {0x3F, 0x0A, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set created or modified"},
- {0x3F, 0x0B, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set deleted"},
- {0x3F, 0x0C, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set deassigned"},
- {0x3F, 0x0D, D | T | W | R | O | M | C | A | E | B | K,
- "Volume set reassigned"},
- {0x3F, 0x0E, D | T | L | P | W | R | S | O | M | C | A | E,
- "Reported luns data has changed"},
- {0x3F, 0x10, D | T | W | R | O | M | B, "Medium loadable"},
- {0x3F, 0x11, D | T | W | R | O | M | B,
- "Medium auxiliary memory accessible"},
- {0x40, 0x00, D, "Ram failure (should use 40 nn)"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x40, 0x00, SC_ALL_DEVS,
- "Diagnostic failure on component nn (80h-ffh)"},
- {0x41, 0x00, D, "Data path failure (should use 40 nn)"},
- {0x42, 0x00, D, "Power-on or self-test failure (should use 40 nn)"},
- {0x43, 0x00, SC_ALL_DEVS, "Message error"},
- {0x44, 0x00, SC_ALL_DEVS, "Internal target failure"},
- {0x45, 0x00, SC_ALL_DEVS, "Select or reselect failure"},
- {0x46, 0x00, D | T | L | P | W | R | S | O | M | C | B | K,
- "Unsuccessful soft reset"},
- {0x47, 0x00, SC_ALL_DEVS, "Scsi parity error"},
- {0x47, 0x01, SC_ALL_DEVS, "Data phase CRC error detected"},
- {0x47, 0x02, SC_ALL_DEVS,
- "Scsi parity error detected during st data phase"},
- {0x47, 0x03, SC_ALL_DEVS, "Information unit CRC error detected"},
- {0x47, 0x04, SC_ALL_DEVS,
- "Asynchronous information protection error detected"},
- {0x47, 0x05, SC_ALL_DEVS, "Protocol service CRC error"},
- {0x48, 0x00, SC_ALL_DEVS, "Initiator detected error message received"},
- {0x49, 0x00, SC_ALL_DEVS, "Invalid message error"},
- {0x4A, 0x00, SC_ALL_DEVS, "Command phase error"},
- {0x4B, 0x00, SC_ALL_DEVS, "Data phase error"},
- {0x4C, 0x00, SC_ALL_DEVS, SC_LOGICAL_UNIT "failed self-configuration"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x4D, 0x00, SC_ALL_DEVS,
- "Tagged overlapped commands (nn = queue tag)"},
- {0x4E, 0x00, SC_ALL_DEVS, "Overlapped commands attempted"},
- {0x50, 0x00, T, "Write append error"},
- {0x50, 0x01, T, "Write append position error"},
- {0x50, 0x02, T, "Position error related to timing"},
- {0x51, 0x00, T | R | O, "Erase failure"},
- {0x52, 0x00, T, "Cartridge fault"},
- {0x53, 0x00, D | T | L | W | R | S | O | M | B | K,
- "Media load or eject failed"},
- {0x53, 0x01, T, "Unload tape failure"},
- {0x53, 0x02, D | T | W | R | O | M | B | K, "Medium removal prevented"},
- {0x54, 0x00, P, "Scsi to host system interface failure"},
- {0x55, 0x00, P, "System resource failure"},
- {0x55, 0x01, D | O | B | K, "System buffer full"},
- {0x55, 0x02, D | T | L | P | W | R | S | O | M | A | E | K,
- "Insufficient reservation resources"},
- {0x55, 0x03, D | T | L | P | W | R | S | O | M | C | A | E,
- "Insufficient resources"},
- {0x55, 0x04, D | T | L | P | W | R | S | O | M | A | E,
- "Insufficient registration resources"},
- {0x55, 0x05, D | T | P | W | R | O | M | A | E | B | K,
- "Insufficient access control resources"},
- {0x55, 0x06, D | T | W | R | O | M | B,
- "Auxiliary memory out of space"},
- {0x57, 0x00, R, "Unable to recover table-of-contents"},
- {0x58, 0x00, O, "Generation does not exist"},
- {0x59, 0x00, O, "Updated block read"},
- {0x5A, 0x00, D | T | L | P | W | R | S | O | M | B | K,
- "Operator request or state change input"},
- {0x5A, 0x01, D | T | W | R | O | M | B | K,
- "Operator medium removal request"},
- {0x5A, 0x02, D | T | W | R | O | A | B | K,
- "Operator selected write protect"},
- {0x5A, 0x03, D | T | W | R | O | A | B | K,
- "Operator selected write permit"},
- {0x5B, 0x00, D | T | L | P | W | R | S | O | M | K, "Log exception"},
- {0x5B, 0x01, D | T | L | P | W | R | S | O | M | K,
- "Threshold condition met"},
- {0x5B, 0x02, D | T | L | P | W | R | S | O | M | K,
- "Log counter at maximum"},
- {0x5B, 0x03, D | T | L | P | W | R | S | O | M | K,
- "Log list codes exhausted"},
- {0x5C, 0x00, D | O, "Rpl status change"},
- {0x5C, 0x01, D | O, "Spindles synchronized"},
- {0x5C, 0x02, D | O, "Spindles not synchronized"},
- {0x5D, 0x00, SC_ALL_DEVS, "Failure prediction threshold exceeded"},
- {0x5D, 0x01, R | B, "Media failure prediction threshold exceeded"},
- {0x5D, 0x02, R,
- SC_LOGICAL_UNIT "failure prediction threshold exceeded"},
- {0x5D, 0x03, R, "spare area exhaustion prediction threshold exceeded"},
- /* large series of "impending failure" messages */
- {0x5D, 0x10, D | B, SC_HARDWARE_IF "general hard drive failure"},
- {0x5D, 0x11, D | B, SC_HARDWARE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x12, D | B, SC_HARDWARE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x13, D | B, SC_HARDWARE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x14, D | B, SC_HARDWARE_IF "too many block reassigns"},
- {0x5D, 0x15, D | B, SC_HARDWARE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x16, D | B, SC_HARDWARE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x17, D | B, SC_HARDWARE_IF "channel parametrics"},
- {0x5D, 0x18, D | B, SC_HARDWARE_IF "controller detected"},
- {0x5D, 0x19, D | B, SC_HARDWARE_IF "throughput performance"},
- {0x5D, 0x1A, D | B, SC_HARDWARE_IF "seek time performance"},
- {0x5D, 0x1B, D | B, SC_HARDWARE_IF "spin-up retry count"},
- {0x5D, 0x1C, D | B, SC_HARDWARE_IF "drive calibration retry count"},
- {0x5D, 0x20, D | B, SC_CONTROLLER_IF "general hard drive failure"},
- {0x5D, 0x21, D | B, SC_CONTROLLER_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x22, D | B, SC_CONTROLLER_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x23, D | B, SC_CONTROLLER_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x24, D | B, SC_CONTROLLER_IF "too many block reassigns"},
- {0x5D, 0x25, D | B, SC_CONTROLLER_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x26, D | B, SC_CONTROLLER_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x27, D | B, SC_CONTROLLER_IF "channel parametrics"},
- {0x5D, 0x28, D | B, SC_CONTROLLER_IF "controller detected"},
- {0x5D, 0x29, D | B, SC_CONTROLLER_IF "throughput performance"},
- {0x5D, 0x2A, D | B, SC_CONTROLLER_IF "seek time performance"},
- {0x5D, 0x2B, D | B, SC_CONTROLLER_IF "spin-up retry count"},
- {0x5D, 0x2C, D | B, SC_CONTROLLER_IF "drive calibration retry count"},
- {0x5D, 0x30, D | B, SC_DATA_CHANNEL_IF "general hard drive failure"},
- {0x5D, 0x31, D | B, SC_DATA_CHANNEL_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x32, D | B, SC_DATA_CHANNEL_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x33, D | B, SC_DATA_CHANNEL_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x34, D | B, SC_DATA_CHANNEL_IF "too many block reassigns"},
- {0x5D, 0x35, D | B, SC_DATA_CHANNEL_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x36, D | B, SC_DATA_CHANNEL_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x37, D | B, SC_DATA_CHANNEL_IF "channel parametrics"},
- {0x5D, 0x38, D | B, SC_DATA_CHANNEL_IF "controller detected"},
- {0x5D, 0x39, D | B, SC_DATA_CHANNEL_IF "throughput performance"},
- {0x5D, 0x3A, D | B, SC_DATA_CHANNEL_IF "seek time performance"},
- {0x5D, 0x3B, D | B, SC_DATA_CHANNEL_IF "spin-up retry count"},
- {0x5D, 0x3C, D | B, SC_DATA_CHANNEL_IF "drive calibration retry count"},
- {0x5D, 0x40, D | B, SC_SERVO_IF "general hard drive failure"},
- {0x5D, 0x41, D | B, SC_SERVO_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x42, D | B, SC_SERVO_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x43, D | B, SC_SERVO_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x44, D | B, SC_SERVO_IF "too many block reassigns"},
- {0x5D, 0x45, D | B, SC_SERVO_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x46, D | B, SC_SERVO_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x47, D | B, SC_SERVO_IF "channel parametrics"},
- {0x5D, 0x48, D | B, SC_SERVO_IF "controller detected"},
- {0x5D, 0x49, D | B, SC_SERVO_IF "throughput performance"},
- {0x5D, 0x4A, D | B, SC_SERVO_IF "seek time performance"},
- {0x5D, 0x4B, D | B, SC_SERVO_IF "spin-up retry count"},
- {0x5D, 0x4C, D | B, SC_SERVO_IF "drive calibration retry count"},
- {0x5D, 0x50, D | B, SC_SPINDLE_IF "general hard drive failure"},
- {0x5D, 0x51, D | B, SC_SPINDLE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x52, D | B, SC_SPINDLE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x53, D | B, SC_SPINDLE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x54, D | B, SC_SPINDLE_IF "too many block reassigns"},
- {0x5D, 0x55, D | B, SC_SPINDLE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x56, D | B, SC_SPINDLE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x57, D | B, SC_SPINDLE_IF "channel parametrics"},
- {0x5D, 0x58, D | B, SC_SPINDLE_IF "controller detected"},
- {0x5D, 0x59, D | B, SC_SPINDLE_IF "throughput performance"},
- {0x5D, 0x5A, D | B, SC_SPINDLE_IF "seek time performance"},
- {0x5D, 0x5B, D | B, SC_SPINDLE_IF "spin-up retry count"},
- {0x5D, 0x5C, D | B, SC_SPINDLE_IF "drive calibration retry count"},
- {0x5D, 0x60, D | B, SC_FIRMWARE_IF "general hard drive failure"},
- {0x5D, 0x61, D | B, SC_FIRMWARE_IF "drive" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x62, D | B, SC_FIRMWARE_IF "data" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x63, D | B, SC_FIRMWARE_IF "seek" SC_ERROR_RATE_TOO_HIGH},
- {0x5D, 0x64, D | B, SC_FIRMWARE_IF "too many block reassigns"},
- {0x5D, 0x65, D | B, SC_FIRMWARE_IF "access" SC_TIMES_TOO_HIGH},
- {0x5D, 0x66, D | B, SC_FIRMWARE_IF "start unit" SC_TIMES_TOO_HIGH},
- {0x5D, 0x67, D | B, SC_FIRMWARE_IF "channel parametrics"},
- {0x5D, 0x68, D | B, SC_FIRMWARE_IF "controller detected"},
- {0x5D, 0x69, D | B, SC_FIRMWARE_IF "throughput performance"},
- {0x5D, 0x6A, D | B, SC_FIRMWARE_IF "seek time performance"},
- {0x5D, 0x6B, D | B, SC_FIRMWARE_IF "spin-up retry count"},
- {0x5D, 0x6C, D | B, SC_FIRMWARE_IF "drive calibration retry count"},
- {0x5D, 0xFF, SC_ALL_DEVS,
- "Failure prediction threshold exceeded (false)"},
- {0x5E, 0x00, D | T | L | P | W | R | S | O | C | A | K,
- "Low power condition on"},
- {0x5E, 0x01, D | T | L | P | W | R | S | O | C | A | K,
- "Idle condition activated by timer"},
- {0x5E, 0x02, D | T | L | P | W | R | S | O | C | A | K,
- "Standby condition activated by timer"},
- {0x5E, 0x03, D | T | L | P | W | R | S | O | C | A | K,
- "Idle condition activated by command"},
- {0x5E, 0x04, D | T | L | P | W | R | S | O | C | A | K,
- "Standby condition activated by command"},
- {0x5E, 0x41, B, "Power state change to active"},
- {0x5E, 0x42, B, "Power state change to idle"},
- {0x5E, 0x43, B, "Power state change to standby"},
- {0x5E, 0x45, B, "Power state change to sleep"},
- {0x5E, 0x47, B | K, "Power state change to device control"},
- {0x60, 0x00, S, "Lamp failure"},
- {0x61, 0x00, S, "Video acquisition error"},
- {0x61, 0x01, S, "Unable to acquire video"},
- {0x61, 0x02, S, "Out of focus"},
- {0x62, 0x00, S, "Scan head positioning error"},
- {0x63, 0x00, R, "End of user area encountered on this track"},
- {0x63, 0x01, R, "Packet does not fit in available space"},
- {0x64, 0x00, R, "Illegal mode for this track"},
- {0x64, 0x01, R, "Invalid packet size"},
- {0x65, 0x00, SC_ALL_DEVS, "Voltage fault"},
- {0x66, 0x00, S, "Automatic document feeder cover up"},
- {0x66, 0x01, S, "Automatic document feeder lift up"},
- {0x66, 0x02, S, "Document jam in automatic document feeder"},
- {0x66, 0x03, S, "Document miss feed automatic in document feeder"},
- {0x67, 0x00, A, "Configuration failure"},
- {0x67, 0x01, A, "Configuration of incapable logical units failed"},
- {0x67, 0x02, A, "Add logical unit failed"},
- {0x67, 0x03, A, "Modification of logical unit failed"},
- {0x67, 0x04, A, "Exchange of logical unit failed"},
- {0x67, 0x05, A, "Remove of logical unit failed"},
- {0x67, 0x06, A, "Attachment of logical unit failed"},
- {0x67, 0x07, A, "Creation of logical unit failed"},
- {0x67, 0x08, A, "Assign failure occurred"},
- {0x67, 0x09, A, "Multiply assigned logical unit"},
- {0x67, 0x0A, SC_ALL_DEVS, "Set target port groups command failed"},
- {0x68, 0x00, A, SC_LOGICAL_UNIT "not configured"},
- {0x69, 0x00, A, "Data loss on logical unit"},
- {0x69, 0x01, A, "Multiple logical unit failures"},
- {0x69, 0x02, A, "Parity/data mismatch"},
- {0x6A, 0x00, A, "Informational,refer to log"},
- {0x6B, 0x00, A, "State change has occurred"},
- {0x6B, 0x01, A, "Redundancy level got better"},
- {0x6B, 0x02, A, "Redundancy level got worse"},
- {0x6C, 0x00, A, "Rebuild failure occurred"},
- {0x6D, 0x00, A, "Recalculate failure occurred"},
- {0x6E, 0x00, A, "Command to logical unit failed"},
- {0x6F, 0x00, R,
- "Copy protection key exchange failure - authentication failure"},
- {0x6F, 0x01, R,
- "Copy protection key exchange failure - key not present"},
- {0x6F, 0x02, R,
- "Copy protection key exchange failure - key not established"},
- {0x6F, 0x03, R, "Read of scrambled sector without authentication"},
- {0x6F, 0x04, R,
- "Media region code is mismatched to logical unit region"},
- {0x6F, 0x05, R,
- "Drive region must be permanent/region reset count error"},
- /*
- * FIXME(eric) - need a way to represent wildcards here.
- */
- {0x70, 0x00, T, "Decompression exception short algorithm id of nn"},
- {0x71, 0x00, T, "Decompression exception long algorithm id"},
- {0x72, 0x00, R, "Session fixation error"},
- {0x72, 0x01, R, "Session fixation error writing lead-in"},
- {0x72, 0x02, R, "Session fixation error writing lead-out"},
- {0x72, 0x03, R, "Session fixation error - incomplete track in session"},
- {0x72, 0x04, R, "Empty or partially written reserved track"},
- {0x72, 0x05, R, "No more track reservations allowed"},
- {0x73, 0x00, R, "Cd control error"},
- {0x73, 0x01, R, "Power calibration area almost full"},
- {0x73, 0x02, R, "Power calibration area is full"},
- {0x73, 0x03, R, "Power calibration area error"},
- {0x73, 0x04, R, "Program memory area update failure"},
- {0x73, 0x05, R, "Program memory area is full"},
- {0x73, 0x06, R, "RMA/PMA is full"},
- {0, 0, 0, NULL}
-};
-
-static const char *sc_oft_used[0x1f] = {
- "umulig", /* index 0x0 should be impossible */
- "Audio play operation ",
- "Logical unit ",
- "not ready, ",
- " operation",
- " in progress ",
- "Hardware impending failure ",
- "Controller impending failure ",
- "Data channel impending failure ", /* index 0x8 */
- "Servo impending failure ",
- "Spindle impending failure ",
- "Firmware impending failure ",
- "Recovered data ",
- " error rate too high",
- " times too high",
-};
-
-static const char *snstext[] = {
- "No Sense", /* There is no sense information */
- "Recovered Error", /* The last command completed successfully
- but used error correction */
- "Not Ready", /* The addressed target is not ready */
- "Medium Error", /* Data error detected on the medium */
- "Hardware Error", /* Controller or device failure */
- "Illegal Request",
- "Unit Attention", /* Removable medium was changed, or
- the target has been reset */
- "Data Protect", /* Access to the data is blocked */
- "Blank Check", /* Reached unexpected written or unwritten
- region of the medium */
- "Key=9", /* Vendor specific */
- "Copy Aborted", /* COPY or COMPARE was aborted */
- "Aborted Command", /* The target aborted the command */
- "Equal", /* SEARCH DATA found data equal (obsolete) */
- "Volume Overflow", /* Medium full with still data to be written */
- "Miscompare", /* Source data and data on the medium
- do not agree */
- "Key=15" /* Reserved */
-};
-
-static
-void sg_print_asc_ascq(unsigned char asc, unsigned char ascq)
-{
- int k, j;
- char obuff[256];
- const char *ccp;
- const char *oup;
- char c;
- int found = 0;
-
- for (k = 0; additional[k].text; k++) {
- if (additional[k].code1 == asc && additional[k].code2 == ascq) {
- found = 1;
- ccp = additional[k].text;
- for (j = 0; *ccp && (j < sizeof(obuff)); ++ccp) {
- c = *ccp;
- if ((c < 0x20) && (c > 0)) {
- oup = sc_oft_used[(int)c];
- if (oup) {
- strcpy(obuff + j, oup);
- j += strlen(oup);
- } else {
- strcpy(obuff + j, "???");
- j += 3;
- }
- } else
- obuff[j++] = c;
- }
- if (j < sizeof(obuff))
- obuff[j] = '\0';
- else
- obuff[sizeof(obuff) - 1] = '\0';
- fprintf(OUTP, "Additional sense: %s\n", obuff);
- }
- }
- if (found)
- return;
-
- for (k = 0; additional2[k].text; k++) {
- if ((additional2[k].code1 == asc) &&
- (ascq >= additional2[k].code2_min) &&
- (ascq <= additional2[k].code2_max)) {
- found = 1;
- fprintf(OUTP, "Additional sense: ");
- fprintf(OUTP, additional2[k].text, ascq);
- fprintf(OUTP, "\n");
- }
- }
- if (!found)
- fprintf(OUTP, "ASC=%2x ASCQ=%2x\n", asc, ascq);
-}
-
-/* Print sense information */
-void sg_print_sense(const char *leadin, const unsigned char *sense_buffer,
- int sb_len)
-{
- int k, s;
- int sense_key, sense_class, valid, code;
- int descriptor_format = 0;
- const char *error = NULL;
-
- if (sb_len < 1) {
- fprintf(OUTP, "sense buffer empty\n");
- return;
- }
- sense_class = (sense_buffer[0] >> 4) & 0x07;
- code = sense_buffer[0] & 0xf;
- valid = sense_buffer[0] & 0x80;
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
-
- if (sense_class == 7) { /* extended sense data */
- s = sense_buffer[7] + 8;
- if (s > sb_len) {
- fprintf(OUTP,
- "Sense buffer too small (at %d bytes), %d bytes "
- "truncated\n", sb_len, s - sb_len);
- s = sb_len;
- }
-
- switch (code) {
- case 0x0:
- error = "Current"; /* error concerns current command */
- break;
- case 0x1:
- error = "Deferred"; /* error concerns some earlier command */
- /* e.g., an earlier write to disk cache succeeded, but
- now the disk discovers that it cannot write the data */
- break;
- case 0x2:
- descriptor_format = 1;
- error = "Descriptor current";
- /* new descriptor sense format */
- break;
- case 0x3:
- descriptor_format = 1;
- error = "Descriptor deferred";
- /* new descriptor sense format (deferred report) */
- break;
- default:
- error = "Invalid";
- }
- sense_key = sense_buffer[descriptor_format ? 1 : 2] & 0xf;
- fprintf(OUTP, "%s, Sense key: %s\n", error, snstext[sense_key]);
-
- if (descriptor_format)
- sg_print_asc_ascq(sense_buffer[2], sense_buffer[3]);
- else {
- if (!valid)
- fprintf(OUTP, "[valid=0] ");
- fprintf(OUTP, "Info fld=0x%x, ",
- (int)((sense_buffer[3] << 24) |
- (sense_buffer[4] << 16) | (sense_buffer[5]
- << 8) |
- sense_buffer[6]));
-
- if (sense_buffer[2] & 0x80)
- fprintf(OUTP, "FMK "); /* current command has read a filemark */
- if (sense_buffer[2] & 0x40)
- fprintf(OUTP, "EOM "); /* end-of-medium condition exists */
- if (sense_buffer[2] & 0x20)
- fprintf(OUTP, "ILI "); /* incorrect block length requested */
-
- if (s > 13) {
- if (sense_buffer[12] || sense_buffer[13])
- sg_print_asc_ascq(sense_buffer[12],
- sense_buffer[13]);
- }
- if (sense_key == 5 && s >= 18
- && (sense_buffer[15] & 0x80)) {
- fprintf(OUTP,
- "Sense Key Specific: Error in %s byte %d",
- (sense_buffer[15] & 0x40) ? "Command" :
- "Data",
- (sense_buffer[16] << 8) |
- sense_buffer[17]);
- if (sense_buffer[15] & 0x08) {
- fprintf(OUTP, " bit %d\n",
- sense_buffer[15] & 0x07);
- } else {
- fprintf(OUTP, "\n");
- }
- }
- }
-
- } else { /* non-extended sense data */
-
- /*
- * Standard says:
- * sense_buffer[0] & 0200 : address valid
- * sense_buffer[0] & 0177 : vendor-specific error code
- * sense_buffer[1] & 0340 : vendor-specific
- * sense_buffer[1..3] : 21-bit logical block address
- */
-
- if (sb_len < 4) {
- fprintf(OUTP,
- "sense buffer too short (4 byte minimum)\n");
- return;
- }
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
- if (sense_buffer[0] < 15)
- fprintf(OUTP,
- "old sense: key %s\n",
- snstext[sense_buffer[0] & 0x0f]);
- else
- fprintf(OUTP, "sns = %2x %2x\n", sense_buffer[0],
- sense_buffer[2]);
-
- fprintf(OUTP, "Non-extended sense class %d code 0x%0x ",
- sense_class, code);
- s = 4;
- }
-
- fprintf(OUTP, "Raw sense data (in hex):\n ");
- for (k = 0; k < s; ++k) {
- if ((k > 0) && (0 == (k % 24)))
- fprintf(OUTP, "\n ");
- fprintf(OUTP, "%02x ", sense_buffer[k]);
- }
- fprintf(OUTP, "\n");
-}
-
-static const char *hostbyte_table[] = {
- "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT",
- "DID_BAD_TARGET",
- "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
- "DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL
-};
-
-void sg_print_host_status(int host_status)
-{
- static int maxcode = 0;
- int i;
-
- if (!maxcode) {
- for (i = 0; hostbyte_table[i]; i++) ;
- maxcode = i - 1;
- }
- fprintf(OUTP, "Host_status=0x%02x", host_status);
- if (host_status > maxcode) {
- fprintf(OUTP, "is invalid ");
- return;
- }
- fprintf(OUTP, "(%s) ", hostbyte_table[host_status]);
-}
-
-static const char *driverbyte_table[] = {
- "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA",
- "DRIVER_ERROR",
- "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE", NULL
-};
-
-static const char *driversuggest_table[] = { "SUGGEST_OK",
- "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
- unknown, unknown, unknown, "SUGGEST_SENSE", NULL
-};
-
-void sg_print_driver_status(int driver_status)
-{
- static int driver_max = 0, suggest_max = 0;
- int i;
- int dr = driver_status & SG_ERR_DRIVER_MASK;
- int su = (driver_status & SG_ERR_SUGGEST_MASK) >> 4;
-
- if (!driver_max) {
- for (i = 0; driverbyte_table[i]; i++) ;
- driver_max = i;
- for (i = 0; driversuggest_table[i]; i++) ;
- suggest_max = i;
- }
- fprintf(OUTP, "Driver_status=0x%02x", driver_status);
- fprintf(OUTP, " (%s,%s) ",
- dr < driver_max ? driverbyte_table[dr] : "invalid",
- su < suggest_max ? driversuggest_table[su] : "invalid");
-}
-
-static int sg_sense_print(const char *leadin, int scsi_status,
- int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- int done_leadin = 0;
- int done_sense = 0;
-
- scsi_status &= 0x7e; /*sanity */
- if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
- return 1; /* No problems */
- if (0 != scsi_status) {
- if (leadin)
- fprintf(OUTP, "%s: ", leadin);
- done_leadin = 1;
- fprintf(OUTP, "scsi status: ");
- sg_print_scsi_status(scsi_status);
- fprintf(OUTP, "\n");
- if (sense_buffer && ((scsi_status == SCSI_CHECK_CONDITION) ||
- (scsi_status ==
- SCSI_COMMAND_TERMINATED))) {
- sg_print_sense(0, sense_buffer, sb_len);
- done_sense = 1;
- }
- }
- if (0 != host_status) {
- if (leadin && (!done_leadin))
- fprintf(OUTP, "%s: ", leadin);
- if (done_leadin)
- fprintf(OUTP, "plus...: ");
- else
- done_leadin = 1;
- sg_print_host_status(host_status);
- fprintf(OUTP, "\n");
- }
- if (0 != driver_status) {
- if (leadin && (!done_leadin))
- fprintf(OUTP, "%s: ", leadin);
- if (done_leadin)
- fprintf(OUTP, "plus...: ");
- else
- done_leadin = 1;
- sg_print_driver_status(driver_status);
- fprintf(OUTP, "\n");
- if (sense_buffer && (!done_sense) &&
- (SG_ERR_DRIVER_SENSE == (0xf & driver_status)))
- sg_print_sense(0, sense_buffer, sb_len);
- }
- return 0;
-}
-
-#ifdef SG_IO
-int sg_chk_n_print3(const char *leadin, struct sg_io_hdr *hp)
-{
- return sg_sense_print(leadin, hp->status, hp->host_status,
- hp->driver_status, hp->sbp, hp->sb_len_wr);
-}
-#endif
-
-int sg_chk_n_print(const char *leadin, int masked_status,
- int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- return sg_sense_print(leadin, scsi_status, host_status, driver_status,
- sense_buffer, sb_len);
-}
-
-#ifdef SG_IO
-int sg_err_category3(struct sg_io_hdr *hp)
-{
- return sg_err_category_new(hp->status, hp->host_status,
- hp->driver_status, hp->sbp, hp->sb_len_wr);
-}
-#endif
-
-int sg_err_category(int masked_status, int host_status,
- int driver_status, const unsigned char *sense_buffer,
- int sb_len)
-{
- int scsi_status = (masked_status << 1) & 0x7e;
-
- return sg_err_category_new(scsi_status, host_status, driver_status,
- sense_buffer, sb_len);
-}
-
-int sg_err_category_new(int scsi_status, int host_status, int driver_status,
- const unsigned char *sense_buffer, int sb_len)
-{
- scsi_status &= 0x7e;
- if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
- return SG_ERR_CAT_CLEAN;
- if ((SCSI_CHECK_CONDITION == scsi_status) ||
- (SCSI_COMMAND_TERMINATED == scsi_status) ||
- (SG_ERR_DRIVER_SENSE == (0xf & driver_status))) {
- if (sense_buffer && (sb_len > 2)) {
- int sense_key;
- unsigned char asc;
-
- if (sense_buffer[0] & 0x2) {
- sense_key = sense_buffer[1] & 0xf;
- asc = sense_buffer[2];
- } else {
- sense_key = sense_buffer[2] & 0xf;
- asc = (sb_len > 12) ? sense_buffer[12] : 0;
- }
-
- if (RECOVERED_ERROR == sense_key)
- return SG_ERR_CAT_RECOVERED;
- else if (UNIT_ATTENTION == sense_key) {
- if (0x28 == asc)
- return SG_ERR_CAT_MEDIA_CHANGED;
- if (0x29 == asc)
- return SG_ERR_CAT_RESET;
- }
- }
- return SG_ERR_CAT_SENSE;
- }
- if (0 != host_status) {
- if ((SG_ERR_DID_NO_CONNECT == host_status) ||
- (SG_ERR_DID_BUS_BUSY == host_status) ||
- (SG_ERR_DID_TIME_OUT == host_status))
- return SG_ERR_CAT_TIMEOUT;
- }
- if (0 != driver_status) {
- if (SG_ERR_DRIVER_TIMEOUT == driver_status)
- return SG_ERR_CAT_TIMEOUT;
- }
- return SG_ERR_CAT_OTHER;
-}
-
-int sg_get_command_size(unsigned char opcode)
-{
- return COMMAND_SIZE(opcode);
-}
-
-void sg_get_command_name(unsigned char opcode, int buff_len, char *buff)
-{
- const char **table = commands[group(opcode)];
-
- if ((NULL == buff) || (buff_len < 1))
- return;
-
- switch ((unsigned long)table) {
- case RESERVED_GROUP:
- strncpy(buff, reserved, buff_len);
- break;
- case VENDOR_GROUP:
- strncpy(buff, vendor, buff_len);
- break;
- default:
- strncpy(buff, table[opcode & 0x1f], buff_len);
- break;
- }
-}
diff --git a/testcases/kernel/fs/scsi/ltpscsi/sg_err.h b/testcases/kernel/fs/scsi/ltpscsi/sg_err.h
deleted file mode 100644
index 735f8a940..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_err.h
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef SG_ERR_H
-#define SG_ERR_H
-
-/* Feel free to copy and modify this GPL-ed code into your applications. */
-
-/* Version 0.89 (20030313)
-*/
-
-
-/* Some of the following error/status codes are exchanged between the
- various layers of the SCSI sub-system in Linux and should never
- reach the user. They are placed here for completeness. What appears
- here is copied from drivers/scsi/scsi.h which is not visible in
- the user space. */
-
-#ifndef SCSI_CHECK_CONDITION
-/* Following are the "true" SCSI status codes. Linux has traditionally
- used a 1 bit right and masked version of these. So now CHECK_CONDITION
- and friends (in <scsi/scsi.h>) are deprecated. */
-#define SCSI_CHECK_CONDITION 0x2
-#define SCSI_CONDITION_MET 0x4
-#define SCSI_BUSY 0x8
-#define SCSI_IMMEDIATE 0x10
-#define SCSI_IMMEDIATE_CONDITION_MET 0x14
-#define SCSI_RESERVATION_CONFLICT 0x18
-#define SCSI_COMMAND_TERMINATED 0x22
-#define SCSI_TASK_SET_FULL 0x28
-#define SCSI_ACA_ACTIVE 0x30
-#define SCSI_TASK_ABORTED 0x40
-#endif
-
-/* The following are 'host_status' codes */
-#ifndef DID_OK
-#define DID_OK 0x00
-#endif
-#ifndef DID_NO_CONNECT
-#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */
-#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */
-#define DID_TIME_OUT 0x03 /* Timed out for some other reason */
-#define DID_BAD_TARGET 0x04 /* Bad target (id?) */
-#define DID_ABORT 0x05 /* Told to abort for some other reason */
-#define DID_PARITY 0x06 /* Parity error (on SCSI bus) */
-#define DID_ERROR 0x07 /* Internal error */
-#define DID_RESET 0x08 /* Reset by somebody */
-#define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */
-#define DID_PASSTHROUGH 0x0a /* Force command past mid-level */
-#define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */
-#endif
-
-/* These defines are to isolate applictaions from kernel define changes */
-#define SG_ERR_DID_OK DID_OK
-#define SG_ERR_DID_NO_CONNECT DID_NO_CONNECT
-#define SG_ERR_DID_BUS_BUSY DID_BUS_BUSY
-#define SG_ERR_DID_TIME_OUT DID_TIME_OUT
-#define SG_ERR_DID_BAD_TARGET DID_BAD_TARGET
-#define SG_ERR_DID_ABORT DID_ABORT
-#define SG_ERR_DID_PARITY DID_PARITY
-#define SG_ERR_DID_ERROR DID_ERROR
-#define SG_ERR_DID_RESET DID_RESET
-#define SG_ERR_DID_BAD_INTR DID_BAD_INTR
-#define SG_ERR_DID_PASSTHROUGH DID_PASSTHROUGH
-#define SG_ERR_DID_SOFT_ERROR DID_SOFT_ERROR
-
-/* The following are 'driver_status' codes */
-#ifndef DRIVER_OK
-#define DRIVER_OK 0x00
-#endif
-#ifndef DRIVER_BUSY
-#define DRIVER_BUSY 0x01
-#define DRIVER_SOFT 0x02
-#define DRIVER_MEDIA 0x03
-#define DRIVER_ERROR 0x04
-#define DRIVER_INVALID 0x05
-#define DRIVER_TIMEOUT 0x06
-#define DRIVER_HARD 0x07
-#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */
-
-/* Following "suggests" are "or-ed" with one of previous 8 entries */
-#define SUGGEST_RETRY 0x10
-#define SUGGEST_ABORT 0x20
-#define SUGGEST_REMAP 0x30
-#define SUGGEST_DIE 0x40
-#define SUGGEST_SENSE 0x80
-#define SUGGEST_IS_OK 0xff
-#endif
-#ifndef DRIVER_MASK
-#define DRIVER_MASK 0x0f
-#endif
-#ifndef SUGGEST_MASK
-#define SUGGEST_MASK 0xf0
-#endif
-
-/* These defines are to isolate applictaions from kernel define changes */
-#define SG_ERR_DRIVER_OK DRIVER_OK
-#define SG_ERR_DRIVER_BUSY DRIVER_BUSY
-#define SG_ERR_DRIVER_SOFT DRIVER_SOFT
-#define SG_ERR_DRIVER_MEDIA DRIVER_MEDIA
-#define SG_ERR_DRIVER_ERROR DRIVER_ERROR
-#define SG_ERR_DRIVER_INVALID DRIVER_INVALID
-#define SG_ERR_DRIVER_TIMEOUT DRIVER_TIMEOUT
-#define SG_ERR_DRIVER_HARD DRIVER_HARD
-#define SG_ERR_DRIVER_SENSE DRIVER_SENSE
-#define SG_ERR_SUGGEST_RETRY SUGGEST_RETRY
-#define SG_ERR_SUGGEST_ABORT SUGGEST_ABORT
-#define SG_ERR_SUGGEST_REMAP SUGGEST_REMAP
-#define SG_ERR_SUGGEST_DIE SUGGEST_DIE
-#define SG_ERR_SUGGEST_SENSE SUGGEST_SENSE
-#define SG_ERR_SUGGEST_IS_OK SUGGEST_IS_OK
-#define SG_ERR_DRIVER_MASK DRIVER_MASK
-#define SG_ERR_SUGGEST_MASK SUGGEST_MASK
-
-
-
-/* The following "print" functions send ACSII to stdout */
-extern void sg_print_command(const unsigned char * command);
-extern void sg_print_sense(const char * leadin,
- const unsigned char * sense_buffer, int sb_len);
-extern void sg_print_status(int masked_status);
-extern void sg_print_scsi_status(int scsi_status);
-extern void sg_print_host_status(int host_status);
-extern void sg_print_driver_status(int driver_status);
-
-/* sg_chk_n_print() returns 1 quietly if there are no errors/warnings
- else it prints to standard output and returns 0. */
-extern int sg_chk_n_print(const char * leadin, int masked_status,
- int host_status, int driver_status,
- const unsigned char * sense_buffer, int sb_len);
-
-/* The following function declaration is for the sg version 3 driver.
- Only version 3 sg_err.c defines it. */
-struct sg_io_hdr;
-extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp);
-
-
-/* The following "category" function returns one of the following */
-#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */
-#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
-#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */
-#define SG_ERR_CAT_TIMEOUT 3
-#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */
-#define SG_ERR_CAT_SENSE 98 /* Something else is in the sense buffer */
-#define SG_ERR_CAT_OTHER 99 /* Some other error/warning has occurred */
-
-extern int sg_err_category(int masked_status, int host_status,
- int driver_status, const unsigned char * sense_buffer,
- int sb_len);
-
-extern int sg_err_category_new(int scsi_status, int host_status,
- int driver_status, const unsigned char * sense_buffer,
- int sb_len);
-
-/* The following function declaration is for the sg version 3 driver.
- Only version 3 sg_err.c defines it. */
-extern int sg_err_category3(struct sg_io_hdr * hp);
-
-/* Returns length of SCSI command given the opcode (first byte) */
-extern int sg_get_command_size(unsigned char opcode);
-
-extern void sg_get_command_name(unsigned char opcode, int buff_len,
- char * buff);
-
-#endif
diff --git a/testcases/kernel/fs/scsi/ltpscsi/sg_include.h b/testcases/kernel/fs/scsi/ltpscsi/sg_include.h
deleted file mode 100644
index 5baca3cc8..000000000
--- a/testcases/kernel/fs/scsi/ltpscsi/sg_include.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifdef SG_KERNEL_INCLUDES
- #include "/usr/src/linux/include/scsi/sg.h"
- #include "/usr/src/linux/include/scsi/scsi.h"
-#else
- #ifdef SG_TRICK_GNU_INCLUDES
- #include <linux/../scsi/sg.h>
- #include <linux/../scsi/scsi.h>
- #else
- #include <scsi/sg.h>
- #include <scsi/scsi.h>
- #endif
-#endif
-
-/*
- Getting the correct include files for the sg interface can be an ordeal.
- In a perfect world, one would just write:
- #include <scsi/sg.h>
- #include <scsi/scsi.h>
- This would include the files found in the /usr/include/scsi directory.
- Those files are maintained with the GNU library which may or may not
- agree with the kernel and version of sg driver that is running. Any
- many cases this will not matter. However in some it might, for example
- glibc 2.1's include files match the sg driver found in the lk 2.2
- series. Hence if glibc 2.1 is used with lk 2.4 then the additional
- sg v3 interface will not be visible.
- If this is a problem then defining SG_KERNEL_INCLUDES will access the
- kernel supplied header files (assuming they are in the normal place).
- The GNU library maintainers and various kernel people don't like
- this approach (but it does work).
- The technique selected by defining SG_TRICK_GNU_INCLUDES worked (and
- was used) prior to glibc 2.2 . Prior to that version /usr/include/linux
- was a symbolic link to /usr/src/linux/include/linux .
-
- There are other approaches if this include "mixup" causes pain. These
- would involve include files being copied or symbolic links being
- introduced.
-
- Sorry about the inconvenience. Typically neither SG_KERNEL_INCLUDES
- nor SG_TRICK_GNU_INCLUDES is defined.
-
- dpg 20010415
-*/
--
2.42.0
More information about the ltp
mailing list