Hello community, here is the log from the commit of package hdparm for openSUSE:Factory checked in at 2012-02-07 14:45:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hdparm (Old) and /work/SRC/openSUSE:Factory/.hdparm.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hdparm", Maintainer is "[email protected]" Changes: -------- --- /work/SRC/openSUSE:Factory/hdparm/hdparm.changes 2012-01-09 16:22:53.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.hdparm.new/hdparm.changes 2012-02-07 14:45:51.000000000 +0100 @@ -1,0 +2,8 @@ +Mon Feb 6 13:44:39 UTC 2012 - [email protected] + +- update to hdparm-9.39 + - added -R flag to control Read-Write-Verify feature, courtesy of + Gordan Bobic + - nuked leftover sgio.c.orig file + +------------------------------------------------------------------- Old: ---- hdparm-9.38.tar.gz New: ---- hdparm-9.39.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hdparm.spec ++++++ --- /var/tmp/diff_new_pack.PJ3hjV/_old 2012-02-07 14:45:54.000000000 +0100 +++ /var/tmp/diff_new_pack.PJ3hjV/_new 2012-02-07 14:45:54.000000000 +0100 @@ -16,10 +16,11 @@ # + Name: hdparm PreReq: %insserv_prereq %fillup_prereq coreutils Provides: base:/sbin/hdparm -Version: 9.38 +Version: 9.39 Release: 0 Summary: A Program to get and set hard disk parameters License: PERMISSIVE-OSI-COMPLIANT ++++++ hdparm-9.38.tar.gz -> hdparm-9.39.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/Changelog new/hdparm-9.39/Changelog --- old/hdparm-9.38/Changelog 2012-01-06 17:47:10.000000000 +0100 +++ new/hdparm-9.39/Changelog 2012-02-06 14:45:27.000000000 +0100 @@ -1,4 +1,7 @@ -9.37+ +hdparm-9.39 + - added -R flag to control Read-Write-Verify feature, courtesy of Gordan Bobic + - nuked leftover sgio.c.orig file +hdparm-9.38 - updated wiper.sh to allow all SCSI_DISK major numbers - updated handing for very long SECURITY-ERASE times - added -J flag for wdidle3 set/get diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/hdparm.8 new/hdparm-9.39/hdparm.8 --- old/hdparm-9.38/hdparm.8 2012-01-07 22:58:56.000000000 +0100 +++ new/hdparm-9.39/hdparm.8 2012-02-03 04:24:42.000000000 +0100 @@ -1,4 +1,4 @@ -.TH HDPARM 8 "January 2012" "Version 9.38" +.TH HDPARM 8 "January 2012" "Version 9.39" .SH NAME hdparm \- get/set SATA/IDE device parameters @@ -542,6 +542,17 @@ .I -r Get/set read-only flag for the device. When set, Linux disallows write operations on the device. .TP +.I -R +Get/set Write-Read-Verify feature, if the drive supports it. +Usage: +.B -R0 +(disable) or +.B -R1 +(enable). This feature is intended to have the drive firmware automatically +read-back any data that is written by software, to verify that the data was +successfully written. This is generally overkill, and can slow down disk +writes by as much as a factor of two (or more). +.TP .I --read-sector Reads from the specified sector number, and dumps the contents in hex to standard output. The sector number must be given (base10) after this option. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/hdparm.c new/hdparm-9.39/hdparm.c --- old/hdparm-9.38/hdparm.c 2012-01-07 22:57:24.000000000 +0100 +++ new/hdparm-9.39/hdparm.c 2012-02-03 04:24:33.000000000 +0100 @@ -1,5 +1,5 @@ /* hdparm.c - Command line interface to get/set hard disk parameters */ -/* - by Mark Lord (C) 1994-2008 -- freely distributable */ +/* - by Mark Lord (C) 1994-2012 -- freely distributable */ #define _LARGEFILE64_SOURCE /*for lseek64*/ #define _BSD_SOURCE /* for strtoll() */ #include <unistd.h> @@ -35,7 +35,7 @@ extern const char *minor_str[]; -#define VERSION "v9.38" +#define VERSION "v9.39" #ifndef O_DIRECT #define O_DIRECT 040000 /* direct disk access, not easily obtained from headers */ @@ -101,6 +101,7 @@ static int set_busstate = 0, get_busstate = 0, busstate = 0; static int set_reread_partn = 0, get_reread_partn; static int set_acoustic = 0, get_acoustic = 0, acoustic = 0; +static int write_read_verify = 0, get_write_read_verify = 0, set_write_read_verify = 0; static int make_bad_sector = 0, make_bad_sector_flagged; static __u64 make_bad_sector_addr = ~0ULL; @@ -1451,7 +1452,7 @@ " -q Change next setting quietly\n" " -Q Get/set DMA queue_depth (if supported)\n" " -r Get/set device readonly flag (DANGEROUS to set)\n" - " -R Obsolete\n" + " -R Get/set device write-read-verify flag\n" " -s Set power-up in standby flag (0/1) (DANGEROUS)\n" " -S Set standby (spindown) timeout\n" " -t Perform device read timings\n" @@ -1809,6 +1810,19 @@ perror(" HDIO_DRIVE_CMD:ACOUSTIC failed"); } } + if (set_write_read_verify) { + __u8 args[4]; + if (get_write_read_verify) + printf(" setting write-read-verify to %d\n", write_read_verify); + args[0] = ATA_OP_SETFEATURES; + args[1] = write_read_verify; + args[2] = write_read_verify ? 0x0b : 0x8b; + args[3] = 0; + if (do_drive_cmd(fd, args, 0)) { + err = errno; + perror(" HDIO_DRIVE_CMD:WRV failed"); + } + } if (set_wcache) { if (get_wcache) { printf(" setting drive write-caching to %d", wcache); @@ -2231,6 +2245,16 @@ printf(" acoustic = not supported\n"); } } + if (get_write_read_verify) { + get_identify_data(fd); + if (id) { + int supported = id[119] & 0x2; + if (supported) + printf(" write-read-verify = %2u\n", id[120] & 0x2); + else + printf(" write-read-verify = not supported\n"); + } + } if (get_busstate) { if (ioctl(fd, HDIO_GET_BUSSTATE, &parm)) { err = errno; @@ -2760,6 +2784,7 @@ case SET_PARM('s',"powerup-in-standby",powerup_in_standby,0,1); case SET_PARM('S',"standby-interval",standby,0,255); case GET_SET_PARM('r',"read-only",readonly,0,1); + case GET_SET_PARM('R',"write-read-verify",write_read_verify,0,3); case DO_FLAG('t',do_timings); case DO_FLAG('T',do_ctimings); case GET_SET_PARM('u',"unmask-irq",unmask,0,1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/hdparm.lsm new/hdparm-9.39/hdparm.lsm --- old/hdparm-9.38/hdparm.lsm 2012-01-07 23:00:13.000000000 +0100 +++ new/hdparm-9.39/hdparm.lsm 2012-02-03 04:26:50.000000000 +0100 @@ -1,8 +1,9 @@ Begin4 Title: hdparm -Version: 9.38 -Entered-date: 2012-01-07 +Version: 9.39 +Entered-date: 2012-02-02 Description: hdparm - get/set hard disk parameters for Linux SATA/IDE drives. + v9.38 Added -R, courtesy of Gordan Bobic v9.38 Added -J, fixed erase timeouts, updated wiper.sh v9.37 Enable --fibmap to work on RAID1; other tweaks v9.36 manpage updates, wiper.sh version 3.1 @@ -112,7 +113,7 @@ Maintained-by: [email protected] (Mark Lord) Primary-site: http://sourceforge.net/projects/hdparm/ Alternate-site: http://www.ibiblio.org/pub/Linux/system/hardware - 131K hdparm-9.38.tar.gz + 127K hdparm-9.39.tar.gz 4K hdparm.lsm Platforms: Linux Copying-policy: BSD License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/sgio.c new/hdparm-9.39/sgio.c --- old/hdparm-9.38/sgio.c 2012-01-06 17:06:03.000000000 +0100 +++ new/hdparm-9.39/sgio.c 2012-01-09 04:12:16.000000000 +0100 @@ -20,7 +20,7 @@ extern int verbose; extern int prefer_ata12; -static const int default_timeout_secs = 15; +static const unsigned int default_timeout_secs = 15; /* * Taskfile layout for SG_ATA_16 cdb: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.38/sgio.c.orig new/hdparm-9.39/sgio.c.orig --- old/hdparm-9.38/sgio.c.orig 2010-10-19 15:10:00.000000000 +0200 +++ new/hdparm-9.39/sgio.c.orig 1970-01-01 01:00:00.000000000 +0100 @@ -1,580 +0,0 @@ -/* sgio.c - by Mark Lord (C) 2007 -- freely distributable */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <scsi/scsi.h> -#include <scsi/sg.h> - -#include "sgio.h" -#include "hdparm.h" - -#include <linux/hdreg.h> - -extern int verbose; -extern int prefer_ata12; - -static const int default_timeout_secs = 15; - -/* - * Taskfile layout for SG_ATA_16 cdb: - * - * LBA48: - * cdb[ 3] = hob_feat - * cdb[ 5] = hob_nsect - * cdb[ 7] = hob_lbal - * cdb[ 9] = hob_lbam - * cdb[11] = hob_lbah - * - * LBA28/LBA48: - * cdb[ 4] = feat - * cdb[ 6] = nsect - * cdb[ 8] = lbal - * cdb[10] = lbam - * cdb[12] = lbah - * cdb[13] = device - * cdb[14] = command - * - * Taskfile layout for SG_ATA_12 cdb: - * - * cdb[ 3] = feat - * cdb[ 4] = nsect - * cdb[ 5] = lbal - * cdb[ 6] = lbam - * cdb[ 7] = lbah - * cdb[ 8] = device - * cdb[ 9] = command - * - * dxfer_direction choices: - * SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV, SG_DXFER_NONE - */ - -#if 0 /* maybe use this in sg16 later.. ? */ -static inline int get_rw (__u8 ata_op) -{ - switch (ata_op) { - case ATA_OP_DSM: - case ATA_OP_WRITE_PIO: - case ATA_OP_WRITE_LONG: - case ATA_OP_WRITE_LONG_ONCE: - case ATA_OP_WRITE_PIO_EXT: - case ATA_OP_WRITE_DMA_EXT: - case ATA_OP_WRITE_FPDMA: - case ATA_OP_WRITE_UNC_EXT: - case ATA_OP_WRITE_DMA: - case ATA_OP_SECURITY_UNLOCK: - case ATA_OP_SECURITY_DISABLE: - case ATA_OP_SECURITY_ERASE_UNIT: - case ATA_OP_SECURITY_SET_PASS: - return SG_WRITE; - default: - return SG_READ; - } -} -#endif - -static inline int needs_lba48 (__u8 ata_op, __u64 lba, unsigned int nsect) -{ - switch (ata_op) { - case ATA_OP_DSM: - case ATA_OP_READ_PIO_EXT: - case ATA_OP_READ_DMA_EXT: - case ATA_OP_WRITE_PIO_EXT: - case ATA_OP_WRITE_DMA_EXT: - case ATA_OP_READ_VERIFY_EXT: - case ATA_OP_WRITE_UNC_EXT: - case ATA_OP_READ_NATIVE_MAX_EXT: - case ATA_OP_SET_MAX_EXT: - case ATA_OP_FLUSHCACHE_EXT: - return 1; - case ATA_OP_SECURITY_ERASE_PREPARE: - case ATA_OP_SECURITY_ERASE_UNIT: - return 0; - } - if (lba >= lba28_limit) - return 1; - if (nsect) { - if (nsect > 0xff) - return 1; - if ((lba + nsect - 1) >= lba28_limit) - return 1; - } - return 0; -} - -static inline int is_dma (__u8 ata_op) -{ - switch (ata_op) { - case ATA_OP_DSM: - case ATA_OP_READ_DMA_EXT: - case ATA_OP_READ_FPDMA: - case ATA_OP_WRITE_DMA_EXT: - case ATA_OP_WRITE_FPDMA: - case ATA_OP_READ_DMA: - case ATA_OP_WRITE_DMA: - return SG_DMA; - default: - return SG_PIO; - } -} - -void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect) -{ - memset(tf, 0, sizeof(*tf)); - tf->command = ata_op; - tf->dev = ATA_USING_LBA; - tf->lob.lbal = lba; - tf->lob.lbam = lba >> 8; - tf->lob.lbah = lba >> 16; - tf->lob.nsect = nsect; - if (needs_lba48(ata_op, lba, nsect)) { - tf->is_lba48 = 1; - tf->hob.nsect = nsect >> 8; - tf->hob.lbal = lba >> 24; - tf->hob.lbam = lba >> 32; - tf->hob.lbah = lba >> 40; - } else { - tf->dev |= (lba >> 24) & 0x0f; - } -} - -#ifdef SG_IO - -__u64 tf_to_lba (struct ata_tf *tf) -{ - __u32 lba24, lbah; - __u64 lba64; - - lba24 = (tf->lob.lbah << 16) | (tf->lob.lbam << 8) | (tf->lob.lbal); - if (tf->is_lba48) - lbah = (tf->hob.lbah << 16) | (tf->hob.lbam << 8) | (tf->hob.lbal); - else - lbah = (tf->dev & 0x0f); - lba64 = (((__u64)lbah) << 24) | (__u64)lba24; - return lba64; -} - -enum { - SG_CDB2_TLEN_NODATA = 0 << 0, - SG_CDB2_TLEN_FEAT = 1 << 0, - SG_CDB2_TLEN_NSECT = 2 << 0, - - SG_CDB2_TLEN_BYTES = 0 << 2, - SG_CDB2_TLEN_SECTORS = 1 << 2, - - SG_CDB2_TDIR_TO_DEV = 0 << 3, - SG_CDB2_TDIR_FROM_DEV = 1 << 3, - - SG_CDB2_CHECK_COND = 1 << 5, -}; - -static void dump_bytes (const char *prefix, unsigned char *p, int len) -{ - int i; - - if (prefix) - fprintf(stderr, "%s: ", prefix); - for (i = 0; i < len; ++i) - fprintf(stderr, " %02x", p[i]); - fprintf(stderr, "\n"); -} - -int sg16 (int fd, int rw, int dma, struct ata_tf *tf, - void *data, unsigned int data_bytes, unsigned int timeout_secs) -{ - unsigned char cdb[SG_ATA_16_LEN]; - unsigned char sb[32], *desc; - struct scsi_sg_io_hdr io_hdr; - int prefer12 = prefer_ata12, demanded_sense = 0; - - if (tf->command == ATA_OP_PIDENTIFY) - prefer12 = 0; - - memset(&cdb, 0, sizeof(cdb)); - memset(&sb, 0, sizeof(sb)); - memset(&io_hdr, 0, sizeof(struct scsi_sg_io_hdr)); - if (data && data_bytes && !rw) - memset(data, 0, data_bytes); - - if (dma) { - //cdb[1] = data ? (rw ? SG_ATA_PROTO_UDMA_OUT : SG_ATA_PROTO_UDMA_IN) : SG_ATA_PROTO_NON_DATA; - cdb[1] = data ? SG_ATA_PROTO_DMA : SG_ATA_PROTO_NON_DATA; - } else { - cdb[1] = data ? (rw ? SG_ATA_PROTO_PIO_OUT : SG_ATA_PROTO_PIO_IN) : SG_ATA_PROTO_NON_DATA; - } - - /* libata/AHCI workaround: don't demand sense data for IDENTIFY commands */ - if (data) { - cdb[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS; - cdb[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV; - } else { - cdb[2] = SG_CDB2_CHECK_COND; - } - - if (!prefer12 || tf->is_lba48) { - cdb[ 0] = SG_ATA_16; - cdb[ 4] = tf->lob.feat; - cdb[ 6] = tf->lob.nsect; - cdb[ 8] = tf->lob.lbal; - cdb[10] = tf->lob.lbam; - cdb[12] = tf->lob.lbah; - cdb[13] = tf->dev; - cdb[14] = tf->command; - if (tf->is_lba48) { - cdb[ 1] |= SG_ATA_LBA48; - cdb[ 3] = tf->hob.feat; - cdb[ 5] = tf->hob.nsect; - cdb[ 7] = tf->hob.lbal; - cdb[ 9] = tf->hob.lbam; - cdb[11] = tf->hob.lbah; - } - io_hdr.cmd_len = SG_ATA_16_LEN; - } else { - cdb[ 0] = SG_ATA_12; - cdb[ 3] = tf->lob.feat; - cdb[ 4] = tf->lob.nsect; - cdb[ 5] = tf->lob.lbal; - cdb[ 6] = tf->lob.lbam; - cdb[ 7] = tf->lob.lbah; - cdb[ 8] = tf->dev; - cdb[ 9] = tf->command; - io_hdr.cmd_len = SG_ATA_12_LEN; - } - - io_hdr.interface_id = 'S'; - io_hdr.mx_sb_len = sizeof(sb); - io_hdr.dxfer_direction = data ? (rw ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV) : SG_DXFER_NONE; - io_hdr.dxfer_len = data ? data_bytes : 0; - io_hdr.dxferp = data; - io_hdr.cmdp = cdb; - io_hdr.sbp = sb; - io_hdr.pack_id = tf_to_lba(tf); - io_hdr.timeout = (timeout_secs ? timeout_secs : default_timeout_secs) * 1000; /* msecs */ - - if (verbose) { - dump_bytes("outgoing cdb", cdb, sizeof(cdb)); - if (rw && data) - dump_bytes("outgoing_data", data, data_bytes); - } - - if (ioctl(fd, SG_IO, &io_hdr) == -1) { - if (verbose) - perror("ioctl(fd,SG_IO)"); - return -1; /* SG_IO not supported */ - } - - if (verbose) - fprintf(stderr, "SG_IO: ATA_%u status=0x%x, host_status=0x%x, driver_status=0x%x\n", - io_hdr.cmd_len, io_hdr.status, io_hdr.host_status, io_hdr.driver_status); - - if (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION) { - if (verbose) - fprintf(stderr, "SG_IO: bad status: 0x%x\n", io_hdr.status); - errno = EBADE; - return -1; - } - if (io_hdr.host_status) { - if (verbose) - fprintf(stderr, "SG_IO: bad host status: 0x%x\n", io_hdr.host_status); - errno = EBADE; - return -1; - } - if (verbose) { - dump_bytes("SG_IO: sb[]", sb, sizeof(sb)); - if (!rw && data) - dump_bytes("incoming_data", data, data_bytes); - } - - if (io_hdr.driver_status && (io_hdr.driver_status != SG_DRIVER_SENSE)) { - if (verbose) - fprintf(stderr, "SG_IO: bad driver status: 0x%x\n", io_hdr.driver_status); - errno = EBADE; - return -1; - } - - desc = sb + 8; - if (io_hdr.driver_status != SG_DRIVER_SENSE) { - if (sb[0] | sb[1] | sb[2] | sb[3] | sb[4] | sb[5] | sb[6] | sb[7] | sb[8] | sb[9]) { - static int second_try = 0; - if (!second_try++) - fprintf(stderr, "SG_IO: questionable sense data, results may be incorrect\n"); - } else if (demanded_sense) { - static int second_try = 0; - if (!second_try++) - fprintf(stderr, "SG_IO: missing sense data, results may be incorrect\n"); - } - } else if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) { - dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb)); - } - - if (verbose) { - unsigned int len = desc[1] + 2, maxlen = sizeof(sb) - 8 - 2; - if (len > maxlen) - len = maxlen; - dump_bytes("SG_IO: desc[]", desc, len); - } - - tf->is_lba48 = desc[ 2] & 1; - tf->error = desc[ 3]; - tf->lob.nsect = desc[ 5]; - tf->lob.lbal = desc[ 7]; - tf->lob.lbam = desc[ 9]; - tf->lob.lbah = desc[11]; - tf->dev = desc[12]; - tf->status = desc[13]; - tf->hob.feat = 0; - if (tf->is_lba48) { - tf->hob.nsect = desc[ 4]; - tf->hob.lbal = desc[ 6]; - tf->hob.lbam = desc[ 8]; - tf->hob.lbah = desc[10]; - } else { - tf->hob.nsect = 0; - tf->hob.lbal = 0; - tf->hob.lbam = 0; - tf->hob.lbah = 0; - } - - if (verbose) - fprintf(stderr, " ATA_%u stat=%02x err=%02x nsect=%02x lbal=%02x lbam=%02x lbah=%02x dev=%02x\n", - io_hdr.cmd_len, tf->status, tf->error, tf->lob.nsect, tf->lob.lbal, tf->lob.lbam, tf->lob.lbah, tf->dev); - - if (tf->status & (ATA_STAT_ERR | ATA_STAT_DRQ)) { - if (verbose) { - fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n", - tf->command, tf->status, tf->error); - } - errno = EIO; - return -1; - } - return 0; -} - -#endif /* SG_IO */ - -int do_drive_cmd (int fd, unsigned char *args, unsigned int timeout_secs) -{ -#ifdef SG_IO - - struct ata_tf tf; - void *data = NULL; - unsigned int data_bytes = 0; - int rc; - - if (args == NULL) - goto use_legacy_ioctl; - /* - * Reformat and try to issue via SG_IO: - * args[0]: command in; status out. - * args[1]: lbal for SMART, nsect for all others; error out - * args[2]: feat in; nsect out. - * args[3]: data-count (512 multiple) for all cmds. - */ - tf_init(&tf, args[0], 0, 0); - tf.lob.nsect = args[1]; - tf.lob.feat = args[2]; - if (args[3]) { - data_bytes = args[3] * 512; - data = args + 4; - if (!tf.lob.nsect) - tf.lob.nsect = args[3]; - } - if (tf.command == ATA_OP_SMART) { - tf.lob.nsect = args[3]; - tf.lob.lbal = args[1]; - tf.lob.lbam = 0x4f; - tf.lob.lbah = 0xc2; - } - - rc = sg16(fd, SG_READ, is_dma(tf.command), &tf, data, data_bytes, timeout_secs); - if (rc == -1) { - if (errno == EINVAL || errno == ENODEV || errno == EBADE) - goto use_legacy_ioctl; - } - - if (rc == 0 || errno == EIO) { - args[0] = tf.status; - args[1] = tf.error; - args[2] = tf.lob.nsect; - } - return rc; - -use_legacy_ioctl: -#endif /* SG_IO */ - if (verbose) { - if (args) - fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n"); - } - return ioctl(fd, HDIO_DRIVE_CMD, args); -} - -int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs) -{ - int rc; -#ifdef SG_IO - struct ata_tf tf; - void *data = NULL; - unsigned int data_bytes = 0; - int rw = SG_READ; - /* - * Reformat and try to issue via SG_IO: - */ - tf_init(&tf, 0, 0, 0); -#if 1 /* debugging */ - if (verbose) { - printf("oflags.lob_all=0x%02x, flags={", r->oflags.lob_all); - if (r->oflags.lob.feat) printf(" feat"); - if (r->oflags.lob.nsect)printf(" nsect"); - if (r->oflags.lob.lbal) printf(" lbal"); - if (r->oflags.lob.lbam) printf(" lbam"); - if (r->oflags.lob.lbah) printf(" lbah"); - if (r->oflags.lob.dev) printf(" dev"); - if (r->oflags.lob.command) printf(" command"); - printf(" }\n"); - printf("oflags.hob_all=0x%02x, flags={", r->oflags.hob_all); - if (r->oflags.hob.feat) printf(" feat"); - if (r->oflags.hob.nsect)printf(" nsect"); - if (r->oflags.hob.lbal) printf(" lbal"); - if (r->oflags.hob.lbam) printf(" lbam"); - if (r->oflags.hob.lbah) printf(" lbah"); - printf(" }\n"); - } -#endif - if (r->oflags.lob.feat) tf.lob.feat = r->lob.feat; - if (r->oflags.lob.lbal) tf.lob.lbal = r->lob.lbal; - if (r->oflags.lob.nsect) tf.lob.nsect = r->lob.nsect; - if (r->oflags.lob.lbam) tf.lob.lbam = r->lob.lbam; - if (r->oflags.lob.lbah) tf.lob.lbah = r->lob.lbah; - if (r->oflags.lob.dev) tf.dev = r->lob.dev; - if (r->oflags.lob.command) tf.command = r->lob.command; - if (needs_lba48(tf.command,0,0) || r->oflags.hob_all || r->iflags.hob_all) { - tf.is_lba48 = 1; - if (r->oflags.hob.feat) tf.hob.feat = r->hob.feat; - if (r->oflags.hob.lbal) tf.hob.lbal = r->hob.lbal; - if (r->oflags.hob.nsect)tf.hob.nsect = r->hob.nsect; - if (r->oflags.hob.lbam) tf.hob.lbam = r->hob.lbam; - if (r->oflags.hob.lbah) tf.hob.lbah = r->hob.lbah; - if (verbose) - fprintf(stderr, "using LBA48 taskfile\n"); - } - switch (r->cmd_req) { - case TASKFILE_CMD_REQ_OUT: - case TASKFILE_CMD_REQ_RAW_OUT: - data_bytes = r->obytes; - data = r->data; - rw = SG_WRITE; - break; - case TASKFILE_CMD_REQ_IN: - data_bytes = r->ibytes; - data = r->data; - break; - } - - rc = sg16(fd, rw, is_dma(tf.command), &tf, data, data_bytes, timeout_secs); - if (rc == -1) { - if (errno == EINVAL || errno == ENODEV || errno == EBADE) - goto use_legacy_ioctl; - } - - if (rc == 0 || errno == EIO) { - if (r->iflags.lob.feat) r->lob.feat = tf.error; - if (r->iflags.lob.lbal) r->lob.lbal = tf.lob.lbal; - if (r->iflags.lob.nsect) r->lob.nsect = tf.lob.nsect; - if (r->iflags.lob.lbam) r->lob.lbam = tf.lob.lbam; - if (r->iflags.lob.lbah) r->lob.lbah = tf.lob.lbah; - if (r->iflags.lob.dev) r->lob.dev = tf.dev; - if (r->iflags.lob.command) r->lob.command = tf.status; - if (r->iflags.hob.feat) r->hob.feat = tf.hob.feat; - if (r->iflags.hob.lbal) r->hob.lbal = tf.hob.lbal; - if (r->iflags.hob.nsect) r->hob.nsect = tf.hob.nsect; - if (r->iflags.hob.lbam) r->hob.lbam = tf.hob.lbam; - if (r->iflags.hob.lbah) r->hob.lbah = tf.hob.lbah; - } - return rc; - -use_legacy_ioctl: -#else - timeout_secs = 0; /* keep compiler happy */ -#endif /* SG_IO */ - if (verbose) - fprintf(stderr, "trying legacy HDIO_DRIVE_TASKFILE\n"); - errno = 0; - - rc = ioctl(fd, HDIO_DRIVE_TASKFILE, r); - if (verbose) { - int err = errno; - fprintf(stderr, "rc=%d, errno=%d, returned ATA registers: ", rc, err); - if (r->iflags.lob.feat) fprintf(stderr, " er=%02x", r->lob.feat); - if (r->iflags.lob.nsect) fprintf(stderr, " ns=%02x", r->lob.nsect); - if (r->iflags.lob.lbal) fprintf(stderr, " ll=%02x", r->lob.lbal); - if (r->iflags.lob.lbam) fprintf(stderr, " lm=%02x", r->lob.lbam); - if (r->iflags.lob.lbah) fprintf(stderr, " lh=%02x", r->lob.lbah); - if (r->iflags.lob.dev) fprintf(stderr, " dh=%02x", r->lob.dev); - if (r->iflags.lob.command) fprintf(stderr, " st=%02x", r->lob.command); - if (r->iflags.hob.feat) fprintf(stderr, " err=%02x", r->hob.feat); - if (r->iflags.hob.nsect) fprintf(stderr, " err=%02x", r->hob.nsect); - if (r->iflags.hob.lbal) fprintf(stderr, " err=%02x", r->hob.lbal); - if (r->iflags.hob.lbam) fprintf(stderr, " err=%02x", r->hob.lbam); - if (r->iflags.hob.lbah) fprintf(stderr, " err=%02x", r->hob.lbah); - fprintf(stderr, "\n"); - errno = err; - } - if (rc == -1 && errno == EINVAL) { - fprintf(stderr, "The running kernel lacks CONFIG_IDE_TASK_IOCTL support for this device.\n"); - errno = EINVAL; - } - return rc; -} - -void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48, - __u64 lba, unsigned int nsect, int data_bytes) -{ - memset(r, 0, sizeof(struct hdio_taskfile) + data_bytes); - if (!data_bytes) { - r->dphase = TASKFILE_DPHASE_NONE; - r->cmd_req = TASKFILE_CMD_REQ_NODATA; - } else if (rw == RW_WRITE) { - r->dphase = TASKFILE_DPHASE_PIO_OUT; - r->cmd_req = TASKFILE_CMD_REQ_RAW_OUT; - r->obytes = data_bytes; - } else { /* rw == RW_READ */ - r->dphase = TASKFILE_DPHASE_PIO_IN; - r->cmd_req = TASKFILE_CMD_REQ_IN; - r->ibytes = data_bytes; - } - r->lob.command = ata_op; - r->oflags.lob.command = 1; - r->oflags.lob.dev = 1; - r->oflags.lob.lbal = 1; - r->oflags.lob.lbam = 1; - r->oflags.lob.lbah = 1; - r->oflags.lob.nsect = 1; - - r->iflags.lob.command = 1; - r->iflags.lob.feat = 1; - - r->lob.nsect = nsect; - r->lob.lbal = lba; - r->lob.lbam = lba >> 8; - r->lob.lbah = lba >> 16; - r->lob.dev = 0xa0 | ATA_USING_LBA; - - if (needs_lba48(ata_op, lba, nsect) || force_lba48) { - r->hob.nsect = nsect >> 8; - r->hob.lbal = lba >> 24; - r->hob.lbam = lba >> 32; - r->hob.lbah = lba >> 40; - r->oflags.hob.nsect = 1; - r->oflags.hob.lbal = 1; - r->oflags.hob.lbam = 1; - r->oflags.hob.lbah = 1; - } else { - r->lob.dev |= (lba >> 24) & 0x0f; - } -} -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
