diff options
Diffstat (limited to 'testcases/kernel/fs/scsi')
20 files changed, 0 insertions, 10764 deletions
diff --git a/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h b/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h deleted file mode 100644 index 24a85c95c..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/Ltpfs.h +++ /dev/null @@ -1,71 +0,0 @@ - -#define FS_LTP_TEST_COMPONENT 0x00020999 -#define FS_LTP_TEST_CLASS "ltp_test" -#define FS_LTP_TEST_HID "FS0999" -#define FS_LTP_TEST_DRIVER_NAME "FS LTP Test Driver" -#define FS_LTP_TEST_DEVICE_NAME "LTP Test" -#define FS_LTP_TEST_FILE_STATE "state" -#define FS_LTP_TEST_NOTIFY_STATUS 0x80 -#define FS_LTP_TEST_STATUS_OFFLINE 0x00 -#define FS_LTP_TEST_STATUS_ONLINE 0x01 -#define FS_LTP_TEST_STATUS_UNKNOWN 0xFF -#define _COMPONENT FS_LTP_TEST_COMPONENT -#define FS_TLP_TEST_MODULE_NAME ("fs_ltp_test") -#define FS_NS_SYSTEM_BUS "_SB_" -#define FS_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" -#define FS_BATTERY_FORMAT_BST "NNNN" - - -#define FS_TYPE_ANY 0x00 -#define FS_TYPE_INTEGER 0x01 /* Byte/Word/Dword/Zero/One/Ones */ -#define FS_TYPE_STRING 0x02 -#define FS_TYPE_BUFFER 0x03 -#define FS_TYPE_PACKAGE 0x04 /* byte_const, multiple data_term/Constant/super_name */ -#define FS_TYPE_FIELD_UNIT 0x05 -#define FS_TYPE_DEVICE 0x06 /* Name, multiple Node */ -#define FS_TYPE_EVENT 0x07 -#define FS_TYPE_METHOD 0x08 /* Name, byte_const, multiple Code */ -#define FS_TYPE_MUTEX 0x09 -#define FS_TYPE_REGION 0x0A -#define FS_TYPE_POWER 0x0B /* Name,byte_const,word_const,multi Node */ -#define FS_TYPE_PROCESSOR 0x0C /* Name,byte_const,Dword_const,byte_const,multi nm_o */ -#define FS_TYPE_THERMAL 0x0D /* Name, multiple Node */ -#define FS_TYPE_BUFFER_FIELD 0x0E -#define FS_TYPE_DDB_HANDLE 0x0F -#define FS_TYPE_DEBUG_OBJECT 0x10 - -#define FS_TYPE_EXTERNAL_MAX 0x10 -#define LTPMAJOR 256 - -/* Use 'k' as magic number */ -#define LTPFS_IOC_MAGIC 'k' -#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) - - -#define DEV_PATH "/dev" -#define LTP_FS_DIR_NAME "" -#define LTP_FS_DEV_NAME "LTPFS" -#define LTP_FS_DEV_NODE_PATH DEV_PATH "/" -#define LTP_FS_DEVICE_NAME DEV_PATH "/" LTP_FS_DEV_NAME -#define MINOR_SHIFT_BITS 3 -#define MAX_PARTITIONS 8 /* partition 0 + 7 more possible due to 3 bit partition number field */ -#define MAX_NUM_DISKS 3 /* number of real devices */ - -#define MPDEV_FLAG_CLEAR 0 -#define MPDEV_FLAG_SET 1 - -typedef struct _ltpdev_cmd { - u_int32_t cmd; // input - 0==recover, 1==fail - u_int32_t status; // ouput - 0==success -} ltpdev_cmd_t; - -typedef enum ltpdev_ioctl_cmds_s { - /* version commands */ - LTP_AIO_IOCTL_NUMBER = 0x5500, - LTP_BIO_IOCTL_NUMBER = 0x5501 -} ltpdev_ioctl_cmds_t; - -// define the ioctl cmds -#define LTPAIODEV_CMD _IOR( LTPMAJOR, LTP_AIO_IOCTL_NUMBER, ltpdev_cmd_t **) -#define LTPBIODEV_CMD _IOR( LTPMAJOR, LTP_BIO_IOCTL_NUMBER, ltpdev_cmd_t **) - diff --git a/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c b/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c deleted file mode 100644 index 0b561702e..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/LtpfsCmds.c +++ /dev/null @@ -1,315 +0,0 @@ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/ioctl.h> -#include <linux/pm.h> -#include <linux/genhd.h> -#include <linux/bio.h> -#include <linux/mm.h> -#include <linux/swap.h> -#include <linux/bio.h> -#include <linux/blk.h> -#include <linux/slab.h> -#include <linux/mempool.h> -#include <linux/workqueue.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/quotaops.h> -#include <linux/pagemap.h> -#include <linux/dnotify.h> -#include <linux/smp_lock.h> -#include <linux/personality.h> -#include <linux/security.h> -#include <linux/buffer_head.h> -#include <asm/namei.h> -#include <asm/uaccess.h> - -#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) -#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) -#define TEST_MEM_SIZE 4096 -#define FALSE 0 -#include "Ltpfs.h" - -static int ltpdev_open(struct inode *inode, struct file *pfile); -static int ltpdev_release(struct inode *inode, struct file *pfile); -static int ltpdev_ioctl(struct inode *pinode, struct file *pfile, - unsigned int cmd, unsigned long arg); -static int do_buffer_c_tests(void); - -static struct block_device_operations blkops = { -open: ltpdev_open, -release:ltpdev_release, -ioctl: ltpdev_ioctl, -}; - -int ltp_fs_major = LTPMAJOR; -int test_iteration = 0; - -static char genhd_flags = 0; -static struct gendisk *gd_ptr; -static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; - -MODULE_AUTHOR("Martin Ridgeway <mridge@us.ibm.com>"); -MODULE_DESCRIPTION(FS_LTP_TEST_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -/* - * Device operations for the virtual FS devices - */ - -static struct pm_dev *ltp_pm_dev = NULL; -struct block_device *ltplookup_bdev(const char *path); -int path_lookup(const char *name, unsigned int flags, struct nameidata *nd); -//static int __emul_lookup_dentry(const char *name, struct nameidata *nd); -void path_release(struct nameidata *nd); - -static int ltpdev_open(struct inode *pinode, struct file *pfile) -{ - printk(KERN_ALERT "ltpdev_open \n"); - return 0; -} - -static int ltpdev_release(struct inode *pinode, struct file *pfile) -{ - - printk(KERN_ALERT "ltpdev_release \n"); - return 0; -} - -static int ltpdev_ioctl(struct inode *pinode, struct file *pfile, - unsigned int cmd, unsigned long arg) -{ - - struct bio *my_bio = NULL; - struct bio *my_bio_copy = NULL; - request_queue_t *q = NULL; - struct block_device *bdev = NULL; - unsigned long uaddr; - - unsigned int bytes_done = 100; - - int error = 0; - int rc = 0; - - /*****************************************************************************/ - - printk(KERN_ALERT "ltpdev_ioctl fs tests\n"); - - switch (cmd) { - - case LTPAIODEV_CMD: - printk(KERN_ALERT "Running AIO FS tests \n"); - printk(KERN_ALERT "AIO FS tests complete\n"); - break; - - case LTPBIODEV_CMD: - - printk(KERN_ALERT "Running BIO FS tests \n"); - - my_bio = bio_alloc(GFP_KERNEL, 0); - if (!my_bio) { - printk(KERN_ALERT - "Error getting kernel slab memory !!\n"); - } else { - printk(KERN_ALERT "kernel slab memory alloc OK\n"); - } - - bio_endio(my_bio, bytes_done, error); - - printk(KERN_ALERT "Return from bio_endio = %d \n", error); - - my_bio_copy = bio_clone(my_bio, GFP_ATOMIC); - - if (!my_bio_copy) { - printk(KERN_ALERT - "Error getting kernel bio clone !!\n"); - } else { - printk(KERN_ALERT "kernel bio clone OK\n"); - } - - my_bio_copy = bio_clone(my_bio, GFP_NOIO); - - if (!my_bio_copy) { - printk(KERN_ALERT - "Error getting kernel bio clone !!\n"); - } else { - printk(KERN_ALERT "kernel bio clone OK\n"); - } - -// q = bdev_get_queue(my_bio->bi_bdev); - -// rc = bio_phys_segments(q, my_bio); - -// rc = bio_hw_segments(q, my_bio); - - bdev = lookup_bdev(LTP_FS_DEVICE_NAME); - - printk(KERN_ALERT "return from bdev size %d\n", - bdev->bd_block_size); - - printk(KERN_ALERT "Return from phys_segments = %d \n", rc); - -// Don't use this API, causes system to hang and corrupts FS -// bio_put(my_bio); - - (char *)uaddr = kmalloc(TEST_MEM_SIZE, GFP_KERNEL); - - my_bio_copy = bio_map_user(bdev, uaddr, TEST_MEM_SIZE, FALSE); - - printk(KERN_ALERT "Return from bio_map_user %p\n", my_bio_copy); - - do_buffer_c_tests(); - - printk(KERN_ALERT "BIO FS tests complete\n"); - - break; - } - - return 0; -} - -static int ltp_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - return 0; -} - -int init_module(void) -{ - int result; - - printk(KERN_ALERT "ltpdev_init_module \n"); - - ltp_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, ltp_pm_callback); - - result = register_blkdev(ltp_fs_major, LTP_FS_DEV_NAME); - - printk(KERN_ALERT "LTP FS: register_blkdev result=%d major %d\n", - result, ltp_fs_major); - - if (result < 0) { - printk(KERN_ALERT "LTP FS: can't get major %d\n", ltp_fs_major); - return result; - } - - gd_ptr = kmalloc(sizeof(struct gendisk *), GFP_KERNEL); - - if (!gd_ptr) { - printk(KERN_ALERT "ERROR getting memory !!!\n"); - return 0; - } - - gd_ptr = alloc_disk(1); - - printk(KERN_ALERT "gd_ptr after alloc = %p \n", gd_ptr); - - gd_ptr->major = ltp_fs_major; - gd_ptr->first_minor = 0; - gd_ptr->fops = &blkops; - gd_ptr->driverfs_dev = NULL; - gd_ptr->capacity = MAX_NUM_DISKS; - gd_ptr->flags = genhd_flags; - - sprintf(gd_ptr->disk_name, LTP_FS_DEV_NAME); - - add_disk(gd_ptr); - - return 0; -} - -void cleanup_module(void) -{ - - printk(KERN_ALERT "Exiting module and cleaning up \n"); - - pm_unregister(ltp_pm_dev); - - put_disk(gd_ptr); - - del_gendisk(gd_ptr); - - unregister_blkdev(ltp_fs_major, LTP_FS_DEV_NAME); - -} - -static int do_buffer_c_tests() -{ - int line_no = 0; - - printk(KERN_ALERT "Starting buffer.c coverage tests... \n"); - - __buffer_error("Test file", line_no); - - printk(KERN_ALERT "buffer.c coverage tests complete...\n"); - - return 0; -} - -/** - * lookup_bdev - lookup a struct block_device by name - * - * @path: special file representing the block device - * - * Get a reference to the blockdevice at @path in the current - * namespace if possible and return it. Return ERR_PTR(error) - * otherwise. - */ -struct block_device *lookup_bdev(const char *path) -{ - struct block_device *bdev; - struct inode *inode; - struct nameidata nd; - int error; - - if (!path || !*path) - return ERR_PTR(-EINVAL); - - error = path_lookup(path, LOOKUP_FOLLOW, &nd); - if (error) - return ERR_PTR(error); - - inode = nd.dentry->d_inode; - error = -ENOTBLK; - if (!S_ISBLK(inode->i_mode)) - goto fail; - error = -EACCES; - if (nd.mnt->mnt_flags & MNT_NODEV) - goto fail; - error = bd_acquire(inode); - if (error) - goto fail; - bdev = inode->i_bdev; - -out: - path_release(&nd); - return bdev; -fail: - bdev = ERR_PTR(error); - goto out; -} - -int bd_acquire(struct inode *inode) -{ - struct block_device *bdev; - spin_lock(&bdev_lock); - if (inode->i_bdev) { - atomic_inc(&inode->i_bdev->bd_count); - spin_unlock(&bdev_lock); - return 0; - } - spin_unlock(&bdev_lock); - bdev = bdget(kdev_t_to_nr(inode->i_rdev)); - if (!bdev) - return -ENOMEM; - spin_lock(&bdev_lock); - if (!inode->i_bdev) { - inode->i_bdev = bdev; - inode->i_mapping = bdev->bd_inode->i_mapping; - list_add(&inode->i_devices, &bdev->bd_inodes); - } else if (inode->i_bdev != bdev) - BUG(); - spin_unlock(&bdev_lock); - return 0; -} diff --git a/testcases/kernel/fs/scsi/ltpfs/Makefile b/testcases/kernel/fs/scsi/ltpfs/Makefile deleted file mode 100644 index 5f4030661..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Makefile for GCOV profiling kernel module -# - -#KERNELDIR := ../linux-2.5.73 -CFLAGS := $(CFLAGS) -Wall -g - -ifneq ($(KERNELRELEASE),) - -obj-m := LtpfsCmds.o -obj-p := ltpfstest -else -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) M=$(PWD) modules - ${CC} $(CFLAGS) -o ltpfstest -lm main.c -# $(MAKE) -C $(KERNELDIR) M=$(PWD) modules -endif - -clean: - rm -f LtpfsCmds.o - rm -f LtpfsCmds.ko - rm -f LtpfsCmds.bb - rm -f LtpfsCmds.bbg - rm -f LtpfsCmds.mod.c - rm -f LtpfsCmds.mod.o - rm -f .*.mod* - rm -f .*.cmd diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1 deleted file mode 100644 index 65086d536..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part1 +++ /dev/null @@ -1,4 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the EXT2 & NFS filesystems -bfs101 ltpfstest /test/growfiles/ext2 -bfs102 ltpfstest /test/growfiles/nfs diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2 deleted file mode 100644 index 86514908e..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part2 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the XFS filesystems -bfs201 ltpfstest /test/growfiles/xfs diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3 deleted file mode 100644 index 4f2ee5f21..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part3 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the MSDOS filesystems -bfs101 ltpfstest /test/growfiles/msdos diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4 deleted file mode 100644 index 84519512c..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part4 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the Reiser filesystems -bfs401 ltpfstest /test/growfiles/reiser diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5 deleted file mode 100644 index c3fa4d7aa..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part5 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the Minix filesystems -bfs501 ltpfstest /test/growfiles/minix diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6 deleted file mode 100644 index 0d600fe8e..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part6 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the EXT3 filesystems -bfs601 ltpfstest /test/growfiles/ext3 diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7 b/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7 deleted file mode 100644 index c9904d6be..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfs.part7 +++ /dev/null @@ -1,3 +0,0 @@ -#DESCRIPTION:filesystem tests -# Check the JFS filesystems -bfs701 ltpfstest /test/growfiles/jfs diff --git a/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh b/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh deleted file mode 100755 index ed3d8e2ab..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/ltpfsio.sh +++ /dev/null @@ -1,154 +0,0 @@ --#!/bin/sh -# This script should be run prior to running executing the filesystem tests. -# valid devices need to be passed for the test to work correctly -# 10/06/03 mridge@us.ibm.com added instance and time command line options -# -# - -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 ] [ -n nfsmount ] - defaults: - part1=$part1 - nfsmount=$nfsmount - ltproot=$TPROOT - tmpdir=$TMPBASE - - example: ${0##*/} -a hdc1 -b hdc2 -c hdc3 -d hdc4 -n mytesthost:/testmountdir - - - This test will ONLY run on a 2.5.66 or higher kernel system. - - - 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:n:v: arg -do case $arg in - a) part1=$OPTARG;; - n) nfsmount=$OPTARG;; - v) verb=$OPTARG;; - - \?) echo "************** Help Info: ********************" - usage;; - esac -done - -if [ ! -n "$part1" ]; then - echo "Missing 1st partition. You must pass 4 partitions for testing" - usage; - exit -fi - -if [ ! -n "$nfsmount" ]; then - echo "Missing NFS partition. You must pass an NFS mount point 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/ext2 >/dev/null 2>&1 -mkdir /test/growfiles/msdos >/dev/null 2>&1 -mkdir /test/growfiles/reiser >/dev/null 2>&1 -mkdir /test/growfiles/minix >/dev/null 2>&1 -mkdir /test/growfiles/xfs >/dev/null 2>&1 -mkdir /test/growfiles/nfs >/dev/null 2>&1 -mkdir /test/growfiles/jfs >/dev/null 2>&1 -mkdir /test/growfiles/ext3 >/dev/null 2>&1 - - -mkfs -V -t ext2 /dev/$part1 - - -mount -v -t nfs $nfsmount /test/growfiles/nfs -mount -v /dev/$part1 /test/growfiles/ext2 - - -echo "************ Running tests " -sort -R ${LTPROOT}/runtest/ltpfs.part1 -o ${TMPBASE}/ltpfs.part1 - -${LTPROOT}/pan/pan -e -S -a ltpfspart1 -n ltpfspart1 -l lvmlogfile -f ${TMPBASE}/ltpfs.part1 & - -wait $! - -umount -v -t nfs $nfsmount -umount -v /dev/$part1 -mkfs.xfs -f /dev/$part1 -mount -v /dev/$part1 /test/growfiles/xfs - - -sort -R ${LTPROOT}/runtest/ltpfs.part2 -o ${TMPBASE}/ltpfs.part2 - -${LTPROOT}/pan/pan -e -S -a ltpfspart2 -n ltpfspart2 -l lvmlogfile -f ${TMPBASE}/ltpfs.part2 & - -wait $! - -mkfs -V -t msdos /dev/$part1 -umount -v /dev/$part1 -mount -v /dev/$part1 /test/growfiles/msdos - -sort -R ${LTPROOT}/runtest/ltpfs.part3 -o ${TMPBASE}/ltpfs.part3 - -${LTPROOT}/pan/pan -e -S -a ltpfspart3 -n ltpfspart3 -l lvmlogfile -f ${TMPBASE}/ltpfs.part3 & - -wait $! - -umount -v /dev/$part1 -mkreiserfs /dev/$part1 <yesenter.txt -mount -v /dev/$part1 /test/growfiles/reiser - -sort -R ${LTPROOT}/runtest/ltpfs.part4 -o ${TMPBASE}/ltpfs.part4 - -${LTPROOT}/pan/pan -e -S -a ltpfspart4 -n ltpfspart4 -l lvmlogfile -f ${TMPBASE}/ltpfs.part4 & - -wait $! - -umount -v /dev/$part1 -mkfs -V -t minix /dev/$part1 -mount -v /dev/$part1 /test/growfiles/minix - -sort -R ${LTPROOT}/runtest/ltpfs.part5 -o ${TMPBASE}/ltpfs.part5 - -${LTPROOT}/pan/pan -e -S -a ltpfspart5 -n ltpfspart5 -l lvmlogfile -f ${TMPBASE}/ltpfs.part5 & - -wait $! - -umount -v /dev/$part1 -mkfs -V -t ext3 /dev/$part1 -mount -v /dev/$part1 /test/growfiles/ext3 - -sort -R ${LTPROOT}/runtest/ltpfs.part6 -o ${TMPBASE}/ltpfs.part6 - -${LTPROOT}/pan/pan -e -S -a ltpfspart6 -n ltpfspart6 -l lvmlogfile -f ${TMPBASE}/ltpfs.part6 & - -wait $! - -umount -v /dev/$part1 -mkfs -V -t jfs /dev/$part1 <yesenter.txt -mount -v -t jfs /dev/$part1 /test/growfiles/jfs - -sort -R ${LTPROOT}/runtest/ltpfs.part7 -o ${TMPBASE}/ltpfs.part7 - -${LTPROOT}/pan/pan -e -S -a ltpfspart7 -n ltpfspart7 -l lvmlogfile -f ${TMPBASE}/ltpfs.part7 & - -wait $! - - diff --git a/testcases/kernel/fs/scsi/ltpfs/main.c b/testcases/kernel/fs/scsi/ltpfs/main.c deleted file mode 100644 index 90a5531ac..000000000 --- a/testcases/kernel/fs/scsi/ltpfs/main.c +++ /dev/null @@ -1,647 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <math.h> -#include <time.h> -#include <ftw.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <linux/kd.h> -#include <linux/errno.h> - -#include "Ltpfs.h" - -#define M_2PI (M_PI*2) -#define MAXN 4096 -#define MAXFSIZE 1024 * 192 -#define FILE_CREATE_COUNT 256 -#define FAIL 0 -#define SUCCESS 1 -#define MAXNUM 5000 -#define BUFFSIZE 8192 -#define AVEFSIZE (MAXFSIZE/2) -#define POOLDISKSPACE (AVEFSIZE*128) -#define MAXERROR 1024 -#define FILES_ONLY 0x01 -#define ALL 0x00 - -// Globals - -char wbuf[MAXFSIZE]; -int startc = 0; -int showchar[] = { 124, 47, 45, 92, 124, 47, 45, 92 }; - -int nullFileHandle; -static int openlog[2] = { 0, 0 }; - -int cFileCount, dFileCount, errorCount; -static int disk_space_pool = 0; -char rootPath[BUFFSIZE]; - -int LTP_fs_open_block_device(void); -int do_fs_thump_tests(char *path); -int do_create_file_test(char *path); -int makedir(char *dir1); -int changedir(char *dir); -int do_random_access_test(int maxNum); -int do_random_create_delete(int maxNum); -int create_file(char *filename); -int delete_file(char *filename); -int gen_random_file_size(int min, int max); -int open_read_close(char *fname); -int create_or_delete(char *fname); -int do_tree_cleanup(char *path, int flag); -int cleanup_files(char *file, struct stat *statBuff, int flag); -int cleanup_dirs(char *file, struct stat *statBuff, int flag); - -int ltp_block_dev_handle = 0; /* handle to LTP Test block device */ -int ltp_fileHandle = 0; -char *fileBuf; - -int main(int argc, char **argv) -{ - - ltpdev_cmd_t cmd = { 0, 0 }; - int rc, i, tmpHandle; - struct stat statBuf; - - printf("[%s] - Running test program\n", argv[0]); - - rc = LTP_fs_open_block_device(); - - if (!rc) { - - ltp_block_dev_handle = open(LTP_FS_DEVICE_NAME, O_RDWR); - - if (ltp_block_dev_handle < 0) { - printf - ("ERROR: Open of device %s failed %d errno = %d\n", - LTP_FS_DEVICE_NAME, ltp_block_dev_handle, errno); - } else { - rc = ioctl(ltp_block_dev_handle, LTPAIODEV_CMD, &cmd); - - printf("return from AIO ioctl %d \n", rc); - - rc = ioctl(ltp_block_dev_handle, LTPBIODEV_CMD, &cmd); - - printf("return from BIO ioctl %d \n", rc); - } - - } else { - printf("ERROR: Create/open block device failed\n"); - } - - ltp_fileHandle = - open("/tmp/testfile", O_CREAT | O_RDWR | O_SYNC | FASYNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if (ltp_fileHandle > 0) { - - tmpHandle = open("/usr/include/ctype.h", O_RDONLY); - - if (tmpHandle > 0) { - - rc = fstat(tmpHandle, &statBuf); - - if (!rc) { - fileBuf = malloc(statBuf.st_size); - - if (fileBuf) { - - read(tmpHandle, fileBuf, - statBuf.st_size); - close(tmpHandle); - write(ltp_fileHandle, fileBuf, - statBuf.st_size); - - for (i = 0; i < 100; i++) { - read(ltp_fileHandle, fileBuf, - statBuf.st_size * i); - write(ltp_fileHandle, fileBuf, - statBuf.st_size * i); - } - } - - } - - } else { - printf("ERROR: Create/open file failed\n"); - } - } - - printf("*** Starting FileSystem thump tests....****\n"); - printf("*** Please be patient, this may take a little while... ***\n"); - - for (i = 1; i < argc; i++) { - printf("Running test %d of %d on FileSystem %s \n", i, argc - 1, - argv[i]); - if (strcmp(argv[i], "|") != 0) { - strcpy(rootPath, argv[i]); - rc = do_fs_thump_tests(argv[i]); - if (rc != 0 && rc != ENOSPC) { - printf - ("ERROR: Failed on FileSystem %s with errno %d \n", - argv[i], rc); - } - } else { - printf("Test Program complete..\n"); - break; - } - - } - - printf("Test Program complete..\n"); - - return 0; -} - -int do_fs_thump_tests(char *path) -{ - int rc = 0; - - printf("Changing to directory %s \n", path); - - changedir(path); - - cFileCount = 0; - dFileCount = 0; - - rc |= do_create_file_test(path); - rc |= do_random_access_test(MAXNUM); - rc |= do_tree_cleanup(path, FILES_ONLY); - rc |= do_random_create_delete(MAXNUM); - rc |= do_tree_cleanup(path, ALL); - - return rc; - -} - -int do_tree_cleanup(char *path, int flag) -{ - - if (flag == FILES_ONLY) { - printf("Cleaning up test files...\n"); - ftw(path, (void *)cleanup_files, MAXNUM); - } else { - printf("Cleaning up everything in the test directory...\n"); - ftw(path, (void *)cleanup_files, MAXNUM); - ftw(path, (void *)cleanup_dirs, MAXNUM); - } - - return 0; -} - -int cleanup_files(char *file, struct stat *statBuff, int flag) -{ - int rc = 0; - - if (flag == FTW_F) { - if (unlink(file)) { - printf("ERROR:%d removing file %s\n", errno, file); - } - } - - return rc; -} - -int cleanup_dirs(char *file, struct stat *statBuff, int flag) -{ - int rc = 0; - - //printf("%s:Cleaning up directory %s \n", __FUNCTION__, file); - - if (strcmp(rootPath, file) == 0) { - return 0; - } - - if (flag == FTW_F) { - if (unlink(file)) { - printf("ERROR:%d removing file %s\n", errno, file); - } - } else if (flag == FTW_D) { - changedir(file); - ftw(file, (void *)cleanup_dirs, MAXNUM); - rmdir(file); - - } else { - printf("No idea what we found here\n"); - } - - return rc; -} - -int do_create_file_test(char *path) -{ - int i = 0; - int j = 0; - int k = 0; - int l = 0; - int rc = 0; - - char dir1[MAXN]; - char dir2[MAXN]; - char dir3[MAXN]; - char filename[MAXN]; - - time_t t; - - int maxfiles = 0xFFFFFF; - - time(&t); - - srandom((unsigned int)getpid() ^ - (((unsigned int)t << 16) | (unsigned int)t >> 16)); - - printf("Creating files...\n"); - - for (i = 0; i < FILE_CREATE_COUNT; i++) { - - sprintf(dir1, "%2.2x", i); - - makedir(dir1); - - changedir(dir1); - - for (j = 0; j < FILE_CREATE_COUNT; j++) { - - sprintf(dir2, "%2.2x", j); - - makedir(dir2); - - changedir(dir2); - - for (k = 0; k < FILE_CREATE_COUNT; k++) { - - sprintf(dir3, "%2.2x", k); - makedir(dir3); - changedir(dir3); - - for (l = 0; l < FILE_CREATE_COUNT; l++) { - sprintf(filename, "%s%s%s%2.2x", dir1, - dir2, dir3, l); - rc = create_file(filename); - if (rc != 0 || maxfiles < dFileCount++) { - if (rc != ENOSPC) { - printf - ("ERROR: failed error:%d creating all the test files ! \n", - errno); - printf - ("ERROR2: rc:%d -- dFileCount:%d \n", - rc, dFileCount); - } - goto end; - } - } - changedir("../"); - } - changedir("../"); - } - changedir("../"); - } -end: - fprintf(stderr, "\nTotal create files: %d\n", cFileCount); - printf("Done\n"); - return rc; -} - -int makedir(char *dir1) -{ - if (mkdir(dir1, S_IRWXU) < 0) { - perror(dir1); - return (errno); - } - return 0; -} - -int changedir(char *dir) -{ - if (chdir(dir) < 0) { - perror(dir); - return (errno); - } - - return 0; -} - -int create_file(char *filename) -{ - int fileHandle; - int randomsize; - - if ((fileHandle = creat(filename, S_IRWXU)) < 0) { - - fprintf(stderr, "\nERROR line %d: Total create files: %d\n", - __LINE__, cFileCount); - perror(filename); - return (errno); - } - - if ((randomsize = gen_random_file_size(0, MAXFSIZE)) < 0) { - randomsize = MAXFSIZE; - } - if (write(fileHandle, wbuf, randomsize) < 0) { - - fprintf(stderr, "\nERROR:%d line%d: Total create files: %d\n", - errno, __LINE__, cFileCount); - close(fileHandle); - - perror(filename); - return (errno); - } - - cFileCount++; - close(fileHandle); - return 0; -} - -int delete_file(char *filename) -{ - struct stat buf; - int st; - - st = stat(filename, &buf); - - if (st < 0) { - errorCount++; - printf("ERROR line %d: Getting file stats %s \n", __LINE__, - filename); - return (-1); - } - - disk_space_pool += buf.st_size; - - if (unlink(filename) < 0) { - errorCount++; - printf("ERROR line %d: Removing file %s \n", __LINE__, - filename); - return (-1); - } - - dFileCount++; - return 0; -} - -int LTP_fs_open_block_device() -{ - dev_t devt; - struct stat statbuf; - int rc = 0; - - if (ltp_block_dev_handle == 0) { - - /* check for the /dev/LTPFSTest subdir, and create if it does not exist. - * - * If devfs is running and mounted on /dev, these checks will all pass, - * so a new node will not be created. - */ - devt = makedev(LTPMAJOR, 0); - - rc = stat(LTP_FS_DEV_NODE_PATH, &statbuf); - - if (rc) { - if (errno == ENOENT) { - /* dev node does not exist. */ - rc = mkdir(LTP_FS_DEV_NODE_PATH, - (S_IFDIR | S_IRWXU | S_IRGRP | - S_IXGRP | S_IROTH | S_IXOTH)); - } else { - printf - ("ERROR: Problem with LTP FS dev directory. Error code from stat() is %d\n\n", - errno); - } - - } else { - if (!(statbuf.st_mode & S_IFDIR)) { - rc = unlink(LTP_FS_DEV_NODE_PATH); - if (!rc) { - rc = mkdir(LTP_FS_DEV_NODE_PATH, - (S_IFDIR | S_IRWXU | S_IRGRP - | S_IXGRP | S_IROTH | - S_IXOTH)); - } - } - } - - /* - * Check for the /dev/ltp-fs/block_device node, and create if it does not - * exist. - */ - rc = stat(LTP_FS_DEVICE_NAME, &statbuf); - if (rc) { - if (errno == ENOENT) { - /* dev node does not exist */ - rc = mknod(LTP_FS_DEVICE_NAME, - (S_IFBLK | S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP), devt); - } else { - printf - ("ERROR:Problem with LTP FS block device node directory. Error code form stat() is %d\n\n", - errno); - } - - } else { - /* - * /dev/ltp-fs/block_device exists. Check to make sure it is for a - * block device and that it has the right major and minor. - */ - if ((!(statbuf.st_mode & S_IFBLK)) || - (statbuf.st_rdev != devt)) { - - /* Recreate the dev node. */ - rc = unlink(LTP_FS_DEVICE_NAME); - if (!rc) { - rc = mknod(LTP_FS_DEVICE_NAME, - (S_IFBLK | S_IRUSR | S_IWUSR - | S_IRGRP | S_IWGRP), devt); - } - } - } - - } - - return rc; -} - -int gen_random_file_size(int min, int max) -{ - double u1, u2, z; - int i; - int ave; - int range; - int ZZ; - if (min >= max) { - return (-1); - } - range = max - min; - ave = range / 2; - for (i = 0; i < 10; i++) { - u1 = ((double)(random() % 1000000)) / 1000000; - u2 = ((double)(random() % 1000000)) / 1000000; - z = sqrt(-2.0 * log(u1)) * cos(M_2PI * u2); - ZZ = min + (ave + (z * (ave / 4))); - if (ZZ >= min && ZZ < max) { - return (ZZ); - } - } - return (-1); -} - -int do_random_access_test(int maxNum) -{ - int r; - char fname[1024]; - time_t t; - int i; - - printf("Running random access test...\n"); - changedir(rootPath); - - if (maxNum < 1 || maxNum > MAXNUM) { - printf("out of size %d\n", maxNum); - return 1; - } - - time(&t); - srandom((unsigned int)getpid() ^ - (((unsigned int)t << 16) | (unsigned int)t >> 16)); - - if ((nullFileHandle = open("/dev/null", O_WRONLY)) < 0) { - perror("/dev/null"); - return (errno); - } - - /* 00/00/00/00 */ - for (i = 0; i < maxNum; i++) { - - r = random() % maxNum; - - sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x", - ((r >> 16) & 0xFF), - ((r >> 8) & 0xFF), - ((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF)); - - open_read_close(fname); - } - close(nullFileHandle); - printf("Success:\t%d\nFail:\t%d\n", openlog[SUCCESS], openlog[FAIL]); - return 0; -} - -int open_read_close(char *fname) -{ - int fileHandle, fileHandle2; - char buffer[BUFFSIZE]; - int c; - - if ((fileHandle = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) { - openlog[FAIL]++; - printf("ERROR:opening file %s failed %d \n", fname, errno); - return (errno); - } - - if ((fileHandle2 = open(fname, O_RDONLY | O_SYNC | O_ASYNC)) < 0) { - openlog[FAIL]++; - printf("ERROR:2nd opening file %s failed %d \n", fname, errno); - return (errno); - } - - openlog[SUCCESS]++; - - while ((c = read(fileHandle, buffer, BUFFSIZE)) > 0) { - if (write(nullFileHandle, buffer, c) < 0) { - perror("/dev/null"); - printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS], - openlog[FAIL]); - close(fileHandle2); - close(fileHandle); - return (errno); - } - if ((c = read(fileHandle2, buffer, BUFFSIZE)) > 0) { - if (write(nullFileHandle, buffer, c) < 0) { - perror("/dev/null"); - printf("Opened\t %d\nUnopend:\t%d\n", - openlog[SUCCESS], openlog[FAIL]); - close(fileHandle2); - close(fileHandle); - return (errno); - } - } - } - - if (c < 0) { - perror(fname); - printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS], - openlog[FAIL]); - return (errno); - } - - close(fileHandle2); - close(fileHandle); - return 0; -} - -int create_or_delete(char *fname) -{ - int r, rc; - - r = (random() & 1); - - /* create */ - if ((create_file(fname) == 0)) { - rc = delete_file(fname); - } else { - printf("Error: %d creating random file \n", errno); - } - - if ((errorCount > dFileCount || errorCount > cFileCount) - && (errorCount > MAXERROR)) { - fprintf(stderr, "Too many errors -- Aborting test\n"); - fprintf(stderr, "Total create files: %d\n", cFileCount); - fprintf(stderr, "Total delete files: %d\n", dFileCount); - fprintf(stderr, "Total error : %d\n", errorCount); - return (MAXERROR); - } - - return 0; -} - -int do_random_create_delete(int maxNum) -{ - int r, rc = 0; - char fname[1024]; - time_t t; - int i; - - printf("Running random create/delete test...\n"); - - if (maxNum < 1 || maxNum > MAXNUM) { - printf("MAX out of size %d\n", maxNum); - return (maxNum); - } - - time(&t); - srandom((unsigned int)getpid() ^ - (((unsigned int)t << 16) | (unsigned int)t >> 16)); - - /* 00/00/00/00 */ - for (i = 0; i < maxNum && rc != MAXERROR; i++) { - r = random() % maxNum; - sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x", - ((r >> 16) & 0xFF), - ((r >> 8) & 0xFF), - ((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF)); - - rc = create_or_delete(fname); - } - - fprintf(stderr, "Total create files: %d\n", cFileCount); - fprintf(stderr, "Total delete files: %d\n", dFileCount); - fprintf(stderr, "Total error : %d\n", errorCount); - return (rc); -} 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 -*/ |