Mon Mar 16 12:52:32 2009 UTC ()
fix sign-compare issues


(lukem)
diff -r1.52 -r1.53 src/sbin/atactl/atactl.c

cvs diff -r1.52 -r1.53 src/sbin/atactl/atactl.c (switch to unified diff)

--- src/sbin/atactl/atactl.c 2008/08/25 00:45:56 1.52
+++ src/sbin/atactl/atactl.c 2009/03/16 12:52:32 1.53
@@ -1,1317 +1,1317 @@ @@ -1,1317 +1,1317 @@
1/* $NetBSD: atactl.c,v 1.52 2008/08/25 00:45:56 dholland Exp $ */ 1/* $NetBSD: atactl.c,v 1.53 2009/03/16 12:52:32 lukem Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Ken Hornstein. 8 * by Ken Hornstein.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * atactl(8) - a program to control ATA devices. 33 * atactl(8) - a program to control ATA devices.
34 */ 34 */
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36 36
37#ifndef lint 37#ifndef lint
38__RCSID("$NetBSD: atactl.c,v 1.52 2008/08/25 00:45:56 dholland Exp $"); 38__RCSID("$NetBSD: atactl.c,v 1.53 2009/03/16 12:52:32 lukem Exp $");
39#endif 39#endif
40 40
41 41
42#include <sys/param.h> 42#include <sys/param.h>
43#include <sys/ioctl.h> 43#include <sys/ioctl.h>
44#include <err.h> 44#include <err.h>
45#include <errno.h> 45#include <errno.h>
46#include <fcntl.h> 46#include <fcntl.h>
47#include <stdio.h> 47#include <stdio.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <string.h> 49#include <string.h>
50#include <unistd.h> 50#include <unistd.h>
51#include <util.h> 51#include <util.h>
52 52
53#include <dev/ata/atareg.h> 53#include <dev/ata/atareg.h>
54#include <sys/ataio.h> 54#include <sys/ataio.h>
55 55
56struct ata_smart_error { 56struct ata_smart_error {
57 struct { 57 struct {
58 u_int8_t device_control; 58 u_int8_t device_control;
59 u_int8_t features; 59 u_int8_t features;
60 u_int8_t sector_count; 60 u_int8_t sector_count;
61 u_int8_t sector_number; 61 u_int8_t sector_number;
62 u_int8_t cylinder_low; 62 u_int8_t cylinder_low;
63 u_int8_t cylinder_high; 63 u_int8_t cylinder_high;
64 u_int8_t device_head; 64 u_int8_t device_head;
65 u_int8_t command; 65 u_int8_t command;
66 u_int8_t timestamp[4]; 66 u_int8_t timestamp[4];
67 } command[5]; 67 } command[5];
68 struct { 68 struct {
69 u_int8_t reserved; 69 u_int8_t reserved;
70 u_int8_t error; 70 u_int8_t error;
71 u_int8_t sector_count; 71 u_int8_t sector_count;
72 u_int8_t sector_number; 72 u_int8_t sector_number;
73 u_int8_t cylinder_low; 73 u_int8_t cylinder_low;
74 u_int8_t cylinder_high; 74 u_int8_t cylinder_high;
75 u_int8_t device_head; 75 u_int8_t device_head;
76 u_int8_t status; 76 u_int8_t status;
77 u_int8_t extended_error[19]; 77 u_int8_t extended_error[19];
78 u_int8_t state; 78 u_int8_t state;
79 u_int8_t lifetime[2]; 79 u_int8_t lifetime[2];
80 } error_data; 80 } error_data;
81} __packed; 81} __packed;
82 82
83struct ata_smart_errorlog { 83struct ata_smart_errorlog {
84 u_int8_t data_structure_revision; 84 u_int8_t data_structure_revision;
85 u_int8_t mostrecenterror; 85 u_int8_t mostrecenterror;
86 struct ata_smart_error log_entries[5]; 86 struct ata_smart_error log_entries[5];
87 u_int16_t device_error_count; 87 u_int16_t device_error_count;
88 u_int8_t reserved[57]; 88 u_int8_t reserved[57];
89 u_int8_t checksum; 89 u_int8_t checksum;
90} __packed; 90} __packed;
91 91
92struct command { 92struct command {
93 const char *cmd_name; 93 const char *cmd_name;
94 const char *arg_names; 94 const char *arg_names;
95 void (*cmd_func)(int, char *[]); 95 void (*cmd_func)(int, char *[]);
96}; 96};
97 97
98struct bitinfo { 98struct bitinfo {
99 u_int bitmask; 99 u_int bitmask;
100 const char *string; 100 const char *string;
101}; 101};
102 102
103void usage(void); 103void usage(void);
104void ata_command(struct atareq *); 104void ata_command(struct atareq *);
105void print_bitinfo(const char *, const char *, u_int, struct bitinfo *); 105void print_bitinfo(const char *, const char *, u_int, struct bitinfo *);
106void print_bitinfo2(const char *, const char *, u_int, u_int, struct bitinfo *); 106void print_bitinfo2(const char *, const char *, u_int, u_int, struct bitinfo *);
107void print_smart_status(void *, void *); 107void print_smart_status(void *, void *);
108void print_error_entry(int, struct ata_smart_error *); 108void print_error_entry(int, struct ata_smart_error *);
109void print_selftest_entry(int, struct ata_smart_selftest *); 109void print_selftest_entry(int, struct ata_smart_selftest *);
110 110
111void print_error(void *); 111void print_error(void *);
112void print_selftest(void *); 112void print_selftest(void *);
113 113
114struct ataparams *getataparams(void); 114struct ataparams *getataparams(void);
115 115
116int is_smart(void); 116int is_smart(void);
117 117
118int fd; /* file descriptor for device */ 118int fd; /* file descriptor for device */
119const char *dvname; /* device name */ 119const char *dvname; /* device name */
120char dvname_store[MAXPATHLEN]; /* for opendisk(3) */ 120char dvname_store[MAXPATHLEN]; /* for opendisk(3) */
121const char *cmdname; /* command user issued */ 121const char *cmdname; /* command user issued */
122const char *argnames; /* helpstring: expected arguments */ 122const char *argnames; /* helpstring: expected arguments */
123 123
124void device_identify(int, char *[]); 124void device_identify(int, char *[]);
125void device_setidle(int, char *[]); 125void device_setidle(int, char *[]);
126void device_idle(int, char *[]); 126void device_idle(int, char *[]);
127void device_apm(int, char *[]); 127void device_apm(int, char *[]);
128void device_checkpower(int, char *[]); 128void device_checkpower(int, char *[]);
129void device_smart(int, char *[]); 129void device_smart(int, char *[]);
130void device_security(int, char *[]); 130void device_security(int, char *[]);
131 131
132void device_smart_temp(struct ata_smart_attr *, uint64_t); 132void device_smart_temp(struct ata_smart_attr *, uint64_t);
133 133
134struct command device_commands[] = { 134struct command device_commands[] = {
135 { "identify", "", device_identify }, 135 { "identify", "", device_identify },
136 { "setidle", "idle-timer", device_setidle }, 136 { "setidle", "idle-timer", device_setidle },
137 { "apm", "disable|set #", device_apm }, 137 { "apm", "disable|set #", device_apm },
138 { "setstandby", "standby-timer", device_setidle }, 138 { "setstandby", "standby-timer", device_setidle },
139 { "idle", "", device_idle }, 139 { "idle", "", device_idle },
140 { "standby", "", device_idle }, 140 { "standby", "", device_idle },
141 { "sleep", "", device_idle }, 141 { "sleep", "", device_idle },
142 { "checkpower", "", device_checkpower }, 142 { "checkpower", "", device_checkpower },
143 { "smart", "enable|disable|status|offline #|error-log|selftest-log", 143 { "smart", "enable|disable|status|offline #|error-log|selftest-log",
144 device_smart }, 144 device_smart },
145 { "security", "freeze|status", device_security }, 145 { "security", "freeze|status", device_security },
146 { NULL, NULL, NULL }, 146 { NULL, NULL, NULL },
147}; 147};
148 148
149void bus_reset(int, char *[]); 149void bus_reset(int, char *[]);
150 150
151struct command bus_commands[] = { 151struct command bus_commands[] = {
152 { "reset", "", bus_reset }, 152 { "reset", "", bus_reset },
153 { NULL, NULL, NULL }, 153 { NULL, NULL, NULL },
154}; 154};
155 155
156/* 156/*
157 * Tables containing bitmasks used for error reporting and 157 * Tables containing bitmasks used for error reporting and
158 * device identification. 158 * device identification.
159 */ 159 */
160 160
161struct bitinfo ata_caps[] = { 161struct bitinfo ata_caps[] = {
162 { WDC_CAP_DMA, "DMA" }, 162 { WDC_CAP_DMA, "DMA" },
163 { WDC_CAP_LBA, "LBA" }, 163 { WDC_CAP_LBA, "LBA" },
164 { ATA_CAP_STBY, "ATA standby timer values" }, 164 { ATA_CAP_STBY, "ATA standby timer values" },
165 { WDC_CAP_IORDY, "IORDY operation" }, 165 { WDC_CAP_IORDY, "IORDY operation" },
166 { WDC_CAP_IORDY_DSBL, "IORDY disabling" }, 166 { WDC_CAP_IORDY_DSBL, "IORDY disabling" },
167 { 0, NULL }, 167 { 0, NULL },
168}; 168};
169 169
170struct bitinfo ata_vers[] = { 170struct bitinfo ata_vers[] = {
171 { WDC_VER_ATA1, "ATA-1" }, 171 { WDC_VER_ATA1, "ATA-1" },
172 { WDC_VER_ATA2, "ATA-2" }, 172 { WDC_VER_ATA2, "ATA-2" },
173 { WDC_VER_ATA3, "ATA-3" }, 173 { WDC_VER_ATA3, "ATA-3" },
174 { WDC_VER_ATA4, "ATA-4" }, 174 { WDC_VER_ATA4, "ATA-4" },
175 { WDC_VER_ATA5, "ATA-5" }, 175 { WDC_VER_ATA5, "ATA-5" },
176 { WDC_VER_ATA6, "ATA-6" }, 176 { WDC_VER_ATA6, "ATA-6" },
177 { WDC_VER_ATA7, "ATA-7" }, 177 { WDC_VER_ATA7, "ATA-7" },
178 { 0, NULL }, 178 { 0, NULL },
179}; 179};
180 180
181struct bitinfo ata_cmd_set1[] = { 181struct bitinfo ata_cmd_set1[] = {
182 { WDC_CMD1_NOP, "NOP command" }, 182 { WDC_CMD1_NOP, "NOP command" },
183 { WDC_CMD1_RB, "READ BUFFER command" }, 183 { WDC_CMD1_RB, "READ BUFFER command" },
184 { WDC_CMD1_WB, "WRITE BUFFER command" }, 184 { WDC_CMD1_WB, "WRITE BUFFER command" },
185 { WDC_CMD1_HPA, "Host Protected Area feature set" }, 185 { WDC_CMD1_HPA, "Host Protected Area feature set" },
186 { WDC_CMD1_DVRST, "DEVICE RESET command" }, 186 { WDC_CMD1_DVRST, "DEVICE RESET command" },
187 { WDC_CMD1_SRV, "SERVICE interrupt" }, 187 { WDC_CMD1_SRV, "SERVICE interrupt" },
188 { WDC_CMD1_RLSE, "release interrupt" }, 188 { WDC_CMD1_RLSE, "release interrupt" },
189 { WDC_CMD1_AHEAD, "look-ahead" }, 189 { WDC_CMD1_AHEAD, "look-ahead" },
190 { WDC_CMD1_CACHE, "write cache" }, 190 { WDC_CMD1_CACHE, "write cache" },
191 { WDC_CMD1_PKT, "PACKET command feature set" }, 191 { WDC_CMD1_PKT, "PACKET command feature set" },
192 { WDC_CMD1_PM, "Power Management feature set" }, 192 { WDC_CMD1_PM, "Power Management feature set" },
193 { WDC_CMD1_REMOV, "Removable Media feature set" }, 193 { WDC_CMD1_REMOV, "Removable Media feature set" },
194 { WDC_CMD1_SEC, "Security Mode feature set" }, 194 { WDC_CMD1_SEC, "Security Mode feature set" },
195 { WDC_CMD1_SMART, "SMART feature set" }, 195 { WDC_CMD1_SMART, "SMART feature set" },
196 { 0, NULL }, 196 { 0, NULL },
197}; 197};
198 198
199struct bitinfo ata_cmd_set2[] = { 199struct bitinfo ata_cmd_set2[] = {
200 { ATA_CMD2_FCE, "FLUSH CACHE EXT command" }, 200 { ATA_CMD2_FCE, "FLUSH CACHE EXT command" },
201 { WDC_CMD2_FC, "FLUSH CACHE command" }, 201 { WDC_CMD2_FC, "FLUSH CACHE command" },
202 { WDC_CMD2_DCO, "Device Configuration Overlay feature set" }, 202 { WDC_CMD2_DCO, "Device Configuration Overlay feature set" },
203 { ATA_CMD2_LBA48, "48-bit Address feature set" }, 203 { ATA_CMD2_LBA48, "48-bit Address feature set" },
204 { WDC_CMD2_AAM, "Automatic Acoustic Management feature set" }, 204 { WDC_CMD2_AAM, "Automatic Acoustic Management feature set" },
205 { WDC_CMD2_SM, "SET MAX security extension" }, 205 { WDC_CMD2_SM, "SET MAX security extension" },
206 { WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" }, 206 { WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" },
207 { WDC_CMD2_PUIS, "Power-Up In Standby feature set" }, 207 { WDC_CMD2_PUIS, "Power-Up In Standby feature set" },
208 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" }, 208 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
209 { ATA_CMD2_APM, "Advanced Power Management feature set" }, 209 { ATA_CMD2_APM, "Advanced Power Management feature set" },
210 { ATA_CMD2_CFA, "CFA feature set" }, 210 { ATA_CMD2_CFA, "CFA feature set" },
211 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" }, 211 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
212 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" }, 212 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
213 { 0, NULL }, 213 { 0, NULL },
214}; 214};
215 215
216struct bitinfo ata_cmd_ext[] = { 216struct bitinfo ata_cmd_ext[] = {
217 { ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" }, 217 { ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" },
218 { ATA_CMDE_TL, "Time-limited Read/Write" }, 218 { ATA_CMDE_TL, "Time-limited Read/Write" },
219 { ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" }, 219 { ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" },
220 { ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" }, 220 { ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" },
221 { ATA_CMDE_WWN, "World Wide name" }, 221 { ATA_CMDE_WWN, "World Wide name" },
222 { ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" }, 222 { ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" },
223 { ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" }, 223 { ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" },
224 { ATA_CMDE_GPL, "General Purpose Logging feature set" }, 224 { ATA_CMDE_GPL, "General Purpose Logging feature set" },
225 { ATA_CMDE_STREAM, "Streaming feature set" }, 225 { ATA_CMDE_STREAM, "Streaming feature set" },
226 { ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" }, 226 { ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" },
227 { ATA_CMDE_MS, "Media serial number" }, 227 { ATA_CMDE_MS, "Media serial number" },
228 { ATA_CMDE_SST, "SMART self-test" }, 228 { ATA_CMDE_SST, "SMART self-test" },
229 { ATA_CMDE_SEL, "SMART error logging" }, 229 { ATA_CMDE_SEL, "SMART error logging" },
230 { 0, NULL }, 230 { 0, NULL },
231}; 231};
232 232
233struct bitinfo ata_sata_caps[] = { 233struct bitinfo ata_sata_caps[] = {
234 { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" }, 234 { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
235 { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" }, 235 { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
236 { SATA_NATIVE_CMDQ, "Native Command Queuing" }, 236 { SATA_NATIVE_CMDQ, "Native Command Queuing" },
237 { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" }, 237 { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
238 { SATA_PHY_EVNT_CNT, "PHY Event Counters" }, 238 { SATA_PHY_EVNT_CNT, "PHY Event Counters" },
239 { 0, NULL }, 239 { 0, NULL },
240}; 240};
241 241
242struct bitinfo ata_sata_feat[] = { 242struct bitinfo ata_sata_feat[] = {
243 { SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" }, 243 { SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" },
244 { SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" }, 244 { SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" },
245 { SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" }, 245 { SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" },
246 { SATA_IN_ORDER_DATA, "In-order Data Delivery" }, 246 { SATA_IN_ORDER_DATA, "In-order Data Delivery" },
247 { SATA_SW_STTNGS_PRS, "Software Settings Preservation" }, 247 { SATA_SW_STTNGS_PRS, "Software Settings Preservation" },
248 { 0, NULL }, 248 { 0, NULL },
249}; 249};
250 250
251static const struct { 251static const struct {
252 const int id; 252 const int id;
253 const char *name; 253 const char *name;
254 void (*special)(struct ata_smart_attr *, uint64_t); 254 void (*special)(struct ata_smart_attr *, uint64_t);
255} smart_attrs[] = { 255} smart_attrs[] = {
256 { 1, "Raw read error rate", NULL }, 256 { 1, "Raw read error rate", NULL },
257 { 2, "Throughput performance", NULL }, 257 { 2, "Throughput performance", NULL },
258 { 3, "Spin-up time", NULL }, 258 { 3, "Spin-up time", NULL },
259 { 4, "Start/stop count", NULL }, 259 { 4, "Start/stop count", NULL },
260 { 5, "Reallocated sector count", NULL }, 260 { 5, "Reallocated sector count", NULL },
261 { 6, "Read channel margin", NULL }, 261 { 6, "Read channel margin", NULL },
262 { 7, "Seek error rate", NULL }, 262 { 7, "Seek error rate", NULL },
263 { 8, "Seek time performance", NULL }, 263 { 8, "Seek time performance", NULL },
264 { 9, "Power-on hours count", NULL }, 264 { 9, "Power-on hours count", NULL },
265 { 10, "Spin retry count", NULL }, 265 { 10, "Spin retry count", NULL },
266 { 11, "Calibration retry count", NULL }, 266 { 11, "Calibration retry count", NULL },
267 { 12, "Device power cycle count", NULL }, 267 { 12, "Device power cycle count", NULL },
268 { 13, "Soft read error rate", NULL }, 268 { 13, "Soft read error rate", NULL },
269 { 189, "High Fly Writes", NULL }, 269 { 189, "High Fly Writes", NULL },
270 { 190, "Airflow Temperature", device_smart_temp }, 270 { 190, "Airflow Temperature", device_smart_temp },
271 { 191, "G-sense error rate", NULL }, 271 { 191, "G-sense error rate", NULL },
272 { 192, "Power-off retract count", NULL }, 272 { 192, "Power-off retract count", NULL },
273 { 193, "Load cycle count", NULL }, 273 { 193, "Load cycle count", NULL },
274 { 194, "Temperature", device_smart_temp}, 274 { 194, "Temperature", device_smart_temp},
275 { 195, "Hardware ECC Recovered", NULL }, 275 { 195, "Hardware ECC Recovered", NULL },
276 { 196, "Reallocated event count", NULL }, 276 { 196, "Reallocated event count", NULL },
277 { 197, "Current pending sector", NULL }, 277 { 197, "Current pending sector", NULL },
278 { 198, "Offline uncorrectable", NULL }, 278 { 198, "Offline uncorrectable", NULL },
279 { 199, "Ultra DMA CRC error count", NULL }, 279 { 199, "Ultra DMA CRC error count", NULL },
280 { 200, "Write error rate", NULL }, 280 { 200, "Write error rate", NULL },
281 { 201, "Soft read error rate", NULL }, 281 { 201, "Soft read error rate", NULL },
282 { 202, "Data address mark errors", NULL }, 282 { 202, "Data address mark errors", NULL },
283 { 203, "Run out cancel", NULL }, 283 { 203, "Run out cancel", NULL },
284 { 204, "Soft ECC correction", NULL }, 284 { 204, "Soft ECC correction", NULL },
285 { 205, "Thermal asperity check", NULL }, 285 { 205, "Thermal asperity check", NULL },
286 { 206, "Flying height", NULL }, 286 { 206, "Flying height", NULL },
287 { 207, "Spin high current", NULL }, 287 { 207, "Spin high current", NULL },
288 { 208, "Spin buzz", NULL }, 288 { 208, "Spin buzz", NULL },
289 { 209, "Offline seek performance", NULL }, 289 { 209, "Offline seek performance", NULL },
290 { 220, "Disk shift", NULL }, 290 { 220, "Disk shift", NULL },
291 { 221, "G-Sense error rate", NULL }, 291 { 221, "G-Sense error rate", NULL },
292 { 222, "Loaded hours", NULL }, 292 { 222, "Loaded hours", NULL },
293 { 223, "Load/unload retry count", NULL }, 293 { 223, "Load/unload retry count", NULL },
294 { 224, "Load friction", NULL }, 294 { 224, "Load friction", NULL },
295 { 225, "Load/unload cycle count", NULL }, 295 { 225, "Load/unload cycle count", NULL },
296 { 226, "Load-in time", NULL }, 296 { 226, "Load-in time", NULL },
297 { 227, "Torque amplification count", NULL }, 297 { 227, "Torque amplification count", NULL },
298 { 228, "Power-off retract count", NULL }, 298 { 228, "Power-off retract count", NULL },
299 { 230, "GMR head amplitude", NULL }, 299 { 230, "GMR head amplitude", NULL },
300 { 231, "Temperature", device_smart_temp }, 300 { 231, "Temperature", device_smart_temp },
301 { 240, "Head flying hours", NULL }, 301 { 240, "Head flying hours", NULL },
302 { 250, "Read error retry rate", NULL }, 302 { 250, "Read error retry rate", NULL },
303 { 0, "Unknown", NULL }, 303 { 0, "Unknown", NULL },
304}; 304};
305 305
306struct bitinfo ata_sec_st[] = { 306struct bitinfo ata_sec_st[] = {
307 { WDC_SEC_SUPP, "supported" }, 307 { WDC_SEC_SUPP, "supported" },
308 { WDC_SEC_EN, "enabled" }, 308 { WDC_SEC_EN, "enabled" },
309 { WDC_SEC_LOCKED, "locked" }, 309 { WDC_SEC_LOCKED, "locked" },
310 { WDC_SEC_FROZEN, "frozen" }, 310 { WDC_SEC_FROZEN, "frozen" },
311 { WDC_SEC_EXP, "expired" }, 311 { WDC_SEC_EXP, "expired" },
312 { WDC_SEC_ESE_SUPP, "enhanced erase support" }, 312 { WDC_SEC_ESE_SUPP, "enhanced erase support" },
313 { WDC_SEC_LEV_MAX, "maximum level" }, 313 { WDC_SEC_LEV_MAX, "maximum level" },
314 { 0, NULL }, 314 { 0, NULL },
315}; 315};
316 316
317int 317int
318main(int argc, char *argv[]) 318main(int argc, char *argv[])
319{ 319{
320 int i; 320 int i;
321 struct command *commands = NULL; 321 struct command *commands = NULL;
322 322
323 /* Must have at least: device command */ 323 /* Must have at least: device command */
324 if (argc < 3) 324 if (argc < 3)
325 usage(); 325 usage();
326 326
327 /* Skip program name, get and skip device name and command. */ 327 /* Skip program name, get and skip device name and command. */
328 dvname = argv[1]; 328 dvname = argv[1];
329 cmdname = argv[2]; 329 cmdname = argv[2];
330 argv += 3; 330 argv += 3;
331 argc -= 3; 331 argc -= 3;
332 332
333 /* 333 /*
334 * Open the device 334 * Open the device
335 */ 335 */
336 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0); 336 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0);
337 if (fd == -1) { 337 if (fd == -1) {
338 if (errno == ENOENT) { 338 if (errno == ENOENT) {
339 /* 339 /*
340 * Device doesn't exist. Probably trying to open 340 * Device doesn't exist. Probably trying to open
341 * a device which doesn't use disk semantics for 341 * a device which doesn't use disk semantics for
342 * device name. Try again, specifying "cooked", 342 * device name. Try again, specifying "cooked",
343 * which leaves off the "r" in front of the device's 343 * which leaves off the "r" in front of the device's
344 * name. 344 * name.
345 */ 345 */
346 fd = opendisk(dvname, O_RDWR, dvname_store, 346 fd = opendisk(dvname, O_RDWR, dvname_store,
347 sizeof(dvname_store), 1); 347 sizeof(dvname_store), 1);
348 if (fd == -1) 348 if (fd == -1)
349 err(1, "%s", dvname); 349 err(1, "%s", dvname);
350 } else 350 } else
351 err(1, "%s", dvname); 351 err(1, "%s", dvname);
352 } 352 }
353 353
354 /* 354 /*
355 * Point the dvname at the actual device name that opendisk() opened. 355 * Point the dvname at the actual device name that opendisk() opened.
356 */ 356 */
357 dvname = dvname_store; 357 dvname = dvname_store;
358 358
359 /* Look up and call the command. */ 359 /* Look up and call the command. */
360 for (i = 0; device_commands[i].cmd_name != NULL; i++) { 360 for (i = 0; device_commands[i].cmd_name != NULL; i++) {
361 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) { 361 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
362 commands = &device_commands[i]; 362 commands = &device_commands[i];
363 break; 363 break;
364 } 364 }
365 } 365 }
366 if (commands == NULL) { 366 if (commands == NULL) {
367 for (i = 0; bus_commands[i].cmd_name != NULL; i++) { 367 for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
368 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) { 368 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
369 commands = &bus_commands[i]; 369 commands = &bus_commands[i];
370 break; 370 break;
371 } 371 }
372 } 372 }
373 } 373 }
374 if (commands == NULL) 374 if (commands == NULL)
375 errx(1, "unknown command: %s", cmdname); 375 errx(1, "unknown command: %s", cmdname);
376 376
377 argnames = commands->arg_names; 377 argnames = commands->arg_names;
378 378
379 (*commands->cmd_func)(argc, argv); 379 (*commands->cmd_func)(argc, argv);
380 exit(0); 380 exit(0);
381} 381}
382 382
383void 383void
384usage(void) 384usage(void)
385{ 385{
386 int i; 386 int i;
387 387
388 fprintf(stderr, "usage: %s device command [arg [...]]\n", 388 fprintf(stderr, "usage: %s device command [arg [...]]\n",
389 getprogname()); 389 getprogname());
390 390
391 fprintf(stderr, " Available device commands:\n"); 391 fprintf(stderr, " Available device commands:\n");
392 for (i=0; device_commands[i].cmd_name != NULL; i++) 392 for (i=0; device_commands[i].cmd_name != NULL; i++)
393 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name, 393 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
394 device_commands[i].arg_names); 394 device_commands[i].arg_names);
395 395
396 fprintf(stderr, " Available bus commands:\n"); 396 fprintf(stderr, " Available bus commands:\n");
397 for (i=0; bus_commands[i].cmd_name != NULL; i++) 397 for (i=0; bus_commands[i].cmd_name != NULL; i++)
398 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name, 398 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
399 bus_commands[i].arg_names); 399 bus_commands[i].arg_names);
400 400
401 exit(1); 401 exit(1);
402} 402}
403 403
404/* 404/*
405 * Wrapper that calls ATAIOCCOMMAND and checks for errors 405 * Wrapper that calls ATAIOCCOMMAND and checks for errors
406 */ 406 */
407 407
408void 408void
409ata_command(struct atareq *req) 409ata_command(struct atareq *req)
410{ 410{
411 int error; 411 int error;
412 412
413 error = ioctl(fd, ATAIOCCOMMAND, req); 413 error = ioctl(fd, ATAIOCCOMMAND, req);
414 414
415 if (error == -1) 415 if (error == -1)
416 err(1, "ATAIOCCOMMAND failed"); 416 err(1, "ATAIOCCOMMAND failed");
417 417
418 switch (req->retsts) { 418 switch (req->retsts) {
419 419
420 case ATACMD_OK: 420 case ATACMD_OK:
421 return; 421 return;
422 case ATACMD_TIMEOUT: 422 case ATACMD_TIMEOUT:
423 fprintf(stderr, "ATA command timed out\n"); 423 fprintf(stderr, "ATA command timed out\n");
424 exit(1); 424 exit(1);
425 case ATACMD_DF: 425 case ATACMD_DF:
426 fprintf(stderr, "ATA device returned a Device Fault\n"); 426 fprintf(stderr, "ATA device returned a Device Fault\n");
427 exit(1); 427 exit(1);
428 case ATACMD_ERROR: 428 case ATACMD_ERROR:
429 if (req->error & WDCE_ABRT) 429 if (req->error & WDCE_ABRT)
430 fprintf(stderr, "ATA device returned Aborted " 430 fprintf(stderr, "ATA device returned Aborted "
431 "Command\n"); 431 "Command\n");
432 else 432 else
433 fprintf(stderr, "ATA device returned error register " 433 fprintf(stderr, "ATA device returned error register "
434 "%0x\n", req->error); 434 "%0x\n", req->error);
435 exit(1); 435 exit(1);
436 default: 436 default:
437 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code " 437 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code "
438 "%d\n", req->retsts); 438 "%d\n", req->retsts);
439 exit(1); 439 exit(1);
440 } 440 }
441} 441}
442 442
443/* 443/*
444 * Print out strings associated with particular bitmasks 444 * Print out strings associated with particular bitmasks
445 */ 445 */
446 446
447void 447void
448print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo) 448print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo)
449{ 449{
450 450
451 for (; binfo->bitmask != 0; binfo++) 451 for (; binfo->bitmask != 0; binfo++)
452 if (bits & binfo->bitmask) 452 if (bits & binfo->bitmask)
453 printf("%s%s%s", bf, binfo->string, af); 453 printf("%s%s%s", bf, binfo->string, af);
454} 454}
455 455
456void 456void
457print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, struct bitinfo *binfo) 457print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, struct bitinfo *binfo)
458{ 458{
459 459
460 for (; binfo->bitmask != 0; binfo++) 460 for (; binfo->bitmask != 0; binfo++)
461 if (bits & binfo->bitmask) 461 if (bits & binfo->bitmask)
462 printf("%s%s (%s)%s", bf, binfo->string, 462 printf("%s%s (%s)%s", bf, binfo->string,
463 (enables & binfo->bitmask) ? "enabled" : "disabled", 463 (enables & binfo->bitmask) ? "enabled" : "disabled",
464 af); 464 af);
465} 465}
466 466
467 467
468/* 468/*
469 * Try to print SMART temperature field 469 * Try to print SMART temperature field
470 */ 470 */
471 471
472void 472void
473device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value) 473device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value)
474{ 474{
475 printf("%" PRIu8, attr->raw[0]); 475 printf("%" PRIu8, attr->raw[0]);
476 if (attr->raw[0] != raw_value) 476 if (attr->raw[0] != raw_value)
477 printf(" Lifetime max/min %" PRIu8 "/%" PRIu8,  477 printf(" Lifetime max/min %" PRIu8 "/%" PRIu8,
478 attr->raw[2], attr->raw[4]); 478 attr->raw[2], attr->raw[4]);
479} 479}
480 480
481 481
482/* 482/*
483 * Print out SMART attribute thresholds and values 483 * Print out SMART attribute thresholds and values
484 */ 484 */
485 485
486void 486void
487print_smart_status(void *vbuf, void *tbuf) 487print_smart_status(void *vbuf, void *tbuf)
488{ 488{
489 struct ata_smart_attributes *value_buf = vbuf; 489 struct ata_smart_attributes *value_buf = vbuf;
490 struct ata_smart_thresholds *threshold_buf = tbuf; 490 struct ata_smart_thresholds *threshold_buf = tbuf;
491 struct ata_smart_attr *attr; 491 struct ata_smart_attr *attr;
492 uint64_t raw_value; 492 uint64_t raw_value;
493 int flags; 493 int flags;
494 int i, j; 494 int i, j;
495 int aid; 495 int aid;
496 u_int8_t checksum; 496 u_int8_t checksum;
497 497
498 for (i = checksum = 0; i < 512; i++) 498 for (i = checksum = 0; i < 512; i++)
499 checksum += ((u_int8_t *) value_buf)[i]; 499 checksum += ((u_int8_t *) value_buf)[i];
500 if (checksum != 0) { 500 if (checksum != 0) {
501 fprintf(stderr, "SMART attribute values checksum error\n"); 501 fprintf(stderr, "SMART attribute values checksum error\n");
502 return; 502 return;
503 } 503 }
504 504
505 for (i = checksum = 0; i < 512; i++) 505 for (i = checksum = 0; i < 512; i++)
506 checksum += ((u_int8_t *) threshold_buf)[i]; 506 checksum += ((u_int8_t *) threshold_buf)[i];
507 if (checksum != 0) { 507 if (checksum != 0) {
508 fprintf(stderr, "SMART attribute thresholds checksum error\n"); 508 fprintf(stderr, "SMART attribute thresholds checksum error\n");
509 return; 509 return;
510 } 510 }
511 511
512 printf("id value thresh crit collect reliability description\t\t\traw\n"); 512 printf("id value thresh crit collect reliability description\t\t\traw\n");
513 for (i = 0; i < 256; i++) { 513 for (i = 0; i < 256; i++) {
514 int thresh = 0; 514 int thresh = 0;
515 515
516 attr = NULL; 516 attr = NULL;
517 517
518 for (j = 0; j < 30; j++) { 518 for (j = 0; j < 30; j++) {
519 if (value_buf->attributes[j].id == i) 519 if (value_buf->attributes[j].id == i)
520 attr = &value_buf->attributes[j]; 520 attr = &value_buf->attributes[j];
521 if (threshold_buf->thresholds[j].id == i) 521 if (threshold_buf->thresholds[j].id == i)
522 thresh = threshold_buf->thresholds[j].value; 522 thresh = threshold_buf->thresholds[j].value;
523 } 523 }
524 524
525 if (thresh && attr == NULL) 525 if (thresh && attr == NULL)
526 errx(1, "threshold but not attr %d", i); 526 errx(1, "threshold but not attr %d", i);
527 if (attr == NULL) 527 if (attr == NULL)
528 continue; 528 continue;
529 529
530 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF) 530 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF)
531 continue; 531 continue;
532 532
533 for (aid = 0;  533 for (aid = 0;
534 smart_attrs[aid].id != i && smart_attrs[aid].id != 0;  534 smart_attrs[aid].id != i && smart_attrs[aid].id != 0;
535 aid++) 535 aid++)
536 ; 536 ;
537 537
538 flags = le16toh(attr->flags); 538 flags = le16toh(attr->flags);
539 539
540 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t", 540 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t",
541 i, attr->value, thresh, 541 i, attr->value, thresh,
542 flags & WDSM_ATTR_ADVISORY ? "yes" : "no", 542 flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
543 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline", 543 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
544 attr->value > thresh ? "posi" : "nega", 544 attr->value > thresh ? "posi" : "nega",
545 smart_attrs[aid].name); 545 smart_attrs[aid].name);
546 546
547 for (j = 0, raw_value = 0; j < 6; j++) 547 for (j = 0, raw_value = 0; j < 6; j++)
548 raw_value += ((uint64_t)attr->raw[j]) << (8*j); 548 raw_value += ((uint64_t)attr->raw[j]) << (8*j);
549 549
550 if (smart_attrs[aid].special) 550 if (smart_attrs[aid].special)
551 (*smart_attrs[aid].special)(attr, raw_value); 551 (*smart_attrs[aid].special)(attr, raw_value);
552 else 552 else
553 printf("%" PRIu64, raw_value); 553 printf("%" PRIu64, raw_value);
554 printf("\n"); 554 printf("\n");
555 } 555 }
556 } 556 }
557 557
558struct { 558struct {
559 int number; 559 int number;
560 const char *name; 560 const char *name;
561} selftest_name[] = { 561} selftest_name[] = {
562 { 0, "Off-line" }, 562 { 0, "Off-line" },
563 { 1, "Short off-line" }, 563 { 1, "Short off-line" },
564 { 2, "Extended off-line" }, 564 { 2, "Extended off-line" },
565 { 127, "Abort off-line test" }, 565 { 127, "Abort off-line test" },
566 { 129, "Short captive" }, 566 { 129, "Short captive" },
567 { 130, "Extended captive" }, 567 { 130, "Extended captive" },
568 { 256, "Unknown test" }, /* larger then u_int8_t */ 568 { 256, "Unknown test" }, /* larger then u_int8_t */
569 { 0, NULL } 569 { 0, NULL }
570}; 570};
571 571
572const char *selftest_status[] = { 572const char *selftest_status[] = {
573 "No error", 573 "No error",
574 "Aborted by the host", 574 "Aborted by the host",
575 "Interrupted by the host by reset", 575 "Interrupted by the host by reset",
576 "Fatal error or unknown test error", 576 "Fatal error or unknown test error",
577 "Unknown test element failed", 577 "Unknown test element failed",
578 "Electrical test element failed", 578 "Electrical test element failed",
579 "The Servo (and/or seek) test element failed", 579 "The Servo (and/or seek) test element failed",
580 "Read element of test failed", 580 "Read element of test failed",
581 "Reserved", 581 "Reserved",
582 "Reserved", 582 "Reserved",
583 "Reserved", 583 "Reserved",
584 "Reserved", 584 "Reserved",
585 "Reserved", 585 "Reserved",
586 "Reserved", 586 "Reserved",
587 "Reserved", 587 "Reserved",
588 "Self-test in progress" 588 "Self-test in progress"
589}; 589};
590 590
591void 591void
592print_error_entry(int num, struct ata_smart_error *le) 592print_error_entry(int num, struct ata_smart_error *le)
593{ 593{
594 int i; 594 int i;
595 595
596 printf("Log entry: %d\n", num); 596 printf("Log entry: %d\n", num);
597 597
598 for (i = 0; i < 5; i++) 598 for (i = 0; i < 5; i++)
599 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i, 599 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i,
600 le->command[i].device_control, 600 le->command[i].device_control,
601 le->command[i].features, 601 le->command[i].features,
602 le->command[i].sector_count, 602 le->command[i].sector_count,
603 le->command[i].sector_number, 603 le->command[i].sector_number,
604 le->command[i].cylinder_low, 604 le->command[i].cylinder_low,
605 le->command[i].cylinder_high, 605 le->command[i].cylinder_high,
606 le->command[i].device_head, 606 le->command[i].device_head,
607 le->command[i].command, 607 le->command[i].command,
608 le->command[i].timestamp[3], 608 le->command[i].timestamp[3],
609 le->command[i].timestamp[2], 609 le->command[i].timestamp[2],
610 le->command[i].timestamp[1], 610 le->command[i].timestamp[1],
611 le->command[i].timestamp[0]); 611 le->command[i].timestamp[0]);
612 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x status=%02x state=%02x lifetime=%02x%02x\n", 612 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x status=%02x state=%02x lifetime=%02x%02x\n",
613 le->error_data.error, 613 le->error_data.error,
614 le->error_data.sector_count, 614 le->error_data.sector_count,
615 le->error_data.sector_number, 615 le->error_data.sector_number,
616 le->error_data.cylinder_low, 616 le->error_data.cylinder_low,
617 le->error_data.cylinder_high, 617 le->error_data.cylinder_high,
618 le->error_data.device_head, 618 le->error_data.device_head,
619 le->error_data.status, 619 le->error_data.status,
620 le->error_data.state, 620 le->error_data.state,
621 le->error_data.lifetime[1], 621 le->error_data.lifetime[1],
622 le->error_data.lifetime[0]); 622 le->error_data.lifetime[0]);
623 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 623 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
624 le->error_data.extended_error[0], 624 le->error_data.extended_error[0],
625 le->error_data.extended_error[1], 625 le->error_data.extended_error[1],
626 le->error_data.extended_error[2], 626 le->error_data.extended_error[2],
627 le->error_data.extended_error[3], 627 le->error_data.extended_error[3],
628 le->error_data.extended_error[4], 628 le->error_data.extended_error[4],
629 le->error_data.extended_error[5], 629 le->error_data.extended_error[5],
630 le->error_data.extended_error[6], 630 le->error_data.extended_error[6],
631 le->error_data.extended_error[7], 631 le->error_data.extended_error[7],
632 le->error_data.extended_error[8], 632 le->error_data.extended_error[8],
633 le->error_data.extended_error[9], 633 le->error_data.extended_error[9],
634 le->error_data.extended_error[10], 634 le->error_data.extended_error[10],
635 le->error_data.extended_error[11], 635 le->error_data.extended_error[11],
636 le->error_data.extended_error[12], 636 le->error_data.extended_error[12],
637 le->error_data.extended_error[13], 637 le->error_data.extended_error[13],
638 le->error_data.extended_error[14], 638 le->error_data.extended_error[14],
639 le->error_data.extended_error[15], 639 le->error_data.extended_error[15],
640 le->error_data.extended_error[15], 640 le->error_data.extended_error[15],
641 le->error_data.extended_error[17], 641 le->error_data.extended_error[17],
642 le->error_data.extended_error[18]); 642 le->error_data.extended_error[18]);
643} 643}
644 644
645void 645void
646print_error(void *buf) 646print_error(void *buf)
647{ 647{
648 struct ata_smart_errorlog *erlog = buf; 648 struct ata_smart_errorlog *erlog = buf;
649 u_int8_t checksum; 649 u_int8_t checksum;
650 int i; 650 int i;
651 651
652 for (i = checksum = 0; i < 512; i++) 652 for (i = checksum = 0; i < 512; i++)
653 checksum += ((u_int8_t *) buf)[i]; 653 checksum += ((u_int8_t *) buf)[i];
654 if (checksum != 0) { 654 if (checksum != 0) {
655 fprintf(stderr, "SMART error log checksum error\n"); 655 fprintf(stderr, "SMART error log checksum error\n");
656 return; 656 return;
657 } 657 }
658 658
659 if (erlog->data_structure_revision != 1) { 659 if (erlog->data_structure_revision != 1) {
660 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n", 660 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n",
661 erlog->data_structure_revision); 661 erlog->data_structure_revision);
662 return; 662 return;
663 } 663 }
664 664
665 if (erlog->mostrecenterror == 0) { 665 if (erlog->mostrecenterror == 0) {
666 printf("No errors have been logged\n"); 666 printf("No errors have been logged\n");
667 return; 667 return;
668 } 668 }
669  669
670 if (erlog->mostrecenterror > 5) { 670 if (erlog->mostrecenterror > 5) {
671 fprintf(stderr, "Most recent error is too large\n"); 671 fprintf(stderr, "Most recent error is too large\n");
672 return; 672 return;
673 } 673 }
674  674
675 for (i = erlog->mostrecenterror; i < 5; i++) 675 for (i = erlog->mostrecenterror; i < 5; i++)
676 print_error_entry(i, &erlog->log_entries[i]); 676 print_error_entry(i, &erlog->log_entries[i]);
677 for (i = 0; i < erlog->mostrecenterror; i++) 677 for (i = 0; i < erlog->mostrecenterror; i++)
678 print_error_entry(i, &erlog->log_entries[i]); 678 print_error_entry(i, &erlog->log_entries[i]);
679 printf("device error count: %d\n", erlog->device_error_count); 679 printf("device error count: %d\n", erlog->device_error_count);
680} 680}
681 681
682void 682void
683print_selftest_entry(int num, struct ata_smart_selftest *le) 683print_selftest_entry(int num, struct ata_smart_selftest *le)
684{ 684{
685 unsigned char *p; 685 unsigned char *p;
686 int i; 686 size_t i;
687 687
688 /* check if all zero */ 688 /* check if all zero */
689 for (p = (void *)le, i = 0; i < sizeof(*le); i++) 689 for (p = (void *)le, i = 0; i < sizeof(*le); i++)
690 if (p[i] != 0) 690 if (p[i] != 0)
691 break; 691 break;
692 if (i == sizeof(*le)) 692 if (i == sizeof(*le))
693 return; 693 return;
694 694
695 printf("Log entry: %d\n", num); 695 printf("Log entry: %d\n", num);
696 696
697 /* Get test name */ 697 /* Get test name */
698 for (i = 0; selftest_name[i].name != NULL; i++) 698 for (i = 0; selftest_name[i].name != NULL; i++)
699 if (selftest_name[i].number == le->number) 699 if (selftest_name[i].number == le->number)
700 break; 700 break;
701 701
702 if (selftest_name[i].name == NULL) 702 if (selftest_name[i].name == NULL)
703 printf("\tName: (%d)\n", le->number); 703 printf("\tName: (%d)\n", le->number);
704 else 704 else
705 printf("\tName: %s\n", selftest_name[i].name); 705 printf("\tName: %s\n", selftest_name[i].name);
706 printf("\tStatus: %s\n", selftest_status[le->status >> 4]); 706 printf("\tStatus: %s\n", selftest_status[le->status >> 4]);
707 /* XXX This generally should not be set when a self-test is completed, 707 /* XXX This generally should not be set when a self-test is completed,
708 and at any rate is useless. - mycroft */ 708 and at any rate is useless. - mycroft */
709 if (le->status >> 4 == 15) 709 if (le->status >> 4 == 15)
710 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf); 710 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf);
711 else if (le->status >> 4 != 0) 711 else if (le->status >> 4 != 0)
712 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error)); 712 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error));
713} 713}
714 714
715void 715void
716print_selftest(void *buf) 716print_selftest(void *buf)
717{ 717{
718 struct ata_smart_selftestlog *stlog = buf; 718 struct ata_smart_selftestlog *stlog = buf;
719 u_int8_t checksum; 719 u_int8_t checksum;
720 int i; 720 int i;
721 721
722 for (i = checksum = 0; i < 512; i++) 722 for (i = checksum = 0; i < 512; i++)
723 checksum += ((u_int8_t *) buf)[i]; 723 checksum += ((u_int8_t *) buf)[i];
724 if (checksum != 0) { 724 if (checksum != 0) {
725 fprintf(stderr, "SMART selftest log checksum error\n"); 725 fprintf(stderr, "SMART selftest log checksum error\n");
726 return; 726 return;
727 } 727 }
728 728
729 if (le16toh(stlog->data_structure_revision) != 1) { 729 if (le16toh(stlog->data_structure_revision) != 1) {
730 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n", 730 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n",
731 le16toh(stlog->data_structure_revision)); 731 le16toh(stlog->data_structure_revision));
732 return; 732 return;
733 } 733 }
734 734
735 if (stlog->mostrecenttest == 0) { 735 if (stlog->mostrecenttest == 0) {
736 printf("No self-tests have been logged\n"); 736 printf("No self-tests have been logged\n");
737 return; 737 return;
738 } 738 }
739  739
740 if (stlog->mostrecenttest > 22) { 740 if (stlog->mostrecenttest > 22) {
741 fprintf(stderr, "Most recent test is too large\n"); 741 fprintf(stderr, "Most recent test is too large\n");
742 return; 742 return;
743 } 743 }
744  744
745 for (i = stlog->mostrecenttest; i < 22; i++) 745 for (i = stlog->mostrecenttest; i < 22; i++)
746 print_selftest_entry(i, &stlog->log_entries[i]); 746 print_selftest_entry(i, &stlog->log_entries[i]);
747 for (i = 0; i < stlog->mostrecenttest; i++) 747 for (i = 0; i < stlog->mostrecenttest; i++)
748 print_selftest_entry(i, &stlog->log_entries[i]); 748 print_selftest_entry(i, &stlog->log_entries[i]);
749} 749}
750 750
751struct ataparams * 751struct ataparams *
752getataparams() 752getataparams()
753{ 753{
754 struct atareq req; 754 struct atareq req;
755 static union { 755 static union {
756 unsigned char inbuf[DEV_BSIZE]; 756 unsigned char inbuf[DEV_BSIZE];
757 struct ataparams inqbuf; 757 struct ataparams inqbuf;
758 } inbuf; 758 } inbuf;
759 759
760 memset(&inbuf, 0, sizeof(inbuf)); 760 memset(&inbuf, 0, sizeof(inbuf));
761 memset(&req, 0, sizeof(req)); 761 memset(&req, 0, sizeof(req));
762 762
763 req.flags = ATACMD_READ; 763 req.flags = ATACMD_READ;
764 req.command = WDCC_IDENTIFY; 764 req.command = WDCC_IDENTIFY;
765 req.databuf = (caddr_t)&inbuf; 765 req.databuf = (caddr_t)&inbuf;
766 req.datalen = sizeof(inbuf); 766 req.datalen = sizeof(inbuf);
767 req.timeout = 1000; 767 req.timeout = 1000;
768 768
769 ata_command(&req); 769 ata_command(&req);
770 770
771 return (&inbuf.inqbuf); 771 return (&inbuf.inqbuf);
772} 772}
773 773
774/* 774/*
775 * is_smart: 775 * is_smart:
776 * 776 *
777 * Detect whether device supports SMART and SMART is enabled. 777 * Detect whether device supports SMART and SMART is enabled.
778 */ 778 */
779 779
780int 780int
781is_smart(void) 781is_smart(void)
782{ 782{
783 int retval = 0; 783 int retval = 0;
784 struct ataparams *inqbuf; 784 struct ataparams *inqbuf;
785 const char *status; 785 const char *status;
786 786
787 inqbuf = getataparams(); 787 inqbuf = getataparams();
788 788
789 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 789 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
790 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) { 790 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
791 fprintf(stderr, "SMART unsupported\n"); 791 fprintf(stderr, "SMART unsupported\n");
792 } else { 792 } else {
793 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 || 793 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 ||
794 inqbuf->atap_cmd_set2 == 0xffff || 794 inqbuf->atap_cmd_set2 == 0xffff ||
795 inqbuf->atap_cmd_set2 == 0x0000) { 795 inqbuf->atap_cmd_set2 == 0x0000) {
796 status = "status unknown"; 796 status = "status unknown";
797 retval = 2; 797 retval = 2;
798 } else { 798 } else {
799 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) { 799 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) {
800 status = "enabled"; 800 status = "enabled";
801 retval = 1; 801 retval = 1;
802 } else { 802 } else {
803 status = "disabled"; 803 status = "disabled";
804 retval = 3; 804 retval = 3;
805 } 805 }
806 } 806 }
807 printf("SMART supported, SMART %s\n", status); 807 printf("SMART supported, SMART %s\n", status);
808 } 808 }
809 } 809 }
810 return retval; 810 return retval;
811} 811}
812 812
813/* 813/*
814 * extract_string: copy a block of bytes out of ataparams and make 814 * extract_string: copy a block of bytes out of ataparams and make
815 * a proper string out of it, truncating trailing spaces and preserving 815 * a proper string out of it, truncating trailing spaces and preserving
816 * strict typing. And also, not doing unaligned accesses. 816 * strict typing. And also, not doing unaligned accesses.
817 */ 817 */
818static void 818static void
819extract_string(char *buf, size_t bufmax, 819extract_string(char *buf, size_t bufmax,
820 uint8_t *bytes, unsigned numbytes, 820 uint8_t *bytes, unsigned numbytes,
821 int needswap) 821 int needswap)
822{ 822{
823 unsigned i; 823 unsigned i;
824 size_t j; 824 size_t j;
825 unsigned char ch1, ch2; 825 unsigned char ch1, ch2;
826 826
827 for (i = 0, j = 0; i < numbytes; i += 2) { 827 for (i = 0, j = 0; i < numbytes; i += 2) {
828 ch1 = bytes[i]; 828 ch1 = bytes[i];
829 ch2 = bytes[i+1]; 829 ch2 = bytes[i+1];
830 if (needswap && j < bufmax-1) { 830 if (needswap && j < bufmax-1) {
831 buf[j++] = ch2; 831 buf[j++] = ch2;
832 } 832 }
833 if (j < bufmax-1) { 833 if (j < bufmax-1) {
834 buf[j++] = ch1; 834 buf[j++] = ch1;
835 } 835 }
836 if (!needswap && j < bufmax-1) { 836 if (!needswap && j < bufmax-1) {
837 buf[j++] = ch2; 837 buf[j++] = ch2;
838 } 838 }
839 } 839 }
840 while (j > 0 && buf[j-1] == ' ') { 840 while (j > 0 && buf[j-1] == ' ') {
841 j--; 841 j--;
842 } 842 }
843 buf[j] = '\0'; 843 buf[j] = '\0';
844} 844}
845 845
846/* 846/*
847 * DEVICE COMMANDS 847 * DEVICE COMMANDS
848 */ 848 */
849 849
850/* 850/*
851 * device_identify: 851 * device_identify:
852 * 852 *
853 * Display the identity of the device 853 * Display the identity of the device
854 */ 854 */
855void 855void
856device_identify(int argc, char *argv[]) 856device_identify(int argc, char *argv[])
857{ 857{
858 struct ataparams *inqbuf; 858 struct ataparams *inqbuf;
859 char model[sizeof(inqbuf->atap_model)]; 859 char model[sizeof(inqbuf->atap_model)];
860 char revision[sizeof(inqbuf->atap_revision)]; 860 char revision[sizeof(inqbuf->atap_revision)];
861 char serial[sizeof(inqbuf->atap_serial)]; 861 char serial[sizeof(inqbuf->atap_serial)];
862 int needswap = 0; 862 int needswap = 0;
863 863
864 /* No arguments. */ 864 /* No arguments. */
865 if (argc != 0) 865 if (argc != 0)
866 usage(); 866 usage();
867 867
868 inqbuf = getataparams(); 868 inqbuf = getataparams();
869 869
870#if BYTE_ORDER == LITTLE_ENDIAN 870#if BYTE_ORDER == LITTLE_ENDIAN
871 /* 871 /*
872 * On little endian machines, we need to shuffle the string 872 * On little endian machines, we need to shuffle the string
873 * byte order. However, we don't have to do this for NEC or 873 * byte order. However, we don't have to do this for NEC or
874 * Mitsumi ATAPI devices 874 * Mitsumi ATAPI devices
875 */ 875 */
876 876
877 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 877 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
878 ((inqbuf->atap_model[0] == 'N' && 878 ((inqbuf->atap_model[0] == 'N' &&
879 inqbuf->atap_model[1] == 'E') || 879 inqbuf->atap_model[1] == 'E') ||
880 (inqbuf->atap_model[0] == 'F' && 880 (inqbuf->atap_model[0] == 'F' &&
881 inqbuf->atap_model[1] == 'X')))) { 881 inqbuf->atap_model[1] == 'X')))) {
882 needswap = 1; 882 needswap = 1;
883 } 883 }
884#endif 884#endif
885 885
886 /* 886 /*
887 * Copy the info strings out, stripping off blanks. 887 * Copy the info strings out, stripping off blanks.
888 */ 888 */
889 extract_string(model, sizeof(model), 889 extract_string(model, sizeof(model),
890 inqbuf->atap_model, sizeof(inqbuf->atap_model), 890 inqbuf->atap_model, sizeof(inqbuf->atap_model),
891 needswap); 891 needswap);
892 extract_string(revision, sizeof(revision), 892 extract_string(revision, sizeof(revision),
893 inqbuf->atap_revision, sizeof(inqbuf->atap_revision), 893 inqbuf->atap_revision, sizeof(inqbuf->atap_revision),
894 needswap); 894 needswap);
895 extract_string(serial, sizeof(serial), 895 extract_string(serial, sizeof(serial),
896 inqbuf->atap_serial, sizeof(inqbuf->atap_serial), 896 inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
897 needswap); 897 needswap);
898 898
899 printf("Model: %s, Rev: %s, Serial #: %s\n", 899 printf("Model: %s, Rev: %s, Serial #: %s\n",
900 model, revision, serial); 900 model, revision, serial);
901 901
902 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 902 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
903 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 903 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
904 "removable"); 904 "removable");
905 905
906 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0) 906 if ((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == 0)
907 printf("Cylinders: %d, heads: %d, sec/track: %d, total " 907 printf("Cylinders: %d, heads: %d, sec/track: %d, total "
908 "sectors: %d\n", inqbuf->atap_cylinders, 908 "sectors: %d\n", inqbuf->atap_cylinders,
909 inqbuf->atap_heads, inqbuf->atap_sectors, 909 inqbuf->atap_heads, inqbuf->atap_sectors,
910 (inqbuf->atap_capacity[1] << 16) | 910 (inqbuf->atap_capacity[1] << 16) |
911 inqbuf->atap_capacity[0]); 911 inqbuf->atap_capacity[0]);
912 912
913 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) 913 if (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)
914 printf("Device supports command queue depth of %d\n", 914 printf("Device supports command queue depth of %d\n",
915 inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK); 915 inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK);
916 916
917 printf("Device capabilities:\n"); 917 printf("Device capabilities:\n");
918 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 918 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps);
919 919
920 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 920 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
921 printf("Device supports following standards:\n"); 921 printf("Device supports following standards:\n");
922 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 922 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers);
923 printf("\n"); 923 printf("\n");
924 } 924 }
925 925
926 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 926 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
927 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 927 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
928 printf("Command set support:\n"); 928 printf("Command set support:\n");
929 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 929 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff)
930 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 930 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1,
931 inqbuf->atap_cmd1_en, ata_cmd_set1); 931 inqbuf->atap_cmd1_en, ata_cmd_set1);
932 else 932 else
933 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 933 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1,
934 ata_cmd_set1); 934 ata_cmd_set1);
935 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 935 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff)
936 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 936 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2,
937 inqbuf->atap_cmd2_en, ata_cmd_set2); 937 inqbuf->atap_cmd2_en, ata_cmd_set2);
938 else 938 else
939 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 939 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2,
940 ata_cmd_set2); 940 ata_cmd_set2);
941 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 941 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff)
942 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 942 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext,
943 ata_cmd_ext); 943 ata_cmd_ext);
944 } 944 }
945 945
946 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) { 946 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) {
947 printf("Serial ATA capabilities:\n"); 947 printf("Serial ATA capabilities:\n");
948 print_bitinfo("\t", "\n", inqbuf->atap_sata_caps, ata_sata_caps); 948 print_bitinfo("\t", "\n", inqbuf->atap_sata_caps, ata_sata_caps);
949 } 949 }
950 950
951 if (inqbuf->atap_sata_features_supp != 0 && inqbuf->atap_sata_features_supp != 0xffff) { 951 if (inqbuf->atap_sata_features_supp != 0 && inqbuf->atap_sata_features_supp != 0xffff) {
952 printf("Serial ATA features:\n"); 952 printf("Serial ATA features:\n");
953 if (inqbuf->atap_sata_features_en != 0 && inqbuf->atap_sata_features_en != 0xffff) 953 if (inqbuf->atap_sata_features_en != 0 && inqbuf->atap_sata_features_en != 0xffff)
954 print_bitinfo2("\t", "\n", inqbuf->atap_sata_features_supp, inqbuf->atap_sata_features_en, ata_sata_feat); 954 print_bitinfo2("\t", "\n", inqbuf->atap_sata_features_supp, inqbuf->atap_sata_features_en, ata_sata_feat);
955 else 955 else
956 print_bitinfo("\t", "\n", inqbuf->atap_sata_features_supp, ata_sata_feat); 956 print_bitinfo("\t", "\n", inqbuf->atap_sata_features_supp, ata_sata_feat);
957 } 957 }
958 958
959 return; 959 return;
960} 960}
961 961
962/* 962/*
963 * device idle: 963 * device idle:
964 * 964 *
965 * issue the IDLE IMMEDIATE command to the drive 965 * issue the IDLE IMMEDIATE command to the drive
966 */ 966 */
967void 967void
968device_idle(int argc, char *argv[]) 968device_idle(int argc, char *argv[])
969{ 969{
970 struct atareq req; 970 struct atareq req;
971 971
972 /* No arguments. */ 972 /* No arguments. */
973 if (argc != 0) 973 if (argc != 0)
974 usage(); 974 usage();
975 975
976 memset(&req, 0, sizeof(req)); 976 memset(&req, 0, sizeof(req));
977 977
978 if (strcmp(cmdname, "idle") == 0) 978 if (strcmp(cmdname, "idle") == 0)
979 req.command = WDCC_IDLE_IMMED; 979 req.command = WDCC_IDLE_IMMED;
980 else if (strcmp(cmdname, "standby") == 0) 980 else if (strcmp(cmdname, "standby") == 0)
981 req.command = WDCC_STANDBY_IMMED; 981 req.command = WDCC_STANDBY_IMMED;
982 else 982 else
983 req.command = WDCC_SLEEP; 983 req.command = WDCC_SLEEP;
984 984
985 req.timeout = 1000; 985 req.timeout = 1000;
986 986
987 ata_command(&req); 987 ata_command(&req);
988 988
989 return; 989 return;
990} 990}
991 991
992/* 992/*
993 * device apm: 993 * device apm:
994 * 994 *
995 * enable/disable/control the APM feature of the drive 995 * enable/disable/control the APM feature of the drive
996 */ 996 */
997void 997void
998device_apm(int argc, char *argv[]) 998device_apm(int argc, char *argv[])
999{ 999{
1000 struct atareq req; 1000 struct atareq req;
1001 long l; 1001 long l;
1002 1002
1003 memset(&req, 0, sizeof(req)); 1003 memset(&req, 0, sizeof(req));
1004 if (argc >= 1) { 1004 if (argc >= 1) {
1005 req.command = SET_FEATURES; 1005 req.command = SET_FEATURES;
1006 req.timeout = 1000; 1006 req.timeout = 1000;
1007  1007
1008 if (strcmp(argv[0], "disable") == 0) 1008 if (strcmp(argv[0], "disable") == 0)
1009 req.features = WDSF_APM_DS; 1009 req.features = WDSF_APM_DS;
1010 else if (strcmp(argv[0], "set") == 0 && argc >= 2 && 1010 else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
1011 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) { 1011 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
1012  1012
1013 req.features = WDSF_APM_EN; 1013 req.features = WDSF_APM_EN;
1014 req.sec_count = l + 1; 1014 req.sec_count = l + 1;
1015 } else 1015 } else
1016 usage(); 1016 usage();
1017 } else 1017 } else
1018 usage(); 1018 usage();
1019  1019
1020 ata_command(&req); 1020 ata_command(&req);
1021} 1021}
1022  1022
1023 1023
1024/* 1024/*
1025 * Set the idle timer on the disk. Set it for either idle mode or 1025 * Set the idle timer on the disk. Set it for either idle mode or
1026 * standby mode, depending on how we were invoked. 1026 * standby mode, depending on how we were invoked.
1027 */ 1027 */
1028 1028
1029void 1029void
1030device_setidle(int argc, char *argv[]) 1030device_setidle(int argc, char *argv[])
1031{ 1031{
1032 unsigned long idle; 1032 unsigned long idle;
1033 struct atareq req; 1033 struct atareq req;
1034 char *end; 1034 char *end;
1035 1035
1036 /* Only one argument */ 1036 /* Only one argument */
1037 if (argc != 1) 1037 if (argc != 1)
1038 usage(); 1038 usage();
1039 1039
1040 idle = strtoul(argv[0], &end, 0); 1040 idle = strtoul(argv[0], &end, 0);
1041 1041
1042 if (*end != '\0') { 1042 if (*end != '\0') {
1043 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 1043 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]);
1044 exit(1); 1044 exit(1);
1045 } 1045 }
1046 1046
1047 if (idle > 19800) { 1047 if (idle > 19800) {
1048 fprintf(stderr, "Idle time has a maximum value of 5.5 " 1048 fprintf(stderr, "Idle time has a maximum value of 5.5 "
1049 "hours\n"); 1049 "hours\n");
1050 exit(1); 1050 exit(1);
1051 } 1051 }
1052 1052
1053 if (idle != 0 && idle < 5) { 1053 if (idle != 0 && idle < 5) {
1054 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 1054 fprintf(stderr, "Idle timer must be at least 5 seconds\n");
1055 exit(1); 1055 exit(1);
1056 } 1056 }
1057 1057
1058 memset(&req, 0, sizeof(req)); 1058 memset(&req, 0, sizeof(req));
1059 1059
1060 if (idle <= 240*5) 1060 if (idle <= 240*5)
1061 req.sec_count = idle / 5; 1061 req.sec_count = idle / 5;
1062 else 1062 else
1063 req.sec_count = idle / (30*60) + 240; 1063 req.sec_count = idle / (30*60) + 240;
1064 1064
1065 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 1065 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE;
1066 req.timeout = 1000; 1066 req.timeout = 1000;
1067 1067
1068 ata_command(&req); 1068 ata_command(&req);
1069 1069
1070 return; 1070 return;
1071} 1071}
1072 1072
1073/* 1073/*
1074 * Query the device for the current power mode 1074 * Query the device for the current power mode
1075 */ 1075 */
1076 1076
1077void 1077void
1078device_checkpower(int argc, char *argv[]) 1078device_checkpower(int argc, char *argv[])
1079{ 1079{
1080 struct atareq req; 1080 struct atareq req;
1081 1081
1082 /* No arguments. */ 1082 /* No arguments. */
1083 if (argc != 0) 1083 if (argc != 0)
1084 usage(); 1084 usage();
1085 1085
1086 memset(&req, 0, sizeof(req)); 1086 memset(&req, 0, sizeof(req));
1087 1087
1088 req.command = WDCC_CHECK_PWR; 1088 req.command = WDCC_CHECK_PWR;
1089 req.timeout = 1000; 1089 req.timeout = 1000;
1090 req.flags = ATACMD_READREG; 1090 req.flags = ATACMD_READREG;
1091 1091
1092 ata_command(&req); 1092 ata_command(&req);
1093 1093
1094 printf("Current power status: "); 1094 printf("Current power status: ");
1095 1095
1096 switch (req.sec_count) { 1096 switch (req.sec_count) {
1097 case 0x00: 1097 case 0x00:
1098 printf("Standby mode\n"); 1098 printf("Standby mode\n");
1099 break; 1099 break;
1100 case 0x80: 1100 case 0x80:
1101 printf("Idle mode\n"); 1101 printf("Idle mode\n");
1102 break; 1102 break;
1103 case 0xff: 1103 case 0xff:
1104 printf("Active mode\n"); 1104 printf("Active mode\n");
1105 break; 1105 break;
1106 default: 1106 default:
1107 printf("Unknown power code (%02x)\n", req.sec_count); 1107 printf("Unknown power code (%02x)\n", req.sec_count);
1108 } 1108 }
1109 1109
1110 return; 1110 return;
1111} 1111}
1112 1112
1113/* 1113/*
1114 * device_smart: 1114 * device_smart:
1115 * 1115 *
1116 * Display SMART status 1116 * Display SMART status
1117 */ 1117 */
1118void 1118void
1119device_smart(int argc, char *argv[]) 1119device_smart(int argc, char *argv[])
1120{ 1120{
1121 struct atareq req; 1121 struct atareq req;
1122 unsigned char inbuf[DEV_BSIZE]; 1122 unsigned char inbuf[DEV_BSIZE];
1123 unsigned char inbuf2[DEV_BSIZE]; 1123 unsigned char inbuf2[DEV_BSIZE];
1124 1124
1125 if (argc < 1) 1125 if (argc < 1)
1126 usage(); 1126 usage();
1127 1127
1128 if (strcmp(argv[0], "enable") == 0) { 1128 if (strcmp(argv[0], "enable") == 0) {
1129 memset(&req, 0, sizeof(req)); 1129 memset(&req, 0, sizeof(req));
1130 1130
1131 req.features = WDSM_ENABLE_OPS; 1131 req.features = WDSM_ENABLE_OPS;
1132 req.command = WDCC_SMART; 1132 req.command = WDCC_SMART;
1133 req.cylinder = WDSMART_CYL; 1133 req.cylinder = WDSMART_CYL;
1134 req.timeout = 1000; 1134 req.timeout = 1000;
1135 1135
1136 ata_command(&req); 1136 ata_command(&req);
1137 1137
1138 is_smart(); 1138 is_smart();
1139 } else if (strcmp(argv[0], "disable") == 0) { 1139 } else if (strcmp(argv[0], "disable") == 0) {
1140 memset(&req, 0, sizeof(req)); 1140 memset(&req, 0, sizeof(req));
1141 1141
1142 req.features = WDSM_DISABLE_OPS; 1142 req.features = WDSM_DISABLE_OPS;
1143 req.command = WDCC_SMART; 1143 req.command = WDCC_SMART;
1144 req.cylinder = WDSMART_CYL; 1144 req.cylinder = WDSMART_CYL;
1145 req.timeout = 1000; 1145 req.timeout = 1000;
1146 1146
1147 ata_command(&req); 1147 ata_command(&req);
1148 1148
1149 is_smart(); 1149 is_smart();
1150 } else if (strcmp(argv[0], "status") == 0) { 1150 } else if (strcmp(argv[0], "status") == 0) {
1151 int rv; 1151 int rv;
1152 1152
1153 rv = is_smart(); 1153 rv = is_smart();
1154 1154
1155 if (!rv) { 1155 if (!rv) {
1156 fprintf(stderr, "SMART not supported\n"); 1156 fprintf(stderr, "SMART not supported\n");
1157 return; 1157 return;
1158 } else if (rv == 3) 1158 } else if (rv == 3)
1159 return; 1159 return;
1160 1160
1161 memset(&inbuf, 0, sizeof(inbuf)); 1161 memset(&inbuf, 0, sizeof(inbuf));
1162 memset(&req, 0, sizeof(req)); 1162 memset(&req, 0, sizeof(req));
1163 1163
1164 req.features = WDSM_STATUS; 1164 req.features = WDSM_STATUS;
1165 req.command = WDCC_SMART; 1165 req.command = WDCC_SMART;
1166 req.cylinder = WDSMART_CYL; 1166 req.cylinder = WDSMART_CYL;
1167 req.timeout = 1000; 1167 req.timeout = 1000;
1168  1168
1169 ata_command(&req); 1169 ata_command(&req);
1170 1170
1171 if (req.cylinder != WDSMART_CYL) { 1171 if (req.cylinder != WDSMART_CYL) {
1172 fprintf(stderr, "Threshold exceeds condition\n"); 1172 fprintf(stderr, "Threshold exceeds condition\n");
1173 } 1173 }
1174 1174
1175 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1175 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional
1176 * features, the following ata_command()'s may error 1176 * features, the following ata_command()'s may error
1177 * and exit(). 1177 * and exit().
1178 */ 1178 */
1179 1179
1180 memset(&inbuf, 0, sizeof(inbuf)); 1180 memset(&inbuf, 0, sizeof(inbuf));
1181 memset(&req, 0, sizeof(req)); 1181 memset(&req, 0, sizeof(req));
1182 1182
1183 req.flags = ATACMD_READ; 1183 req.flags = ATACMD_READ;
1184 req.features = WDSM_RD_DATA; 1184 req.features = WDSM_RD_DATA;
1185 req.command = WDCC_SMART; 1185 req.command = WDCC_SMART;
1186 req.databuf = (caddr_t) inbuf; 1186 req.databuf = (caddr_t) inbuf;
1187 req.datalen = sizeof(inbuf); 1187 req.datalen = sizeof(inbuf);
1188 req.cylinder = WDSMART_CYL; 1188 req.cylinder = WDSMART_CYL;
1189 req.timeout = 1000; 1189 req.timeout = 1000;
1190  1190
1191 ata_command(&req); 1191 ata_command(&req);
1192 1192
1193 memset(&inbuf2, 0, sizeof(inbuf2)); 1193 memset(&inbuf2, 0, sizeof(inbuf2));
1194 memset(&req, 0, sizeof(req)); 1194 memset(&req, 0, sizeof(req));
1195 1195
1196 req.flags = ATACMD_READ; 1196 req.flags = ATACMD_READ;
1197 req.features = WDSM_RD_THRESHOLDS; 1197 req.features = WDSM_RD_THRESHOLDS;
1198 req.command = WDCC_SMART; 1198 req.command = WDCC_SMART;
1199 req.databuf = (caddr_t) inbuf2; 1199 req.databuf = (caddr_t) inbuf2;
1200 req.datalen = sizeof(inbuf2); 1200 req.datalen = sizeof(inbuf2);
1201 req.cylinder = WDSMART_CYL; 1201 req.cylinder = WDSMART_CYL;
1202 req.timeout = 1000; 1202 req.timeout = 1000;
1203 1203
1204 ata_command(&req); 1204 ata_command(&req);
1205 1205
1206 print_smart_status(inbuf, inbuf2); 1206 print_smart_status(inbuf, inbuf2);
1207 1207
1208 } else if (strcmp(argv[0], "offline") == 0) { 1208 } else if (strcmp(argv[0], "offline") == 0) {
1209 if (argc != 2) 1209 if (argc != 2)
1210 usage(); 1210 usage();
1211 if (!is_smart()) { 1211 if (!is_smart()) {
1212 fprintf(stderr, "SMART not supported\n"); 1212 fprintf(stderr, "SMART not supported\n");
1213 return; 1213 return;
1214 } 1214 }
1215 1215
1216 memset(&req, 0, sizeof(req)); 1216 memset(&req, 0, sizeof(req));
1217 1217
1218 req.features = WDSM_EXEC_OFFL_IMM; 1218 req.features = WDSM_EXEC_OFFL_IMM;
1219 req.command = WDCC_SMART; 1219 req.command = WDCC_SMART;
1220 req.cylinder = WDSMART_CYL; 1220 req.cylinder = WDSMART_CYL;
1221 req.sec_num = atol(argv[1]); 1221 req.sec_num = atol(argv[1]);
1222 req.timeout = 10000; 1222 req.timeout = 10000;
1223 1223
1224 ata_command(&req); 1224 ata_command(&req);
1225 } else if (strcmp(argv[0], "error-log") == 0) { 1225 } else if (strcmp(argv[0], "error-log") == 0) {
1226 if (!is_smart()) { 1226 if (!is_smart()) {
1227 fprintf(stderr, "SMART not supported\n"); 1227 fprintf(stderr, "SMART not supported\n");
1228 return; 1228 return;
1229 } 1229 }
1230 1230
1231 memset(&inbuf, 0, sizeof(inbuf)); 1231 memset(&inbuf, 0, sizeof(inbuf));
1232 memset(&req, 0, sizeof(req)); 1232 memset(&req, 0, sizeof(req));
1233  1233
1234 req.flags = ATACMD_READ; 1234 req.flags = ATACMD_READ;
1235 req.features = WDSM_RD_LOG; 1235 req.features = WDSM_RD_LOG;
1236 req.sec_count = 1; 1236 req.sec_count = 1;
1237 req.sec_num = 1; 1237 req.sec_num = 1;
1238 req.command = WDCC_SMART; 1238 req.command = WDCC_SMART;
1239 req.databuf = (caddr_t) inbuf; 1239 req.databuf = (caddr_t) inbuf;
1240 req.datalen = sizeof(inbuf); 1240 req.datalen = sizeof(inbuf);
1241 req.cylinder = WDSMART_CYL; 1241 req.cylinder = WDSMART_CYL;
1242 req.timeout = 1000; 1242 req.timeout = 1000;
1243  1243
1244 ata_command(&req); 1244 ata_command(&req);
1245  1245
1246 print_error(inbuf); 1246 print_error(inbuf);
1247 } else if (strcmp(argv[0], "selftest-log") == 0) { 1247 } else if (strcmp(argv[0], "selftest-log") == 0) {
1248 if (!is_smart()) { 1248 if (!is_smart()) {
1249 fprintf(stderr, "SMART not supported\n"); 1249 fprintf(stderr, "SMART not supported\n");
1250 return; 1250 return;
1251 } 1251 }
1252 1252
1253 memset(&inbuf, 0, sizeof(inbuf)); 1253 memset(&inbuf, 0, sizeof(inbuf));
1254 memset(&req, 0, sizeof(req)); 1254 memset(&req, 0, sizeof(req));
1255  1255
1256 req.flags = ATACMD_READ; 1256 req.flags = ATACMD_READ;
1257 req.features = WDSM_RD_LOG; 1257 req.features = WDSM_RD_LOG;
1258 req.sec_count = 1; 1258 req.sec_count = 1;
1259 req.sec_num = 6; 1259 req.sec_num = 6;
1260 req.command = WDCC_SMART; 1260 req.command = WDCC_SMART;
1261 req.databuf = (caddr_t) inbuf; 1261 req.databuf = (caddr_t) inbuf;
1262 req.datalen = sizeof(inbuf); 1262 req.datalen = sizeof(inbuf);
1263 req.cylinder = WDSMART_CYL; 1263 req.cylinder = WDSMART_CYL;
1264 req.timeout = 1000; 1264 req.timeout = 1000;
1265  1265
1266 ata_command(&req); 1266 ata_command(&req);
1267  1267
1268 print_selftest(inbuf); 1268 print_selftest(inbuf);
1269 1269
1270 } else { 1270 } else {
1271 usage(); 1271 usage();
1272 } 1272 }
1273 return; 1273 return;
1274} 1274}
1275 1275
1276void 1276void
1277device_security(int argc, char *argv[]) 1277device_security(int argc, char *argv[])
1278{ 1278{
1279 struct atareq req; 1279 struct atareq req;
1280 struct ataparams *inqbuf; 1280 struct ataparams *inqbuf;
1281 1281
1282 /* need subcommand */ 1282 /* need subcommand */
1283 if (argc < 1) 1283 if (argc < 1)
1284 usage(); 1284 usage();
1285 1285
1286 if (strcmp(argv[0], "freeze") == 0) { 1286 if (strcmp(argv[0], "freeze") == 0) {
1287 memset(&req, 0, sizeof(req)); 1287 memset(&req, 0, sizeof(req));
1288 req.command = WDCC_SECURITY_FREEZE; 1288 req.command = WDCC_SECURITY_FREEZE;
1289 req.timeout = 1000; 1289 req.timeout = 1000;
1290 ata_command(&req); 1290 ata_command(&req);
1291 } else if (strcmp(argv[0], "status") == 0) { 1291 } else if (strcmp(argv[0], "status") == 0) {
1292 inqbuf = getataparams(); 1292 inqbuf = getataparams();
1293 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1293 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
1294 } else 1294 } else
1295 usage(); 1295 usage();
1296 1296
1297 return; 1297 return;
1298} 1298}
1299 1299
1300/* 1300/*
1301 * bus_reset: 1301 * bus_reset:
1302 * Reset an ATA bus (will reset all devices on the bus) 1302 * Reset an ATA bus (will reset all devices on the bus)
1303 */ 1303 */
1304void 1304void
1305bus_reset(int argc, char *argv[]) 1305bus_reset(int argc, char *argv[])
1306{ 1306{
1307 int error; 1307 int error;
1308 1308
1309 /* no args */ 1309 /* no args */
1310 if (argc != 0) 1310 if (argc != 0)
1311 usage(); 1311 usage();
1312 1312
1313 error = ioctl(fd, ATABUSIORESET, NULL); 1313 error = ioctl(fd, ATABUSIORESET, NULL);
1314 1314
1315 if (error == -1) 1315 if (error == -1)
1316 err(1, "ATABUSIORESET failed"); 1316 err(1, "ATABUSIORESET failed");
1317} 1317}