~ubuntu-branches/ubuntu/saucy/hdparm/saucy

« back to all changes in this revision

Viewing changes to hdparm.c

  • Committer: Steve Langasek
  • Date: 2012-10-25 03:08:04 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: steve.langasek@canonical.com-20121025030804-l50mshoma6jtp6kg
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* hdparm.c - Command line interface to get/set hard disk parameters */
2
 
/*          - by Mark Lord (C) 1994-2008 -- freely distributable */
 
1
/*
 
2
 * hdparm.c - Command line interface to get/set hard disk parameters.
 
3
 *          - by Mark Lord (C) 1994-2012 -- freely distributable.
 
4
 */
3
5
#define _LARGEFILE64_SOURCE /*for lseek64*/
4
6
#define _BSD_SOURCE     /* for strtoll() */
5
7
#include <unistd.h>
23
25
#include <linux/types.h>
24
26
#include <linux/fs.h>
25
27
#include <linux/major.h>
 
28
#include <endian.h>
26
29
#include <asm/byteorder.h>
27
30
 
28
31
#include "hdparm.h"
35
38
 
36
39
extern const char *minor_str[];
37
40
 
38
 
#define VERSION "v9.37"
 
41
#define VERSION "v9.42"
39
42
 
40
43
#ifndef O_DIRECT
41
44
#define O_DIRECT        040000  /* direct disk access, not easily obtained from headers */
55
58
static int do_identity = 0, get_geom = 0, noisy = 1, quiet = 0;
56
59
static int do_flush_wcache = 0;
57
60
 
58
 
//static int set_wdidle3  = 0;
 
61
static int set_wdidle3  = 0, get_wdidle3 = 0, wdidle3 = 0;
59
62
static int   set_timings_offset = 0;
60
63
static __u64 timings_offset = 0;
61
64
static int set_fsreadahead= 0, get_fsreadahead= 0, fsreadahead= 0;
101
104
static int      set_busstate = 0, get_busstate = 0, busstate = 0;
102
105
static int      set_reread_partn = 0, get_reread_partn;
103
106
static int      set_acoustic = 0, get_acoustic = 0, acoustic = 0;
 
107
static int write_read_verify = 0, get_write_read_verify = 0, set_write_read_verify = 0;
104
108
 
105
109
static int   make_bad_sector = 0, make_bad_sector_flagged;
106
110
static __u64 make_bad_sector_addr = ~0ULL;
706
710
        if (id) {
707
711
                timeout = id[idx];
708
712
                if (timeout && timeout <= 0xff) {
709
 
                        if (timeout == 0xff)
 
713
                        /*
 
714
                         * 0xff means "more than 254 2-minute intervals (508+ minutes),
 
715
                         * but we really want a better idea than that.
 
716
                         * Norman Diamond suggests allowing 1sec per 30MB of capacity.
 
717
                         */
 
718
                        if (timeout == 0xff) {
 
719
                                __u64 lba_limit = get_lba_capacity(id);
 
720
                                __u64 estimate = (lba_limit / 2048ULL) / 30ULL / 60;
710
721
                                timeout = 508 + 60;  /* spec says > 508 minutes */
711
 
                        else
712
 
                                timeout = (timeout * 2) + 5;  /* Add on a 5min margin */
 
722
                                if (timeout < estimate)
 
723
                                        timeout = estimate;
 
724
                        } else {
 
725
                                timeout = (timeout * 2) + 30;  /* Add on a 30min margin */
 
726
                        }
713
727
                }
714
728
        }
715
729
        if (!timeout)
716
730
                timeout = 2 * 60;  /* default: two hours */
717
 
        timeout *= 60; /* secs */
 
731
        timeout *= 60; /* convert minutes to seconds */
718
732
        return timeout;
719
733
}
720
734
 
738
752
        r->dphase       = TASKFILE_DPHASE_PIO_OUT;
739
753
        r->obytes       = 512;
740
754
        r->lob.command  = security_command;
 
755
        r->oflags.lob.nsect = 1;
 
756
        r->lob.nsect        = 1;
741
757
        data            = (__u8*)r->data;
742
758
        data[0]         = security_master & 0x01;
743
759
        memcpy(data+2, security_password, 32);
766
782
                                if (!id)
767
783
                                        exit(EIO);
768
784
                                revcode = id[92];
769
 
                                if (revcode == 0xffff)
 
785
                                if (revcode == 0xfffe)
770
786
                                        revcode = 0;
771
787
                                revcode += 1;
772
788
                                data[34] = revcode;
778
794
                        exit(EINVAL);
779
795
        }
780
796
        printf(" Issuing %s command, password=\"%s\", user=%s",
781
 
                description, security_password, data[0] ? "master" : "user");
 
797
                description, security_password, (data[0] & 1) ? "master" : "user");
782
798
        if (security_command == ATA_OP_SECURITY_SET_PASS)
783
799
                printf(", mode=%s", data[1] ? "max" : "high");
784
800
        printf("\n");
911
927
        unsigned int i;
912
928
 
913
929
        for (i = 0; i < (count*256/8); ++i) {
914
 
                printf("%04x %04x %04x %04x %04x %04x %04x %04x\n", w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
 
930
#if 0
 
931
                printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
 
932
                        w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
915
933
                w += 8;
 
934
#else
 
935
                int word;
 
936
                for (word = 0; word < 8; ++word) {
 
937
                        printf("%04x", le16toh(w[0]));
 
938
                        ++w;
 
939
                        putchar(word == 7 ? '\n' : ' ');
 
940
                }
 
941
#endif
916
942
        }
917
943
}
918
944
 
949
975
        exit(EINVAL);
950
976
}
951
977
 
952
 
#if 0
953
 
static int do_wdidle3 (int fd, const char *devname)
954
 
{
955
 
        struct ata_tf tf;
956
 
        int err = 0;
957
 
        const unsigned char vu_op = 0x8a;
958
 
 
959
 
        abort_if_not_full_device(fd, 0, devname, NULL);
960
 
        confirm_please_destroy_my_drive("--wdidle3", "This is not fully implemented yet, and could destroy the drive and/or all data on it.");
961
 
        printf("attempting to tweak Western Digital \"idle-3\" parameters\n");
962
 
        fflush(stdout);
963
 
 
964
 
  {
965
 
    unsigned char bits;
966
 
    for (bits = 0; bits <= 0x1f; ++bits) {
967
 
        tf_init(&tf, vu_op, 0, 0);
968
 
        tf.lob.feat  = 'W';
969
 
        tf.lob.nsect = 'D';
970
 
        tf.lob.lbal  = 'C';
971
 
        tf.lob.lbam  = 0x00;
972
 
        tf.lob.lbah  = 0x00;
973
 
        tf.dev       = 0xa0 | (tf.dev & 0xb0) | (bits & 0xf);
974
 
        if (bits >= 0x10)
975
 
                tf.dev |= 0x40;
976
 
 
977
 
        /* This probably wants to transfer data, but.. ???? */
978
 
        if (sg16(fd, SG_WRITE, SG_PIO, &tf, NULL, 0, 5 /* seconds */)) {
979
 
                err = errno;
980
 
                perror("FAILED");
981
 
        } else {
982
 
                printf("succeeded\n");
983
 
        }
984
 
    }
985
 
  }
986
 
        return err;
987
 
}
988
 
#endif
989
 
 
990
978
static __u16 *get_dco_identify_data (int fd, int quietly)
991
979
{
992
980
        static __u8 args[4+512];
1016
1004
        __u64 max = 0;
1017
1005
        struct hdio_taskfile r;
1018
1006
 
 
1007
        get_identify_data(fd);
 
1008
        if (!id)
 
1009
                exit(EIO);
1019
1010
        memset(&r, 0, sizeof(r));
1020
1011
        r.cmd_req = TASKFILE_CMD_REQ_NODATA;
1021
1012
        r.dphase  = TASKFILE_DPHASE_NONE;
1027
1018
        r.iflags.lob.lbah     = 1;
1028
1019
        r.lob.dev = 0x40;
1029
1020
 
1030
 
        get_identify_data(fd);
1031
 
        if (!id)
1032
 
                exit(EIO);
1033
1021
        if (((id[83] & 0xc400) == 0x4400) && (id[86] & 0x0400)) {
1034
1022
                r.iflags.hob.lbal  = 1;
1035
1023
                r.iflags.hob.lbam  = 1;
1466
1454
        " -H   Read temperature from drive (Hitachi only)\n"
1467
1455
        " -i   Display drive identification\n"
1468
1456
        " -I   Detailed/current information directly from drive\n"
 
1457
        " -J   Get/set Western DIgital \"Idle3\" timeout for a WDC \"Green\" drive (DANGEROUS)\n"
1469
1458
        " -k   Get/set keep_settings_over_reset flag (0/1)\n"
1470
1459
        " -K   Set drive keep_features_over_reset flag (0/1)\n"
1471
1460
        " -L   Set drive doorlock (0/1) (removable harddisks only)\n"
1478
1467
        " -q   Change next setting quietly\n"
1479
1468
        " -Q   Get/set DMA queue_depth (if supported)\n"
1480
1469
        " -r   Get/set device readonly flag (DANGEROUS to set)\n"
1481
 
        " -R   Obsolete\n"
 
1470
        " -R   Get/set device write-read-verify flag\n"
1482
1471
        " -s   Set power-up in standby flag (0/1) (DANGEROUS)\n"
1483
1472
        " -S   Set standby (spindown) timeout\n"
1484
1473
        " -t   Perform device read timings\n"
1518
1507
        " --trim-sector-ranges        Tell SSD firmware to discard unneeded data sectors: lba:count ..\n"
1519
1508
        " --trim-sector-ranges-stdin  Same as above, but reads lba:count pairs from stdin\n"
1520
1509
        " --verbose         Display extra diagnostics from some commands\n"
1521
 
        //" --wdidle3         Issue the Western Digitial \"Idle3\" command (EXTREMELY DANGEROUS)\n"
1522
1510
        " --write-sector    Repair/overwrite a (possibly bad) sector directly on the media (VERY DANGEROUS)\n"
1523
1511
        "\n");
1524
1512
        exit(rc);
1544
1532
        " --security-erase    PASSWD  Erase a (locked) drive.\n"
1545
1533
        " --security-erase-enhanced PASSWD   Enhanced-erase a (locked) drive.\n"
1546
1534
        "\n"
1547
 
        " The above four commands may optionally be preceeded by these options:\n"
 
1535
        " The above four commands may optionally be preceded by these options:\n"
1548
1536
        " --security-mode  LEVEL      Use LEVEL to select security level:\n"
1549
1537
        "                                  h   high security (default).\n"
1550
1538
        "                                  m   maximum security.\n"
1578
1566
                exit(do_trim_from_stdin(fd, devname));
1579
1567
        }
1580
1568
 
1581
 
        //if (set_wdidle3)
1582
 
        //      do_wdidle3(fd, devname);
 
1569
        if (set_wdidle3) {
 
1570
                unsigned char timeout = wdidle3_msecs_to_timeout(wdidle3);
 
1571
                confirm_please_destroy_my_drive("-J", "This implementation is not as thorough as the official WDIDLE3.EXE. Use at your own risk!");
 
1572
                if (get_wdidle3) {
 
1573
                        printf(" setting wdidle3 to ");
 
1574
                        wdidle3_print_timeout(timeout);
 
1575
                        putchar('\n');
 
1576
                }
 
1577
                err = wdidle3_set_timeout(fd, timeout);
 
1578
        }
1583
1579
        if (set_fsreadahead) {
1584
1580
                if (get_fsreadahead)
1585
1581
                        printf(" setting fs readahead to %d\n", fsreadahead);
1829
1825
                        perror(" HDIO_DRIVE_CMD:ACOUSTIC failed");
1830
1826
                }
1831
1827
        }
 
1828
        if (set_write_read_verify) {
 
1829
                __u8 args[4];
 
1830
                if (get_write_read_verify)
 
1831
                        printf(" setting write-read-verify to %d\n", write_read_verify);
 
1832
                args[0] = ATA_OP_SETFEATURES;
 
1833
                args[1] = write_read_verify;
 
1834
                args[2] = write_read_verify ? 0x0b : 0x8b;
 
1835
                args[3] = 0;
 
1836
                if (do_drive_cmd(fd, args, 0)) {
 
1837
                        err = errno;
 
1838
                        perror(" HDIO_DRIVE_CMD:WRV failed");
 
1839
                }
 
1840
        }
1832
1841
        if (set_wcache) {
1833
1842
                if (get_wcache) {
1834
1843
                        printf(" setting drive write-caching to %d", wcache);
1847
1856
                if (!wcache)
1848
1857
                        err = flush_wcache(fd);
1849
1858
        }
 
1859
        if (set_standby) {
 
1860
                __u8 args[4] = {ATA_OP_SETIDLE,standby,0,0};
 
1861
                if (get_standby) {
 
1862
                        printf(" setting standby to %u", standby);
 
1863
                        interpret_standby();
 
1864
                }
 
1865
                if (do_drive_cmd(fd, args, 0)) {
 
1866
                        err = errno;
 
1867
                        perror(" HDIO_DRIVE_CMD(setidle) failed");
 
1868
                }
 
1869
        }
1850
1870
        if (set_standbynow) {
1851
1871
                __u8 args1[4] = {ATA_OP_STANDBYNOW1,0,0,0};
1852
1872
                __u8 args2[4] = {ATA_OP_STANDBYNOW2,0,0,0};
1923
1943
                        perror(" HDIO_DRIVE_CMD(seagatepwrsave) failed");
1924
1944
                }
1925
1945
        }
1926
 
        if (set_standby) {
1927
 
                __u8 args[4] = {ATA_OP_SETIDLE,standby,0,0};
1928
 
                if (get_standby) {
1929
 
                        printf(" setting standby to %u", standby);
1930
 
                        interpret_standby();
1931
 
                }
1932
 
                if (do_drive_cmd(fd, args, 0)) {
1933
 
                        err = errno;
1934
 
                        perror(" HDIO_DRIVE_CMD(setidle) failed");
1935
 
                }
1936
 
        }
1937
1946
        if (set_busstate) {
1938
1947
                if (get_busstate)
1939
1948
                        printf(" setting bus state to %d (%s)\n", busstate, busstate_str(busstate));
2149
2158
                                printf("%lld\n", start_lba);
2150
2159
                }
2151
2160
        }
 
2161
        if (get_wdidle3) {
 
2162
                unsigned char timeout = 0;
 
2163
                err = wdidle3_get_timeout(fd, &timeout);
 
2164
                if (!err) {
 
2165
                        printf(" wdidle3      = ");
 
2166
                        wdidle3_print_timeout(timeout);
 
2167
                        putchar('\n');
 
2168
                }
 
2169
        }
2152
2170
        if (get_powermode) {
2153
2171
                __u8 args[4] = {ATA_OP_CHECKPOWERMODE1,0,0,0};
2154
2172
                const char *state = "unknown";
2242
2260
                                printf(" acoustic      = not supported\n");
2243
2261
                }
2244
2262
        }
 
2263
        if (get_write_read_verify) {
 
2264
                get_identify_data(fd);
 
2265
                if (id) {
 
2266
                                int supported = id[119] & 0x2;
 
2267
                                if (supported)
 
2268
                                        printf(" write-read-verify = %2u\n", id[120] & 0x2);
 
2269
                                else
 
2270
                                        printf(" write-read-verify = not supported\n");
 
2271
                }
 
2272
        }
2245
2273
        if (get_busstate) {
2246
2274
                if (ioctl(fd, HDIO_GET_BUSSTATE, &parm)) {
2247
2275
                        err = errno;
2670
2698
        } else if (0 == strcasecmp(name, "read-sector")) {
2671
2699
                read_sector = 1;
2672
2700
                get_u64_parm(0, 0, NULL, &read_sector_addr, 0, lba_limit, name, lba_emsg);
2673
 
        //} else if (0 == strcasecmp(name, "wdidle3")) {
2674
 
        //      set_wdidle3 = 1;
2675
2701
        } else if (0 == strcasecmp(name, "Istdout")) {
2676
2702
                do_IDentity = 2;
2677
2703
        } else if (0 == strcasecmp(name, "security-mode")) {
2759
2785
                                case     SET_FLAG('H',hitachi_temp);
2760
2786
                                case      DO_FLAG('i',do_identity);
2761
2787
                                case      DO_FLAG('I',do_IDentity);
 
2788
                                case GET_SET_PARM('J',"WDC-idle3-timeout",wdidle3,0,300);
2762
2789
                                case GET_SET_PARM('k',"kernel-keep-settings",keep,0,1);
2763
2790
                                case     SET_PARM('K',"drive-keep-settings",dkeep,0,1);
2764
2791
                                case     SET_PARM('L',"door-lock",doorlock,0,1);
2772
2799
                                case     SET_PARM('s',"powerup-in-standby",powerup_in_standby,0,1);
2773
2800
                                case     SET_PARM('S',"standby-interval",standby,0,255);
2774
2801
                                case GET_SET_PARM('r',"read-only",readonly,0,1);
 
2802
                                case GET_SET_PARM('R',"write-read-verify",write_read_verify,0,3);
2775
2803
                                case      DO_FLAG('t',do_timings);
2776
2804
                                case      DO_FLAG('T',do_ctimings);
2777
2805
                                case GET_SET_PARM('u',"unmask-irq",unmask,0,1);