• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/hdparm-9.43/

Lines Matching defs:*

0 #include <unistd.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <sys/syscall.h>
8 #include <linux/types.h>
9 #include <linux/fs.h>
11 #include "sgio.h"
12 #include "hdparm.h"
14 extern int verbose; /* hdparm.c */
17 * The Western Digital (WD) "Green" drive IDLE3 timeout value is 8-bits.
18 * Earlier models used a strict value from 8.0 to 25.5 seconds (0x50 to 0xff).
19 * Later models use 8.0 to 12.7 secs (0x50 to 0x7f), and 30 to 300 secs (0x81 to 0x8a).
20 * Other values are undefined, but have been observed on some drives.
22 * Older drives (from WDIDLE3.EXE documentation):
23 * 0x00 timer disabled.
24 * 0x50-0xff timeout in tenths of a second, from 8.0 to 25.5 seconds.
27 * Some drives (found by observation):
28 * 0x01-0x50 timeout in seconds, from 1 to 30 seconds (?).
30 * Newer drives (from WDIDLE3.EXE documentation):
31 * 0x00 timer disabled.
32 * 0x01-0x49 not permitted by WDIDLE3.EXE; reports as 0.1 to 7.9 seconds.
33 * 0x50-0x7f timeout in tenths of a second, from 8.0 to 12.7 seconds.
34 * 0x80 not permitted by WDIDLE3.EXE; reports as 12.8 seconds.
35 * 0x81-0x8a timeout in 30s of seconds, from 30 to 300 seconds.
36 * 0x90-0xff not permitted; reports as 330 to 3810 seconds.
38 * A WD whitepaper identified some models/versions of drives with the "older" firmware,
39 * but no comprehensive list exists. Models with firmware 02.01B01 are "older",
40 * and models with "02.01B02" are "newer".
42 * The real WDIDLE3 utility determines the correct value ranges
43 * by interogating the drive somehow, or perhaps based on the reported firmware version.
45 * WDIDLE3.EXE also writes some scary looking full 512-byte sequences to the drives
46 * in addition to what we do here.
48 * So this (hdparm) method may be somewhat risky, since it doesn't do everything WD does.
51 enum {
52 WDC_VSC_DISABLED = 'D',
53 WDC_VSC_ENABLED = 'E',
54 WDC_IDLE3_READ = 1,
55 WDC_IDLE3_WRITE = 2,
56 WDC_OP_TIMEOUT_SECS = 12,
57 WDC_TIMEOUT_THRESHOLD = 128,
60 static int wdidle3_issue (int fd, int rw, struct ata_tf *tf, void *data, const char *msg)
62 int ret = sg16(fd, rw, SG_PIO, tf, data, data ? 512 : 0, WDC_OP_TIMEOUT_SECS);
63 if (ret != 0) {
64 ret = errno;
65 perror(msg);
67 return ret;
71 * Note: when WD vendor-specific-commands (vsc) are enabled,
72 * the ATA_OP_SMART command is "enhanced" to support additional
73 * functions to read/write specific data "registers" from the firmware.
74 * This may (or not) also cause regular SMART commands to fail (?).
76 static int wdidle3_vsc_enable_disable (int fd, int setting)
78 struct ata_tf tf;
79 unsigned long long vendor_WD0 = ('W' << 16) | ('D' << 8) | 0;
81 tf_init(&tf, ATA_OP_VENDOR_SPECIFIC_0x80, vendor_WD0, 0);
82 tf.lob.feat = setting;
83 tf.dev = 0xa0;
84 return wdidle3_issue(fd, SG_WRITE, &tf, NULL, __func__);
88 * This sends a key (password? I2C address?) to the drive
89 * in preparation for a data_in or data_out command.
91 static int wdidle3_vsc_send_key (int fd, int rw)
93 char data[512];
94 struct ata_tf tf;
96 memset(data, 0, sizeof(data));
97 tf_init(&tf, ATA_OP_SMART, 0xc24fbe, 1);
98 tf.lob.feat = 0xd6;
99 tf.dev = 0xa0;
100 data[ 0] = 0x2a;
101 data[ 2] = rw;
102 data[ 4] = 0x02;
103 data[ 6] = 0x0d;
104 data[ 8] = 0x16;
105 data[10] = 0x01;
106 return wdidle3_issue(fd, SG_WRITE, &tf, data, __func__);
110 * This reads a data value from the drive.
112 static int wdidle3_data_in (int fd, unsigned char *timeout)
114 char data[512];
115 int ret;
116 struct ata_tf tf;
118 memset(data, 0, sizeof(data));
119 tf_init(&tf, ATA_OP_SMART, 0xc24fbf, 1);
120 tf.lob.feat = 0xd5;
121 tf.dev = 0xa0;
122 ret = wdidle3_issue(fd, SG_READ, &tf, data, __func__);
123 if (!ret)
124 *timeout = data[0];
125 return ret;
129 * This writes a data value to the drive.
131 static int wdidle3_vsc_data_out (int fd, unsigned char timeout)
133 char data[512];
134 struct ata_tf tf;
136 memset(data, 0, sizeof(data));
137 tf_init(&tf, ATA_OP_SMART, 0xc24fbf, 1);
138 tf.lob.feat = 0xd6;
139 tf.dev = 0xa0;
140 data[0] = timeout;
141 return wdidle3_issue(fd, SG_WRITE, &tf, data, __func__);
144 int wdidle3_set_timeout (int fd, unsigned char timeout)
146 int ret, ret2;
148 ret = wdidle3_vsc_enable_disable(fd, WDC_VSC_ENABLED);
149 if (!ret) {
150 ret = wdidle3_vsc_send_key(fd, WDC_IDLE3_WRITE);
151 if (!ret)
152 ret = wdidle3_vsc_data_out(fd, timeout);
153 ret2 = wdidle3_vsc_enable_disable(fd, WDC_VSC_DISABLED);
154 if (!ret)
155 ret = ret2;
157 return ret;
160 int wdidle3_get_timeout (int fd, unsigned char *timeout)
162 int ret, ret2;
164 ret = wdidle3_vsc_enable_disable(fd, WDC_VSC_ENABLED);
165 if (!ret) {
166 ret = wdidle3_vsc_send_key(fd, WDC_IDLE3_READ);
167 if (!ret)
168 ret = wdidle3_data_in(fd, timeout);
169 ret2 = wdidle3_vsc_enable_disable(fd, WDC_VSC_DISABLED);
170 if (!ret)
171 ret = ret2;
173 return ret;
176 unsigned char wdidle3_msecs_to_timeout (unsigned int secs)
178 unsigned char timeout;
180 if (secs == 0)
181 timeout = 0; /* disabled */
182 else if (secs < 8)
183 timeout = 80; /* 8.0 seconds minimum */
184 else if (secs <= (WDC_TIMEOUT_THRESHOLD / 10))
185 timeout = secs * 10; /* 8.0 to 12.7 seconds */
186 else {
187 secs += 29; /* round up to next multiple of 30 */
188 if (secs > 300)
189 secs = 300; /* max timeout is 300 secs */
190 timeout = (secs / 30) + WDC_TIMEOUT_THRESHOLD;
192 return timeout;
195 void wdidle3_print_timeout (unsigned char timeout)
197 if (verbose)
198 printf("[raw=0x%02x] ", timeout); //FIXME
199 if (timeout == 0)
200 printf("disabled");
201 else if (timeout < 0x50 || timeout == WDC_TIMEOUT_THRESHOLD)
202 printf("%u ??", timeout);
203 else if (timeout < WDC_TIMEOUT_THRESHOLD)
204 printf("%u.%u secs", timeout / 10, timeout % 10);
205 else {
206 if (timeout > (WDC_TIMEOUT_THRESHOLD + 10))
207 printf("%u ??", timeout);
208 else
209 printf("%u secs", (timeout - WDC_TIMEOUT_THRESHOLD) * 30);
210 printf(" (or %u.%u secs for older drives)", timeout / 10, timeout % 10);