GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/atactl/atactl.c Lines: 0 779 0.0 %
Date: 2017-11-07 Branches: 0 425 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: atactl.c,v 1.46 2015/08/20 22:02:20 deraadt Exp $	*/
2
/*	$NetBSD: atactl.c,v 1.4 1999/02/24 18:49:14 jwise Exp $	*/
3
4
/*-
5
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6
 * All rights reserved.
7
 *
8
 * This code is derived from software contributed to The NetBSD Foundation
9
 * by Ken Hornstein.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGE.
31
 */
32
33
/*
34
 * atactl(8) - a program to control ATA devices.
35
 */
36
37
#include <sys/param.h>	/* DEV_BSIZE */
38
#include <sys/ioctl.h>
39
40
#include <err.h>
41
#include <errno.h>
42
#include <fcntl.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
#include <util.h>
48
49
#include <dev/ata/atareg.h>
50
#include <dev/ic/wdcreg.h>
51
#include <dev/ic/wdcevent.h>
52
#include <sys/ataio.h>
53
54
#include "atasec.h"
55
#include "atasmart.h"
56
57
struct command {
58
	const char *cmd_name;
59
	void (*cmd_func)(int, char *[]);
60
};
61
62
struct bitinfo {
63
	u_int bitmask;
64
	const char *string;
65
};
66
67
struct valinfo {
68
	int value;
69
	const char *string;
70
};
71
72
int  main(int, char *[]);
73
__dead void usage(void);
74
void ata_command(struct atareq *);
75
void print_bitinfo(const char *, u_int, struct bitinfo *);
76
int  strtoval(const char *, struct valinfo *);
77
const char *valtostr(int, struct valinfo *);
78
79
int	fd;				/* file descriptor for device */
80
81
extern char *__progname;		/* from crt0.o */
82
83
void    device_dump(int, char*[]);
84
void	device_identify(int, char *[]);
85
void	device_setidle(int, char *[]);
86
void	device_idle(int, char *[]);
87
void	device_checkpower(int, char *[]);
88
void	device_acoustic(int, char *[]);
89
void	device_apm(int, char *[]);
90
void	device_feature(int, char *[]);
91
void	device_sec_setpass(int, char *[]);
92
void	device_sec_unlock(int, char *[]);
93
void	device_sec_erase(int, char *[]);
94
void	device_sec_freeze(int, char *[]);
95
void	device_sec_disablepass(int, char *[]);
96
void	device_smart_enable(int, char *[]);
97
void	device_smart_disable(int, char *[]);
98
void	device_smart_status(int, char *[]);
99
void	device_smart_autosave(int, char *[]);
100
void	device_smart_offline(int, char *[]);
101
void	device_smart_read(int, char *[]);
102
void	device_smart_readlog(int, char *[]);
103
void	device_attr(int, char *[]);
104
105
void	smart_print_errdata(struct smart_log_errdata *);
106
int	smart_cksum(u_int8_t *, size_t);
107
108
char 	*sec_getpass(int, int);
109
110
struct command commands[] = {
111
	{ "dump",		device_dump },
112
	{ "identify",		device_identify },
113
	{ "setidle",		device_setidle },
114
	{ "setstandby",		device_setidle },
115
	{ "idle",		device_idle },
116
	{ "standby",		device_idle },
117
	{ "sleep",		device_idle },
118
	{ "checkpower",		device_checkpower },
119
	{ "acousticdisable",	device_feature },
120
	{ "acousticset",	device_acoustic },
121
	{ "apmdisable",		device_feature },
122
	{ "apmset",		device_apm },
123
	{ "poddisable",		device_feature },
124
	{ "podenable",		device_feature },
125
	{ "puisdisable",	device_feature },
126
	{ "puisenable",		device_feature },
127
	{ "puisspinup",		device_feature },
128
	{ "readaheaddisable",	device_feature },
129
	{ "readaheadenable",	device_feature },
130
	{ "secsetpass",		device_sec_setpass },
131
	{ "secunlock",		device_sec_unlock },
132
	{ "secerase",		device_sec_erase },
133
	{ "secfreeze",		device_sec_freeze },
134
	{ "secdisablepass",	device_sec_disablepass },
135
	{ "smartenable", 	device_smart_enable },
136
	{ "smartdisable", 	device_smart_disable },
137
	{ "smartstatus", 	device_smart_status },
138
	{ "smartautosave",	device_smart_autosave },
139
	{ "smartoffline",	device_smart_offline },
140
	{ "smartread",		device_smart_read },
141
	{ "smartreadlog",	device_smart_readlog },
142
	{ "readattr",		device_attr },
143
	{ "writecachedisable",	device_feature },
144
	{ "writecacheenable",	device_feature },
145
	{ NULL,		NULL },
146
};
147
148
/*
149
 * Tables containing bitmasks used for error reporting and
150
 * device identification.
151
 */
152
153
struct bitinfo ata_caps[] = {
154
	{ ATA_CAP_STBY, "ATA standby timer values" },
155
	{ WDC_CAP_IORDY, "IORDY operation" },
156
	{ WDC_CAP_IORDY_DSBL, "IORDY disabling" },
157
	{ 0, NULL },
158
};
159
160
struct bitinfo ata_vers[] = {
161
	{ WDC_VER_ATA1,	 "ATA-1" },
162
	{ WDC_VER_ATA2,	 "ATA-2" },
163
	{ WDC_VER_ATA3,	 "ATA-3" },
164
	{ WDC_VER_ATA4,	 "ATA-4" },
165
	{ WDC_VER_ATA5,	 "ATA-5" },
166
	{ WDC_VER_ATA6,	 "ATA-6" },
167
	{ WDC_VER_ATA7,	 "ATA-7" },
168
	{ WDC_VER_ATA8,	 "ATA-8" },
169
	{ WDC_VER_ATA9,	 "ATA-9" },
170
	{ WDC_VER_ATA10, "ATA-10" },
171
	{ WDC_VER_ATA11, "ATA-11" },
172
	{ WDC_VER_ATA12, "ATA-12" },
173
	{ WDC_VER_ATA13, "ATA-13" },
174
	{ WDC_VER_ATA14, "ATA-14" },
175
	{ 0, NULL },
176
};
177
178
struct bitinfo ata_cmd_set1[] = {
179
	{ WDC_CMD1_NOP, "NOP command" },
180
	{ WDC_CMD1_RB, "READ BUFFER command" },
181
	{ WDC_CMD1_WB, "WRITE BUFFER command" },
182
	{ WDC_CMD1_HPA, "Host Protected Area feature set" },
183
	{ WDC_CMD1_DVRST, "DEVICE RESET command" },
184
	{ WDC_CMD1_SRV, "SERVICE interrupt" },
185
	{ WDC_CMD1_RLSE, "Release interrupt" },
186
	{ WDC_CMD1_AHEAD, "Read look-ahead" },
187
	{ WDC_CMD1_CACHE, "Write cache" },
188
	{ WDC_CMD1_PKT, "PACKET command feature set" },
189
	{ WDC_CMD1_PM, "Power Management feature set" },
190
	{ WDC_CMD1_REMOV, "Removable Media feature set" },
191
	{ WDC_CMD1_SEC, "Security Mode feature set" },
192
	{ WDC_CMD1_SMART, "SMART feature set" },
193
	{ 0, NULL },
194
};
195
196
struct bitinfo ata_cmd_set2[] = {
197
	{ ATAPI_CMD2_FCE, "Flush Cache Ext command" },
198
	{ ATAPI_CMD2_FC, "Flush Cache command" },
199
	{ ATAPI_CMD2_DCO, "Device Configuration Overlay feature set" },
200
	{ ATAPI_CMD2_48AD, "48bit address feature set" },
201
	{ ATAPI_CMD2_AAM, "Automatic Acoustic Management feature set" },
202
	{ ATAPI_CMD2_SM, "Set Max security extension commands" },
203
	{ ATAPI_CMD2_SF, "Set Features subcommand required" },
204
	{ ATAPI_CMD2_PUIS, "Power-up in standby feature set" },
205
	{ WDC_CMD2_RMSN, "Removable Media Status Notification feature set" },
206
	{ ATA_CMD2_APM, "Advanced Power Management feature set" },
207
	{ ATA_CMD2_CFA, "CFA feature set" },
208
	{ ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" },
209
	{ WDC_CMD2_DM, "DOWNLOAD MICROCODE command" },
210
	{ 0, NULL },
211
};
212
213
struct bitinfo ata_cmd_ext[] = {
214
	{ ATAPI_CMDE_IIUF, "IDLE IMMEDIATE with UNLOAD FEATURE" },
215
	{ ATAPI_CMDE_MSER, "Media serial number" },
216
	{ ATAPI_CMDE_TEST, "SMART self-test" },
217
	{ ATAPI_CMDE_SLOG, "SMART error logging" },
218
	{ 0, NULL },
219
};
220
221
/*
222
 * Tables containing bitmasks and values used for
223
 * SMART commands.
224
 */
225
226
struct bitinfo smart_offcap[] = {
227
	{ SMART_OFFCAP_EXEC, "execute immediate" },
228
	{ SMART_OFFCAP_ABORT, "abort/restart" },
229
	{ SMART_OFFCAP_READSCAN, "read scanning" },
230
	{ SMART_OFFCAP_SELFTEST, "self-test routines" },
231
	{ 0, NULL}
232
};
233
234
struct bitinfo smart_smartcap[] = {
235
	{ SMART_SMARTCAP_SAVE, "saving SMART data" },
236
	{ SMART_SMARTCAP_AUTOSAVE, "enable/disable attribute autosave" },
237
	{ 0, NULL }
238
};
239
240
struct valinfo smart_autosave[] = {
241
	{ SMART_AUTOSAVE_EN, "enable" },
242
	{ SMART_AUTOSAVE_DS, "disable" },
243
	{ 0, NULL }
244
};
245
246
struct valinfo smart_offline[] = {
247
	{ SMART_OFFLINE_COLLECT, "collect" },
248
	{ SMART_OFFLINE_SHORTOFF, "shortoffline" },
249
	{ SMART_OFFLINE_EXTENOFF, "extenoffline" },
250
	{ SMART_OFFLINE_ABORT, "abort" },
251
	{ SMART_OFFLINE_SHORTCAP, "shortcaptive" },
252
	{ SMART_OFFLINE_EXTENCAP, "extencaptive" },
253
	{ 0, NULL }
254
};
255
256
struct valinfo smart_readlog[] = {
257
	{ SMART_READLOG_DIR, "directory" },
258
	{ SMART_READLOG_SUM, "summary" },
259
	{ SMART_READLOG_COMP, "comp" },
260
	{ SMART_READLOG_SELF, "selftest" },
261
	{ 0, NULL }
262
};
263
264
struct valinfo smart_offstat[] = {
265
	{ SMART_OFFSTAT_NOTSTART, "never started" },
266
	{ SMART_OFFSTAT_COMPLETE, "completed ok" },
267
	{ SMART_OFFSTAT_SUSPEND, "suspended by an interrupting command" },
268
	{ SMART_OFFSTAT_INTR, "aborted by an interrupting command" },
269
	{ SMART_OFFSTAT_ERROR, "aborted due to fatal error" },
270
	{ 0, NULL }
271
};
272
273
struct valinfo smart_selfstat[] = {
274
	{ SMART_SELFSTAT_COMPLETE, "completed ok or not started" },
275
	{ SMART_SELFSTAT_ABORT, "aborted" },
276
	{ SMART_SELFSTAT_INTR, "hardware or software reset" },
277
	{ SMART_SELFSTAT_ERROR, "fatal error" },
278
	{ SMART_SELFSTAT_UNKFAIL, "unknown test element failed" },
279
	{ SMART_SELFSTAT_ELFAIL, "electrical test element failed" },
280
	{ SMART_SELFSTAT_SRVFAIL, "servo test element failed" },
281
	{ SMART_SELFSTAT_RDFAIL, "read test element failed" },
282
	{ 0, NULL }
283
};
284
285
struct valinfo smart_logstat[] = {
286
	{ SMART_LOG_STATE_UNK, "unknown" },
287
	{ SMART_LOG_STATE_SLEEP, "sleep" },
288
	{ SMART_LOG_STATE_ACTIDL, "active/idle" },
289
	{ SMART_LOG_STATE_OFFSELF, "off-line or self-test" },
290
	{ 0, NULL }
291
};
292
293
/*
294
 * Tables containing values used for reading
295
 * device attributes.
296
 */
297
298
struct valinfo ibm_attr_names[] = {
299
	{ 1, "Raw Read Error Rate" },
300
	{ 2, "Throughput Performance" },
301
	{ 3, "Spin Up Time" },
302
	{ 4, "Start/Stop Count" },
303
	{ 5, "Reallocated Sector Count" },
304
	{ 6, "Read Channel Margin" },
305
	{ 7, "Seek Error Rate" },
306
	{ 8, "Seek Time Performance" },
307
	{ 9, "Power-On Hours Count" },
308
	{ 10, "Spin Retry Count" },
309
	{ 11, "Calibration Retry Count" },
310
	{ 12, "Device Power Cycle Count" },
311
	{ 13, "Soft Read Error Rate" },
312
	{ 189, "High Fly Writes" },
313
	{ 190, "Airflow Temperature" },
314
	{ 191, "G-Sense Error Rate" },
315
	{ 192, "Power-Off Retract Count" },
316
	{ 193, "Load Cycle Count" },
317
	{ 194, "Temperature" },
318
	{ 195, "Hardware ECC Recovered" },
319
	{ 196, "Reallocation Event Count" },
320
	{ 197, "Current Pending Sector Count" },
321
	{ 198, "Off-Line Scan Uncorrectable Sector Count" },
322
	{ 199, "Ultra DMA CRC Error Count" },
323
	{ 200, "Write Error Rate" },
324
	{ 201, "Soft Read Error Rate" },
325
	{ 202, "Data Address Mark Errors" },
326
	{ 203, "Run Out Cancel" },
327
	{ 204, "Soft ECC Correction" },
328
	{ 205, "Thermal Asperity Check" },
329
	{ 206, "Flying Height" },
330
	{ 207, "Spin High Current" },
331
	{ 208, "Spin Buzz" },
332
	{ 209, "Offline Seek Performance" },
333
	{ 220, "Disk Shift" },
334
	{ 221, "G-Sense Error Rate" },
335
	{ 222, "Loaded Hours" },
336
	{ 223, "Load/Unload Retry Count" },
337
	{ 224, "Load Friction" },
338
	{ 225, "Load/Unload Cycle Count" },
339
	{ 226, "Load-In Time" },
340
	{ 227, "Torque Amplification Count" },
341
	{ 228, "Power-Off Retract Count" },
342
	{ 230, "GMR Head Amplitude" },
343
	{ 231, "Temperature" },
344
	{ 240, "Head Flying Hours" },
345
	{ 250, "Read Error Retry Rate" },
346
	{ 0, NULL },
347
};
348
349
#define MAKEWORD(b1, b2) \
350
	(b2 << 8 | b1)
351
#define MAKEDWORD(b1, b2, b3, b4) \
352
	(b4 << 24 | b3 << 16 | b2 << 8 | b1)
353
354
int
355
main(int argc, char *argv[])
356
{
357
	struct command	*cmdp;
358
359
	if (argc < 2)
360
		usage();
361
362
	/*
363
	 * Open the device
364
	 */
365
	if ((fd = opendev(argv[1], O_RDWR, OPENDEV_PART, NULL)) == -1)
366
		err(1, "%s", argv[1]);
367
368
	/* Skip program name and device name. */
369
	if (argc != 2) {
370
		argv += 2;
371
		argc -= 2;
372
	} else {
373
		argv[1] = "identify";
374
		argv += 1;
375
		argc -= 1;
376
	}
377
378
	/* Look up and call the command. */
379
	for (cmdp = commands; cmdp->cmd_name != NULL; cmdp++)
380
		if (strcmp(argv[0], cmdp->cmd_name) == 0)
381
			break;
382
	if (cmdp->cmd_name == NULL)
383
		errx(1, "unknown command: %s", argv[0]);
384
385
	(cmdp->cmd_func)(argc, argv);
386
387
	return (0);
388
}
389
390
__dead void
391
usage(void)
392
{
393
394
	fprintf(stderr, "usage: %s device [command [arg]]\n", __progname);
395
	exit(1);
396
}
397
398
/*
399
 * Wrapper that calls ATAIOCCOMMAND and checks for errors
400
 */
401
void
402
ata_command(struct atareq *req)
403
{
404
	if (ioctl(fd, ATAIOCCOMMAND, req) == -1)
405
		err(1, "ATAIOCCOMMAND failed");
406
407
	switch (req->retsts) {
408
409
	case ATACMD_OK:
410
		return;
411
	case ATACMD_TIMEOUT:
412
		errx(1, "ATA command timed out");
413
	case ATACMD_DF:
414
		errx(1, "ATA device returned a Device Fault");
415
	case ATACMD_ERROR:
416
		if (req->error & WDCE_ABRT)
417
			errx(1, "ATA device returned Aborted Command");
418
		else
419
			errx(1, "ATA device returned error register %0x",
420
			    req->error);
421
	default:
422
		errx(1, "ATAIOCCOMMAND returned unknown result code %d",
423
		    req->retsts);
424
	}
425
}
426
427
/*
428
 * Print out strings associated with particular bitmasks
429
 */
430
void
431
print_bitinfo(const char *f, u_int bits, struct bitinfo *binfo)
432
{
433
434
	for (; binfo->bitmask != 0; binfo++)
435
		if (bits & binfo->bitmask)
436
			printf(f, binfo->string);
437
}
438
439
/*
440
 * strtoval():
441
 *    returns value associated with given string,
442
 *    if no value found -1 is returned.
443
 */
444
int
445
strtoval(const char *str, struct valinfo *vinfo)
446
{
447
	for (; vinfo->string != NULL; vinfo++)
448
		if (strcmp(str, vinfo->string) == 0)
449
			return (vinfo->value);
450
	return (-1);
451
}
452
453
/*
454
 * valtostr():
455
 *    returns string associated with given value,
456
 *    if no string found NULL is returned.
457
 */
458
const char *
459
valtostr(int val, struct valinfo *vinfo)
460
{
461
	for (; vinfo->string != NULL; vinfo++)
462
		if (val == vinfo->value)
463
			return (vinfo->string);
464
	return (NULL);
465
}
466
467
/*
468
 * DEVICE COMMANDS
469
 */
470
471
/*
472
 * device dump:
473
 *
474
 * extract issued ATA requests from the log buffer
475
 */
476
void
477
device_dump(int argc, char *argv[])
478
{
479
	unsigned char buf[131072];
480
	atagettrace_t agt;
481
	unsigned int total;
482
	unsigned int p = 0;
483
	int type;
484
	const char *types[] = { NULL, "status", "error", "ATAPI",
485
	    "ATAPI done", "ATA cmd", "ATA", "select slave",
486
	    "select master", "register read", "ATA LBA48" };
487
	int num_types = sizeof(types) / sizeof(types[0]);
488
	int info;
489
	int entrysize;
490
	int i;
491
	int flags;
492
493
	if (argc != 1)
494
		goto usage;
495
496
	memset(&agt, 0, sizeof(agt));
497
	agt.buf_size = sizeof(buf);
498
	agt.buf = buf;
499
500
	if (ioctl(fd, ATAIOGETTRACE, &agt) == -1)
501
		err(1, "ATAIOGETTRACE failed");
502
503
	total = agt.bytes_copied;
504
505
	/* Parse entries */
506
	while (p < total) {
507
		type = buf[p++];
508
		if (p >= total)
509
			return;
510
		if (type <= 0 || type >= num_types)
511
			return;
512
513
		info = buf[p++];
514
		if (p >= total)
515
			return;
516
		entrysize = (info & 0x1f);
517
518
		printf ("ch %d", (info >> 5) & 0x7);
519
		printf(": %s", types[type]);
520
521
		switch (type) {
522
		case WDCEVENT_STATUS:
523
			if (entrysize != 1)
524
				return;
525
526
			printf(": 0x%x", buf[p]);
527
			if (buf[p] & WDCS_BSY)
528
				printf(" BSY");
529
			if (buf[p] & WDCS_DRDY)
530
				printf(" DRDY");
531
			if (buf[p] & WDCS_DWF)
532
				printf(" DWF");
533
			if (buf[p] & WDCS_DSC)
534
				printf(" DSC");
535
			if (buf[p] & WDCS_DRQ)
536
				printf(" DRQ");
537
			if (buf[p] & WDCS_CORR)
538
				printf(" CORR");
539
			if (buf[p] & WDCS_IDX)
540
				printf(" IDX");
541
			if (buf[p] & WDCS_ERR)
542
				printf(" ERR");
543
544
			p++;
545
			entrysize = 0;
546
			break;
547
		case WDCEVENT_ERROR:
548
			if (entrysize != 1)
549
				return;
550
551
			printf(": 0x%x", buf[p]);
552
			if (buf[p] & WDCE_BBK)
553
				printf(" BBK/CRC");
554
			if (buf[p] & WDCE_UNC)
555
				printf(" UNC");
556
			if (buf[p] & WDCE_MC)
557
				printf(" MC");
558
			if (buf[p] & WDCE_IDNF)
559
				printf(" IDNF");
560
			if (buf[p] & WDCE_MCR)
561
				printf(" MCR");
562
			if (buf[p] & WDCE_ABRT)
563
				printf(" ABRT");
564
			if (buf[p] & WDCE_TK0NF)
565
				printf(" TK0NF");
566
			if (buf[p] & WDCE_AMNF)
567
				printf(" AMNF");
568
569
			p++;
570
			entrysize = 0;
571
			break;
572
		case WDCEVENT_ATAPI_CMD:
573
			if (entrysize < 2 || p + 2 > total)
574
				return;
575
576
			flags = (buf[p] << 8) + buf[p + 1];
577
			printf(": flags 0x%x", flags);
578
			if (flags & 0x0100)
579
				printf(" MEDIA");
580
			if (flags & 0x0080)
581
				printf(" SENSE");
582
			if (flags & 0x0040)
583
				printf(" DMA");
584
			if (flags & 0x0020)
585
				printf(" POLL");
586
			if (flags & 0x0004)
587
				printf(" TIMEOUT");
588
			if (flags & 0x0002)
589
				printf(" ATAPI");
590
591
			p += 2;
592
			entrysize -= 2;
593
			break;
594
		case WDCEVENT_ATAPI_DONE:
595
			if (entrysize != 3 || p + 3 > total)
596
				return;
597
598
			flags = (buf[p] << 8) + buf[p + 1];
599
			printf(": flags 0x%x", flags);
600
			if (flags & 0x0100)
601
				printf(" MEDIA");
602
			if (flags & 0x0080)
603
				printf(" SENSE");
604
			if (flags & 0x0040)
605
				printf(" DMA");
606
			if (flags & 0x0020)
607
				printf(" POLL");
608
			if (flags & 0x0004)
609
				printf(" TIMEOUT");
610
			if (flags & 0x0002)
611
				printf(" ATAPI");
612
613
			printf(", error 0x%x", buf[p + 2]);
614
			switch (buf[p + 2]) {
615
			case 1:
616
				printf(" (sense)");
617
				break;
618
			case 2:
619
				printf(" (driver failure)");
620
				break;
621
			case 3:
622
				printf(" (timeout)");
623
				break;
624
			case 4:
625
				printf(" (busy)");
626
				break;
627
			case 5:
628
				printf(" (ATAPI sense)");
629
				break;
630
			case 8:
631
				printf(" (reset)");
632
				break;
633
			}
634
635
			p += 3;
636
			entrysize  = 0;
637
			break;
638
		case WDCEVENT_ATA_LONG:
639
			if (entrysize != 7 || p + 7 > total)
640
				return;
641
642
			printf(": ");
643
			switch (buf[p + 6]) {
644
			case WDCC_READDMA:
645
				printf("READ DMA");
646
				break;
647
			case WDCC_WRITEDMA:
648
				printf("WRITE DMA");
649
				break;
650
			default:
651
				printf("CMD 0x%x", buf[p + 6]);
652
			}
653
			printf(" head %d, precomp %d, cyl_hi %d, "
654
			    "cyl_lo %d, sec %d, cnt %d",
655
			    buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
656
			    buf[p + 4], buf[p + 5]);
657
658
			p += 7;
659
			entrysize = 0;
660
			break;
661
		case WDCEVENT_REG:
662
			if (entrysize != 3 || p + 3 > total)
663
				return;
664
665
			switch (buf[p]) {
666
			case 1:
667
				printf(": error");
668
				break;
669
			case 2:
670
				printf(": ireason");
671
				break;
672
			case 3:
673
				printf(": lba_lo");
674
				break;
675
			case 4:
676
				printf(": lba_mi");
677
				break;
678
			case 5:
679
				printf(": lba_hi");
680
				break;
681
			case 6:
682
				printf(": sdh");
683
				break;
684
			case 7:
685
				printf(": status");
686
				break;
687
			case 8:
688
				printf(": altstatus");
689
				break;
690
			default:
691
				printf(": unknown register %d", buf[p]);
692
			}
693
			printf(": 0x%x", (buf[p + 1] << 8) + buf[p + 2]);
694
695
			p += 3;
696
			entrysize = 0;
697
			break;
698
		case WDCEVENT_ATA_EXT:
699
			if (entrysize != 9 || p + 9 > total)
700
				return;
701
702
			printf(": ");
703
			switch (buf[p + 8]) {
704
			case WDCC_READDMA_EXT:
705
				printf("READ DMA EXT");
706
				break;
707
			case WDCC_WRITEDMA_EXT:
708
				printf("WRITE DMA EXT");
709
				break;
710
			default:
711
				printf("CMD 0x%x", buf[p + 8]);
712
			}
713
			printf(" lba_hi1 %d, lba_hi2 %d, "
714
			    "lba_mi1 %d, lba_mi2 %d, lba_lo1 %d, lba_lo2 %d, "
715
			    "count1 %d, count2 %d",
716
			    buf[p], buf[p + 1], buf[p + 2], buf[p + 3],
717
			    buf[p + 4], buf[p + 5], buf[p + 6],
718
			    buf[p + 7]);
719
720
			p += 9;
721
			entrysize = 0;
722
			break;
723
		}
724
725
		if (entrysize > 0)
726
			printf(":");
727
		for (i = 0; i < entrysize; i++) {
728
			printf (" 0x%02x", buf[p]);
729
			if (++p >= total)
730
				break;
731
		}
732
		printf("\n");
733
	}
734
735
	return;
736
737
usage:
738
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
739
	exit(1);
740
}
741
742
/*
743
 * device_identify:
744
 *
745
 *	Display the identity of the device
746
 */
747
void
748
device_identify(int argc, char *argv[])
749
{
750
	struct ataparams *inqbuf;
751
	struct atareq req;
752
	char inbuf[DEV_BSIZE];
753
	u_int64_t capacity;
754
	u_int8_t *s;
755
756
	if (argc != 1)
757
		goto usage;
758
759
	memset(&inbuf, 0, sizeof(inbuf));
760
	memset(&req, 0, sizeof(req));
761
762
	inqbuf = (struct ataparams *) inbuf;
763
764
	req.flags = ATACMD_READ;
765
	req.command = WDCC_IDENTIFY;
766
	req.databuf = (caddr_t) inbuf;
767
	req.datalen = sizeof(inbuf);
768
	req.timeout = 1000;
769
770
	ata_command(&req);
771
772
	if (BYTE_ORDER == BIG_ENDIAN) {
773
		swap16_multi((u_int16_t *)inbuf, 10);
774
		swap16_multi(((u_int16_t *)inbuf) + 20, 3);
775
		swap16_multi(((u_int16_t *)inbuf) + 47, sizeof(inbuf) / 2 - 47);
776
	}
777
778
	if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
779
	      ((inqbuf->atap_model[0] == 'N' &&
780
		  inqbuf->atap_model[1] == 'E') ||
781
	       (inqbuf->atap_model[0] == 'F' &&
782
		  inqbuf->atap_model[1] == 'X')))) {
783
		swap16_multi((u_int16_t *)(inqbuf->atap_model),
784
		    sizeof(inqbuf->atap_model) / 2);
785
		swap16_multi((u_int16_t *)(inqbuf->atap_serial),
786
		    sizeof(inqbuf->atap_serial) / 2);
787
		swap16_multi((u_int16_t *)(inqbuf->atap_revision),
788
		    sizeof(inqbuf->atap_revision) / 2);
789
	}
790
791
	/*
792
	 * Strip blanks off of the info strings.
793
	 */
794
795
	for (s = &inqbuf->atap_model[sizeof(inqbuf->atap_model) - 1];
796
	    s >= inqbuf->atap_model && *s == ' '; s--)
797
		*s = '\0';
798
799
	for (s = &inqbuf->atap_revision[sizeof(inqbuf->atap_revision) - 1];
800
	    s >= inqbuf->atap_revision && *s == ' '; s--)
801
		*s = '\0';
802
803
	for (s = &inqbuf->atap_serial[sizeof(inqbuf->atap_serial) - 1];
804
	    s >= inqbuf->atap_serial && *s == ' '; s--)
805
		*s = '\0';
806
807
	printf("Model: %.*s, Rev: %.*s, Serial #: %.*s\n",
808
	    (int) sizeof(inqbuf->atap_model), inqbuf->atap_model,
809
	    (int) sizeof(inqbuf->atap_revision), inqbuf->atap_revision,
810
	    (int) sizeof(inqbuf->atap_serial), inqbuf->atap_serial);
811
812
	printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
813
	       "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
814
	       "removable");
815
816
	if (inqbuf->atap_cmd2_en & ATAPI_CMD2_48AD)
817
		capacity = ((u_int64_t)inqbuf->atap_max_lba[3] << 48) |
818
		    ((u_int64_t)inqbuf->atap_max_lba[2] << 32) |
819
		    ((u_int64_t)inqbuf->atap_max_lba[1] << 16) |
820
		    (u_int64_t)inqbuf->atap_max_lba[0];
821
	else
822
		capacity = (inqbuf->atap_capacity[1] << 16) |
823
		    inqbuf->atap_capacity[0];
824
	printf("Cylinders: %d, heads: %d, sec/track: %d, total "
825
	    "sectors: %llu\n", inqbuf->atap_cylinders,
826
	    inqbuf->atap_heads, inqbuf->atap_sectors, capacity);
827
828
	if ((inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ) &&
829
	    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK))
830
		printf("Device supports command queue depth of %d\n",
831
		    (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1);
832
833
	printf("Device capabilities:\n");
834
	print_bitinfo("\t%s\n", inqbuf->atap_capabilities1, ata_caps);
835
836
	if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) {
837
		printf("Device supports the following standards:\n");
838
		print_bitinfo("%s ", inqbuf->atap_ata_major, ata_vers);
839
		printf("\n");
840
	}
841
842
	if ((inqbuf->atap_cmd_set1 & WDC_CMD1_SEC) &&
843
	    inqbuf->atap_mpasswd_rev != 0 &&
844
	    inqbuf->atap_mpasswd_rev != 0xffff)
845
		printf("Master password revision code 0x%04x\n",
846
		    inqbuf->atap_mpasswd_rev);
847
848
	if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff &&
849
	    inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) {
850
		printf("Device supports the following command sets:\n");
851
		print_bitinfo("\t%s\n", inqbuf->atap_cmd_set1, ata_cmd_set1);
852
		print_bitinfo("\t%s\n", inqbuf->atap_cmd_set2, ata_cmd_set2);
853
		print_bitinfo("\t%s\n", inqbuf->atap_cmd_ext, ata_cmd_ext);
854
	}
855
856
	if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
857
		printf("Device has enabled the following command "
858
		    "sets/features:\n");
859
		print_bitinfo("\t%s\n", inqbuf->atap_cmd1_en, ata_cmd_set1);
860
		print_bitinfo("\t%s\n", inqbuf->atap_cmd2_en, ata_cmd_set2);
861
	}
862
863
	return;
864
865
usage:
866
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
867
	exit(1);
868
}
869
870
/*
871
 * device idle:
872
 *
873
 * issue the IDLE IMMEDIATE command to the drive
874
 */
875
void
876
device_idle(int argc, char *argv[])
877
{
878
	struct atareq req;
879
880
	if (argc != 1)
881
		goto usage;
882
883
	memset(&req, 0, sizeof(req));
884
885
	if (strcmp(argv[0], "idle") == 0)
886
		req.command = WDCC_IDLE_IMMED;
887
	else if (strcmp(argv[0], "standby") == 0)
888
		req.command = WDCC_STANDBY_IMMED;
889
	else
890
		req.command = WDCC_SLEEP;
891
892
	req.timeout = 1000;
893
894
	ata_command(&req);
895
896
	return;
897
usage:
898
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
899
	exit(1);
900
}
901
902
/*
903
 * SECURITY SET PASSWORD command
904
 */
905
void
906
device_sec_setpass(int argc, char *argv[])
907
{
908
	struct atareq req;
909
	struct sec_password pwd;
910
	char *pass, inbuf[DEV_BSIZE];
911
	struct ataparams *inqbuf = (struct ataparams *)inbuf;
912
913
	if (argc < 2)
914
		goto usage;
915
916
	memset(&pwd, 0, sizeof(pwd));
917
918
	if (strcmp(argv[1], "user") == 0 && argc == 3)
919
		pwd.ctrl |= SEC_PASSWORD_USER;
920
	else if (strcmp(argv[1], "master") == 0 && argc == 2)
921
		pwd.ctrl |= SEC_PASSWORD_MASTER;
922
	else
923
		goto usage;
924
	if (argc == 3) {
925
		if (strcmp(argv[2], "high") == 0)
926
			pwd.ctrl |= SEC_LEVEL_HIGH;
927
		else if (strcmp(argv[2], "maximum") == 0)
928
			pwd.ctrl |= SEC_LEVEL_MAX;
929
		else
930
			goto usage;
931
	}
932
933
	/*
934
	 * Issue IDENTIFY command to obtain master password
935
	 * revision code and decrement its value.
936
	 * The valid revision codes are 0x0001 through 0xfffe.
937
	 * If the device returns 0x0000 or 0xffff as a revision
938
	 * code then the master password revision code is not
939
	 * supported so don't touch it.
940
	 */
941
	memset(&inbuf, 0, sizeof(inbuf));
942
	memset(&req, 0, sizeof(req));
943
944
	req.command = WDCC_IDENTIFY;
945
	req.timeout = 1000;
946
	req.flags = ATACMD_READ;
947
	req.databuf = (caddr_t)inbuf;
948
	req.datalen = sizeof(inbuf);
949
950
	ata_command(&req);
951
952
	pwd.revision = inqbuf->atap_mpasswd_rev;
953
	if (pwd.revision != 0 && pwd.revision != 0xffff && --pwd.revision == 0)
954
		pwd.revision = 0xfffe;
955
956
	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 1);
957
	memcpy(pwd.password, pass, strlen(pass));
958
959
	memset(&req, 0, sizeof(req));
960
961
	req.command = ATA_SEC_SET_PASSWORD;
962
	req.timeout = 1000;
963
	req.flags = ATACMD_WRITE;
964
	req.databuf = (caddr_t)&pwd;
965
	req.datalen = sizeof(pwd);
966
967
	ata_command(&req);
968
969
	return;
970
usage:
971
	fprintf(stderr, "usage: %s device %s user high | maximum\n",
972
	    __progname, argv[0]);
973
	fprintf(stderr, "       %s device %s master\n", __progname, argv[0]);
974
	exit(1);
975
}
976
977
/*
978
 * SECURITY UNLOCK command
979
 */
980
void
981
device_sec_unlock(int argc, char *argv[])
982
{
983
	struct atareq req;
984
	struct sec_password pwd;
985
	char *pass;
986
987
	if (argc != 2)
988
		goto usage;
989
990
	memset(&pwd, 0, sizeof(pwd));
991
992
	if (strcmp(argv[1], "user") == 0)
993
		pwd.ctrl |= SEC_PASSWORD_USER;
994
	else if (strcmp(argv[1], "master") == 0)
995
		pwd.ctrl |= SEC_PASSWORD_MASTER;
996
	else
997
		goto usage;
998
999
	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1000
	memcpy(pwd.password, pass, strlen(pass));
1001
1002
	memset(&req, 0, sizeof(req));
1003
1004
	req.command = ATA_SEC_UNLOCK;
1005
	req.timeout = 1000;
1006
	req.flags = ATACMD_WRITE;
1007
	req.databuf = (caddr_t)&pwd;
1008
	req.datalen = sizeof(pwd);
1009
1010
	ata_command(&req);
1011
1012
	return;
1013
usage:
1014
	fprintf(stderr, "usage: %s device %s user | master\n", __progname,
1015
	    argv[0]);
1016
	exit(1);
1017
}
1018
1019
/*
1020
 * SECURITY ERASE UNIT command
1021
 */
1022
void
1023
device_sec_erase(int argc, char *argv[])
1024
{
1025
	struct atareq req;
1026
	struct sec_password pwd;
1027
	char *pass;
1028
1029
	if (argc < 2)
1030
		goto usage;
1031
1032
	memset(&pwd, 0, sizeof(pwd));
1033
1034
	if (strcmp(argv[1], "user") == 0)
1035
		pwd.ctrl |= SEC_PASSWORD_USER;
1036
	else if (strcmp(argv[1], "master") == 0)
1037
		pwd.ctrl |= SEC_PASSWORD_MASTER;
1038
	else
1039
		goto usage;
1040
	if (argc == 2)
1041
		pwd.ctrl |= SEC_ERASE_NORMAL;
1042
	else if (argc == 3 && strcmp(argv[2], "enhanced") == 0)
1043
		pwd.ctrl |= SEC_ERASE_ENHANCED;
1044
	else
1045
		goto usage;
1046
1047
	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1048
	memcpy(pwd.password, pass, strlen(pass));
1049
1050
	 /* Issue SECURITY ERASE PREPARE command before */
1051
	memset(&req, 0, sizeof(req));
1052
1053
	req.command = ATA_SEC_ERASE_PREPARE;
1054
	req.timeout = 1000;
1055
1056
	ata_command(&req);
1057
1058
	memset(&req, 0, sizeof(req));
1059
1060
	req.command = ATA_SEC_ERASE_UNIT;
1061
	req.timeout = 1000;
1062
	req.flags = ATACMD_WRITE;
1063
	req.databuf = (caddr_t)&pwd;
1064
	req.datalen = sizeof(pwd);
1065
1066
	ata_command(&req);
1067
1068
	return;
1069
usage:
1070
	fprintf(stderr, "usage: %s device %s user | master [enhanced]\n",
1071
	    __progname, argv[0]);
1072
	exit(1);
1073
}
1074
1075
/*
1076
 * SECURITY FREEZE LOCK command
1077
 */
1078
void
1079
device_sec_freeze(int argc, char *argv[])
1080
{
1081
	struct atareq req;
1082
1083
	if (argc != 1)
1084
		goto usage;
1085
1086
	memset(&req, 0, sizeof(req));
1087
1088
	req.command = ATA_SEC_FREEZE_LOCK;
1089
	req.timeout = 1000;
1090
1091
	ata_command(&req);
1092
1093
	return;
1094
usage:
1095
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1096
	exit(1);
1097
}
1098
1099
/*
1100
 * SECURITY DISABLE PASSWORD command
1101
 */
1102
void
1103
device_sec_disablepass(int argc, char *argv[])
1104
{
1105
	struct atareq req;
1106
	struct sec_password pwd;
1107
	char *pass;
1108
1109
	if (argc != 2)
1110
		goto usage;
1111
1112
	memset(&pwd, 0, sizeof(pwd));
1113
1114
	if (strcmp(argv[1], "user") == 0)
1115
		pwd.ctrl |= SEC_PASSWORD_USER;
1116
	else if (strcmp(argv[1], "master") == 0)
1117
		pwd.ctrl |= SEC_PASSWORD_MASTER;
1118
	else
1119
		goto usage;
1120
1121
	pass = sec_getpass(pwd.ctrl & SEC_PASSWORD_MASTER, 0);
1122
	memcpy(pwd.password, pass, strlen(pass));
1123
1124
	memset(&req, 0, sizeof(req));
1125
1126
	req.command = ATA_SEC_DISABLE_PASSWORD;
1127
	req.timeout = 1000;
1128
	req.flags = ATACMD_WRITE;
1129
	req.databuf = (caddr_t)&pwd;
1130
	req.datalen = sizeof(pwd);
1131
1132
	ata_command(&req);
1133
1134
	return;
1135
usage:
1136
	fprintf(stderr, "usage: %s device %s user | master\n", __progname,
1137
	    argv[0]);
1138
	exit(1);
1139
}
1140
1141
char *
1142
sec_getpass(int ident, int confirm)
1143
{
1144
	char *pass, buf[33];
1145
1146
	if ((pass = getpass(ident ? "Master password:" :
1147
	    "User password:")) == NULL)
1148
		err(1, "getpass()");
1149
	if (strlen(pass) > 32)
1150
		errx(1, "password too long");
1151
	if (confirm) {
1152
		strlcpy(buf, pass, sizeof(buf));
1153
		if ((pass = getpass(ident ? "Retype master password:" :
1154
		    "Retype user password:")) == NULL)
1155
			err(1, "getpass()");
1156
		if (strcmp(pass, buf) != 0)
1157
			errx(1, "password mismatch");
1158
	}
1159
1160
	return (pass);
1161
}
1162
1163
/*
1164
 * SMART ENABLE OPERATIONS command
1165
 */
1166
void
1167
device_smart_enable(int argc, char *argv[])
1168
{
1169
	struct atareq req;
1170
1171
	if (argc != 1)
1172
		goto usage;
1173
1174
	memset(&req, 0, sizeof(req));
1175
1176
	req.command = ATAPI_SMART;
1177
	req.cylinder = 0xc24f;
1178
	req.timeout = 1000;
1179
	req.features = ATA_SMART_EN;
1180
1181
	ata_command(&req);
1182
1183
	return;
1184
usage:
1185
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1186
	exit(1);
1187
}
1188
1189
/*
1190
 * SMART DISABLE OPERATIONS command
1191
 */
1192
void
1193
device_smart_disable(int argc, char *argv[])
1194
{
1195
	struct atareq req;
1196
1197
	if (argc != 1)
1198
		goto usage;
1199
1200
	memset(&req, 0, sizeof(req));
1201
1202
	req.command = ATAPI_SMART;
1203
	req.cylinder = 0xc24f;
1204
	req.timeout = 1000;
1205
	req.features = ATA_SMART_DS;
1206
1207
	ata_command(&req);
1208
1209
	return;
1210
usage:
1211
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1212
	exit(1);
1213
}
1214
1215
/*
1216
 * SMART STATUS command
1217
 */
1218
void
1219
device_smart_status(int argc, char *argv[])
1220
{
1221
	struct atareq req;
1222
1223
	if (argc != 1)
1224
		goto usage;
1225
1226
	memset(&req, 0, sizeof(req));
1227
1228
	req.command = ATAPI_SMART;
1229
	req.cylinder = 0xc24f;
1230
	req.timeout = 1000;
1231
	req.features = ATA_SMART_STATUS;
1232
1233
	ata_command(&req);
1234
1235
	if (req.cylinder == 0xc24f)
1236
		printf("No SMART threshold exceeded\n");
1237
	else if (req.cylinder == 0x2cf4) {
1238
		errx(2, "SMART threshold exceeded!");
1239
	} else {
1240
		errx(1, "Unknown response %02x!", req.cylinder);
1241
	}
1242
1243
	return;
1244
usage:
1245
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1246
	exit(1);
1247
}
1248
1249
/*
1250
 * SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE command
1251
 */
1252
void
1253
device_smart_autosave(int argc, char *argv[])
1254
{
1255
	struct atareq req;
1256
	int val;
1257
1258
	if (argc != 2)
1259
		goto usage;
1260
1261
	memset(&req, 0, sizeof(req));
1262
1263
	req.command = ATAPI_SMART;
1264
	req.cylinder = 0xc24f;
1265
	req.timeout = 1000;
1266
	req.features = ATA_SMART_AUTOSAVE;
1267
	if ((val = strtoval(argv[1], smart_autosave)) == -1)
1268
		goto usage;
1269
	req.sec_num = val;
1270
1271
	ata_command(&req);
1272
1273
	return;
1274
usage:
1275
	fprintf(stderr, "usage: %s device %s enable | disable\n", __progname,
1276
	    argv[0]);
1277
	exit(1);
1278
}
1279
1280
/*
1281
 * SMART EXECUTE OFF-LINE IMMEDIATE command
1282
 */
1283
void
1284
device_smart_offline(int argc, char *argv[])
1285
{
1286
	struct atareq req;
1287
	int val;
1288
1289
	if (argc != 2)
1290
		goto usage;
1291
1292
	memset(&req, 0, sizeof(req));
1293
1294
	req.command = ATAPI_SMART;
1295
	req.cylinder = 0xc24f;
1296
	req.timeout = 1000;
1297
	req.features = ATA_SMART_OFFLINE;
1298
	if ((val = strtoval(argv[1], smart_offline)) == -1)
1299
		goto usage;
1300
	req.sec_num = val;
1301
1302
	ata_command(&req);
1303
1304
	return;
1305
usage:
1306
	fprintf(stderr, "usage: %s device %s subcommand\n", __progname,
1307
	    argv[0]);
1308
	exit(1);
1309
}
1310
1311
/*
1312
 * SMART READ DATA command
1313
 */
1314
void
1315
device_smart_read(int argc, char *argv[])
1316
{
1317
	struct atareq req;
1318
	struct smart_read data;
1319
1320
	if (argc != 1)
1321
		goto usage;
1322
1323
	memset(&req, 0, sizeof(req));
1324
	memset(&data, 0, sizeof(data));
1325
1326
	req.command = ATAPI_SMART;
1327
	req.cylinder = 0xc24f;
1328
	req.timeout = 1000;
1329
	req.features = ATA_SMART_READ;
1330
	req.flags = ATACMD_READ;
1331
	req.databuf = (caddr_t)&data;
1332
	req.datalen = sizeof(data);
1333
1334
	ata_command(&req);
1335
1336
	if (smart_cksum((u_int8_t *)&data, sizeof(data)) != 0)
1337
		errx(1, "Checksum mismatch");
1338
1339
	printf("Off-line data collection:\n");
1340
	printf("    status: %s\n",
1341
	    valtostr(data.offstat & 0x7f, smart_offstat));
1342
	printf("    activity completion time: %d seconds\n",
1343
	    letoh16(data.time));
1344
	printf("    capabilities:\n");
1345
	print_bitinfo("\t%s\n", data.offcap, smart_offcap);
1346
	printf("Self-test execution:\n");
1347
	printf("    status: %s\n", valtostr(SMART_SELFSTAT_STAT(data.selfstat),
1348
	    smart_selfstat));
1349
	if (SMART_SELFSTAT_STAT(data.selfstat) == SMART_SELFSTAT_PROGRESS)
1350
		printf("remains %d%% of total time\n",
1351
		    SMART_SELFSTAT_PCNT(data.selfstat));
1352
	printf("    recommended polling time:\n");
1353
	printf("\tshort routine: %d minutes\n", data.shtime);
1354
	printf("\textended routine: %d minutes\n", data.extime);
1355
	printf("SMART capabilities:\n");
1356
	print_bitinfo("    %s\n", letoh16(data.smartcap), smart_smartcap);
1357
	printf("Error logging: ");
1358
	if (data.errcap & SMART_ERRCAP_ERRLOG)
1359
		printf("supported\n");
1360
	else
1361
		printf("not supported\n");
1362
1363
	return;
1364
usage:
1365
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1366
	exit(1);
1367
}
1368
1369
/*
1370
 * SMART READ LOG command
1371
 */
1372
void
1373
device_smart_readlog(int argc, char *argv[])
1374
{
1375
	struct atareq req;
1376
	int val;
1377
	u_int8_t inbuf[DEV_BSIZE];
1378
1379
	if (argc != 2)
1380
		goto usage;
1381
1382
	memset(&req, 0, sizeof(req));
1383
	memset(&inbuf, 0, sizeof(inbuf));
1384
1385
	req.command = ATAPI_SMART;
1386
	req.cylinder = 0xc24f;
1387
	req.timeout = 1000;
1388
	req.features = ATA_SMART_READLOG;
1389
	req.flags = ATACMD_READ;
1390
	req.sec_count = 1;
1391
	req.databuf = (caddr_t)inbuf;
1392
	req.datalen = sizeof(inbuf);
1393
	if ((val = strtoval(argv[1], smart_readlog)) == -1)
1394
		goto usage;
1395
	req.sec_num = val;
1396
1397
	ata_command(&req);
1398
1399
	if (strcmp(argv[1], "directory") == 0) {
1400
		struct smart_log_dir *data = (struct smart_log_dir *)inbuf;
1401
		int i;
1402
1403
		if (data->version != SMART_LOG_MSECT) {
1404
			printf("Device doesn't support multi-sector logs\n");
1405
			return;
1406
		}
1407
1408
		for (i = 0; i < 255; i++)
1409
			printf("Log address %d: %d sectors\n", i + 1,
1410
			    data->entry[i].sec_num);
1411
	} else if (strcmp(argv[1], "summary") == 0) {
1412
		struct smart_log_sum *data = (struct smart_log_sum *)inbuf;
1413
		int i, n, nerr;
1414
1415
		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1416
			errx(1, "Checksum mismatch");
1417
1418
		if (data->index == 0) {
1419
			printf("No log entries\n");
1420
			return;
1421
		}
1422
1423
		nerr = letoh16(data->err_cnt);
1424
		printf("Error count: %d\n\n", nerr);
1425
		/*
1426
		 * Five error log data structures form a circular
1427
		 * buffer. data->index points to the most recent
1428
		 * record and err_cnt contains total error number.
1429
		 * We pass from the most recent record to the
1430
		 * latest one.
1431
		 */
1432
		i = data->index - 1;
1433
		n = 0;
1434
		do {
1435
			printf("Error %d:\n", n + 1);
1436
			smart_print_errdata(&data->errdata[i--]);
1437
			if (i == -1)
1438
				i = 4;
1439
		} while (++n < (nerr > 5 ? 5 : nerr));
1440
	} else if (strcmp(argv[1], "comp") == 0) {
1441
		struct smart_log_comp *data = (struct smart_log_comp *)inbuf;
1442
		u_int8_t *newbuf;
1443
		int i, n, nerr, nsect;
1444
1445
		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1446
			errx(1, "Checksum mismatch");
1447
1448
		if (data->index == 0) {
1449
			printf("No log entries\n");
1450
			return;
1451
		}
1452
1453
		i = data->index - 1;
1454
		nerr = letoh16(data->err_cnt);
1455
		printf("Error count: %d\n", nerr);
1456
		/*
1457
		 * From the first sector we obtain total error number
1458
		 * and calculate necessary number of sectors to read.
1459
		 * All read error data structures form a circular
1460
		 * buffer and we pass from the most recent record to
1461
		 * the latest one.
1462
		 */
1463
		nsect = nerr / 5 + (nerr % 5 != 0 ? 1 : 0);
1464
		if ((newbuf = calloc(nsect, DEV_BSIZE)) == NULL)
1465
			err(1, "calloc()");
1466
		memset(&req, 0, sizeof(req));
1467
		req.flags = ATACMD_READ;
1468
		req.command = ATAPI_SMART;
1469
		req.features = ATA_SMART_READLOG;
1470
		req.sec_count = nsect;
1471
		req.sec_num = SMART_READLOG_COMP;
1472
		req.cylinder = 0xc24f;
1473
		req.databuf = (caddr_t)newbuf;
1474
		req.datalen = nsect * DEV_BSIZE;
1475
		req.timeout = 1000;
1476
		ata_command(&req);
1477
1478
		n = 0;
1479
		data = (struct smart_log_comp *)
1480
		    (newbuf + (nsect - 1) * DEV_BSIZE);
1481
		do {
1482
			printf("Error %d:\n", n + 1);
1483
			smart_print_errdata(&data->errdata[i-- % 5]);
1484
			if (i == -1)
1485
				i = 254;
1486
			if (i % 5 == 4)
1487
				data = (struct smart_log_comp *)
1488
				    (newbuf + (i / 5) * DEV_BSIZE);
1489
		} while (++n < nerr);
1490
	} else if (strcmp(argv[1], "selftest") == 0) {
1491
		struct smart_log_self *data = (struct smart_log_self *)inbuf;
1492
		int i, n;
1493
1494
		if (smart_cksum(inbuf, sizeof(inbuf)) != 0)
1495
			errx(1, "Checksum mismatch");
1496
1497
		if (data->index == 0) {
1498
			printf("No log entries\n");
1499
			return;
1500
		}
1501
1502
		/* circular buffer of 21 entries */
1503
		i = data->index - 1;
1504
		n = 0;
1505
		do {
1506
			/* don't print empty entries */
1507
			if ((data->desc[i].time1 | data->desc[i].time2) == 0)
1508
				break;
1509
			printf("Test %d\n", n + 1);
1510
			printf("    LBA Low: 0x%x\n", data->desc[i].reg_lbalo);
1511
			printf("    status: %s\n",
1512
			    valtostr(SMART_SELFSTAT_STAT(
1513
			    data->desc[i].selfstat),
1514
			    smart_selfstat));
1515
			printf("    timestamp: %d\n",
1516
			    MAKEWORD(data->desc[i].time1,
1517
				     data->desc[i].time2));
1518
			printf("    failure checkpoint byte: 0x%x\n",
1519
			    data->desc[i].chkpnt);
1520
			printf("    failing LBA: 0x%x\n",
1521
			    MAKEDWORD(data->desc[i].lbafail1,
1522
				      data->desc[i].lbafail2,
1523
				      data->desc[i].lbafail3,
1524
				      data->desc[i].lbafail4));
1525
			if (--i == -1)
1526
				i = 20;
1527
		} while (++n < 21);
1528
	}
1529
1530
	return;
1531
usage:
1532
	fprintf(stderr, "usage: %s device %s log\n", __progname, argv[0]);
1533
	exit(1);
1534
}
1535
1536
#define SMART_PRINTREG(str, reg)				\
1537
	printf(str "0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n",	\
1538
	    data->cmd[0].reg,					\
1539
	    data->cmd[1].reg,					\
1540
	    data->cmd[2].reg,					\
1541
	    data->cmd[3].reg,					\
1542
	    data->cmd[4].reg)
1543
1544
void
1545
smart_print_errdata(struct smart_log_errdata *data)
1546
{
1547
	printf("    error register: 0x%x\n", data->err.reg_err);
1548
	printf("    sector count register: 0x%x\n", data->err.reg_seccnt);
1549
	printf("    LBA Low register: 0x%x\n", data->err.reg_lbalo);
1550
	printf("    LBA Mid register: 0x%x\n", data->err.reg_lbamid);
1551
	printf("    LBA High register: 0x%x\n", data->err.reg_lbahi);
1552
	printf("    device register: 0x%x\n", data->err.reg_dev);
1553
	printf("    status register: 0x%x\n", data->err.reg_stat);
1554
	printf("    state: %s\n", valtostr(data->err.state, smart_logstat));
1555
	printf("    timestamp: %d\n", MAKEWORD(data->err.time1,
1556
					       data->err.time2));
1557
	printf("    history:\n");
1558
	SMART_PRINTREG("\tcontrol register:\t", reg_ctl);
1559
	SMART_PRINTREG("\tfeatures register:\t", reg_feat);
1560
	SMART_PRINTREG("\tsector count register:\t", reg_seccnt);
1561
	SMART_PRINTREG("\tLBA Low register:\t", reg_lbalo);
1562
	SMART_PRINTREG("\tLBA Mid register:\t", reg_lbamid);
1563
	SMART_PRINTREG("\tLBA High register:\t", reg_lbahi);
1564
	SMART_PRINTREG("\tdevice register:\t", reg_dev);
1565
	SMART_PRINTREG("\tcommand register:\t", reg_cmd);
1566
	printf("\ttimestamp:\t\t"
1567
	    "%d\t%d\t%d\t%d\t%d\n",
1568
	    MAKEDWORD(data->cmd[0].time1, data->cmd[0].time2,
1569
		      data->cmd[0].time3, data->cmd[0].time4),
1570
	    MAKEDWORD(data->cmd[1].time1, data->cmd[1].time2,
1571
		      data->cmd[1].time3, data->cmd[1].time4),
1572
	    MAKEDWORD(data->cmd[2].time1, data->cmd[2].time2,
1573
		      data->cmd[2].time3, data->cmd[2].time4),
1574
	    MAKEDWORD(data->cmd[3].time1, data->cmd[3].time2,
1575
		      data->cmd[3].time3, data->cmd[3].time4),
1576
	    MAKEDWORD(data->cmd[4].time1, data->cmd[4].time2,
1577
		      data->cmd[4].time3, data->cmd[4].time4));
1578
}
1579
1580
int
1581
smart_cksum(u_int8_t *data, size_t len)
1582
{
1583
	u_int8_t sum = 0;
1584
	size_t i;
1585
1586
	for (i = 0; i < len; i++)
1587
		sum += data[i];
1588
1589
	return (sum);
1590
}
1591
1592
/*
1593
 * Read device attributes
1594
 */
1595
void
1596
device_attr(int argc, char *argv[])
1597
{
1598
	struct atareq req;
1599
	struct smart_read attr_val;
1600
	struct smart_threshold attr_thr;
1601
	struct attribute *attr;
1602
	struct threshold *thr;
1603
	const char *attr_name;
1604
	static const char hex[]="0123456789abcdef";
1605
	char raw[13], *format;
1606
	int i, k, threshold_exceeded = 0;
1607
1608
	if (argc != 1)
1609
		goto usage;
1610
1611
	memset(&req, 0, sizeof(req));
1612
	memset(&attr_val, 0, sizeof(attr_val));	/* XXX */
1613
	memset(&attr_thr, 0, sizeof(attr_thr));	/* XXX */
1614
1615
	req.command = ATAPI_SMART;
1616
	req.cylinder = 0xc24f;		/* LBA High = C2h, LBA Mid = 4Fh */
1617
	req.timeout = 1000;
1618
1619
	req.features = ATA_SMART_READ;
1620
	req.flags = ATACMD_READ;
1621
	req.databuf = (caddr_t)&attr_val;
1622
	req.datalen = sizeof(attr_val);
1623
	ata_command(&req);
1624
1625
	req.features = ATA_SMART_THRESHOLD;
1626
	req.flags = ATACMD_READ;
1627
	req.databuf = (caddr_t)&attr_thr;
1628
	req.datalen = sizeof(attr_thr);
1629
	ata_command(&req);
1630
1631
	if (attr_val.revision != attr_thr.revision) {
1632
		/*
1633
		 * Non standard vendor implementation.
1634
		 * Return, since we don't know how to use this.
1635
		 */
1636
		return;
1637
	}
1638
1639
	attr = attr_val.attribute;
1640
	thr = attr_thr.threshold;
1641
1642
	printf("Attributes table revision: %d\n", attr_val.revision);
1643
	printf("ID\tAttribute name\t\t\tThreshold\tValue\tRaw\n");
1644
	for (i = 0; i < 30; i++) {
1645
		if (thr[i].id != 0 && thr[i].id == attr[i].id) {
1646
			attr_name = valtostr(thr[i].id, ibm_attr_names);
1647
			if (attr_name == NULL)
1648
				attr_name = "Unknown";
1649
1650
			for (k = 0; k < 6; k++) {
1651
				u_int8_t b;
1652
				b = attr[i].raw[6 - k];
1653
				raw[k + k] = hex[b >> 4];
1654
				raw[k + k + 1] = hex[b & 0x0f];
1655
			}
1656
			raw[k + k] = '\0';
1657
			if (thr[i].value >= attr[i].value) {
1658
				++threshold_exceeded;
1659
				format = "%3d    *%-32.32s %3d\t\t%3d\t0x%s\n";
1660
			} else {
1661
				format = "%3d\t%-32.32s %3d\t\t%3d\t0x%s\n";
1662
			}
1663
			printf(format, thr[i].id, attr_name,
1664
			    thr[i].value, attr[i].value, raw);
1665
		}
1666
	}
1667
	if (threshold_exceeded)
1668
		fprintf(stderr, "One or more threshold values exceeded!\n");
1669
1670
	return;
1671
1672
usage:
1673
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1674
	exit(1);
1675
}
1676
1677
/*
1678
 * Set the automatic acoustic management on the disk.
1679
 */
1680
void
1681
device_acoustic(int argc, char *argv[])
1682
{
1683
	u_char acoustic;
1684
	struct atareq req;
1685
	const char *errstr;
1686
1687
	if (argc != 2)
1688
		goto usage;
1689
1690
	acoustic = strtonum(argv[1], 0, 126, &errstr);
1691
	if (errstr)
1692
		errx(1, "Acoustic management value \"%s\" is %s "
1693
		    "(valid values: 0 - 126)", argv[1], errstr);
1694
1695
	memset(&req, 0, sizeof(req));
1696
1697
	req.sec_count = acoustic + 0x80;
1698
1699
	req.command = SET_FEATURES ;
1700
	req.features = WDSF_AAM_EN ;
1701
	req.timeout = 1000;
1702
1703
	ata_command(&req);
1704
1705
	return;
1706
1707
usage:
1708
	fprintf(stderr, "usage: %s device %s acoustic-management-level\n",
1709
	    __progname, argv[0]);
1710
	exit(1);
1711
}
1712
1713
/*
1714
 * Set the advanced power managmement on the disk. Power management
1715
 * levels are translated from user-range 0-253 to ATAPI levels 1-0xFD
1716
 * to keep a uniform interface to the user.
1717
 */
1718
void
1719
device_apm(int argc, char *argv[])
1720
{
1721
	u_char power;
1722
	struct atareq req;
1723
	const char *errstr;
1724
1725
	if (argc != 2)
1726
		goto usage;
1727
1728
	power = strtonum(argv[1], 0, 253, &errstr);
1729
	if (errstr)
1730
		errx(1, "Advanced power management value \"%s\" is %s "
1731
		    "(valid values: 0 - 253)", argv[1], errstr);
1732
1733
	memset(&req, 0, sizeof(req));
1734
1735
	req.sec_count = power + 0x01;
1736
1737
	req.command = SET_FEATURES ;
1738
	req.features = WDSF_APM_EN ;
1739
	req.timeout = 1000;
1740
1741
	ata_command(&req);
1742
1743
	return;
1744
1745
usage:
1746
	fprintf(stderr, "usage: %s device %s power-management-level\n",
1747
	    __progname, argv[0]);
1748
	exit(1);
1749
}
1750
1751
/*
1752
 * En/disable features (the automatic acoustic managmement, Advanced Power
1753
 * Management) on the disk.
1754
 */
1755
void
1756
device_feature(int argc, char *argv[])
1757
{
1758
	struct atareq req;
1759
1760
	if (argc != 1)
1761
		goto usage;
1762
1763
	memset(&req, 0, sizeof(req));
1764
1765
	req.command = SET_FEATURES ;
1766
1767
	if (strcmp(argv[0], "acousticdisable") == 0)
1768
		req.features = WDSF_AAM_DS;
1769
	else if (strcmp(argv[0], "readaheadenable") == 0)
1770
		req.features = WDSF_READAHEAD_EN;
1771
	else if (strcmp(argv[0], "readaheaddisable") == 0)
1772
		req.features = WDSF_READAHEAD_DS;
1773
	else if (strcmp(argv[0], "writecacheenable") == 0)
1774
		req.features = WDSF_EN_WR_CACHE;
1775
	else if (strcmp(argv[0], "writecachedisable") == 0)
1776
		req.features = WDSF_WRITE_CACHE_DS;
1777
	else if (strcmp(argv[0], "apmdisable") == 0)
1778
		req.features = WDSF_APM_DS;
1779
	else if (strcmp(argv[0], "podenable") == 0)
1780
		req.features = WDSF_POD_EN;
1781
	else if (strcmp(argv[0], "poddisable") == 0)
1782
		req.features = WDSF_POD_DS;
1783
	else if (strcmp(argv[0], "puisenable") == 0)
1784
		req.features = WDSF_PUIS_EN;
1785
	else if (strcmp(argv[0], "puisdisable") == 0)
1786
		req.features = WDSF_PUIS_DS;
1787
	else if (strcmp(argv[0], "puisspinup") == 0)
1788
		req.features = WDSF_PUIS_SPINUP;
1789
	else
1790
		goto usage;
1791
1792
	req.timeout = 1000;
1793
1794
	ata_command(&req);
1795
1796
	return;
1797
1798
usage:
1799
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1800
	exit(1);
1801
}
1802
1803
/*
1804
 * Set the idle timer on the disk.  Set it for either idle mode or
1805
 * standby mode, depending on how we were invoked.
1806
 */
1807
void
1808
device_setidle(int argc, char *argv[])
1809
{
1810
	unsigned long idle;
1811
	struct atareq req;
1812
	char *end;
1813
1814
	if (argc != 2)
1815
		goto usage;
1816
1817
	idle = strtoul(argv[1], &end, 0);
1818
1819
	if (*end != '\0' || idle > 19800)
1820
		errx(1, "Invalid idle time: \"%s\" "
1821
		    "(valid values: 1 - 19800)", argv[1]);
1822
1823
	if (idle != 0 && idle < 5)
1824
		errx(1, "Idle timer must be at least 5 seconds");
1825
1826
	memset(&req, 0, sizeof(req));
1827
1828
	if (idle <= 240 * 5)
1829
		req.sec_count = idle / 5;
1830
	else
1831
		req.sec_count = idle / (30 * 60) + 240;
1832
1833
	if (strcmp(argv[0], "setstandby") == 0)
1834
		req.command = WDCC_STANDBY;
1835
	else if (strcmp(argv[0], "setidle") == 0)
1836
		req.command = WDCC_IDLE;
1837
	else
1838
		goto usage;
1839
	req.timeout = 1000;
1840
1841
	ata_command(&req);
1842
1843
	return;
1844
1845
usage:
1846
	fprintf(stderr, "usage: %s device %s %s\n", __progname, argv[0],
1847
	    (strcmp(argv[0], "setidle") == 0) ? "idle-timer" : "standby-timer");
1848
	exit(1);
1849
}
1850
1851
/*
1852
 * Query the device for the current power mode
1853
 */
1854
void
1855
device_checkpower(int argc, char *argv[])
1856
{
1857
	struct atareq req;
1858
1859
	if (argc != 1)
1860
		goto usage;
1861
1862
	memset(&req, 0, sizeof(req));
1863
1864
	req.command = WDCC_CHECK_PWR;
1865
	req.timeout = 1000;
1866
	req.flags = ATACMD_READREG;
1867
1868
	ata_command(&req);
1869
1870
	printf("Current power status: ");
1871
1872
	switch (req.sec_count) {
1873
	case 0x00:
1874
		printf("Standby mode\n");
1875
		break;
1876
	case 0x80:
1877
		printf("Idle mode\n");
1878
		break;
1879
	case 0xff:
1880
		printf("Active mode\n");
1881
		break;
1882
	default:
1883
		printf("Unknown power code (%02x)\n", req.sec_count);
1884
	}
1885
1886
	return;
1887
usage:
1888
	fprintf(stderr, "usage: %s device %s\n", __progname, argv[0]);
1889
	exit(1);
1890
}