camcontrol.c revision 352293
1/*
2 * Copyright (c) 1997-2007 Kenneth D. Merry
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/11/sbin/camcontrol/camcontrol.c 352293 2019-09-13 15:18:45Z mav $");
31
32#include <sys/ioctl.h>
33#include <sys/stdint.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/endian.h>
37#include <sys/sbuf.h>
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43#include <inttypes.h>
44#include <limits.h>
45#include <fcntl.h>
46#include <ctype.h>
47#include <err.h>
48#include <libutil.h>
49#ifndef MINIMALISTIC
50#include <limits.h>
51#include <inttypes.h>
52#endif
53
54#include <cam/cam.h>
55#include <cam/cam_debug.h>
56#include <cam/cam_ccb.h>
57#include <cam/scsi/scsi_all.h>
58#include <cam/scsi/scsi_da.h>
59#include <cam/scsi/scsi_pass.h>
60#include <cam/scsi/scsi_message.h>
61#include <cam/scsi/smp_all.h>
62#include <cam/ata/ata_all.h>
63#include <camlib.h>
64#include "camcontrol.h"
65
66typedef enum {
67	CAM_CMD_NONE		= 0x00000000,
68	CAM_CMD_DEVLIST		= 0x00000001,
69	CAM_CMD_TUR		= 0x00000002,
70	CAM_CMD_INQUIRY		= 0x00000003,
71	CAM_CMD_STARTSTOP	= 0x00000004,
72	CAM_CMD_RESCAN		= 0x00000005,
73	CAM_CMD_READ_DEFECTS	= 0x00000006,
74	CAM_CMD_MODE_PAGE	= 0x00000007,
75	CAM_CMD_SCSI_CMD	= 0x00000008,
76	CAM_CMD_DEVTREE		= 0x00000009,
77	CAM_CMD_USAGE		= 0x0000000a,
78	CAM_CMD_DEBUG		= 0x0000000b,
79	CAM_CMD_RESET		= 0x0000000c,
80	CAM_CMD_FORMAT		= 0x0000000d,
81	CAM_CMD_TAG		= 0x0000000e,
82	CAM_CMD_RATE		= 0x0000000f,
83	CAM_CMD_DETACH		= 0x00000010,
84	CAM_CMD_REPORTLUNS	= 0x00000011,
85	CAM_CMD_READCAP		= 0x00000012,
86	CAM_CMD_IDENTIFY	= 0x00000013,
87	CAM_CMD_IDLE		= 0x00000014,
88	CAM_CMD_STANDBY		= 0x00000015,
89	CAM_CMD_SLEEP		= 0x00000016,
90	CAM_CMD_SMP_CMD		= 0x00000017,
91	CAM_CMD_SMP_RG		= 0x00000018,
92	CAM_CMD_SMP_PC		= 0x00000019,
93	CAM_CMD_SMP_PHYLIST	= 0x0000001a,
94	CAM_CMD_SMP_MANINFO	= 0x0000001b,
95	CAM_CMD_DOWNLOAD_FW	= 0x0000001c,
96	CAM_CMD_SECURITY	= 0x0000001d,
97	CAM_CMD_HPA		= 0x0000001e,
98	CAM_CMD_SANITIZE	= 0x0000001f,
99	CAM_CMD_PERSIST		= 0x00000020,
100	CAM_CMD_APM		= 0x00000021,
101	CAM_CMD_AAM		= 0x00000022,
102	CAM_CMD_ATTRIB		= 0x00000023,
103	CAM_CMD_OPCODES		= 0x00000024,
104	CAM_CMD_REPROBE		= 0x00000025,
105	CAM_CMD_ZONE		= 0x00000026,
106	CAM_CMD_EPC		= 0x00000027,
107	CAM_CMD_TIMESTAMP	= 0x00000028,
108	CAM_CMD_POWER_MODE	= 0x0000002a,
109	CAM_CMD_DEVTYPE		= 0x0000002b,
110	CAM_CMD_AMA	= 0x0000002c,
111} cam_cmdmask;
112
113typedef enum {
114	CAM_ARG_NONE		= 0x00000000,
115	CAM_ARG_VERBOSE		= 0x00000001,
116	CAM_ARG_DEVICE		= 0x00000002,
117	CAM_ARG_BUS		= 0x00000004,
118	CAM_ARG_TARGET		= 0x00000008,
119	CAM_ARG_LUN		= 0x00000010,
120	CAM_ARG_EJECT		= 0x00000020,
121	CAM_ARG_UNIT		= 0x00000040,
122	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
123	CAM_ARG_FORMAT_BFI	= 0x00000100,
124	CAM_ARG_FORMAT_PHYS	= 0x00000200,
125	CAM_ARG_PLIST		= 0x00000400,
126	CAM_ARG_GLIST		= 0x00000800,
127	CAM_ARG_GET_SERIAL	= 0x00001000,
128	CAM_ARG_GET_STDINQ	= 0x00002000,
129	CAM_ARG_GET_XFERRATE	= 0x00004000,
130	CAM_ARG_INQ_MASK	= 0x00007000,
131	CAM_ARG_TIMEOUT		= 0x00020000,
132	CAM_ARG_CMD_IN		= 0x00040000,
133	CAM_ARG_CMD_OUT		= 0x00080000,
134	CAM_ARG_ERR_RECOVER	= 0x00200000,
135	CAM_ARG_RETRIES		= 0x00400000,
136	CAM_ARG_START_UNIT	= 0x00800000,
137	CAM_ARG_DEBUG_INFO	= 0x01000000,
138	CAM_ARG_DEBUG_TRACE	= 0x02000000,
139	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
140	CAM_ARG_DEBUG_CDB	= 0x08000000,
141	CAM_ARG_DEBUG_XPT	= 0x10000000,
142	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
143	CAM_ARG_DEBUG_PROBE	= 0x40000000,
144} cam_argmask;
145
146struct camcontrol_opts {
147	const char	*optname;
148	uint32_t	cmdnum;
149	cam_argmask	argnum;
150	const char	*subopt;
151};
152
153#ifndef MINIMALISTIC
154struct ata_res_pass16 {
155	u_int16_t reserved[5];
156	u_int8_t flags;
157	u_int8_t error;
158	u_int8_t sector_count_exp;
159	u_int8_t sector_count;
160	u_int8_t lba_low_exp;
161	u_int8_t lba_low;
162	u_int8_t lba_mid_exp;
163	u_int8_t lba_mid;
164	u_int8_t lba_high_exp;
165	u_int8_t lba_high;
166	u_int8_t device;
167	u_int8_t status;
168};
169
170struct ata_set_max_pwd
171{
172	u_int16_t reserved1;
173	u_int8_t password[32];
174	u_int16_t reserved2[239];
175};
176
177static struct scsi_nv task_attrs[] = {
178	{ "simple", MSG_SIMPLE_Q_TAG },
179	{ "head", MSG_HEAD_OF_Q_TAG },
180	{ "ordered", MSG_ORDERED_Q_TAG },
181	{ "iwr", MSG_IGN_WIDE_RESIDUE },
182	{ "aca", MSG_ACA_TASK }
183};
184
185static const char scsicmd_opts[] = "a:c:dfi:o:r";
186static const char readdefect_opts[] = "f:GPqsS:X";
187static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
188static const char smprg_opts[] = "l";
189static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
190static const char smpphylist_opts[] = "lq";
191static char pwd_opt;
192#endif
193
194static struct camcontrol_opts option_table[] = {
195#ifndef MINIMALISTIC
196	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
197	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
198	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
199	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
200	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
201	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
202	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
203	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
204	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHlNqs"},
205	{"reprobe", CAM_CMD_REPROBE, CAM_ARG_NONE, NULL},
206#endif /* MINIMALISTIC */
207	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
208	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
209#ifndef MINIMALISTIC
210	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
211	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
212	{"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
213	{"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
214	{"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
215	{"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
216	{"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
217	{"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
218	{"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
219	{"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
220	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
221	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
222#endif /* MINIMALISTIC */
223	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, "-b"},
224	{"devtype", CAM_CMD_DEVTYPE, CAM_ARG_NONE, ""},
225#ifndef MINIMALISTIC
226	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
227	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "6bdelm:DLP:"},
228	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
229	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
230	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
231	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
232	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
233	{"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
234	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
235	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
236	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
237	{"powermode", CAM_CMD_POWER_MODE, CAM_ARG_NONE, ""},
238	{"apm", CAM_CMD_APM, CAM_ARG_NONE, "l:"},
239	{"aam", CAM_CMD_AAM, CAM_ARG_NONE, "l:"},
240	{"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:qsy"},
241	{"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
242	{"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
243	{"ama", CAM_CMD_AMA, CAM_ARG_NONE, "fqs:"},
244	{"persist", CAM_CMD_PERSIST, CAM_ARG_NONE, "ai:I:k:K:o:ps:ST:U"},
245	{"attrib", CAM_CMD_ATTRIB, CAM_ARG_NONE, "a:ce:F:p:r:s:T:w:V:"},
246	{"opcodes", CAM_CMD_OPCODES, CAM_ARG_NONE, "No:s:T"},
247	{"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"},
248	{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
249	{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
250#endif /* MINIMALISTIC */
251	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
252	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
253	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
254	{NULL, 0, 0, NULL}
255};
256
257struct cam_devitem {
258	struct device_match_result dev_match;
259	int num_periphs;
260	struct periph_match_result *periph_matches;
261	struct scsi_vpd_device_id *device_id;
262	int device_id_len;
263	STAILQ_ENTRY(cam_devitem) links;
264};
265
266struct cam_devlist {
267	STAILQ_HEAD(, cam_devitem) dev_queue;
268	path_id_t path_id;
269};
270
271static cam_cmdmask cmdlist;
272static cam_argmask arglist;
273
274static const char *devtype_names[] = {
275	"none",
276	"scsi",
277	"satl",
278	"ata",
279	"nvme",
280	"mmcsd",
281	"unknown",
282};
283
284camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
285			    uint32_t *cmdnum, cam_argmask *argnum,
286			    const char **subopt);
287#ifndef MINIMALISTIC
288static int getdevlist(struct cam_device *device);
289#endif /* MINIMALISTIC */
290static int getdevtree(int argc, char **argv, char *combinedopt);
291static int getdevtype(struct cam_device *device);
292#ifndef MINIMALISTIC
293static int testunitready(struct cam_device *device, int task_attr,
294			 int retry_count, int timeout, int quiet);
295static int scsistart(struct cam_device *device, int startstop, int loadeject,
296		     int task_attr, int retry_count, int timeout);
297static int scsiinquiry(struct cam_device *device, int task_attr,
298		       int retry_count, int timeout);
299static int scsiserial(struct cam_device *device, int task_attr,
300		      int retry_count, int timeout);
301#endif /* MINIMALISTIC */
302static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
303		     lun_id_t *lun, cam_argmask *arglst);
304static int reprobe(struct cam_device *device);
305static int dorescan_or_reset(int argc, char **argv, int rescan);
306static int rescan_or_reset_bus(path_id_t bus, int rescan);
307static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
308    lun_id_t lun, int scan);
309#ifndef MINIMALISTIC
310static int readdefects(struct cam_device *device, int argc, char **argv,
311		       char *combinedopt, int task_attr, int retry_count,
312		       int timeout);
313static void modepage(struct cam_device *device, int argc, char **argv,
314		     char *combinedopt, int task_attr, int retry_count,
315		     int timeout);
316static int scsicmd(struct cam_device *device, int argc, char **argv,
317		   char *combinedopt, int task_attr, int retry_count,
318		   int timeout);
319static int smpcmd(struct cam_device *device, int argc, char **argv,
320		  char *combinedopt, int retry_count, int timeout);
321static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
322			    char *combinedopt, int retry_count, int timeout);
323static int smpphycontrol(struct cam_device *device, int argc, char **argv,
324			 char *combinedopt, int retry_count, int timeout);
325static int smpmaninfo(struct cam_device *device, int argc, char **argv,
326		      char *combinedopt, int retry_count, int timeout);
327static int getdevid(struct cam_devitem *item);
328static int buildbusdevlist(struct cam_devlist *devlist);
329static void freebusdevlist(struct cam_devlist *devlist);
330static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
331					 uint64_t sasaddr);
332static int smpphylist(struct cam_device *device, int argc, char **argv,
333		      char *combinedopt, int retry_count, int timeout);
334static int tagcontrol(struct cam_device *device, int argc, char **argv,
335		      char *combinedopt);
336static void cts_print(struct cam_device *device,
337		      struct ccb_trans_settings *cts);
338static void cpi_print(struct ccb_pathinq *cpi);
339static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
340static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
341static int get_print_cts(struct cam_device *device, int user_settings,
342			 int quiet, struct ccb_trans_settings *cts);
343static int ratecontrol(struct cam_device *device, int task_attr,
344		       int retry_count, int timeout, int argc, char **argv,
345		       char *combinedopt);
346static int scsiformat(struct cam_device *device, int argc, char **argv,
347		      char *combinedopt, int task_attr, int retry_count,
348		      int timeout);
349static int sanitize(struct cam_device *device, int argc, char **argv,
350			char *combinedopt, int task_attr, int retry_count,
351			int timeout);
352static int scsireportluns(struct cam_device *device, int argc, char **argv,
353			  char *combinedopt, int task_attr, int retry_count,
354			  int timeout);
355static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
356			    char *combinedopt, int task_attr, int retry_count,
357			    int timeout);
358static int atapm(struct cam_device *device, int argc, char **argv,
359		 char *combinedopt, int retry_count, int timeout);
360static int atasecurity(struct cam_device *device, int retry_count, int timeout,
361		       int argc, char **argv, char *combinedopt);
362static int atahpa(struct cam_device *device, int retry_count, int timeout,
363		  int argc, char **argv, char *combinedopt);
364static int ataama(struct cam_device *device, int retry_count, int timeout,
365		  int argc, char **argv, char *combinedopt);
366static int scsiprintoneopcode(struct cam_device *device, int req_opcode,
367			      int sa_set, int req_sa, uint8_t *buf,
368			      uint32_t valid_len);
369static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
370			    uint32_t valid_len);
371static int scsiopcodes(struct cam_device *device, int argc, char **argv,
372		       char *combinedopt, int task_attr, int retry_count,
373		       int timeout, int verbose);
374
375#endif /* MINIMALISTIC */
376#ifndef min
377#define min(a,b) (((a)<(b))?(a):(b))
378#endif
379#ifndef max
380#define max(a,b) (((a)>(b))?(a):(b))
381#endif
382
383camcontrol_optret
384getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
385	  cam_argmask *argnum, const char **subopt)
386{
387	struct camcontrol_opts *opts;
388	int num_matches = 0;
389
390	for (opts = table; (opts != NULL) && (opts->optname != NULL);
391	     opts++) {
392		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
393			*cmdnum = opts->cmdnum;
394			*argnum = opts->argnum;
395			*subopt = opts->subopt;
396			if (++num_matches > 1)
397				return (CC_OR_AMBIGUOUS);
398		}
399	}
400
401	if (num_matches > 0)
402		return (CC_OR_FOUND);
403	else
404		return (CC_OR_NOT_FOUND);
405}
406
407#ifndef MINIMALISTIC
408static int
409getdevlist(struct cam_device *device)
410{
411	union ccb *ccb;
412	char status[32];
413	int error = 0;
414
415	ccb = cam_getccb(device);
416
417	ccb->ccb_h.func_code = XPT_GDEVLIST;
418	ccb->ccb_h.flags = CAM_DIR_NONE;
419	ccb->ccb_h.retry_count = 1;
420	ccb->cgdl.index = 0;
421	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
422	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
423		if (cam_send_ccb(device, ccb) < 0) {
424			warn("error getting device list");
425			cam_freeccb(ccb);
426			return (1);
427		}
428
429		status[0] = '\0';
430
431		switch (ccb->cgdl.status) {
432			case CAM_GDEVLIST_MORE_DEVS:
433				strcpy(status, "MORE");
434				break;
435			case CAM_GDEVLIST_LAST_DEVICE:
436				strcpy(status, "LAST");
437				break;
438			case CAM_GDEVLIST_LIST_CHANGED:
439				strcpy(status, "CHANGED");
440				break;
441			case CAM_GDEVLIST_ERROR:
442				strcpy(status, "ERROR");
443				error = 1;
444				break;
445		}
446
447		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
448			ccb->cgdl.periph_name,
449			ccb->cgdl.unit_number,
450			ccb->cgdl.generation,
451			ccb->cgdl.index,
452			status);
453
454		/*
455		 * If the list has changed, we need to start over from the
456		 * beginning.
457		 */
458		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
459			ccb->cgdl.index = 0;
460	}
461
462	cam_freeccb(ccb);
463
464	return (error);
465}
466#endif /* MINIMALISTIC */
467
468static int
469getdevtree(int argc, char **argv, char *combinedopt)
470{
471	union ccb ccb;
472	int bufsize, fd;
473	unsigned int i;
474	int need_close = 0;
475	int error = 0;
476	int skip_device = 0;
477	int busonly = 0;
478	int c;
479
480	while ((c = getopt(argc, argv, combinedopt)) != -1) {
481		switch(c) {
482		case 'b':
483			if ((arglist & CAM_ARG_VERBOSE) == 0)
484				busonly = 1;
485			break;
486		default:
487			break;
488		}
489	}
490
491	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
492		warn("couldn't open %s", XPT_DEVICE);
493		return (1);
494	}
495
496	bzero(&ccb, sizeof(union ccb));
497
498	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
499	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
500	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
501
502	ccb.ccb_h.func_code = XPT_DEV_MATCH;
503	bufsize = sizeof(struct dev_match_result) * 100;
504	ccb.cdm.match_buf_len = bufsize;
505	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
506	if (ccb.cdm.matches == NULL) {
507		warnx("can't malloc memory for matches");
508		close(fd);
509		return (1);
510	}
511	ccb.cdm.num_matches = 0;
512
513	/*
514	 * We fetch all nodes, since we display most of them in the default
515	 * case, and all in the verbose case.
516	 */
517	ccb.cdm.num_patterns = 0;
518	ccb.cdm.pattern_buf_len = 0;
519
520	/*
521	 * We do the ioctl multiple times if necessary, in case there are
522	 * more than 100 nodes in the EDT.
523	 */
524	do {
525		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
526			warn("error sending CAMIOCOMMAND ioctl");
527			error = 1;
528			break;
529		}
530
531		if ((ccb.ccb_h.status != CAM_REQ_CMP)
532		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
533		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
534			warnx("got CAM error %#x, CDM error %d\n",
535			      ccb.ccb_h.status, ccb.cdm.status);
536			error = 1;
537			break;
538		}
539
540		for (i = 0; i < ccb.cdm.num_matches; i++) {
541			switch (ccb.cdm.matches[i].type) {
542			case DEV_MATCH_BUS: {
543				struct bus_match_result *bus_result;
544
545				/*
546				 * Only print the bus information if the
547				 * user turns on the verbose flag.
548				 */
549				if ((busonly == 0) &&
550				    (arglist & CAM_ARG_VERBOSE) == 0)
551					break;
552
553				bus_result =
554					&ccb.cdm.matches[i].result.bus_result;
555
556				if (need_close) {
557					fprintf(stdout, ")\n");
558					need_close = 0;
559				}
560
561				fprintf(stdout, "scbus%d on %s%d bus %d%s\n",
562					bus_result->path_id,
563					bus_result->dev_name,
564					bus_result->unit_number,
565					bus_result->bus_id,
566					(busonly ? "" : ":"));
567				break;
568			}
569			case DEV_MATCH_DEVICE: {
570				struct device_match_result *dev_result;
571				char vendor[16], product[48], revision[16];
572				char fw[5], tmpstr[256];
573
574				if (busonly == 1)
575					break;
576
577				dev_result =
578				     &ccb.cdm.matches[i].result.device_result;
579
580				if ((dev_result->flags
581				     & DEV_RESULT_UNCONFIGURED)
582				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
583					skip_device = 1;
584					break;
585				} else
586					skip_device = 0;
587
588				if (dev_result->protocol == PROTO_SCSI) {
589				    cam_strvis(vendor, dev_result->inq_data.vendor,
590					   sizeof(dev_result->inq_data.vendor),
591					   sizeof(vendor));
592				    cam_strvis(product,
593					   dev_result->inq_data.product,
594					   sizeof(dev_result->inq_data.product),
595					   sizeof(product));
596				    cam_strvis(revision,
597					   dev_result->inq_data.revision,
598					  sizeof(dev_result->inq_data.revision),
599					   sizeof(revision));
600				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
601					revision);
602				} else if (dev_result->protocol == PROTO_ATA ||
603				    dev_result->protocol == PROTO_SATAPM) {
604				    cam_strvis(product,
605					   dev_result->ident_data.model,
606					   sizeof(dev_result->ident_data.model),
607					   sizeof(product));
608				    cam_strvis(revision,
609					   dev_result->ident_data.revision,
610					  sizeof(dev_result->ident_data.revision),
611					   sizeof(revision));
612				    sprintf(tmpstr, "<%s %s>", product,
613					revision);
614				} else if (dev_result->protocol == PROTO_SEMB) {
615					struct sep_identify_data *sid;
616
617					sid = (struct sep_identify_data *)
618					    &dev_result->ident_data;
619					cam_strvis(vendor, sid->vendor_id,
620					    sizeof(sid->vendor_id),
621					    sizeof(vendor));
622					cam_strvis(product, sid->product_id,
623					    sizeof(sid->product_id),
624					    sizeof(product));
625					cam_strvis(revision, sid->product_rev,
626					    sizeof(sid->product_rev),
627					    sizeof(revision));
628					cam_strvis(fw, sid->firmware_rev,
629					    sizeof(sid->firmware_rev),
630					    sizeof(fw));
631					sprintf(tmpstr, "<%s %s %s %s>",
632					    vendor, product, revision, fw);
633				} else {
634				    sprintf(tmpstr, "<>");
635				}
636				if (need_close) {
637					fprintf(stdout, ")\n");
638					need_close = 0;
639				}
640
641				fprintf(stdout, "%-33s  at scbus%d "
642					"target %d lun %jx (",
643					tmpstr,
644					dev_result->path_id,
645					dev_result->target_id,
646					(uintmax_t)dev_result->target_lun);
647
648				need_close = 1;
649
650				break;
651			}
652			case DEV_MATCH_PERIPH: {
653				struct periph_match_result *periph_result;
654
655				periph_result =
656				      &ccb.cdm.matches[i].result.periph_result;
657
658				if (busonly || skip_device != 0)
659					break;
660
661				if (need_close > 1)
662					fprintf(stdout, ",");
663
664				fprintf(stdout, "%s%d",
665					periph_result->periph_name,
666					periph_result->unit_number);
667
668				need_close++;
669				break;
670			}
671			default:
672				fprintf(stdout, "unknown match type\n");
673				break;
674			}
675		}
676
677	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
678		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
679
680	if (need_close)
681		fprintf(stdout, ")\n");
682
683	close(fd);
684
685	return (error);
686}
687
688static int
689getdevtype(struct cam_device *cam_dev)
690{
691	camcontrol_devtype dt;
692	int error;
693
694	/*
695	 * Get the device type and report it, request no I/O be done to do this.
696	 */
697	error = get_device_type(cam_dev, -1, 0, 0, &dt);
698	if (error != 0 || (unsigned)dt > CC_DT_UNKNOWN) {
699		fprintf(stdout, "illegal\n");
700		return (1);
701	}
702	fprintf(stdout, "%s\n", devtype_names[dt]);
703	return (0);
704}
705
706#ifndef MINIMALISTIC
707static int
708testunitready(struct cam_device *device, int task_attr, int retry_count,
709	      int timeout, int quiet)
710{
711	int error = 0;
712	union ccb *ccb;
713
714	ccb = cam_getccb(device);
715
716	scsi_test_unit_ready(&ccb->csio,
717			     /* retries */ retry_count,
718			     /* cbfcnp */ NULL,
719			     /* tag_action */ task_attr,
720			     /* sense_len */ SSD_FULL_SIZE,
721			     /* timeout */ timeout ? timeout : 5000);
722
723	/* Disable freezing the device queue */
724	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
725
726	if (arglist & CAM_ARG_ERR_RECOVER)
727		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
728
729	if (cam_send_ccb(device, ccb) < 0) {
730		if (quiet == 0)
731			warn("error sending TEST UNIT READY command");
732		cam_freeccb(ccb);
733		return (1);
734	}
735
736	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
737		if (quiet == 0)
738			fprintf(stdout, "Unit is ready\n");
739	} else {
740		if (quiet == 0)
741			fprintf(stdout, "Unit is not ready\n");
742		error = 1;
743
744		if (arglist & CAM_ARG_VERBOSE) {
745			cam_error_print(device, ccb, CAM_ESF_ALL,
746					CAM_EPF_ALL, stderr);
747		}
748	}
749
750	cam_freeccb(ccb);
751
752	return (error);
753}
754
755static int
756scsistart(struct cam_device *device, int startstop, int loadeject,
757	  int task_attr, int retry_count, int timeout)
758{
759	union ccb *ccb;
760	int error = 0;
761
762	ccb = cam_getccb(device);
763
764	/*
765	 * If we're stopping, send an ordered tag so the drive in question
766	 * will finish any previously queued writes before stopping.  If
767	 * the device isn't capable of tagged queueing, or if tagged
768	 * queueing is turned off, the tag action is a no-op.  We override
769	 * the default simple tag, although this also has the effect of
770	 * overriding the user's wishes if he wanted to specify a simple
771	 * tag.
772	 */
773	if ((startstop == 0)
774	 && (task_attr == MSG_SIMPLE_Q_TAG))
775		task_attr = MSG_ORDERED_Q_TAG;
776
777	scsi_start_stop(&ccb->csio,
778			/* retries */ retry_count,
779			/* cbfcnp */ NULL,
780			/* tag_action */ task_attr,
781			/* start/stop */ startstop,
782			/* load_eject */ loadeject,
783			/* immediate */ 0,
784			/* sense_len */ SSD_FULL_SIZE,
785			/* timeout */ timeout ? timeout : 120000);
786
787	/* Disable freezing the device queue */
788	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
789
790	if (arglist & CAM_ARG_ERR_RECOVER)
791		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
792
793	if (cam_send_ccb(device, ccb) < 0) {
794		warn("error sending START STOP UNIT command");
795		cam_freeccb(ccb);
796		return (1);
797	}
798
799	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
800		if (startstop) {
801			fprintf(stdout, "Unit started successfully");
802			if (loadeject)
803				fprintf(stdout,", Media loaded\n");
804			else
805				fprintf(stdout,"\n");
806		} else {
807			fprintf(stdout, "Unit stopped successfully");
808			if (loadeject)
809				fprintf(stdout, ", Media ejected\n");
810			else
811				fprintf(stdout, "\n");
812		}
813	else {
814		error = 1;
815		if (startstop)
816			fprintf(stdout,
817				"Error received from start unit command\n");
818		else
819			fprintf(stdout,
820				"Error received from stop unit command\n");
821
822		if (arglist & CAM_ARG_VERBOSE) {
823			cam_error_print(device, ccb, CAM_ESF_ALL,
824					CAM_EPF_ALL, stderr);
825		}
826	}
827
828	cam_freeccb(ccb);
829
830	return (error);
831}
832
833int
834scsidoinquiry(struct cam_device *device, int argc, char **argv,
835	      char *combinedopt, int task_attr, int retry_count, int timeout)
836{
837	int c;
838	int error = 0;
839
840	while ((c = getopt(argc, argv, combinedopt)) != -1) {
841		switch(c) {
842		case 'D':
843			arglist |= CAM_ARG_GET_STDINQ;
844			break;
845		case 'R':
846			arglist |= CAM_ARG_GET_XFERRATE;
847			break;
848		case 'S':
849			arglist |= CAM_ARG_GET_SERIAL;
850			break;
851		default:
852			break;
853		}
854	}
855
856	/*
857	 * If the user didn't specify any inquiry options, he wants all of
858	 * them.
859	 */
860	if ((arglist & CAM_ARG_INQ_MASK) == 0)
861		arglist |= CAM_ARG_INQ_MASK;
862
863	if (arglist & CAM_ARG_GET_STDINQ)
864		error = scsiinquiry(device, task_attr, retry_count, timeout);
865
866	if (error != 0)
867		return (error);
868
869	if (arglist & CAM_ARG_GET_SERIAL)
870		scsiserial(device, task_attr, retry_count, timeout);
871
872	if (arglist & CAM_ARG_GET_XFERRATE)
873		error = camxferrate(device);
874
875	return (error);
876}
877
878static int
879scsiinquiry(struct cam_device *device, int task_attr, int retry_count,
880	    int timeout)
881{
882	union ccb *ccb;
883	struct scsi_inquiry_data *inq_buf;
884	int error = 0;
885
886	ccb = cam_getccb(device);
887
888	if (ccb == NULL) {
889		warnx("couldn't allocate CCB");
890		return (1);
891	}
892
893	/* cam_getccb cleans up the header, caller has to zero the payload */
894	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
895
896	inq_buf = (struct scsi_inquiry_data *)malloc(
897		sizeof(struct scsi_inquiry_data));
898
899	if (inq_buf == NULL) {
900		cam_freeccb(ccb);
901		warnx("can't malloc memory for inquiry\n");
902		return (1);
903	}
904	bzero(inq_buf, sizeof(*inq_buf));
905
906	/*
907	 * Note that although the size of the inquiry buffer is the full
908	 * 256 bytes specified in the SCSI spec, we only tell the device
909	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
910	 * two reasons for this:
911	 *
912	 *  - The SCSI spec says that when a length field is only 1 byte,
913	 *    a value of 0 will be interpreted as 256.  Therefore
914	 *    scsi_inquiry() will convert an inq_len (which is passed in as
915	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
916	 *    to 0.  Evidently, very few devices meet the spec in that
917	 *    regard.  Some devices, like many Seagate disks, take the 0 as
918	 *    0, and don't return any data.  One Pioneer DVD-R drive
919	 *    returns more data than the command asked for.
920	 *
921	 *    So, since there are numerous devices that just don't work
922	 *    right with the full inquiry size, we don't send the full size.
923	 *
924	 *  - The second reason not to use the full inquiry data length is
925	 *    that we don't need it here.  The only reason we issue a
926	 *    standard inquiry is to get the vendor name, device name,
927	 *    and revision so scsi_print_inquiry() can print them.
928	 *
929	 * If, at some point in the future, more inquiry data is needed for
930	 * some reason, this code should use a procedure similar to the
931	 * probe code.  i.e., issue a short inquiry, and determine from
932	 * the additional length passed back from the device how much
933	 * inquiry data the device supports.  Once the amount the device
934	 * supports is determined, issue an inquiry for that amount and no
935	 * more.
936	 *
937	 * KDM, 2/18/2000
938	 */
939	scsi_inquiry(&ccb->csio,
940		     /* retries */ retry_count,
941		     /* cbfcnp */ NULL,
942		     /* tag_action */ task_attr,
943		     /* inq_buf */ (u_int8_t *)inq_buf,
944		     /* inq_len */ SHORT_INQUIRY_LENGTH,
945		     /* evpd */ 0,
946		     /* page_code */ 0,
947		     /* sense_len */ SSD_FULL_SIZE,
948		     /* timeout */ timeout ? timeout : 5000);
949
950	/* Disable freezing the device queue */
951	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
952
953	if (arglist & CAM_ARG_ERR_RECOVER)
954		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
955
956	if (cam_send_ccb(device, ccb) < 0) {
957		warn("error sending INQUIRY command");
958		cam_freeccb(ccb);
959		return (1);
960	}
961
962	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
963		error = 1;
964
965		if (arglist & CAM_ARG_VERBOSE) {
966			cam_error_print(device, ccb, CAM_ESF_ALL,
967					CAM_EPF_ALL, stderr);
968		}
969	}
970
971	cam_freeccb(ccb);
972
973	if (error != 0) {
974		free(inq_buf);
975		return (error);
976	}
977
978	fprintf(stdout, "%s%d: ", device->device_name,
979		device->dev_unit_num);
980	scsi_print_inquiry(inq_buf);
981
982	free(inq_buf);
983
984	return (0);
985}
986
987static int
988scsiserial(struct cam_device *device, int task_attr, int retry_count,
989	   int timeout)
990{
991	union ccb *ccb;
992	struct scsi_vpd_unit_serial_number *serial_buf;
993	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
994	int error = 0;
995
996	ccb = cam_getccb(device);
997
998	if (ccb == NULL) {
999		warnx("couldn't allocate CCB");
1000		return (1);
1001	}
1002
1003	/* cam_getccb cleans up the header, caller has to zero the payload */
1004	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
1005
1006	serial_buf = (struct scsi_vpd_unit_serial_number *)
1007		malloc(sizeof(*serial_buf));
1008
1009	if (serial_buf == NULL) {
1010		cam_freeccb(ccb);
1011		warnx("can't malloc memory for serial number");
1012		return (1);
1013	}
1014
1015	scsi_inquiry(&ccb->csio,
1016		     /*retries*/ retry_count,
1017		     /*cbfcnp*/ NULL,
1018		     /* tag_action */ task_attr,
1019		     /* inq_buf */ (u_int8_t *)serial_buf,
1020		     /* inq_len */ sizeof(*serial_buf),
1021		     /* evpd */ 1,
1022		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
1023		     /* sense_len */ SSD_FULL_SIZE,
1024		     /* timeout */ timeout ? timeout : 5000);
1025
1026	/* Disable freezing the device queue */
1027	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1028
1029	if (arglist & CAM_ARG_ERR_RECOVER)
1030		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1031
1032	if (cam_send_ccb(device, ccb) < 0) {
1033		warn("error sending INQUIRY command");
1034		cam_freeccb(ccb);
1035		free(serial_buf);
1036		return (1);
1037	}
1038
1039	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1040		error = 1;
1041
1042		if (arglist & CAM_ARG_VERBOSE) {
1043			cam_error_print(device, ccb, CAM_ESF_ALL,
1044					CAM_EPF_ALL, stderr);
1045		}
1046	}
1047
1048	cam_freeccb(ccb);
1049
1050	if (error != 0) {
1051		free(serial_buf);
1052		return (error);
1053	}
1054
1055	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
1056	serial_num[serial_buf->length] = '\0';
1057
1058	if ((arglist & CAM_ARG_GET_STDINQ)
1059	 || (arglist & CAM_ARG_GET_XFERRATE))
1060		fprintf(stdout, "%s%d: Serial Number ",
1061			device->device_name, device->dev_unit_num);
1062
1063	fprintf(stdout, "%.60s\n", serial_num);
1064
1065	free(serial_buf);
1066
1067	return (0);
1068}
1069
1070int
1071camxferrate(struct cam_device *device)
1072{
1073	struct ccb_pathinq cpi;
1074	u_int32_t freq = 0;
1075	u_int32_t speed = 0;
1076	union ccb *ccb;
1077	u_int mb;
1078	int retval = 0;
1079
1080	if ((retval = get_cpi(device, &cpi)) != 0)
1081		return (1);
1082
1083	ccb = cam_getccb(device);
1084
1085	if (ccb == NULL) {
1086		warnx("couldn't allocate CCB");
1087		return (1);
1088	}
1089
1090	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
1091
1092	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1093	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1094
1095	if (((retval = cam_send_ccb(device, ccb)) < 0)
1096	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1097		const char error_string[] = "error getting transfer settings";
1098
1099		if (retval < 0)
1100			warn(error_string);
1101		else
1102			warnx(error_string);
1103
1104		if (arglist & CAM_ARG_VERBOSE)
1105			cam_error_print(device, ccb, CAM_ESF_ALL,
1106					CAM_EPF_ALL, stderr);
1107
1108		retval = 1;
1109
1110		goto xferrate_bailout;
1111
1112	}
1113
1114	speed = cpi.base_transfer_speed;
1115	freq = 0;
1116	if (ccb->cts.transport == XPORT_SPI) {
1117		struct ccb_trans_settings_spi *spi =
1118		    &ccb->cts.xport_specific.spi;
1119
1120		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1121			freq = scsi_calc_syncsrate(spi->sync_period);
1122			speed = freq;
1123		}
1124		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1125			speed *= (0x01 << spi->bus_width);
1126		}
1127	} else if (ccb->cts.transport == XPORT_FC) {
1128		struct ccb_trans_settings_fc *fc =
1129		    &ccb->cts.xport_specific.fc;
1130
1131		if (fc->valid & CTS_FC_VALID_SPEED)
1132			speed = fc->bitrate;
1133	} else if (ccb->cts.transport == XPORT_SAS) {
1134		struct ccb_trans_settings_sas *sas =
1135		    &ccb->cts.xport_specific.sas;
1136
1137		if (sas->valid & CTS_SAS_VALID_SPEED)
1138			speed = sas->bitrate;
1139	} else if (ccb->cts.transport == XPORT_ATA) {
1140		struct ccb_trans_settings_pata *pata =
1141		    &ccb->cts.xport_specific.ata;
1142
1143		if (pata->valid & CTS_ATA_VALID_MODE)
1144			speed = ata_mode2speed(pata->mode);
1145	} else if (ccb->cts.transport == XPORT_SATA) {
1146		struct	ccb_trans_settings_sata *sata =
1147		    &ccb->cts.xport_specific.sata;
1148
1149		if (sata->valid & CTS_SATA_VALID_REVISION)
1150			speed = ata_revision2speed(sata->revision);
1151	}
1152
1153	mb = speed / 1000;
1154	if (mb > 0) {
1155		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1156			device->device_name, device->dev_unit_num,
1157			mb, speed % 1000);
1158	} else {
1159		fprintf(stdout, "%s%d: %dKB/s transfers",
1160			device->device_name, device->dev_unit_num,
1161			speed);
1162	}
1163
1164	if (ccb->cts.transport == XPORT_SPI) {
1165		struct ccb_trans_settings_spi *spi =
1166		    &ccb->cts.xport_specific.spi;
1167
1168		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1169		 && (spi->sync_offset != 0))
1170			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1171				freq % 1000, spi->sync_offset);
1172
1173		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1174		 && (spi->bus_width > 0)) {
1175			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1176			 && (spi->sync_offset != 0)) {
1177				fprintf(stdout, ", ");
1178			} else {
1179				fprintf(stdout, " (");
1180			}
1181			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1182		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1183		 && (spi->sync_offset != 0)) {
1184			fprintf(stdout, ")");
1185		}
1186	} else if (ccb->cts.transport == XPORT_ATA) {
1187		struct ccb_trans_settings_pata *pata =
1188		    &ccb->cts.xport_specific.ata;
1189
1190		printf(" (");
1191		if (pata->valid & CTS_ATA_VALID_MODE)
1192			printf("%s, ", ata_mode2string(pata->mode));
1193		if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1194			printf("ATAPI %dbytes, ", pata->atapi);
1195		if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1196			printf("PIO %dbytes", pata->bytecount);
1197		printf(")");
1198	} else if (ccb->cts.transport == XPORT_SATA) {
1199		struct ccb_trans_settings_sata *sata =
1200		    &ccb->cts.xport_specific.sata;
1201
1202		printf(" (");
1203		if (sata->valid & CTS_SATA_VALID_REVISION)
1204			printf("SATA %d.x, ", sata->revision);
1205		else
1206			printf("SATA, ");
1207		if (sata->valid & CTS_SATA_VALID_MODE)
1208			printf("%s, ", ata_mode2string(sata->mode));
1209		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1210			printf("ATAPI %dbytes, ", sata->atapi);
1211		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1212			printf("PIO %dbytes", sata->bytecount);
1213		printf(")");
1214	}
1215
1216	if (ccb->cts.protocol == PROTO_SCSI) {
1217		struct ccb_trans_settings_scsi *scsi =
1218		    &ccb->cts.proto_specific.scsi;
1219		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1220			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1221				fprintf(stdout, ", Command Queueing Enabled");
1222			}
1223		}
1224	}
1225
1226	fprintf(stdout, "\n");
1227
1228xferrate_bailout:
1229
1230	cam_freeccb(ccb);
1231
1232	return (retval);
1233}
1234
1235static void
1236atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1237{
1238	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1239				((u_int32_t)parm->lba_size_2 << 16);
1240
1241	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1242				((u_int64_t)parm->lba_size48_2 << 16) |
1243				((u_int64_t)parm->lba_size48_3 << 32) |
1244				((u_int64_t)parm->lba_size48_4 << 48);
1245
1246	if (header) {
1247		printf("\nFeature                      "
1248		       "Support  Enabled   Value\n");
1249	}
1250
1251	printf("Host Protected Area (HPA)      ");
1252	if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1253		u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1254		printf("yes      %s     %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1255			lba, hpasize);
1256
1257		printf("HPA - Security                 ");
1258		if (parm->support.command2 & ATA_SUPPORT_MAXSECURITY)
1259			printf("yes      %s\n", (parm->enabled.command2 &
1260			    ATA_SUPPORT_MAXSECURITY) ? "yes" : "no ");
1261		else
1262			printf("no\n");
1263	} else {
1264		printf("no\n");
1265	}
1266}
1267
1268static void
1269ataama_print(struct ata_params *parm, u_int64_t nativesize, int header)
1270{
1271	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1272				((u_int32_t)parm->lba_size_2 << 16);
1273
1274	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1275				((u_int64_t)parm->lba_size48_2 << 16) |
1276				((u_int64_t)parm->lba_size48_3 << 32) |
1277				((u_int64_t)parm->lba_size48_4 << 48);
1278
1279	if (header) {
1280		printf("\nFeature                      "
1281		       "Support  Enabled   Value\n");
1282	}
1283
1284	printf("Accessible Max Address Config  ");
1285	if (parm->support2 & ATA_SUPPORT_AMAX_ADDR) {
1286		u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1287		printf("yes      %s     %ju/%ju\n",
1288		    (nativesize > lba) ? "yes" : "no ", lba, nativesize);
1289	} else {
1290		printf("no\n");
1291	}
1292}
1293
1294static int
1295atasata(struct ata_params *parm)
1296{
1297
1298
1299	if (parm->satacapabilities != 0xffff &&
1300	    parm->satacapabilities != 0x0000)
1301		return 1;
1302
1303	return 0;
1304}
1305
1306static void
1307atacapprint(struct ata_params *parm)
1308{
1309	const char *proto;
1310	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1311				((u_int32_t)parm->lba_size_2 << 16);
1312
1313	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1314				((u_int64_t)parm->lba_size48_2 << 16) |
1315				((u_int64_t)parm->lba_size48_3 << 32) |
1316				((u_int64_t)parm->lba_size48_4 << 48);
1317
1318	printf("\n");
1319	printf("protocol              ");
1320	proto = (parm->config == ATA_PROTO_CFA) ? "CFA" :
1321		(parm->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA";
1322	if (ata_version(parm->version_major) == 0) {
1323		printf("%s", proto);
1324	} else if (ata_version(parm->version_major) <= 7) {
1325		printf("%s-%d", proto,
1326		    ata_version(parm->version_major));
1327	} else if (ata_version(parm->version_major) == 8) {
1328		printf("%s8-ACS", proto);
1329	} else {
1330		printf("ACS-%d %s",
1331		    ata_version(parm->version_major) - 7, proto);
1332	}
1333	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1334		if (parm->satacapabilities & ATA_SATA_GEN3)
1335			printf(" SATA 3.x\n");
1336		else if (parm->satacapabilities & ATA_SATA_GEN2)
1337			printf(" SATA 2.x\n");
1338		else if (parm->satacapabilities & ATA_SATA_GEN1)
1339			printf(" SATA 1.x\n");
1340		else
1341			printf(" SATA\n");
1342	}
1343	else
1344		printf("\n");
1345	printf("device model          %.40s\n", parm->model);
1346	printf("firmware revision     %.8s\n", parm->revision);
1347	printf("serial number         %.20s\n", parm->serial);
1348	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1349		printf("WWN                   %04x%04x%04x%04x\n",
1350		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1351	}
1352	printf("additional product id %.8s\n", parm->product_id);
1353	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1354		printf("media serial number   %.30s\n",
1355		    parm->media_serial);
1356	}
1357
1358	printf("cylinders             %d\n", parm->cylinders);
1359	printf("heads                 %d\n", parm->heads);
1360	printf("sectors/track         %d\n", parm->sectors);
1361	printf("sector size           logical %u, physical %lu, offset %lu\n",
1362	    ata_logical_sector_size(parm),
1363	    (unsigned long)ata_physical_sector_size(parm),
1364	    (unsigned long)ata_logical_sector_offset(parm));
1365
1366	if (parm->config == ATA_PROTO_CFA ||
1367	    (parm->support.command2 & ATA_SUPPORT_CFA))
1368		printf("CFA supported\n");
1369
1370	printf("LBA%ssupported         ",
1371		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1372	if (lbasize)
1373		printf("%d sectors\n", lbasize);
1374	else
1375		printf("\n");
1376
1377	printf("LBA48%ssupported       ",
1378		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1379	if (lbasize48)
1380		printf("%ju sectors\n", (uintmax_t)lbasize48);
1381	else
1382		printf("\n");
1383
1384	printf("PIO supported         PIO");
1385	switch (ata_max_pmode(parm)) {
1386	case ATA_PIO4:
1387		printf("4");
1388		break;
1389	case ATA_PIO3:
1390		printf("3");
1391		break;
1392	case ATA_PIO2:
1393		printf("2");
1394		break;
1395	case ATA_PIO1:
1396		printf("1");
1397		break;
1398	default:
1399		printf("0");
1400	}
1401	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1402		printf(" w/o IORDY");
1403	printf("\n");
1404
1405	printf("DMA%ssupported         ",
1406		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1407	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1408		if (parm->mwdmamodes & 0xff) {
1409			printf("WDMA");
1410			if (parm->mwdmamodes & 0x04)
1411				printf("2");
1412			else if (parm->mwdmamodes & 0x02)
1413				printf("1");
1414			else if (parm->mwdmamodes & 0x01)
1415				printf("0");
1416			printf(" ");
1417		}
1418		if ((parm->atavalid & ATA_FLAG_88) &&
1419		    (parm->udmamodes & 0xff)) {
1420			printf("UDMA");
1421			if (parm->udmamodes & 0x40)
1422				printf("6");
1423			else if (parm->udmamodes & 0x20)
1424				printf("5");
1425			else if (parm->udmamodes & 0x10)
1426				printf("4");
1427			else if (parm->udmamodes & 0x08)
1428				printf("3");
1429			else if (parm->udmamodes & 0x04)
1430				printf("2");
1431			else if (parm->udmamodes & 0x02)
1432				printf("1");
1433			else if (parm->udmamodes & 0x01)
1434				printf("0");
1435			printf(" ");
1436		}
1437	}
1438	printf("\n");
1439
1440	if (parm->media_rotation_rate == 1) {
1441		printf("media RPM             non-rotating\n");
1442	} else if (parm->media_rotation_rate >= 0x0401 &&
1443	    parm->media_rotation_rate <= 0xFFFE) {
1444		printf("media RPM             %d\n",
1445			parm->media_rotation_rate);
1446	}
1447
1448	printf("Zoned-Device Commands ");
1449	switch (parm->support3 & ATA_SUPPORT_ZONE_MASK) {
1450		case ATA_SUPPORT_ZONE_DEV_MANAGED:
1451			printf("device managed\n");
1452			break;
1453		case ATA_SUPPORT_ZONE_HOST_AWARE:
1454			printf("host aware\n");
1455			break;
1456		default:
1457			printf("no\n");
1458	}
1459
1460	printf("\nFeature                      "
1461		"Support  Enabled   Value           Vendor\n");
1462	printf("read ahead                     %s	%s\n",
1463		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1464		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1465	printf("write cache                    %s	%s\n",
1466		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1467		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1468	printf("flush cache                    %s	%s\n",
1469		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1470		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1471	printf("overlap                        %s\n",
1472		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1473	printf("Tagged Command Queuing (TCQ)   %s	%s",
1474		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1475		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1476		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1477			printf("	%d tags\n",
1478			    ATA_QUEUE_LEN(parm->queue) + 1);
1479		} else
1480			printf("\n");
1481	printf("Native Command Queuing (NCQ)   ");
1482	if (atasata(parm) && (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1483		printf("yes		%d tags\n",
1484		    ATA_QUEUE_LEN(parm->queue) + 1);
1485		printf("NCQ Priority Information       %s\n",
1486		    parm->satacapabilities & ATA_SUPPORT_NCQ_PRIO ?
1487		    "yes" : "no");
1488		printf("NCQ Non-Data Command           %s\n",
1489		    parm->satacapabilities2 & ATA_SUPPORT_NCQ_NON_DATA ?
1490		    "yes" : "no");
1491		printf("NCQ Streaming                  %s\n",
1492		    parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1493		    "yes" : "no");
1494		printf("Receive & Send FPDMA Queued    %s\n",
1495		    parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1496		    "yes" : "no");
1497		printf("NCQ Autosense                  %s\n",
1498		    parm->satasupport & ATA_SUPPORT_NCQ_AUTOSENSE ?
1499		    "yes" : "no");
1500	} else
1501		printf("no\n");
1502
1503	printf("SMART                          %s	%s\n",
1504		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1505		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1506	printf("security                       %s	%s\n",
1507		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1508		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1509	printf("power management               %s	%s\n",
1510		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1511		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1512	printf("microcode download             %s	%s\n",
1513		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1514		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1515	printf("advanced power management      %s	%s",
1516		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1517		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1518		if (parm->support.command2 & ATA_SUPPORT_APM) {
1519			printf("	%d/0x%02X\n",
1520			    parm->apm_value & 0xff, parm->apm_value & 0xff);
1521		} else
1522			printf("\n");
1523	printf("automatic acoustic management  %s	%s",
1524		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1525		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1526		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1527			printf("	%d/0x%02X	%d/0x%02X\n",
1528			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1529			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1530			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1531			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1532		} else
1533			printf("\n");
1534	printf("media status notification      %s	%s\n",
1535		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1536		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1537	printf("power-up in Standby            %s	%s\n",
1538		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1539		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1540	printf("write-read-verify              %s	%s",
1541		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1542		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1543		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1544			printf("	%d/0x%x\n",
1545			    parm->wrv_mode, parm->wrv_mode);
1546		} else
1547			printf("\n");
1548	printf("unload                         %s	%s\n",
1549		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1550		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1551	printf("general purpose logging        %s	%s\n",
1552		parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1553		parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1554	printf("free-fall                      %s	%s\n",
1555		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1556		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1557	printf("sense data reporting           %s	%s\n",
1558		parm->support2 & ATA_SUPPORT_SENSE_REPORT ? "yes" : "no",
1559		parm->enabled2 & ATA_SUPPORT_SENSE_REPORT ? "yes" : "no");
1560	printf("extended power conditions      %s	%s\n",
1561		parm->support2 & ATA_SUPPORT_EPC ? "yes" : "no",
1562		parm->enabled2 & ATA_SUPPORT_EPC ? "yes" : "no");
1563	printf("device statistics notification %s	%s\n",
1564		parm->support2 & ATA_SUPPORT_DSN ? "yes" : "no",
1565		parm->enabled2 & ATA_SUPPORT_DSN ? "yes" : "no");
1566	printf("Data Set Management (DSM/TRIM) ");
1567	if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1568		printf("yes\n");
1569		printf("DSM - max 512byte blocks       ");
1570		if (parm->max_dsm_blocks == 0x00)
1571			printf("yes              not specified\n");
1572		else
1573			printf("yes              %d\n",
1574				parm->max_dsm_blocks);
1575
1576		printf("DSM - deterministic read       ");
1577		if (parm->support3 & ATA_SUPPORT_DRAT) {
1578			if (parm->support3 & ATA_SUPPORT_RZAT)
1579				printf("yes              zeroed\n");
1580			else
1581				printf("yes              any value\n");
1582		} else {
1583			printf("no\n");
1584		}
1585	} else {
1586		printf("no\n");
1587	}
1588	printf("encrypts all user data         %s\n",
1589		parm->support3 & ATA_ENCRYPTS_ALL_USER_DATA ? "yes" : "no");
1590	printf("Sanitize                       ");
1591	if (parm->multi & ATA_SUPPORT_SANITIZE) {
1592		printf("yes\t\t%s%s%s\n",
1593		    parm->multi & ATA_SUPPORT_BLOCK_ERASE_EXT ? "block, " : "",
1594		    parm->multi & ATA_SUPPORT_OVERWRITE_EXT ? "overwrite, " : "",
1595		    parm->multi & ATA_SUPPORT_CRYPTO_SCRAMBLE_EXT ? "crypto" : "");
1596		printf("Sanitize - commands allowed    %s\n",
1597		    parm->multi & ATA_SUPPORT_SANITIZE_ALLOWED ? "yes" : "no");
1598		printf("Sanitize - antifreeze lock     %s\n",
1599		    parm->multi & ATA_SUPPORT_ANTIFREEZE_LOCK_EXT ? "yes" : "no");
1600	} else {
1601		printf("no\n");
1602	}
1603}
1604
1605static int
1606scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb)
1607{
1608	struct ata_pass_16 *ata_pass_16;
1609	struct ata_cmd ata_cmd;
1610
1611	ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1612	ata_cmd.command = ata_pass_16->command;
1613	ata_cmd.control = ata_pass_16->control;
1614	ata_cmd.features = ata_pass_16->features;
1615
1616	if (arglist & CAM_ARG_VERBOSE) {
1617		warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1618		      ata_op_string(&ata_cmd),
1619		      ccb->csio.ccb_h.timeout);
1620	}
1621
1622	/* Disable freezing the device queue */
1623	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1624
1625	if (arglist & CAM_ARG_ERR_RECOVER)
1626		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1627
1628	if (cam_send_ccb(device, ccb) < 0) {
1629		warn("error sending ATA %s via pass_16", ata_op_string(&ata_cmd));
1630		return (1);
1631	}
1632
1633	/*
1634	 * Consider any non-CAM_REQ_CMP status as error and report it here,
1635	 * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
1636	 */
1637	if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1638	    (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1639		warnx("ATA %s via pass_16 failed", ata_op_string(&ata_cmd));
1640		if (arglist & CAM_ARG_VERBOSE) {
1641			cam_error_print(device, ccb, CAM_ESF_ALL,
1642					CAM_EPF_ALL, stderr);
1643		}
1644		return (1);
1645	}
1646
1647	return (0);
1648}
1649
1650
1651static int
1652ata_cam_send(struct cam_device *device, union ccb *ccb)
1653{
1654	if (arglist & CAM_ARG_VERBOSE) {
1655		warnx("sending ATA %s with timeout of %u msecs",
1656		      ata_op_string(&(ccb->ataio.cmd)),
1657		      ccb->ataio.ccb_h.timeout);
1658	}
1659
1660	/* Disable freezing the device queue */
1661	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1662
1663	if (arglist & CAM_ARG_ERR_RECOVER)
1664		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1665
1666	if (cam_send_ccb(device, ccb) < 0) {
1667		warn("error sending ATA %s", ata_op_string(&(ccb->ataio.cmd)));
1668		return (1);
1669	}
1670
1671	/*
1672	 * Consider any non-CAM_REQ_CMP status as error and report it here,
1673	 * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
1674	 */
1675	if (!(ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT) &&
1676	    (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1677		warnx("ATA %s failed", ata_op_string(&(ccb->ataio.cmd)));
1678		if (arglist & CAM_ARG_VERBOSE) {
1679			cam_error_print(device, ccb, CAM_ESF_ALL,
1680					CAM_EPF_ALL, stderr);
1681		}
1682		return (1);
1683	}
1684
1685	return (0);
1686}
1687
1688static int
1689ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1690	       u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1691	       u_int8_t tag_action, u_int8_t command, u_int16_t features,
1692	       u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr,
1693	       u_int16_t dxfer_len, int timeout)
1694{
1695	if (data_ptr != NULL) {
1696		if (flags & CAM_DIR_OUT)
1697			ata_flags |= AP_FLAG_TDIR_TO_DEV;
1698		else
1699			ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1700	} else {
1701		ata_flags |= AP_FLAG_TLEN_NO_DATA;
1702	}
1703
1704	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
1705
1706	scsi_ata_pass_16(&ccb->csio,
1707			 retries,
1708			 NULL,
1709			 flags,
1710			 tag_action,
1711			 protocol,
1712			 ata_flags,
1713			 features,
1714			 sector_count,
1715			 lba,
1716			 command,
1717			 /*control*/0,
1718			 data_ptr,
1719			 dxfer_len,
1720			 /*sense_len*/SSD_FULL_SIZE,
1721			 timeout);
1722
1723	return scsi_cam_pass_16_send(device, ccb);
1724}
1725
1726static int
1727ata_try_pass_16(struct cam_device *device)
1728{
1729	struct ccb_pathinq cpi;
1730
1731	if (get_cpi(device, &cpi) != 0) {
1732		warnx("couldn't get CPI");
1733		return (-1);
1734	}
1735
1736	if (cpi.protocol == PROTO_SCSI) {
1737		/* possibly compatible with pass_16 */
1738		return (1);
1739	}
1740
1741	/* likely not compatible with pass_16 */
1742	return (0);
1743}
1744
1745static int
1746ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1747	   u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1748	   u_int8_t tag_action, u_int8_t command, u_int16_t features,
1749	   u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr,
1750	   u_int16_t dxfer_len, int timeout, int force48bit)
1751{
1752	int retval;
1753
1754	retval = ata_try_pass_16(device);
1755	if (retval == -1)
1756		return (1);
1757
1758	if (retval == 1) {
1759		return (ata_do_pass_16(device, ccb, retries, flags, protocol,
1760				      ata_flags, tag_action, command, features,
1761				      lba, sector_count, data_ptr, dxfer_len,
1762				      timeout));
1763	}
1764
1765	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio);
1766	cam_fill_ataio(&ccb->ataio,
1767		       retries,
1768		       NULL,
1769		       flags,
1770		       tag_action,
1771		       data_ptr,
1772		       dxfer_len,
1773		       timeout);
1774
1775	if (force48bit || lba > ATA_MAX_28BIT_LBA)
1776		ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1777	else
1778		ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1779
1780	if (ata_flags & AP_FLAG_CHK_COND)
1781		ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1782
1783	return ata_cam_send(device, ccb);
1784}
1785
1786static void
1787dump_data(uint16_t *ptr, uint32_t len)
1788{
1789	u_int i;
1790
1791	for (i = 0; i < len / 2; i++) {
1792		if ((i % 8) == 0)
1793			printf(" %3d: ", i);
1794		printf("%04hx ", ptr[i]);
1795		if ((i % 8) == 7)
1796			printf("\n");
1797	}
1798	if ((i % 8) != 7)
1799		printf("\n");
1800}
1801
1802static int
1803atahpa_proc_resp(struct cam_device *device, union ccb *ccb, u_int64_t *hpasize)
1804{
1805	uint8_t error = 0, ata_device = 0, status = 0;
1806	uint16_t count = 0;
1807	uint64_t lba = 0;
1808	int retval;
1809
1810	retval = get_ata_status(device, ccb, &error, &count, &lba, &ata_device,
1811	    &status);
1812	if (retval == 1) {
1813		if (arglist & CAM_ARG_VERBOSE) {
1814			cam_error_print(device, ccb, CAM_ESF_ALL,
1815					CAM_EPF_ALL, stderr);
1816		}
1817		warnx("Can't get ATA command status");
1818		return (retval);
1819	}
1820
1821	if (status & ATA_STATUS_ERROR) {
1822		if (arglist & CAM_ARG_VERBOSE) {
1823			cam_error_print(device, ccb, CAM_ESF_ALL,
1824					CAM_EPF_ALL, stderr);
1825		}
1826
1827		if (error & ATA_ERROR_ID_NOT_FOUND) {
1828			warnx("Max address has already been set since "
1829			      "last power-on or hardware reset");
1830		} else if (hpasize == NULL)
1831			warnx("Command failed with ATA error");
1832
1833		return (1);
1834	}
1835
1836	if (hpasize != NULL) {
1837		if (retval == 2 || retval == 6)
1838			return (1);
1839		*hpasize = lba;
1840	}
1841
1842	return (0);
1843}
1844
1845static int
1846ata_read_native_max(struct cam_device *device, int retry_count,
1847		      u_int32_t timeout, union ccb *ccb,
1848		      struct ata_params *parm, u_int64_t *hpasize)
1849{
1850	int error;
1851	u_int cmd, is48bit;
1852	u_int8_t protocol;
1853
1854	is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1855	protocol = AP_PROTO_NON_DATA;
1856
1857	if (is48bit) {
1858		cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1859		protocol |= AP_EXTEND;
1860	} else {
1861		cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1862	}
1863
1864	error = ata_do_cmd(device,
1865			   ccb,
1866			   retry_count,
1867			   /*flags*/CAM_DIR_NONE,
1868			   /*protocol*/protocol,
1869			   /*ata_flags*/AP_FLAG_CHK_COND,
1870			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1871			   /*command*/cmd,
1872			   /*features*/0,
1873			   /*lba*/0,
1874			   /*sector_count*/0,
1875			   /*data_ptr*/NULL,
1876			   /*dxfer_len*/0,
1877			   timeout ? timeout : 5000,
1878			   is48bit);
1879
1880	if (error)
1881		return (error);
1882
1883	return atahpa_proc_resp(device, ccb, hpasize);
1884}
1885
1886static int
1887atahpa_set_max(struct cam_device *device, int retry_count,
1888	      u_int32_t timeout, union ccb *ccb,
1889	      int is48bit, u_int64_t maxsize, int persist)
1890{
1891	int error;
1892	u_int cmd;
1893	u_int8_t protocol;
1894
1895	protocol = AP_PROTO_NON_DATA;
1896
1897	if (is48bit) {
1898		cmd = ATA_SET_MAX_ADDRESS48;
1899		protocol |= AP_EXTEND;
1900	} else {
1901		cmd = ATA_SET_MAX_ADDRESS;
1902	}
1903
1904	/* lba's are zero indexed so the max lba is requested max - 1 */
1905	if (maxsize)
1906		maxsize--;
1907
1908	error = ata_do_cmd(device,
1909			   ccb,
1910			   retry_count,
1911			   /*flags*/CAM_DIR_NONE,
1912			   /*protocol*/protocol,
1913			   /*ata_flags*/AP_FLAG_CHK_COND,
1914			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1915			   /*command*/cmd,
1916			   /*features*/ATA_HPA_FEAT_MAX_ADDR,
1917			   /*lba*/maxsize,
1918			   /*sector_count*/persist,
1919			   /*data_ptr*/NULL,
1920			   /*dxfer_len*/0,
1921			   timeout ? timeout : 1000,
1922			   is48bit);
1923
1924	if (error)
1925		return (error);
1926
1927	return atahpa_proc_resp(device, ccb, NULL);
1928}
1929
1930static int
1931atahpa_password(struct cam_device *device, int retry_count,
1932		u_int32_t timeout, union ccb *ccb,
1933		int is48bit, struct ata_set_max_pwd *pwd)
1934{
1935	u_int cmd;
1936	u_int8_t protocol;
1937
1938	protocol = AP_PROTO_PIO_OUT;
1939	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1940
1941	return (ata_do_cmd(device,
1942			   ccb,
1943			   retry_count,
1944			   /*flags*/CAM_DIR_OUT,
1945			   /*protocol*/protocol,
1946			   /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
1947			    AP_FLAG_TLEN_SECT_CNT,
1948			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1949			   /*command*/cmd,
1950			   /*features*/ATA_HPA_FEAT_SET_PWD,
1951			   /*lba*/0,
1952			   /*sector_count*/sizeof(*pwd) / 512,
1953			   /*data_ptr*/(u_int8_t*)pwd,
1954			   /*dxfer_len*/sizeof(*pwd),
1955			   timeout ? timeout : 1000,
1956			   is48bit));
1957}
1958
1959static int
1960atahpa_lock(struct cam_device *device, int retry_count,
1961	    u_int32_t timeout, union ccb *ccb, int is48bit)
1962{
1963	u_int cmd;
1964	u_int8_t protocol;
1965
1966	protocol = AP_PROTO_NON_DATA;
1967	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1968
1969	return (ata_do_cmd(device,
1970			   ccb,
1971			   retry_count,
1972			   /*flags*/CAM_DIR_NONE,
1973			   /*protocol*/protocol,
1974			   /*ata_flags*/0,
1975			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1976			   /*command*/cmd,
1977			   /*features*/ATA_HPA_FEAT_LOCK,
1978			   /*lba*/0,
1979			   /*sector_count*/0,
1980			   /*data_ptr*/NULL,
1981			   /*dxfer_len*/0,
1982			   timeout ? timeout : 1000,
1983			   is48bit));
1984}
1985
1986static int
1987atahpa_unlock(struct cam_device *device, int retry_count,
1988	      u_int32_t timeout, union ccb *ccb,
1989	      int is48bit, struct ata_set_max_pwd *pwd)
1990{
1991	u_int cmd;
1992	u_int8_t protocol;
1993
1994	protocol = AP_PROTO_PIO_OUT;
1995	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1996
1997	return (ata_do_cmd(device,
1998			   ccb,
1999			   retry_count,
2000			   /*flags*/CAM_DIR_OUT,
2001			   /*protocol*/protocol,
2002			   /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2003			    AP_FLAG_TLEN_SECT_CNT,
2004			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2005			   /*command*/cmd,
2006			   /*features*/ATA_HPA_FEAT_UNLOCK,
2007			   /*lba*/0,
2008			   /*sector_count*/sizeof(*pwd) / 512,
2009			   /*data_ptr*/(u_int8_t*)pwd,
2010			   /*dxfer_len*/sizeof(*pwd),
2011			   timeout ? timeout : 1000,
2012			   is48bit));
2013}
2014
2015static int
2016atahpa_freeze_lock(struct cam_device *device, int retry_count,
2017		   u_int32_t timeout, union ccb *ccb, int is48bit)
2018{
2019	u_int cmd;
2020	u_int8_t protocol;
2021
2022	protocol = AP_PROTO_NON_DATA;
2023	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
2024
2025	return (ata_do_cmd(device,
2026			   ccb,
2027			   retry_count,
2028			   /*flags*/CAM_DIR_NONE,
2029			   /*protocol*/protocol,
2030			   /*ata_flags*/0,
2031			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2032			   /*command*/cmd,
2033			   /*features*/ATA_HPA_FEAT_FREEZE,
2034			   /*lba*/0,
2035			   /*sector_count*/0,
2036			   /*data_ptr*/NULL,
2037			   /*dxfer_len*/0,
2038			   timeout ? timeout : 1000,
2039			   is48bit));
2040}
2041
2042static int
2043ata_get_native_max(struct cam_device *device, int retry_count,
2044		      u_int32_t timeout, union ccb *ccb,
2045		      u_int64_t *nativesize)
2046{
2047	int error;
2048
2049	error = ata_do_cmd(device,
2050			   ccb,
2051			   retry_count,
2052			   /*flags*/CAM_DIR_NONE,
2053			   /*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
2054			   /*ata_flags*/AP_FLAG_CHK_COND,
2055			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2056			   /*command*/ATA_AMAX_ADDR,
2057			   /*features*/ATA_AMAX_ADDR_GET,
2058			   /*lba*/0,
2059			   /*sector_count*/0,
2060			   /*data_ptr*/NULL,
2061			   /*dxfer_len*/0,
2062			   timeout ? timeout : 30 * 1000,
2063			   /*force48bit*/1);
2064
2065	if (error)
2066		return (error);
2067
2068	return atahpa_proc_resp(device, ccb, nativesize);
2069}
2070
2071static int
2072ataama_set(struct cam_device *device, int retry_count,
2073	      u_int32_t timeout, union ccb *ccb, u_int64_t maxsize)
2074{
2075	int error;
2076
2077	/* lba's are zero indexed so the max lba is requested max - 1 */
2078	if (maxsize)
2079		maxsize--;
2080
2081	error = ata_do_cmd(device,
2082			   ccb,
2083			   retry_count,
2084			   /*flags*/CAM_DIR_NONE,
2085			   /*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
2086			   /*ata_flags*/AP_FLAG_CHK_COND,
2087			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2088			   /*command*/ATA_AMAX_ADDR,
2089			   /*features*/ATA_AMAX_ADDR_SET,
2090			   /*lba*/maxsize,
2091			   /*sector_count*/0,
2092			   /*data_ptr*/NULL,
2093			   /*dxfer_len*/0,
2094			   timeout ? timeout : 30 * 1000,
2095			   /*force48bit*/1);
2096
2097	if (error)
2098		return (error);
2099
2100	return atahpa_proc_resp(device, ccb, NULL);
2101}
2102
2103static int
2104ataama_freeze(struct cam_device *device, int retry_count,
2105		   u_int32_t timeout, union ccb *ccb)
2106{
2107
2108	return (ata_do_cmd(device,
2109			   ccb,
2110			   retry_count,
2111			   /*flags*/CAM_DIR_NONE,
2112			   /*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
2113			   /*ata_flags*/0,
2114			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2115			   /*command*/ATA_AMAX_ADDR,
2116			   /*features*/ATA_AMAX_ADDR_FREEZE,
2117			   /*lba*/0,
2118			   /*sector_count*/0,
2119			   /*data_ptr*/NULL,
2120			   /*dxfer_len*/0,
2121			   timeout ? timeout : 30 * 1000,
2122			   /*force48bit*/1));
2123}
2124
2125int
2126ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2127		union ccb *ccb, struct ata_params** ident_bufp)
2128{
2129	struct ata_params *ident_buf;
2130	struct ccb_pathinq cpi;
2131	struct ccb_getdev cgd;
2132	u_int i, error;
2133	int16_t *ptr;
2134	u_int8_t command, retry_command;
2135
2136	if (get_cpi(device, &cpi) != 0) {
2137		warnx("couldn't get CPI");
2138		return (-1);
2139	}
2140
2141	/* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2142	if (cpi.protocol == PROTO_ATA) {
2143		if (get_cgd(device, &cgd) != 0) {
2144			warnx("couldn't get CGD");
2145			return (-1);
2146		}
2147
2148		command = (cgd.protocol == PROTO_ATA) ?
2149		    ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2150		retry_command = 0;
2151	} else {
2152		/* We don't know which for sure so try both */
2153		command = ATA_ATA_IDENTIFY;
2154		retry_command = ATA_ATAPI_IDENTIFY;
2155	}
2156
2157	ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2158	if (ptr == NULL) {
2159		warnx("can't calloc memory for identify\n");
2160		return (1);
2161	}
2162
2163retry:
2164	error = ata_do_cmd(device,
2165			   ccb,
2166			   /*retries*/retry_count,
2167			   /*flags*/CAM_DIR_IN,
2168			   /*protocol*/AP_PROTO_PIO_IN,
2169			   /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2170			    AP_FLAG_TLEN_SECT_CNT,
2171			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2172			   /*command*/command,
2173			   /*features*/0,
2174			   /*lba*/0,
2175			   /*sector_count*/sizeof(struct ata_params) / 512,
2176			   /*data_ptr*/(u_int8_t *)ptr,
2177			   /*dxfer_len*/sizeof(struct ata_params),
2178			   /*timeout*/timeout ? timeout : 30 * 1000,
2179			   /*force48bit*/0);
2180
2181	if (error != 0) {
2182		if (retry_command != 0) {
2183			command = retry_command;
2184			retry_command = 0;
2185			goto retry;
2186		}
2187		free(ptr);
2188		return (1);
2189	}
2190
2191	error = 1;
2192	for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2193		ptr[i] = le16toh(ptr[i]);
2194		if (ptr[i] != 0)
2195			error = 0;
2196	}
2197
2198	/* check for invalid (all zero) response */
2199	if (error != 0) {
2200		warnx("Invalid identify response detected");
2201		free(ptr);
2202		return (error);
2203	}
2204
2205	ident_buf = (struct ata_params *)ptr;
2206	if (strncmp(ident_buf->model, "FX", 2) &&
2207	    strncmp(ident_buf->model, "NEC", 3) &&
2208	    strncmp(ident_buf->model, "Pioneer", 7) &&
2209	    strncmp(ident_buf->model, "SHARP", 5)) {
2210		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2211		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2212		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2213		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2214	}
2215	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2216	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2217	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2218	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2219	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2220	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2221	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2222	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2223	    sizeof(ident_buf->media_serial));
2224
2225	*ident_bufp = ident_buf;
2226
2227	return (0);
2228}
2229
2230
2231static int
2232ataidentify(struct cam_device *device, int retry_count, int timeout)
2233{
2234	union ccb *ccb;
2235	struct ata_params *ident_buf;
2236	u_int64_t hpasize = 0, nativesize = 0;
2237
2238	if ((ccb = cam_getccb(device)) == NULL) {
2239		warnx("couldn't allocate CCB");
2240		return (1);
2241	}
2242
2243	if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2244		cam_freeccb(ccb);
2245		return (1);
2246	}
2247
2248	if (arglist & CAM_ARG_VERBOSE) {
2249		printf("%s%d: Raw identify data:\n",
2250		    device->device_name, device->dev_unit_num);
2251		dump_data((void*)ident_buf, sizeof(struct ata_params));
2252	}
2253
2254	if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2255		ata_read_native_max(device, retry_count, timeout, ccb,
2256				    ident_buf, &hpasize);
2257	}
2258	if (ident_buf->support2 & ATA_SUPPORT_AMAX_ADDR) {
2259		ata_get_native_max(device, retry_count, timeout, ccb,
2260				   &nativesize);
2261	}
2262
2263	printf("%s%d: ", device->device_name, device->dev_unit_num);
2264	ata_print_ident(ident_buf);
2265	camxferrate(device);
2266	atacapprint(ident_buf);
2267	atahpa_print(ident_buf, hpasize, 0);
2268	ataama_print(ident_buf, nativesize, 0);
2269
2270	free(ident_buf);
2271	cam_freeccb(ccb);
2272
2273	return (0);
2274}
2275#endif /* MINIMALISTIC */
2276
2277
2278#ifndef MINIMALISTIC
2279enum {
2280	ATA_SECURITY_ACTION_PRINT,
2281	ATA_SECURITY_ACTION_FREEZE,
2282	ATA_SECURITY_ACTION_UNLOCK,
2283	ATA_SECURITY_ACTION_DISABLE,
2284	ATA_SECURITY_ACTION_ERASE,
2285	ATA_SECURITY_ACTION_ERASE_ENHANCED,
2286	ATA_SECURITY_ACTION_SET_PASSWORD
2287};
2288
2289static void
2290atasecurity_print_time(u_int16_t tw)
2291{
2292
2293	if (tw == 0)
2294		printf("unspecified");
2295	else if (tw >= 255)
2296		printf("> 508 min");
2297	else
2298		printf("%i min", 2 * tw);
2299}
2300
2301static u_int32_t
2302atasecurity_erase_timeout_msecs(u_int16_t timeout)
2303{
2304
2305	if (timeout == 0)
2306		return 2 * 3600 * 1000; /* default: two hours */
2307	else if (timeout > 255)
2308		return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2309
2310	return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2311}
2312
2313
2314static void
2315atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2316{
2317	struct ata_cmd cmd;
2318
2319	bzero(&cmd, sizeof(cmd));
2320	cmd.command = command;
2321	printf("Issuing %s", ata_op_string(&cmd));
2322
2323	if (pwd != NULL) {
2324		char pass[sizeof(pwd->password)+1];
2325
2326		/* pwd->password may not be null terminated */
2327		pass[sizeof(pwd->password)] = '\0';
2328		strncpy(pass, pwd->password, sizeof(pwd->password));
2329		printf(" password='%s', user='%s'",
2330			pass,
2331			(pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2332			"master" : "user");
2333
2334		if (command == ATA_SECURITY_SET_PASSWORD) {
2335			printf(", mode='%s'",
2336			       (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2337			       "maximum" : "high");
2338		}
2339	}
2340
2341	printf("\n");
2342}
2343
2344static int
2345atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2346		   int retry_count, u_int32_t timeout, int quiet)
2347{
2348
2349	if (quiet == 0)
2350		atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2351
2352	return ata_do_cmd(device,
2353			  ccb,
2354			  retry_count,
2355			  /*flags*/CAM_DIR_NONE,
2356			  /*protocol*/AP_PROTO_NON_DATA,
2357			  /*ata_flags*/0,
2358			  /*tag_action*/MSG_SIMPLE_Q_TAG,
2359			  /*command*/ATA_SECURITY_FREEZE_LOCK,
2360			  /*features*/0,
2361			  /*lba*/0,
2362			  /*sector_count*/0,
2363			  /*data_ptr*/NULL,
2364			  /*dxfer_len*/0,
2365			  /*timeout*/timeout,
2366			  /*force48bit*/0);
2367}
2368
2369static int
2370atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2371		   int retry_count, u_int32_t timeout,
2372		   struct ata_security_password *pwd, int quiet)
2373{
2374
2375	if (quiet == 0)
2376		atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2377
2378	return ata_do_cmd(device,
2379			  ccb,
2380			  retry_count,
2381			  /*flags*/CAM_DIR_OUT,
2382			  /*protocol*/AP_PROTO_PIO_OUT,
2383			  /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2384			    AP_FLAG_TLEN_SECT_CNT,
2385			  /*tag_action*/MSG_SIMPLE_Q_TAG,
2386			  /*command*/ATA_SECURITY_UNLOCK,
2387			  /*features*/0,
2388			  /*lba*/0,
2389			  /*sector_count*/sizeof(*pwd) / 512,
2390			  /*data_ptr*/(u_int8_t *)pwd,
2391			  /*dxfer_len*/sizeof(*pwd),
2392			  /*timeout*/timeout,
2393			  /*force48bit*/0);
2394}
2395
2396static int
2397atasecurity_disable(struct cam_device *device, union ccb *ccb,
2398		    int retry_count, u_int32_t timeout,
2399		    struct ata_security_password *pwd, int quiet)
2400{
2401
2402	if (quiet == 0)
2403		atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2404	return ata_do_cmd(device,
2405			  ccb,
2406			  retry_count,
2407			  /*flags*/CAM_DIR_OUT,
2408			  /*protocol*/AP_PROTO_PIO_OUT,
2409			  /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2410			    AP_FLAG_TLEN_SECT_CNT,
2411			  /*tag_action*/MSG_SIMPLE_Q_TAG,
2412			  /*command*/ATA_SECURITY_DISABLE_PASSWORD,
2413			  /*features*/0,
2414			  /*lba*/0,
2415			  /*sector_count*/sizeof(*pwd) / 512,
2416			  /*data_ptr*/(u_int8_t *)pwd,
2417			  /*dxfer_len*/sizeof(*pwd),
2418			  /*timeout*/timeout,
2419			  /*force48bit*/0);
2420}
2421
2422
2423static int
2424atasecurity_erase_confirm(struct cam_device *device,
2425			  struct ata_params* ident_buf)
2426{
2427
2428	printf("\nYou are about to ERASE ALL DATA from the following"
2429	       " device:\n%s%d,%s%d: ", device->device_name,
2430	       device->dev_unit_num, device->given_dev_name,
2431	       device->given_unit_number);
2432	ata_print_ident(ident_buf);
2433
2434	for(;;) {
2435		char str[50];
2436		printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2437
2438		if (fgets(str, sizeof(str), stdin) != NULL) {
2439			if (strncasecmp(str, "yes", 3) == 0) {
2440				return (1);
2441			} else if (strncasecmp(str, "no", 2) == 0) {
2442				return (0);
2443			} else {
2444				printf("Please answer \"yes\" or "
2445				       "\"no\"\n");
2446			}
2447		}
2448	}
2449
2450	/* NOTREACHED */
2451	return (0);
2452}
2453
2454static int
2455atasecurity_erase(struct cam_device *device, union ccb *ccb,
2456		  int retry_count, u_int32_t timeout,
2457		  u_int32_t erase_timeout,
2458		  struct ata_security_password *pwd, int quiet)
2459{
2460	int error;
2461
2462	if (quiet == 0)
2463		atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2464
2465	error = ata_do_cmd(device,
2466			   ccb,
2467			   retry_count,
2468			   /*flags*/CAM_DIR_NONE,
2469			   /*protocol*/AP_PROTO_NON_DATA,
2470			   /*ata_flags*/0,
2471			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2472			   /*command*/ATA_SECURITY_ERASE_PREPARE,
2473			   /*features*/0,
2474			   /*lba*/0,
2475			   /*sector_count*/0,
2476			   /*data_ptr*/NULL,
2477			   /*dxfer_len*/0,
2478			   /*timeout*/timeout,
2479			   /*force48bit*/0);
2480
2481	if (error != 0)
2482		return error;
2483
2484	if (quiet == 0)
2485		atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2486
2487	error = ata_do_cmd(device,
2488			   ccb,
2489			   retry_count,
2490			   /*flags*/CAM_DIR_OUT,
2491			   /*protocol*/AP_PROTO_PIO_OUT,
2492			   /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2493			    AP_FLAG_TLEN_SECT_CNT,
2494			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2495			   /*command*/ATA_SECURITY_ERASE_UNIT,
2496			   /*features*/0,
2497			   /*lba*/0,
2498			   /*sector_count*/sizeof(*pwd) / 512,
2499			   /*data_ptr*/(u_int8_t *)pwd,
2500			   /*dxfer_len*/sizeof(*pwd),
2501			   /*timeout*/erase_timeout,
2502			   /*force48bit*/0);
2503
2504	if (error == 0 && quiet == 0)
2505		printf("\nErase Complete\n");
2506
2507	return error;
2508}
2509
2510static int
2511atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2512			 int retry_count, u_int32_t timeout,
2513			 struct ata_security_password *pwd, int quiet)
2514{
2515
2516	if (quiet == 0)
2517		atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2518
2519	return ata_do_cmd(device,
2520			  ccb,
2521			  retry_count,
2522			  /*flags*/CAM_DIR_OUT,
2523			  /*protocol*/AP_PROTO_PIO_OUT,
2524			  /*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
2525			   AP_FLAG_TLEN_SECT_CNT,
2526			  /*tag_action*/MSG_SIMPLE_Q_TAG,
2527			  /*command*/ATA_SECURITY_SET_PASSWORD,
2528			  /*features*/0,
2529			  /*lba*/0,
2530			  /*sector_count*/sizeof(*pwd) / 512,
2531			  /*data_ptr*/(u_int8_t *)pwd,
2532			  /*dxfer_len*/sizeof(*pwd),
2533			  /*timeout*/timeout,
2534			  /*force48bit*/0);
2535}
2536
2537static void
2538atasecurity_print(struct ata_params *parm)
2539{
2540
2541	printf("\nSecurity Option           Value\n");
2542	if (arglist & CAM_ARG_VERBOSE) {
2543		printf("status                    %04x\n",
2544		       parm->security_status);
2545	}
2546	printf("supported                 %s\n",
2547		parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2548	if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2549		return;
2550	printf("enabled                   %s\n",
2551		parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2552	printf("drive locked              %s\n",
2553		parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2554	printf("security config frozen    %s\n",
2555		parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2556	printf("count expired             %s\n",
2557		parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2558	printf("security level            %s\n",
2559		parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2560	printf("enhanced erase supported  %s\n",
2561		parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2562	printf("erase time                ");
2563	atasecurity_print_time(parm->erase_time);
2564	printf("\n");
2565	printf("enhanced erase time       ");
2566	atasecurity_print_time(parm->enhanced_erase_time);
2567	printf("\n");
2568	printf("master password rev       %04x%s\n",
2569		parm->master_passwd_revision,
2570		parm->master_passwd_revision == 0x0000 ||
2571		parm->master_passwd_revision == 0xFFFF ?  " (unsupported)" : "");
2572}
2573
2574/*
2575 * Validates and copies the password in optarg to the passed buffer.
2576 * If the password in optarg is the same length as the buffer then
2577 * the data will still be copied but no null termination will occur.
2578 */
2579static int
2580ata_getpwd(u_int8_t *passwd, int max, char opt)
2581{
2582	int len;
2583
2584	len = strlen(optarg);
2585	if (len > max) {
2586		warnx("-%c password is too long", opt);
2587		return (1);
2588	} else if (len == 0) {
2589		warnx("-%c password is missing", opt);
2590		return (1);
2591	} else if (optarg[0] == '-'){
2592		warnx("-%c password starts with '-' (generic arg?)", opt);
2593		return (1);
2594	} else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2595		warnx("-%c password conflicts with existing password from -%c",
2596		      opt, pwd_opt);
2597		return (1);
2598	}
2599
2600	/* Callers pass in a buffer which does NOT need to be terminated */
2601	strncpy(passwd, optarg, max);
2602	pwd_opt = opt;
2603
2604	return (0);
2605}
2606
2607enum {
2608	ATA_HPA_ACTION_PRINT,
2609	ATA_HPA_ACTION_SET_MAX,
2610	ATA_HPA_ACTION_SET_PWD,
2611	ATA_HPA_ACTION_LOCK,
2612	ATA_HPA_ACTION_UNLOCK,
2613	ATA_HPA_ACTION_FREEZE_LOCK
2614};
2615
2616static int
2617atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2618		   u_int64_t maxsize, int persist)
2619{
2620	printf("\nYou are about to configure HPA to limit the user accessible\n"
2621	       "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2622	       persist ? "persistently" : "temporarily",
2623	       device->device_name, device->dev_unit_num,
2624	       device->given_dev_name, device->given_unit_number);
2625	ata_print_ident(ident_buf);
2626
2627	for(;;) {
2628		char str[50];
2629		printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2630
2631		if (NULL != fgets(str, sizeof(str), stdin)) {
2632			if (0 == strncasecmp(str, "yes", 3)) {
2633				return (1);
2634			} else if (0 == strncasecmp(str, "no", 2)) {
2635				return (0);
2636			} else {
2637				printf("Please answer \"yes\" or "
2638				       "\"no\"\n");
2639			}
2640		}
2641	}
2642
2643	/* NOTREACHED */
2644	return (0);
2645}
2646
2647static int
2648atahpa(struct cam_device *device, int retry_count, int timeout,
2649       int argc, char **argv, char *combinedopt)
2650{
2651	union ccb *ccb;
2652	struct ata_params *ident_buf;
2653	struct ccb_getdev cgd;
2654	struct ata_set_max_pwd pwd;
2655	int error, confirm, quiet, c, action, actions, persist;
2656	int security, is48bit, pwdsize;
2657	u_int64_t hpasize, maxsize;
2658
2659	actions = 0;
2660	confirm = 0;
2661	quiet = 0;
2662	maxsize = 0;
2663	persist = 0;
2664	security = 0;
2665
2666	memset(&pwd, 0, sizeof(pwd));
2667
2668	/* default action is to print hpa information */
2669	action = ATA_HPA_ACTION_PRINT;
2670	pwdsize = sizeof(pwd.password);
2671
2672	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2673		switch(c){
2674		case 's':
2675			action = ATA_HPA_ACTION_SET_MAX;
2676			maxsize = strtoumax(optarg, NULL, 0);
2677			actions++;
2678			break;
2679
2680		case 'p':
2681			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2682				return (1);
2683			action = ATA_HPA_ACTION_SET_PWD;
2684			security = 1;
2685			actions++;
2686			break;
2687
2688		case 'l':
2689			action = ATA_HPA_ACTION_LOCK;
2690			security = 1;
2691			actions++;
2692			break;
2693
2694		case 'U':
2695			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2696				return (1);
2697			action = ATA_HPA_ACTION_UNLOCK;
2698			security = 1;
2699			actions++;
2700			break;
2701
2702		case 'f':
2703			action = ATA_HPA_ACTION_FREEZE_LOCK;
2704			security = 1;
2705			actions++;
2706			break;
2707
2708		case 'P':
2709			persist = 1;
2710			break;
2711
2712		case 'y':
2713			confirm++;
2714			break;
2715
2716		case 'q':
2717			quiet++;
2718			break;
2719		}
2720	}
2721
2722	if (actions > 1) {
2723		warnx("too many hpa actions specified");
2724		return (1);
2725	}
2726
2727	if (get_cgd(device, &cgd) != 0) {
2728		warnx("couldn't get CGD");
2729		return (1);
2730	}
2731
2732	ccb = cam_getccb(device);
2733	if (ccb == NULL) {
2734		warnx("couldn't allocate CCB");
2735		return (1);
2736	}
2737
2738	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2739	if (error != 0) {
2740		cam_freeccb(ccb);
2741		return (1);
2742	}
2743
2744	if (quiet == 0) {
2745		printf("%s%d: ", device->device_name, device->dev_unit_num);
2746		ata_print_ident(ident_buf);
2747		camxferrate(device);
2748	}
2749
2750	if (action == ATA_HPA_ACTION_PRINT) {
2751		hpasize = 0;
2752		if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)
2753			ata_read_native_max(device, retry_count, timeout, ccb,
2754				    ident_buf, &hpasize);
2755		atahpa_print(ident_buf, hpasize, 1);
2756
2757		cam_freeccb(ccb);
2758		free(ident_buf);
2759		return (error);
2760	}
2761
2762	if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2763		warnx("HPA is not supported by this device");
2764		cam_freeccb(ccb);
2765		free(ident_buf);
2766		return (1);
2767	}
2768
2769	if (security && !(ident_buf->support.command2 & ATA_SUPPORT_MAXSECURITY)) {
2770		warnx("HPA Security is not supported by this device");
2771		cam_freeccb(ccb);
2772		free(ident_buf);
2773		return (1);
2774	}
2775
2776	is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2777
2778	/*
2779	 * The ATA spec requires:
2780	 * 1. Read native max addr is called directly before set max addr
2781	 * 2. Read native max addr is NOT called before any other set max call
2782	 */
2783	switch(action) {
2784	case ATA_HPA_ACTION_SET_MAX:
2785		if (confirm == 0 &&
2786		    atahpa_set_confirm(device, ident_buf, maxsize,
2787		    persist) == 0) {
2788			cam_freeccb(ccb);
2789			free(ident_buf);
2790			return (1);
2791		}
2792
2793		error = ata_read_native_max(device, retry_count, timeout,
2794					    ccb, ident_buf, &hpasize);
2795		if (error == 0) {
2796			error = atahpa_set_max(device, retry_count, timeout,
2797					       ccb, is48bit, maxsize, persist);
2798			if (error == 0) {
2799				if (quiet == 0) {
2800					/* redo identify to get new values */
2801					error = ata_do_identify(device,
2802					    retry_count, timeout, ccb,
2803					    &ident_buf);
2804					atahpa_print(ident_buf, hpasize, 1);
2805				}
2806				/* Hint CAM to reprobe the device. */
2807				reprobe(device);
2808			}
2809		}
2810		break;
2811
2812	case ATA_HPA_ACTION_SET_PWD:
2813		error = atahpa_password(device, retry_count, timeout,
2814					ccb, is48bit, &pwd);
2815		if (error == 0 && quiet == 0)
2816			printf("HPA password has been set\n");
2817		break;
2818
2819	case ATA_HPA_ACTION_LOCK:
2820		error = atahpa_lock(device, retry_count, timeout,
2821				    ccb, is48bit);
2822		if (error == 0 && quiet == 0)
2823			printf("HPA has been locked\n");
2824		break;
2825
2826	case ATA_HPA_ACTION_UNLOCK:
2827		error = atahpa_unlock(device, retry_count, timeout,
2828				      ccb, is48bit, &pwd);
2829		if (error == 0 && quiet == 0)
2830			printf("HPA has been unlocked\n");
2831		break;
2832
2833	case ATA_HPA_ACTION_FREEZE_LOCK:
2834		error = atahpa_freeze_lock(device, retry_count, timeout,
2835					   ccb, is48bit);
2836		if (error == 0 && quiet == 0)
2837			printf("HPA has been frozen\n");
2838		break;
2839
2840	default:
2841		errx(1, "Option currently not supported");
2842	}
2843
2844	cam_freeccb(ccb);
2845	free(ident_buf);
2846
2847	return (error);
2848}
2849
2850enum {
2851	ATA_AMA_ACTION_PRINT,
2852	ATA_AMA_ACTION_SET_MAX,
2853	ATA_AMA_ACTION_FREEZE_LOCK
2854};
2855
2856static int
2857ataama(struct cam_device *device, int retry_count, int timeout,
2858       int argc, char **argv, char *combinedopt)
2859{
2860	union ccb *ccb;
2861	struct ata_params *ident_buf;
2862	struct ccb_getdev cgd;
2863	int error, quiet, c, action, actions;
2864	u_int64_t nativesize, maxsize;
2865
2866	actions = 0;
2867	quiet = 0;
2868	maxsize = 0;
2869
2870	/* default action is to print AMA information */
2871	action = ATA_AMA_ACTION_PRINT;
2872
2873	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2874		switch(c){
2875		case 's':
2876			action = ATA_AMA_ACTION_SET_MAX;
2877			maxsize = strtoumax(optarg, NULL, 0);
2878			actions++;
2879			break;
2880
2881		case 'f':
2882			action = ATA_AMA_ACTION_FREEZE_LOCK;
2883			actions++;
2884			break;
2885
2886		case 'q':
2887			quiet++;
2888			break;
2889		}
2890	}
2891
2892	if (actions > 1) {
2893		warnx("too many AMA actions specified");
2894		return (1);
2895	}
2896
2897	if (get_cgd(device, &cgd) != 0) {
2898		warnx("couldn't get CGD");
2899		return (1);
2900	}
2901
2902	ccb = cam_getccb(device);
2903	if (ccb == NULL) {
2904		warnx("couldn't allocate CCB");
2905		return (1);
2906	}
2907
2908	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2909	if (error != 0) {
2910		cam_freeccb(ccb);
2911		return (1);
2912	}
2913
2914	if (quiet == 0) {
2915		printf("%s%d: ", device->device_name, device->dev_unit_num);
2916		ata_print_ident(ident_buf);
2917		camxferrate(device);
2918	}
2919
2920	if (action == ATA_AMA_ACTION_PRINT) {
2921		nativesize = 0;
2922		if (ident_buf->support2 & ATA_SUPPORT_AMAX_ADDR)
2923			ata_get_native_max(device, retry_count, timeout, ccb,
2924					   &nativesize);
2925		ataama_print(ident_buf, nativesize, 1);
2926
2927		cam_freeccb(ccb);
2928		free(ident_buf);
2929		return (error);
2930	}
2931
2932	if (!(ident_buf->support2 & ATA_SUPPORT_AMAX_ADDR)) {
2933		warnx("Accessible Max Address is not supported by this device");
2934		cam_freeccb(ccb);
2935		free(ident_buf);
2936		return (1);
2937	}
2938
2939	switch(action) {
2940	case ATA_AMA_ACTION_SET_MAX:
2941		error = ata_get_native_max(device, retry_count, timeout, ccb,
2942					   &nativesize);
2943		if (error == 0) {
2944			error = ataama_set(device, retry_count, timeout,
2945				       ccb, maxsize);
2946			if (error == 0) {
2947				if (quiet == 0) {
2948					/* redo identify to get new values */
2949					error = ata_do_identify(device,
2950					    retry_count, timeout, ccb,
2951					    &ident_buf);
2952					ataama_print(ident_buf, nativesize, 1);
2953				}
2954				/* Hint CAM to reprobe the device. */
2955				reprobe(device);
2956			}
2957		}
2958		break;
2959
2960	case ATA_AMA_ACTION_FREEZE_LOCK:
2961		error = ataama_freeze(device, retry_count, timeout,
2962					   ccb);
2963		if (error == 0 && quiet == 0)
2964			printf("Accessible Max Address has been frozen\n");
2965		break;
2966
2967	default:
2968		errx(1, "Option currently not supported");
2969	}
2970
2971	cam_freeccb(ccb);
2972	free(ident_buf);
2973
2974	return (error);
2975}
2976
2977static int
2978atasecurity(struct cam_device *device, int retry_count, int timeout,
2979	    int argc, char **argv, char *combinedopt)
2980{
2981	union ccb *ccb;
2982	struct ata_params *ident_buf;
2983	int error, confirm, quiet, c, action, actions, setpwd;
2984	int security_enabled, erase_timeout, pwdsize;
2985	struct ata_security_password pwd;
2986
2987	actions = 0;
2988	setpwd = 0;
2989	erase_timeout = 0;
2990	confirm = 0;
2991	quiet = 0;
2992
2993	memset(&pwd, 0, sizeof(pwd));
2994
2995	/* default action is to print security information */
2996	action = ATA_SECURITY_ACTION_PRINT;
2997
2998	/* user is master by default as its safer that way */
2999	pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
3000	pwdsize = sizeof(pwd.password);
3001
3002	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3003		switch(c){
3004		case 'f':
3005			action = ATA_SECURITY_ACTION_FREEZE;
3006			actions++;
3007			break;
3008
3009		case 'U':
3010			if (strcasecmp(optarg, "user") == 0) {
3011				pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
3012				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
3013			} else if (strcasecmp(optarg, "master") == 0) {
3014				pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
3015				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
3016			} else {
3017				warnx("-U argument '%s' is invalid (must be "
3018				      "'user' or 'master')", optarg);
3019				return (1);
3020			}
3021			break;
3022
3023		case 'l':
3024			if (strcasecmp(optarg, "high") == 0) {
3025				pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
3026				pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
3027			} else if (strcasecmp(optarg, "maximum") == 0) {
3028				pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
3029				pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
3030			} else {
3031				warnx("-l argument '%s' is unknown (must be "
3032				      "'high' or 'maximum')", optarg);
3033				return (1);
3034			}
3035			break;
3036
3037		case 'k':
3038			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
3039				return (1);
3040			action = ATA_SECURITY_ACTION_UNLOCK;
3041			actions++;
3042			break;
3043
3044		case 'd':
3045			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
3046				return (1);
3047			action = ATA_SECURITY_ACTION_DISABLE;
3048			actions++;
3049			break;
3050
3051		case 'e':
3052			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
3053				return (1);
3054			action = ATA_SECURITY_ACTION_ERASE;
3055			actions++;
3056			break;
3057
3058		case 'h':
3059			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
3060				return (1);
3061			pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
3062			action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
3063			actions++;
3064			break;
3065
3066		case 's':
3067			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
3068				return (1);
3069			setpwd = 1;
3070			if (action == ATA_SECURITY_ACTION_PRINT)
3071				action = ATA_SECURITY_ACTION_SET_PASSWORD;
3072			/*
3073			 * Don't increment action as this can be combined
3074			 * with other actions.
3075			 */
3076			break;
3077
3078		case 'y':
3079			confirm++;
3080			break;
3081
3082		case 'q':
3083			quiet++;
3084			break;
3085
3086		case 'T':
3087			erase_timeout = atoi(optarg) * 1000;
3088			break;
3089		}
3090	}
3091
3092	if (actions > 1) {
3093		warnx("too many security actions specified");
3094		return (1);
3095	}
3096
3097	if ((ccb = cam_getccb(device)) == NULL) {
3098		warnx("couldn't allocate CCB");
3099		return (1);
3100	}
3101
3102	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
3103	if (error != 0) {
3104		cam_freeccb(ccb);
3105		return (1);
3106	}
3107
3108	if (quiet == 0) {
3109		printf("%s%d: ", device->device_name, device->dev_unit_num);
3110		ata_print_ident(ident_buf);
3111		camxferrate(device);
3112	}
3113
3114	if (action == ATA_SECURITY_ACTION_PRINT) {
3115		atasecurity_print(ident_buf);
3116		free(ident_buf);
3117		cam_freeccb(ccb);
3118		return (0);
3119	}
3120
3121	if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
3122		warnx("Security not supported");
3123		free(ident_buf);
3124		cam_freeccb(ccb);
3125		return (1);
3126	}
3127
3128	/* default timeout 15 seconds the same as linux hdparm */
3129	timeout = timeout ? timeout : 15 * 1000;
3130
3131	security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
3132
3133	/* first set the password if requested */
3134	if (setpwd == 1) {
3135		/* confirm we can erase before setting the password if erasing */
3136		if (confirm == 0 &&
3137		    (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
3138		    action == ATA_SECURITY_ACTION_ERASE) &&
3139		    atasecurity_erase_confirm(device, ident_buf) == 0) {
3140			cam_freeccb(ccb);
3141			free(ident_buf);
3142			return (error);
3143		}
3144
3145		if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
3146			pwd.revision = ident_buf->master_passwd_revision;
3147			if (pwd.revision != 0 && pwd.revision != 0xfff &&
3148			    --pwd.revision == 0) {
3149				pwd.revision = 0xfffe;
3150			}
3151		}
3152		error = atasecurity_set_password(device, ccb, retry_count,
3153						 timeout, &pwd, quiet);
3154		if (error != 0) {
3155			cam_freeccb(ccb);
3156			free(ident_buf);
3157			return (error);
3158		}
3159		security_enabled = 1;
3160	}
3161
3162	switch(action) {
3163	case ATA_SECURITY_ACTION_FREEZE:
3164		error = atasecurity_freeze(device, ccb, retry_count,
3165					   timeout, quiet);
3166		break;
3167
3168	case ATA_SECURITY_ACTION_UNLOCK:
3169		if (security_enabled) {
3170			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
3171				error = atasecurity_unlock(device, ccb,
3172					retry_count, timeout, &pwd, quiet);
3173			} else {
3174				warnx("Can't unlock, drive is not locked");
3175				error = 1;
3176			}
3177		} else {
3178			warnx("Can't unlock, security is disabled");
3179			error = 1;
3180		}
3181		break;
3182
3183	case ATA_SECURITY_ACTION_DISABLE:
3184		if (security_enabled) {
3185			/* First unlock the drive if its locked */
3186			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
3187				error = atasecurity_unlock(device, ccb,
3188							   retry_count,
3189							   timeout,
3190							   &pwd,
3191							   quiet);
3192			}
3193
3194			if (error == 0) {
3195				error = atasecurity_disable(device,
3196							    ccb,
3197							    retry_count,
3198							    timeout,
3199							    &pwd,
3200							    quiet);
3201			}
3202		} else {
3203			warnx("Can't disable security (already disabled)");
3204			error = 1;
3205		}
3206		break;
3207
3208	case ATA_SECURITY_ACTION_ERASE:
3209		if (security_enabled) {
3210			if (erase_timeout == 0) {
3211				erase_timeout = atasecurity_erase_timeout_msecs(
3212				    ident_buf->erase_time);
3213			}
3214
3215			error = atasecurity_erase(device, ccb, retry_count,
3216			    timeout, erase_timeout, &pwd, quiet);
3217		} else {
3218			warnx("Can't secure erase (security is disabled)");
3219			error = 1;
3220		}
3221		break;
3222
3223	case ATA_SECURITY_ACTION_ERASE_ENHANCED:
3224		if (security_enabled) {
3225			if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
3226				if (erase_timeout == 0) {
3227					erase_timeout =
3228					    atasecurity_erase_timeout_msecs(
3229						ident_buf->enhanced_erase_time);
3230				}
3231
3232				error = atasecurity_erase(device, ccb,
3233							  retry_count, timeout,
3234							  erase_timeout, &pwd,
3235							  quiet);
3236			} else {
3237				warnx("Enhanced erase is not supported");
3238				error = 1;
3239			}
3240		} else {
3241			warnx("Can't secure erase (enhanced), "
3242			      "(security is disabled)");
3243			error = 1;
3244		}
3245		break;
3246	}
3247
3248	cam_freeccb(ccb);
3249	free(ident_buf);
3250
3251	return (error);
3252}
3253#endif /* MINIMALISTIC */
3254
3255/*
3256 * Convert periph name into a bus, target and lun.
3257 *
3258 * Returns the number of parsed components, or 0.
3259 */
3260static int
3261parse_btl_name(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3262    cam_argmask *arglst)
3263{
3264	int fd;
3265	union ccb ccb;
3266
3267	bzero(&ccb, sizeof(ccb));
3268	ccb.ccb_h.func_code = XPT_GDEVLIST;
3269	if (cam_get_device(tstr, ccb.cgdl.periph_name,
3270	    sizeof(ccb.cgdl.periph_name), &ccb.cgdl.unit_number) == -1) {
3271		warnx("%s", cam_errbuf);
3272		return (0);
3273	}
3274
3275	/*
3276	 * Attempt to get the passthrough device.  This ioctl will
3277	 * fail if the device name is null, if the device doesn't
3278	 * exist, or if the passthrough driver isn't in the kernel.
3279	 */
3280	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
3281		warn("Unable to open %s", XPT_DEVICE);
3282		return (0);
3283	}
3284	if (ioctl(fd, CAMGETPASSTHRU, &ccb) == -1) {
3285		warn("Unable to find bus:target:lun for device %s%d",
3286		    ccb.cgdl.periph_name, ccb.cgdl.unit_number);
3287		close(fd);
3288		return (0);
3289	}
3290	close(fd);
3291	if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3292		const struct cam_status_entry *entry;
3293
3294		entry = cam_fetch_status_entry(ccb.ccb_h.status);
3295		warnx("Unable to find bus:target_lun for device %s%d, "
3296		    "CAM status: %s (%#x)",
3297		    ccb.cgdl.periph_name, ccb.cgdl.unit_number,
3298		    entry ? entry->status_text : "Unknown",
3299		    ccb.ccb_h.status);
3300		return (0);
3301	}
3302
3303	/*
3304	 * The kernel fills in the bus/target/lun.  We don't
3305	 * need the passthrough device name and unit number since
3306	 * we aren't going to open it.
3307	 */
3308	*bus = ccb.ccb_h.path_id;
3309	*target = ccb.ccb_h.target_id;
3310	*lun = ccb.ccb_h.target_lun;
3311	*arglst |= CAM_ARG_BUS | CAM_ARG_TARGET | CAM_ARG_LUN;
3312	return (3);
3313}
3314
3315/*
3316 * Parse out a bus, or a bus, target and lun in the following
3317 * format:
3318 * bus
3319 * bus:target
3320 * bus:target:lun
3321 *
3322 * Returns the number of parsed components, or 0.
3323 */
3324static int
3325parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3326    cam_argmask *arglst)
3327{
3328	char *tmpstr, *end;
3329	int convs = 0;
3330
3331	*bus = CAM_BUS_WILDCARD;
3332	*target = CAM_TARGET_WILDCARD;
3333	*lun = CAM_LUN_WILDCARD;
3334
3335	while (isspace(*tstr) && (*tstr != '\0'))
3336		tstr++;
3337
3338	if (strncasecmp(tstr, "all", strlen("all")) == 0) {
3339		arglist |= CAM_ARG_BUS;
3340		return (1);
3341	}
3342
3343	if (!isdigit(*tstr))
3344		return (parse_btl_name(tstr, bus, target, lun, arglst));
3345
3346	tmpstr = strsep(&tstr, ":");
3347	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3348		*bus = strtol(tmpstr, &end, 0);
3349		if (*end != '\0')
3350			return (0);
3351		*arglst |= CAM_ARG_BUS;
3352		convs++;
3353		tmpstr = strsep(&tstr, ":");
3354		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3355			*target = strtol(tmpstr, &end, 0);
3356			if (*end != '\0')
3357				return (0);
3358			*arglst |= CAM_ARG_TARGET;
3359			convs++;
3360			tmpstr = strsep(&tstr, ":");
3361			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3362				*lun = strtoll(tmpstr, &end, 0);
3363				if (*end != '\0')
3364					return (0);
3365				*arglst |= CAM_ARG_LUN;
3366				convs++;
3367			}
3368		}
3369	}
3370
3371	return convs;
3372}
3373
3374static int
3375dorescan_or_reset(int argc, char **argv, int rescan)
3376{
3377	static const char must[] =
3378	    "you must specify \"all\", a bus, a bus:target:lun or periph to %s";
3379	int rv, error = 0;
3380	path_id_t bus = CAM_BUS_WILDCARD;
3381	target_id_t target = CAM_TARGET_WILDCARD;
3382	lun_id_t lun = CAM_LUN_WILDCARD;
3383	char *tstr;
3384
3385	if (argc < 3) {
3386		warnx(must, rescan? "rescan" : "reset");
3387		return (1);
3388	}
3389
3390	tstr = argv[optind];
3391	while (isspace(*tstr) && (*tstr != '\0'))
3392		tstr++;
3393	if (strncasecmp(tstr, "all", strlen("all")) == 0)
3394		arglist |= CAM_ARG_BUS;
3395	else {
3396		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3397		if (rv != 1 && rv != 3) {
3398			warnx(must, rescan ? "rescan" : "reset");
3399			return (1);
3400		}
3401	}
3402
3403	if (arglist & CAM_ARG_LUN)
3404		error = scanlun_or_reset_dev(bus, target, lun, rescan);
3405	else
3406		error = rescan_or_reset_bus(bus, rescan);
3407
3408	return (error);
3409}
3410
3411static int
3412rescan_or_reset_bus(path_id_t bus, int rescan)
3413{
3414	union ccb *ccb = NULL, *matchccb = NULL;
3415	int fd = -1, retval;
3416	int bufsize;
3417
3418	retval = 0;
3419
3420	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3421		warnx("error opening transport layer device %s", XPT_DEVICE);
3422		warn("%s", XPT_DEVICE);
3423		return (1);
3424	}
3425
3426	ccb = malloc(sizeof(*ccb));
3427	if (ccb == NULL) {
3428		warn("failed to allocate CCB");
3429		retval = 1;
3430		goto bailout;
3431	}
3432	bzero(ccb, sizeof(*ccb));
3433
3434	if (bus != CAM_BUS_WILDCARD) {
3435		ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3436		ccb->ccb_h.path_id = bus;
3437		ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3438		ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3439		ccb->crcn.flags = CAM_FLAG_NONE;
3440
3441		/* run this at a low priority */
3442		ccb->ccb_h.pinfo.priority = 5;
3443
3444		if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3445			warn("CAMIOCOMMAND ioctl failed");
3446			retval = 1;
3447			goto bailout;
3448		}
3449
3450		if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3451			fprintf(stdout, "%s of bus %d was successful\n",
3452			    rescan ? "Re-scan" : "Reset", bus);
3453		} else {
3454			fprintf(stdout, "%s of bus %d returned error %#x\n",
3455				rescan ? "Re-scan" : "Reset", bus,
3456				ccb->ccb_h.status & CAM_STATUS_MASK);
3457			retval = 1;
3458		}
3459
3460		goto bailout;
3461	}
3462
3463
3464	/*
3465	 * The right way to handle this is to modify the xpt so that it can
3466	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3467	 * that isn't implemented, so instead we enumerate the busses and
3468	 * send the rescan or reset to those busses in the case where the
3469	 * given bus is -1 (wildcard).  We don't send a rescan or reset
3470	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3471	 * no-op, sending a rescan to the xpt bus would result in a status of
3472	 * CAM_REQ_INVALID.
3473	 */
3474	matchccb = malloc(sizeof(*matchccb));
3475	if (matchccb == NULL) {
3476		warn("failed to allocate CCB");
3477		retval = 1;
3478		goto bailout;
3479	}
3480	bzero(matchccb, sizeof(*matchccb));
3481	matchccb->ccb_h.func_code = XPT_DEV_MATCH;
3482	matchccb->ccb_h.path_id = CAM_BUS_WILDCARD;
3483	bufsize = sizeof(struct dev_match_result) * 20;
3484	matchccb->cdm.match_buf_len = bufsize;
3485	matchccb->cdm.matches=(struct dev_match_result *)malloc(bufsize);
3486	if (matchccb->cdm.matches == NULL) {
3487		warnx("can't malloc memory for matches");
3488		retval = 1;
3489		goto bailout;
3490	}
3491	matchccb->cdm.num_matches = 0;
3492
3493	matchccb->cdm.num_patterns = 1;
3494	matchccb->cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3495
3496	matchccb->cdm.patterns = (struct dev_match_pattern *)malloc(
3497		matchccb->cdm.pattern_buf_len);
3498	if (matchccb->cdm.patterns == NULL) {
3499		warnx("can't malloc memory for patterns");
3500		retval = 1;
3501		goto bailout;
3502	}
3503	matchccb->cdm.patterns[0].type = DEV_MATCH_BUS;
3504	matchccb->cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3505
3506	do {
3507		unsigned int i;
3508
3509		if (ioctl(fd, CAMIOCOMMAND, matchccb) == -1) {
3510			warn("CAMIOCOMMAND ioctl failed");
3511			retval = 1;
3512			goto bailout;
3513		}
3514
3515		if ((matchccb->ccb_h.status != CAM_REQ_CMP)
3516		 || ((matchccb->cdm.status != CAM_DEV_MATCH_LAST)
3517		   && (matchccb->cdm.status != CAM_DEV_MATCH_MORE))) {
3518			warnx("got CAM error %#x, CDM error %d\n",
3519			      matchccb->ccb_h.status, matchccb->cdm.status);
3520			retval = 1;
3521			goto bailout;
3522		}
3523
3524		for (i = 0; i < matchccb->cdm.num_matches; i++) {
3525			struct bus_match_result *bus_result;
3526
3527			/* This shouldn't happen. */
3528			if (matchccb->cdm.matches[i].type != DEV_MATCH_BUS)
3529				continue;
3530
3531			bus_result =&matchccb->cdm.matches[i].result.bus_result;
3532
3533			/*
3534			 * We don't want to rescan or reset the xpt bus.
3535			 * See above.
3536			 */
3537			if (bus_result->path_id == CAM_XPT_PATH_ID)
3538				continue;
3539
3540			ccb->ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3541						       XPT_RESET_BUS;
3542			ccb->ccb_h.path_id = bus_result->path_id;
3543			ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
3544			ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
3545			ccb->crcn.flags = CAM_FLAG_NONE;
3546
3547			/* run this at a low priority */
3548			ccb->ccb_h.pinfo.priority = 5;
3549
3550			if (ioctl(fd, CAMIOCOMMAND, ccb) == -1) {
3551				warn("CAMIOCOMMAND ioctl failed");
3552				retval = 1;
3553				goto bailout;
3554			}
3555
3556			if ((ccb->ccb_h.status & CAM_STATUS_MASK)==CAM_REQ_CMP){
3557				fprintf(stdout, "%s of bus %d was successful\n",
3558					rescan? "Re-scan" : "Reset",
3559					bus_result->path_id);
3560			} else {
3561				/*
3562				 * Don't bail out just yet, maybe the other
3563				 * rescan or reset commands will complete
3564				 * successfully.
3565				 */
3566				fprintf(stderr, "%s of bus %d returned error "
3567					"%#x\n", rescan? "Re-scan" : "Reset",
3568					bus_result->path_id,
3569					ccb->ccb_h.status & CAM_STATUS_MASK);
3570				retval = 1;
3571			}
3572		}
3573	} while ((matchccb->ccb_h.status == CAM_REQ_CMP)
3574		 && (matchccb->cdm.status == CAM_DEV_MATCH_MORE));
3575
3576bailout:
3577
3578	if (fd != -1)
3579		close(fd);
3580
3581	if (matchccb != NULL) {
3582		free(matchccb->cdm.patterns);
3583		free(matchccb->cdm.matches);
3584		free(matchccb);
3585	}
3586	free(ccb);
3587
3588	return (retval);
3589}
3590
3591static int
3592scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3593{
3594	union ccb ccb;
3595	struct cam_device *device;
3596	int fd;
3597
3598	device = NULL;
3599
3600	if (bus == CAM_BUS_WILDCARD) {
3601		warnx("invalid bus number %d", bus);
3602		return (1);
3603	}
3604
3605	if (target == CAM_TARGET_WILDCARD) {
3606		warnx("invalid target number %d", target);
3607		return (1);
3608	}
3609
3610	if (lun == CAM_LUN_WILDCARD) {
3611		warnx("invalid lun number %jx", (uintmax_t)lun);
3612		return (1);
3613	}
3614
3615	fd = -1;
3616
3617	bzero(&ccb, sizeof(union ccb));
3618
3619	if (scan) {
3620		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3621			warnx("error opening transport layer device %s\n",
3622			    XPT_DEVICE);
3623			warn("%s", XPT_DEVICE);
3624			return (1);
3625		}
3626	} else {
3627		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3628		if (device == NULL) {
3629			warnx("%s", cam_errbuf);
3630			return (1);
3631		}
3632	}
3633
3634	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3635	ccb.ccb_h.path_id = bus;
3636	ccb.ccb_h.target_id = target;
3637	ccb.ccb_h.target_lun = lun;
3638	ccb.ccb_h.timeout = 5000;
3639	ccb.crcn.flags = CAM_FLAG_NONE;
3640
3641	/* run this at a low priority */
3642	ccb.ccb_h.pinfo.priority = 5;
3643
3644	if (scan) {
3645		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3646			warn("CAMIOCOMMAND ioctl failed");
3647			close(fd);
3648			return (1);
3649		}
3650	} else {
3651		if (cam_send_ccb(device, &ccb) < 0) {
3652			warn("error sending XPT_RESET_DEV CCB");
3653			cam_close_device(device);
3654			return (1);
3655		}
3656	}
3657
3658	if (scan)
3659		close(fd);
3660	else
3661		cam_close_device(device);
3662
3663	/*
3664	 * An error code of CAM_BDR_SENT is normal for a BDR request.
3665	 */
3666	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3667	 || ((!scan)
3668	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3669		fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3670		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3671		return (0);
3672	} else {
3673		fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3674		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3675		    ccb.ccb_h.status & CAM_STATUS_MASK);
3676		return (1);
3677	}
3678}
3679
3680#ifndef MINIMALISTIC
3681
3682static struct scsi_nv defect_list_type_map[] = {
3683	{ "block", SRDD10_BLOCK_FORMAT },
3684	{ "extbfi", SRDD10_EXT_BFI_FORMAT },
3685	{ "extphys", SRDD10_EXT_PHYS_FORMAT },
3686	{ "longblock", SRDD10_LONG_BLOCK_FORMAT },
3687	{ "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT },
3688	{ "phys", SRDD10_PHYSICAL_SECTOR_FORMAT }
3689};
3690
3691static int
3692readdefects(struct cam_device *device, int argc, char **argv,
3693	    char *combinedopt, int task_attr, int retry_count, int timeout)
3694{
3695	union ccb *ccb = NULL;
3696	struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
3697	struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
3698	size_t hdr_size = 0, entry_size = 0;
3699	int use_12byte = 0;
3700	int hex_format = 0;
3701	u_int8_t *defect_list = NULL;
3702	u_int8_t list_format = 0;
3703	int list_type_set = 0;
3704	u_int32_t dlist_length = 0;
3705	u_int32_t returned_length = 0, valid_len = 0;
3706	u_int32_t num_returned = 0, num_valid = 0;
3707	u_int32_t max_possible_size = 0, hdr_max = 0;
3708	u_int32_t starting_offset = 0;
3709	u_int8_t returned_format, returned_type;
3710	unsigned int i;
3711	int summary = 0, quiet = 0;
3712	int c, error = 0;
3713	int lists_specified = 0;
3714	int get_length = 1, first_pass = 1;
3715	int mads = 0;
3716
3717	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3718		switch(c){
3719		case 'f':
3720		{
3721			scsi_nv_status status;
3722			int entry_num = 0;
3723
3724			status = scsi_get_nv(defect_list_type_map,
3725			    sizeof(defect_list_type_map) /
3726			    sizeof(defect_list_type_map[0]), optarg,
3727			    &entry_num, SCSI_NV_FLAG_IG_CASE);
3728
3729			if (status == SCSI_NV_FOUND) {
3730				list_format = defect_list_type_map[
3731				    entry_num].value;
3732				list_type_set = 1;
3733			} else {
3734				warnx("%s: %s %s option %s", __func__,
3735				    (status == SCSI_NV_AMBIGUOUS) ?
3736				    "ambiguous" : "invalid", "defect list type",
3737				    optarg);
3738				error = 1;
3739				goto defect_bailout;
3740			}
3741			break;
3742		}
3743		case 'G':
3744			arglist |= CAM_ARG_GLIST;
3745			break;
3746		case 'P':
3747			arglist |= CAM_ARG_PLIST;
3748			break;
3749		case 'q':
3750			quiet = 1;
3751			break;
3752		case 's':
3753			summary = 1;
3754			break;
3755		case 'S': {
3756			char *endptr;
3757
3758			starting_offset = strtoul(optarg, &endptr, 0);
3759			if (*endptr != '\0') {
3760				error = 1;
3761				warnx("invalid starting offset %s", optarg);
3762				goto defect_bailout;
3763			}
3764			break;
3765		}
3766		case 'X':
3767			hex_format = 1;
3768			break;
3769		default:
3770			break;
3771		}
3772	}
3773
3774	if (list_type_set == 0) {
3775		error = 1;
3776		warnx("no defect list format specified");
3777		goto defect_bailout;
3778	}
3779
3780	if (arglist & CAM_ARG_PLIST) {
3781		list_format |= SRDD10_PLIST;
3782		lists_specified++;
3783	}
3784
3785	if (arglist & CAM_ARG_GLIST) {
3786		list_format |= SRDD10_GLIST;
3787		lists_specified++;
3788	}
3789
3790	/*
3791	 * This implies a summary, and was the previous behavior.
3792	 */
3793	if (lists_specified == 0)
3794		summary = 1;
3795
3796	ccb = cam_getccb(device);
3797
3798retry_12byte:
3799
3800	/*
3801	 * We start off asking for just the header to determine how much
3802	 * defect data is available.  Some Hitachi drives return an error
3803	 * if you ask for more data than the drive has.  Once we know the
3804	 * length, we retry the command with the returned length.
3805	 */
3806	if (use_12byte == 0)
3807		dlist_length = sizeof(*hdr10);
3808	else
3809		dlist_length = sizeof(*hdr12);
3810
3811retry:
3812	if (defect_list != NULL) {
3813		free(defect_list);
3814		defect_list = NULL;
3815	}
3816	defect_list = malloc(dlist_length);
3817	if (defect_list == NULL) {
3818		warnx("can't malloc memory for defect list");
3819		error = 1;
3820		goto defect_bailout;
3821	}
3822
3823next_batch:
3824	bzero(defect_list, dlist_length);
3825
3826	/*
3827	 * cam_getccb() zeros the CCB header only.  So we need to zero the
3828	 * payload portion of the ccb.
3829	 */
3830	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
3831
3832	scsi_read_defects(&ccb->csio,
3833			  /*retries*/ retry_count,
3834			  /*cbfcnp*/ NULL,
3835			  /*tag_action*/ task_attr,
3836			  /*list_format*/ list_format,
3837			  /*addr_desc_index*/ starting_offset,
3838			  /*data_ptr*/ defect_list,
3839			  /*dxfer_len*/ dlist_length,
3840			  /*minimum_cmd_size*/ use_12byte ? 12 : 0,
3841			  /*sense_len*/ SSD_FULL_SIZE,
3842			  /*timeout*/ timeout ? timeout : 5000);
3843
3844	/* Disable freezing the device queue */
3845	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3846
3847	if (cam_send_ccb(device, ccb) < 0) {
3848		warn("error sending READ DEFECT DATA command");
3849		error = 1;
3850		goto defect_bailout;
3851	}
3852
3853	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
3854
3855	if (use_12byte == 0) {
3856		hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
3857		hdr_size = sizeof(*hdr10);
3858		hdr_max = SRDDH10_MAX_LENGTH;
3859
3860		if (valid_len >= hdr_size) {
3861			returned_length = scsi_2btoul(hdr10->length);
3862			returned_format = hdr10->format;
3863		} else {
3864			returned_length = 0;
3865			returned_format = 0;
3866		}
3867	} else {
3868		hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list;
3869		hdr_size = sizeof(*hdr12);
3870		hdr_max = SRDDH12_MAX_LENGTH;
3871
3872		if (valid_len >= hdr_size) {
3873			returned_length = scsi_4btoul(hdr12->length);
3874			returned_format = hdr12->format;
3875		} else {
3876			returned_length = 0;
3877			returned_format = 0;
3878		}
3879	}
3880
3881	returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK;
3882	switch (returned_type) {
3883	case SRDD10_BLOCK_FORMAT:
3884		entry_size = sizeof(struct scsi_defect_desc_block);
3885		break;
3886	case SRDD10_LONG_BLOCK_FORMAT:
3887		entry_size = sizeof(struct scsi_defect_desc_long_block);
3888		break;
3889	case SRDD10_EXT_PHYS_FORMAT:
3890	case SRDD10_PHYSICAL_SECTOR_FORMAT:
3891		entry_size = sizeof(struct scsi_defect_desc_phys_sector);
3892		break;
3893	case SRDD10_EXT_BFI_FORMAT:
3894	case SRDD10_BYTES_FROM_INDEX_FORMAT:
3895		entry_size = sizeof(struct scsi_defect_desc_bytes_from_index);
3896		break;
3897	default:
3898		warnx("Unknown defect format 0x%x\n", returned_type);
3899		error = 1;
3900		goto defect_bailout;
3901		break;
3902	}
3903
3904	max_possible_size = (hdr_max / entry_size) * entry_size;
3905	num_returned = returned_length / entry_size;
3906	num_valid = min(returned_length, valid_len - hdr_size);
3907	num_valid /= entry_size;
3908
3909	if (get_length != 0) {
3910		get_length = 0;
3911
3912		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3913		     CAM_SCSI_STATUS_ERROR) {
3914			struct scsi_sense_data *sense;
3915			int error_code, sense_key, asc, ascq;
3916
3917			sense = &ccb->csio.sense_data;
3918			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3919			    ccb->csio.sense_resid, &error_code, &sense_key,
3920			    &asc, &ascq, /*show_errors*/ 1);
3921
3922			/*
3923			 * If the drive is reporting that it just doesn't
3924			 * support the defect list format, go ahead and use
3925			 * the length it reported.  Otherwise, the length
3926			 * may not be valid, so use the maximum.
3927			 */
3928			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3929			 && (asc == 0x1c) && (ascq == 0x00)
3930			 && (returned_length > 0)) {
3931				if ((use_12byte == 0)
3932				 && (returned_length >= max_possible_size)) {
3933					get_length = 1;
3934					use_12byte = 1;
3935					goto retry_12byte;
3936				}
3937				dlist_length = returned_length + hdr_size;
3938			} else if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3939				&& (asc == 0x1f) && (ascq == 0x00)
3940				&& (returned_length > 0)) {
3941				/* Partial defect list transfer */
3942				/*
3943				 * Hitachi drives return this error
3944				 * along with a partial defect list if they
3945				 * have more defects than the 10 byte
3946				 * command can support.  Retry with the 12
3947				 * byte command.
3948				 */
3949				if (use_12byte == 0) {
3950					get_length = 1;
3951					use_12byte = 1;
3952					goto retry_12byte;
3953				}
3954				dlist_length = returned_length + hdr_size;
3955			} else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST)
3956				&& (asc == 0x24) && (ascq == 0x00)) {
3957				/* Invalid field in CDB */
3958				/*
3959				 * SBC-3 says that if the drive has more
3960				 * defects than can be reported with the
3961				 * 10 byte command, it should return this
3962	 			 * error and no data.  Retry with the 12
3963				 * byte command.
3964				 */
3965				if (use_12byte == 0) {
3966					get_length = 1;
3967					use_12byte = 1;
3968					goto retry_12byte;
3969				}
3970				dlist_length = returned_length + hdr_size;
3971			} else {
3972				/*
3973				 * If we got a SCSI error and no valid length,
3974				 * just use the 10 byte maximum.  The 12
3975				 * byte maximum is too large.
3976				 */
3977				if (returned_length == 0)
3978					dlist_length = SRDD10_MAX_LENGTH;
3979				else {
3980					if ((use_12byte == 0)
3981					 && (returned_length >=
3982					     max_possible_size)) {
3983						get_length = 1;
3984						use_12byte = 1;
3985						goto retry_12byte;
3986					}
3987					dlist_length = returned_length +
3988					    hdr_size;
3989				}
3990			}
3991		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3992			    CAM_REQ_CMP){
3993			error = 1;
3994			warnx("Error reading defect header");
3995			if (arglist & CAM_ARG_VERBOSE)
3996				cam_error_print(device, ccb, CAM_ESF_ALL,
3997						CAM_EPF_ALL, stderr);
3998			goto defect_bailout;
3999		} else {
4000			if ((use_12byte == 0)
4001			 && (returned_length >= max_possible_size)) {
4002				get_length = 1;
4003				use_12byte = 1;
4004				goto retry_12byte;
4005			}
4006			dlist_length = returned_length + hdr_size;
4007		}
4008		if (summary != 0) {
4009			fprintf(stdout, "%u", num_returned);
4010			if (quiet == 0) {
4011				fprintf(stdout, " defect%s",
4012					(num_returned != 1) ? "s" : "");
4013			}
4014			fprintf(stdout, "\n");
4015
4016			goto defect_bailout;
4017		}
4018
4019		/*
4020		 * We always limit the list length to the 10-byte maximum
4021		 * length (0xffff).  The reason is that some controllers
4022		 * can't handle larger I/Os, and we can transfer the entire
4023		 * 10 byte list in one shot.  For drives that support the 12
4024		 * byte read defects command, we'll step through the list
4025		 * by specifying a starting offset.  For drives that don't
4026		 * support the 12 byte command's starting offset, we'll
4027		 * just display the first 64K.
4028		 */
4029		dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
4030
4031		goto retry;
4032	}
4033
4034
4035	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
4036	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
4037	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
4038		struct scsi_sense_data *sense;
4039		int error_code, sense_key, asc, ascq;
4040
4041		sense = &ccb->csio.sense_data;
4042		scsi_extract_sense_len(sense, ccb->csio.sense_len -
4043		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
4044		    &ascq, /*show_errors*/ 1);
4045
4046		/*
4047		 * According to the SCSI spec, if the disk doesn't support
4048		 * the requested format, it will generally return a sense
4049		 * key of RECOVERED ERROR, and an additional sense code
4050		 * of "DEFECT LIST NOT FOUND".  HGST drives also return
4051		 * Primary/Grown defect list not found errors.  So just
4052		 * check for an ASC of 0x1c.
4053		 */
4054		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
4055		 && (asc == 0x1c)) {
4056			const char *format_str;
4057
4058			format_str = scsi_nv_to_str(defect_list_type_map,
4059			    sizeof(defect_list_type_map) /
4060			    sizeof(defect_list_type_map[0]),
4061			    list_format & SRDD10_DLIST_FORMAT_MASK);
4062			warnx("requested defect format %s not available",
4063			    format_str ? format_str : "unknown");
4064
4065			format_str = scsi_nv_to_str(defect_list_type_map,
4066			    sizeof(defect_list_type_map) /
4067			    sizeof(defect_list_type_map[0]), returned_type);
4068			if (format_str != NULL) {
4069				warnx("Device returned %s format",
4070				    format_str);
4071			} else {
4072				error = 1;
4073				warnx("Device returned unknown defect"
4074				     " data format %#x", returned_type);
4075				goto defect_bailout;
4076			}
4077		} else {
4078			error = 1;
4079			warnx("Error returned from read defect data command");
4080			if (arglist & CAM_ARG_VERBOSE)
4081				cam_error_print(device, ccb, CAM_ESF_ALL,
4082						CAM_EPF_ALL, stderr);
4083			goto defect_bailout;
4084		}
4085	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4086		error = 1;
4087		warnx("Error returned from read defect data command");
4088		if (arglist & CAM_ARG_VERBOSE)
4089			cam_error_print(device, ccb, CAM_ESF_ALL,
4090					CAM_EPF_ALL, stderr);
4091		goto defect_bailout;
4092	}
4093
4094	if (first_pass != 0) {
4095		fprintf(stderr, "Got %d defect", num_returned);
4096
4097		if ((lists_specified == 0) || (num_returned == 0)) {
4098			fprintf(stderr, "s.\n");
4099			goto defect_bailout;
4100		} else if (num_returned == 1)
4101			fprintf(stderr, ":\n");
4102		else
4103			fprintf(stderr, "s:\n");
4104
4105		first_pass = 0;
4106	}
4107
4108	/*
4109	 * XXX KDM  I should probably clean up the printout format for the
4110	 * disk defects.
4111	 */
4112	switch (returned_type) {
4113	case SRDD10_PHYSICAL_SECTOR_FORMAT:
4114	case SRDD10_EXT_PHYS_FORMAT:
4115	{
4116		struct scsi_defect_desc_phys_sector *dlist;
4117
4118		dlist = (struct scsi_defect_desc_phys_sector *)
4119			(defect_list + hdr_size);
4120
4121		for (i = 0; i < num_valid; i++) {
4122			uint32_t sector;
4123
4124			sector = scsi_4btoul(dlist[i].sector);
4125			if (returned_type == SRDD10_EXT_PHYS_FORMAT) {
4126				mads = (sector & SDD_EXT_PHYS_MADS) ?
4127				       0 : 1;
4128				sector &= ~SDD_EXT_PHYS_FLAG_MASK;
4129			}
4130			if (hex_format == 0)
4131				fprintf(stdout, "%d:%d:%d%s",
4132					scsi_3btoul(dlist[i].cylinder),
4133					dlist[i].head,
4134					scsi_4btoul(dlist[i].sector),
4135					mads ? " - " : "\n");
4136			else
4137				fprintf(stdout, "0x%x:0x%x:0x%x%s",
4138					scsi_3btoul(dlist[i].cylinder),
4139					dlist[i].head,
4140					scsi_4btoul(dlist[i].sector),
4141					mads ? " - " : "\n");
4142			mads = 0;
4143		}
4144		if (num_valid < num_returned) {
4145			starting_offset += num_valid;
4146			goto next_batch;
4147		}
4148		break;
4149	}
4150	case SRDD10_BYTES_FROM_INDEX_FORMAT:
4151	case SRDD10_EXT_BFI_FORMAT:
4152	{
4153		struct scsi_defect_desc_bytes_from_index *dlist;
4154
4155		dlist = (struct scsi_defect_desc_bytes_from_index *)
4156			(defect_list + hdr_size);
4157
4158		for (i = 0; i < num_valid; i++) {
4159			uint32_t bfi;
4160
4161			bfi = scsi_4btoul(dlist[i].bytes_from_index);
4162			if (returned_type == SRDD10_EXT_BFI_FORMAT) {
4163				mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
4164				bfi &= ~SDD_EXT_BFI_FLAG_MASK;
4165			}
4166			if (hex_format == 0)
4167				fprintf(stdout, "%d:%d:%d%s",
4168					scsi_3btoul(dlist[i].cylinder),
4169					dlist[i].head,
4170					scsi_4btoul(dlist[i].bytes_from_index),
4171					mads ? " - " : "\n");
4172			else
4173				fprintf(stdout, "0x%x:0x%x:0x%x%s",
4174					scsi_3btoul(dlist[i].cylinder),
4175					dlist[i].head,
4176					scsi_4btoul(dlist[i].bytes_from_index),
4177					mads ? " - " : "\n");
4178
4179			mads = 0;
4180		}
4181		if (num_valid < num_returned) {
4182			starting_offset += num_valid;
4183			goto next_batch;
4184		}
4185		break;
4186	}
4187	case SRDDH10_BLOCK_FORMAT:
4188	{
4189		struct scsi_defect_desc_block *dlist;
4190
4191		dlist = (struct scsi_defect_desc_block *)
4192			(defect_list + hdr_size);
4193
4194		for (i = 0; i < num_valid; i++) {
4195			if (hex_format == 0)
4196				fprintf(stdout, "%u\n",
4197					scsi_4btoul(dlist[i].address));
4198			else
4199				fprintf(stdout, "0x%x\n",
4200					scsi_4btoul(dlist[i].address));
4201		}
4202
4203		if (num_valid < num_returned) {
4204			starting_offset += num_valid;
4205			goto next_batch;
4206		}
4207
4208		break;
4209	}
4210	case SRDD10_LONG_BLOCK_FORMAT:
4211	{
4212		struct scsi_defect_desc_long_block *dlist;
4213
4214		dlist = (struct scsi_defect_desc_long_block *)
4215			(defect_list + hdr_size);
4216
4217		for (i = 0; i < num_valid; i++) {
4218			if (hex_format == 0)
4219				fprintf(stdout, "%ju\n",
4220					(uintmax_t)scsi_8btou64(
4221					dlist[i].address));
4222			else
4223				fprintf(stdout, "0x%jx\n",
4224					(uintmax_t)scsi_8btou64(
4225					dlist[i].address));
4226		}
4227
4228		if (num_valid < num_returned) {
4229			starting_offset += num_valid;
4230			goto next_batch;
4231		}
4232		break;
4233	}
4234	default:
4235		fprintf(stderr, "Unknown defect format 0x%x\n",
4236			returned_type);
4237		error = 1;
4238		break;
4239	}
4240defect_bailout:
4241
4242	if (defect_list != NULL)
4243		free(defect_list);
4244
4245	if (ccb != NULL)
4246		cam_freeccb(ccb);
4247
4248	return (error);
4249}
4250#endif /* MINIMALISTIC */
4251
4252#if 0
4253void
4254reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
4255{
4256	union ccb *ccb;
4257
4258	ccb = cam_getccb(device);
4259
4260	cam_freeccb(ccb);
4261}
4262#endif
4263
4264#ifndef MINIMALISTIC
4265void
4266mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc,
4267    int page, int subpage, int task_attr, int retry_count, int timeout,
4268    u_int8_t *data, int datalen)
4269{
4270	union ccb *ccb;
4271	int error_code, sense_key, asc, ascq;
4272
4273	ccb = cam_getccb(device);
4274	if (ccb == NULL)
4275		errx(1, "mode_sense: couldn't allocate CCB");
4276
4277retry:
4278	/*
4279	 * MODE SENSE(6) can't handle more then 255 bytes.  If there are more,
4280	 * device must return error, so we should not get trucated data.
4281	 */
4282	if (*cdb_len == 6 && datalen > 255)
4283		datalen = 255;
4284
4285	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4286
4287	scsi_mode_sense_subpage(&ccb->csio,
4288			/* retries */ retry_count,
4289			/* cbfcnp */ NULL,
4290			/* tag_action */ task_attr,
4291			/* dbd */ dbd,
4292			/* pc */ pc << 6,
4293			/* page */ page,
4294			/* subpage */ subpage,
4295			/* param_buf */ data,
4296			/* param_len */ datalen,
4297			/* minimum_cmd_size */ *cdb_len,
4298			/* sense_len */ SSD_FULL_SIZE,
4299			/* timeout */ timeout ? timeout : 5000);
4300	if (llbaa && ccb->csio.cdb_len == 10) {
4301		struct scsi_mode_sense_10 *cdb =
4302		    (struct scsi_mode_sense_10 *)ccb->csio.cdb_io.cdb_bytes;
4303		cdb->byte2 |= SMS10_LLBAA;
4304	}
4305
4306	/* Record what CDB size the above function really set. */
4307	*cdb_len = ccb->csio.cdb_len;
4308
4309	if (arglist & CAM_ARG_ERR_RECOVER)
4310		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4311
4312	/* Disable freezing the device queue */
4313	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4314
4315	if (cam_send_ccb(device, ccb) < 0)
4316		err(1, "error sending mode sense command");
4317
4318	/* In case of ILLEGEL REQUEST try to fall back to 6-byte command. */
4319	if (*cdb_len != 6 &&
4320	    ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID ||
4321	     (scsi_extract_sense_ccb(ccb, &error_code, &sense_key, &asc, &ascq)
4322	      && sense_key == SSD_KEY_ILLEGAL_REQUEST))) {
4323		*cdb_len = 6;
4324		goto retry;
4325	}
4326
4327	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4328		if (arglist & CAM_ARG_VERBOSE) {
4329			cam_error_print(device, ccb, CAM_ESF_ALL,
4330					CAM_EPF_ALL, stderr);
4331		}
4332		cam_freeccb(ccb);
4333		cam_close_device(device);
4334		errx(1, "mode sense command returned error");
4335	}
4336
4337	cam_freeccb(ccb);
4338}
4339
4340void
4341mode_select(struct cam_device *device, int cdb_len, int save_pages,
4342    int task_attr, int retry_count, int timeout, u_int8_t *data, int datalen)
4343{
4344	union ccb *ccb;
4345	int retval;
4346
4347	ccb = cam_getccb(device);
4348
4349	if (ccb == NULL)
4350		errx(1, "mode_select: couldn't allocate CCB");
4351
4352	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
4353
4354	scsi_mode_select_len(&ccb->csio,
4355			 /* retries */ retry_count,
4356			 /* cbfcnp */ NULL,
4357			 /* tag_action */ task_attr,
4358			 /* scsi_page_fmt */ 1,
4359			 /* save_pages */ save_pages,
4360			 /* param_buf */ data,
4361			 /* param_len */ datalen,
4362			 /* minimum_cmd_size */ cdb_len,
4363			 /* sense_len */ SSD_FULL_SIZE,
4364			 /* timeout */ timeout ? timeout : 5000);
4365
4366	if (arglist & CAM_ARG_ERR_RECOVER)
4367		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4368
4369	/* Disable freezing the device queue */
4370	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4371
4372	if (((retval = cam_send_ccb(device, ccb)) < 0)
4373	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4374		if (arglist & CAM_ARG_VERBOSE) {
4375			cam_error_print(device, ccb, CAM_ESF_ALL,
4376					CAM_EPF_ALL, stderr);
4377		}
4378		cam_freeccb(ccb);
4379		cam_close_device(device);
4380
4381		if (retval < 0)
4382			err(1, "error sending mode select command");
4383		else
4384			errx(1, "error sending mode select command");
4385
4386	}
4387
4388	cam_freeccb(ccb);
4389}
4390
4391void
4392modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
4393	 int task_attr, int retry_count, int timeout)
4394{
4395	char *str_subpage;
4396	int c, page = -1, subpage = 0, pc = 0, llbaa = 0;
4397	int binary = 0, cdb_len = 10, dbd = 0, desc = 0, edit = 0, list = 0;
4398
4399	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4400		switch(c) {
4401		case '6':
4402			cdb_len = 6;
4403			break;
4404		case 'b':
4405			binary = 1;
4406			break;
4407		case 'd':
4408			dbd = 1;
4409			break;
4410		case 'e':
4411			edit = 1;
4412			break;
4413		case 'l':
4414			list++;
4415			break;
4416		case 'm':
4417			str_subpage = optarg;
4418			strsep(&str_subpage, ",");
4419			page = strtol(optarg, NULL, 0);
4420			if (str_subpage)
4421			    subpage = strtol(str_subpage, NULL, 0);
4422			if (page < 0 || page > 0x3f)
4423				errx(1, "invalid mode page %d", page);
4424			if (subpage < 0 || subpage > 0xff)
4425				errx(1, "invalid mode subpage %d", subpage);
4426			break;
4427		case 'D':
4428			desc = 1;
4429			break;
4430		case 'L':
4431			llbaa = 1;
4432			break;
4433		case 'P':
4434			pc = strtol(optarg, NULL, 0);
4435			if ((pc < 0) || (pc > 3))
4436				errx(1, "invalid page control field %d", pc);
4437			break;
4438		default:
4439			break;
4440		}
4441	}
4442
4443	if (desc && page == -1)
4444		page = SMS_ALL_PAGES_PAGE;
4445
4446	if (page == -1 && list == 0)
4447		errx(1, "you must specify a mode page!");
4448
4449	if (dbd && desc)
4450		errx(1, "-d and -D are incompatible!");
4451
4452	if (llbaa && cdb_len != 10)
4453		errx(1, "LLBAA bit is not present in MODE SENSE(6)!");
4454
4455	if (list != 0) {
4456		mode_list(device, cdb_len, dbd, pc, list > 1, task_attr,
4457		    retry_count, timeout);
4458	} else {
4459		mode_edit(device, cdb_len, desc, dbd, llbaa, pc, page, subpage,
4460		    edit, binary, task_attr, retry_count, timeout);
4461	}
4462}
4463
4464static int
4465scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4466	int task_attr, int retry_count, int timeout)
4467{
4468	union ccb *ccb;
4469	u_int32_t flags = CAM_DIR_NONE;
4470	u_int8_t *data_ptr = NULL;
4471	u_int8_t cdb[20];
4472	u_int8_t atacmd[12];
4473	struct get_hook hook;
4474	int c, data_bytes = 0, valid_bytes;
4475	int cdb_len = 0;
4476	int atacmd_len = 0;
4477	int dmacmd = 0;
4478	int fpdmacmd = 0;
4479	int need_res = 0;
4480	char *datastr = NULL, *tstr, *resstr = NULL;
4481	int error = 0;
4482	int fd_data = 0, fd_res = 0;
4483	int retval;
4484
4485	ccb = cam_getccb(device);
4486
4487	if (ccb == NULL) {
4488		warnx("scsicmd: error allocating ccb");
4489		return (1);
4490	}
4491
4492	CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
4493
4494	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4495		switch(c) {
4496		case 'a':
4497			tstr = optarg;
4498			while (isspace(*tstr) && (*tstr != '\0'))
4499				tstr++;
4500			hook.argc = argc - optind;
4501			hook.argv = argv + optind;
4502			hook.got = 0;
4503			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
4504						    iget, &hook);
4505			/*
4506			 * Increment optind by the number of arguments the
4507			 * encoding routine processed.  After each call to
4508			 * getopt(3), optind points to the argument that
4509			 * getopt should process _next_.  In this case,
4510			 * that means it points to the first command string
4511			 * argument, if there is one.  Once we increment
4512			 * this, it should point to either the next command
4513			 * line argument, or it should be past the end of
4514			 * the list.
4515			 */
4516			optind += hook.got;
4517			break;
4518		case 'c':
4519			tstr = optarg;
4520			while (isspace(*tstr) && (*tstr != '\0'))
4521				tstr++;
4522			hook.argc = argc - optind;
4523			hook.argv = argv + optind;
4524			hook.got = 0;
4525			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
4526						    iget, &hook);
4527			/*
4528			 * Increment optind by the number of arguments the
4529			 * encoding routine processed.  After each call to
4530			 * getopt(3), optind points to the argument that
4531			 * getopt should process _next_.  In this case,
4532			 * that means it points to the first command string
4533			 * argument, if there is one.  Once we increment
4534			 * this, it should point to either the next command
4535			 * line argument, or it should be past the end of
4536			 * the list.
4537			 */
4538			optind += hook.got;
4539			break;
4540		case 'd':
4541			dmacmd = 1;
4542			break;
4543		case 'f':
4544			fpdmacmd = 1;
4545			break;
4546		case 'i':
4547			if (arglist & CAM_ARG_CMD_OUT) {
4548				warnx("command must either be "
4549				      "read or write, not both");
4550				error = 1;
4551				goto scsicmd_bailout;
4552			}
4553			arglist |= CAM_ARG_CMD_IN;
4554			flags = CAM_DIR_IN;
4555			data_bytes = strtol(optarg, NULL, 0);
4556			if (data_bytes <= 0) {
4557				warnx("invalid number of input bytes %d",
4558				      data_bytes);
4559				error = 1;
4560				goto scsicmd_bailout;
4561			}
4562			hook.argc = argc - optind;
4563			hook.argv = argv + optind;
4564			hook.got = 0;
4565			optind++;
4566			datastr = cget(&hook, NULL);
4567			/*
4568			 * If the user supplied "-" instead of a format, he
4569			 * wants the data to be written to stdout.
4570			 */
4571			if ((datastr != NULL)
4572			 && (datastr[0] == '-'))
4573				fd_data = 1;
4574
4575			data_ptr = (u_int8_t *)malloc(data_bytes);
4576			if (data_ptr == NULL) {
4577				warnx("can't malloc memory for data_ptr");
4578				error = 1;
4579				goto scsicmd_bailout;
4580			}
4581			break;
4582		case 'o':
4583			if (arglist & CAM_ARG_CMD_IN) {
4584				warnx("command must either be "
4585				      "read or write, not both");
4586				error = 1;
4587				goto scsicmd_bailout;
4588			}
4589			arglist |= CAM_ARG_CMD_OUT;
4590			flags = CAM_DIR_OUT;
4591			data_bytes = strtol(optarg, NULL, 0);
4592			if (data_bytes <= 0) {
4593				warnx("invalid number of output bytes %d",
4594				      data_bytes);
4595				error = 1;
4596				goto scsicmd_bailout;
4597			}
4598			hook.argc = argc - optind;
4599			hook.argv = argv + optind;
4600			hook.got = 0;
4601			datastr = cget(&hook, NULL);
4602			data_ptr = (u_int8_t *)malloc(data_bytes);
4603			if (data_ptr == NULL) {
4604				warnx("can't malloc memory for data_ptr");
4605				error = 1;
4606				goto scsicmd_bailout;
4607			}
4608			bzero(data_ptr, data_bytes);
4609			/*
4610			 * If the user supplied "-" instead of a format, he
4611			 * wants the data to be read from stdin.
4612			 */
4613			if ((datastr != NULL)
4614			 && (datastr[0] == '-'))
4615				fd_data = 1;
4616			else
4617				buff_encode_visit(data_ptr, data_bytes, datastr,
4618						  iget, &hook);
4619			optind += hook.got;
4620			break;
4621		case 'r':
4622			need_res = 1;
4623			hook.argc = argc - optind;
4624			hook.argv = argv + optind;
4625			hook.got = 0;
4626			resstr = cget(&hook, NULL);
4627			if ((resstr != NULL) && (resstr[0] == '-'))
4628				fd_res = 1;
4629			optind += hook.got;
4630			break;
4631		default:
4632			break;
4633		}
4634	}
4635
4636	/*
4637	 * If fd_data is set, and we're writing to the device, we need to
4638	 * read the data the user wants written from stdin.
4639	 */
4640	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4641		ssize_t amt_read;
4642		int amt_to_read = data_bytes;
4643		u_int8_t *buf_ptr = data_ptr;
4644
4645		for (amt_read = 0; amt_to_read > 0;
4646		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4647			if (amt_read == -1) {
4648				warn("error reading data from stdin");
4649				error = 1;
4650				goto scsicmd_bailout;
4651			}
4652			amt_to_read -= amt_read;
4653			buf_ptr += amt_read;
4654		}
4655	}
4656
4657	if (arglist & CAM_ARG_ERR_RECOVER)
4658		flags |= CAM_PASS_ERR_RECOVER;
4659
4660	/* Disable freezing the device queue */
4661	flags |= CAM_DEV_QFRZDIS;
4662
4663	if (cdb_len) {
4664		/*
4665		 * This is taken from the SCSI-3 draft spec.
4666		 * (T10/1157D revision 0.3)
4667		 * The top 3 bits of an opcode are the group code.
4668		 * The next 5 bits are the command code.
4669		 * Group 0:  six byte commands
4670		 * Group 1:  ten byte commands
4671		 * Group 2:  ten byte commands
4672		 * Group 3:  reserved
4673		 * Group 4:  sixteen byte commands
4674		 * Group 5:  twelve byte commands
4675		 * Group 6:  vendor specific
4676		 * Group 7:  vendor specific
4677		 */
4678		switch((cdb[0] >> 5) & 0x7) {
4679			case 0:
4680				cdb_len = 6;
4681				break;
4682			case 1:
4683			case 2:
4684				cdb_len = 10;
4685				break;
4686			case 3:
4687			case 6:
4688			case 7:
4689				/* computed by buff_encode_visit */
4690				break;
4691			case 4:
4692				cdb_len = 16;
4693				break;
4694			case 5:
4695				cdb_len = 12;
4696				break;
4697		}
4698
4699		/*
4700		 * We should probably use csio_build_visit or something like that
4701		 * here, but it's easier to encode arguments as you go.  The
4702		 * alternative would be skipping the CDB argument and then encoding
4703		 * it here, since we've got the data buffer argument by now.
4704		 */
4705		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4706
4707		cam_fill_csio(&ccb->csio,
4708		      /*retries*/ retry_count,
4709		      /*cbfcnp*/ NULL,
4710		      /*flags*/ flags,
4711		      /*tag_action*/ task_attr,
4712		      /*data_ptr*/ data_ptr,
4713		      /*dxfer_len*/ data_bytes,
4714		      /*sense_len*/ SSD_FULL_SIZE,
4715		      /*cdb_len*/ cdb_len,
4716		      /*timeout*/ timeout ? timeout : 5000);
4717	} else {
4718		atacmd_len = 12;
4719		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4720		if (need_res)
4721			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4722		if (dmacmd)
4723			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4724		if (fpdmacmd)
4725			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4726
4727		cam_fill_ataio(&ccb->ataio,
4728		      /*retries*/ retry_count,
4729		      /*cbfcnp*/ NULL,
4730		      /*flags*/ flags,
4731		      /*tag_action*/ 0,
4732		      /*data_ptr*/ data_ptr,
4733		      /*dxfer_len*/ data_bytes,
4734		      /*timeout*/ timeout ? timeout : 5000);
4735	}
4736
4737	if (((retval = cam_send_ccb(device, ccb)) < 0)
4738	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4739		const char warnstr[] = "error sending command";
4740
4741		if (retval < 0)
4742			warn(warnstr);
4743		else
4744			warnx(warnstr);
4745
4746		if (arglist & CAM_ARG_VERBOSE) {
4747			cam_error_print(device, ccb, CAM_ESF_ALL,
4748					CAM_EPF_ALL, stderr);
4749		}
4750
4751		error = 1;
4752		goto scsicmd_bailout;
4753	}
4754
4755	if (atacmd_len && need_res) {
4756		if (fd_res == 0) {
4757			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4758					  arg_put, NULL);
4759			fprintf(stdout, "\n");
4760		} else {
4761			fprintf(stdout,
4762			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4763			    ccb->ataio.res.status,
4764			    ccb->ataio.res.error,
4765			    ccb->ataio.res.lba_low,
4766			    ccb->ataio.res.lba_mid,
4767			    ccb->ataio.res.lba_high,
4768			    ccb->ataio.res.device,
4769			    ccb->ataio.res.lba_low_exp,
4770			    ccb->ataio.res.lba_mid_exp,
4771			    ccb->ataio.res.lba_high_exp,
4772			    ccb->ataio.res.sector_count,
4773			    ccb->ataio.res.sector_count_exp);
4774			fflush(stdout);
4775		}
4776	}
4777
4778	if (cdb_len)
4779		valid_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
4780	else
4781		valid_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid;
4782	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4783	 && (arglist & CAM_ARG_CMD_IN)
4784	 && (valid_bytes > 0)) {
4785		if (fd_data == 0) {
4786			buff_decode_visit(data_ptr, valid_bytes, datastr,
4787					  arg_put, NULL);
4788			fprintf(stdout, "\n");
4789		} else {
4790			ssize_t amt_written;
4791			int amt_to_write = valid_bytes;
4792			u_int8_t *buf_ptr = data_ptr;
4793
4794			for (amt_written = 0; (amt_to_write > 0) &&
4795			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4796				amt_to_write -= amt_written;
4797				buf_ptr += amt_written;
4798			}
4799			if (amt_written == -1) {
4800				warn("error writing data to stdout");
4801				error = 1;
4802				goto scsicmd_bailout;
4803			} else if ((amt_written == 0)
4804				&& (amt_to_write > 0)) {
4805				warnx("only wrote %u bytes out of %u",
4806				      valid_bytes - amt_to_write, valid_bytes);
4807			}
4808		}
4809	}
4810
4811scsicmd_bailout:
4812
4813	if ((data_bytes > 0) && (data_ptr != NULL))
4814		free(data_ptr);
4815
4816	cam_freeccb(ccb);
4817
4818	return (error);
4819}
4820
4821static int
4822camdebug(int argc, char **argv, char *combinedopt)
4823{
4824	int c, fd;
4825	path_id_t bus = CAM_BUS_WILDCARD;
4826	target_id_t target = CAM_TARGET_WILDCARD;
4827	lun_id_t lun = CAM_LUN_WILDCARD;
4828	char *tstr;
4829	union ccb ccb;
4830	int error = 0, rv;
4831
4832	bzero(&ccb, sizeof(union ccb));
4833
4834	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4835		switch(c) {
4836		case 'I':
4837			arglist |= CAM_ARG_DEBUG_INFO;
4838			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4839			break;
4840		case 'P':
4841			arglist |= CAM_ARG_DEBUG_PERIPH;
4842			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4843			break;
4844		case 'S':
4845			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4846			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4847			break;
4848		case 'T':
4849			arglist |= CAM_ARG_DEBUG_TRACE;
4850			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4851			break;
4852		case 'X':
4853			arglist |= CAM_ARG_DEBUG_XPT;
4854			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4855			break;
4856		case 'c':
4857			arglist |= CAM_ARG_DEBUG_CDB;
4858			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4859			break;
4860		case 'p':
4861			arglist |= CAM_ARG_DEBUG_PROBE;
4862			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4863			break;
4864		default:
4865			break;
4866		}
4867	}
4868
4869	argc -= optind;
4870	argv += optind;
4871
4872	if (argc <= 0) {
4873		warnx("you must specify \"off\", \"all\" or a bus,");
4874		warnx("bus:target, bus:target:lun or periph");
4875		return (1);
4876	}
4877
4878	tstr = *argv;
4879	while (isspace(*tstr) && (*tstr != '\0'))
4880		tstr++;
4881
4882	if (strncmp(tstr, "off", 3) == 0) {
4883		ccb.cdbg.flags = CAM_DEBUG_NONE;
4884		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4885			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4886			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4887	} else {
4888		rv = parse_btl(tstr, &bus, &target, &lun, &arglist);
4889		if (rv < 1) {
4890			warnx("you must specify \"all\", \"off\", or a bus,");
4891			warnx("bus:target, bus:target:lun or periph to debug");
4892			return (1);
4893		}
4894	}
4895
4896	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4897		warnx("error opening transport layer device %s", XPT_DEVICE);
4898		warn("%s", XPT_DEVICE);
4899		return (1);
4900	}
4901
4902	ccb.ccb_h.func_code = XPT_DEBUG;
4903	ccb.ccb_h.path_id = bus;
4904	ccb.ccb_h.target_id = target;
4905	ccb.ccb_h.target_lun = lun;
4906
4907	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4908		warn("CAMIOCOMMAND ioctl failed");
4909		error = 1;
4910	} else {
4911		if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4912		     CAM_FUNC_NOTAVAIL) {
4913			warnx("CAM debugging not available");
4914			warnx("you need to put options CAMDEBUG in"
4915			      " your kernel config file!");
4916			error = 1;
4917		} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4918			    CAM_REQ_CMP) {
4919			warnx("XPT_DEBUG CCB failed with status %#x",
4920			      ccb.ccb_h.status);
4921			error = 1;
4922		} else {
4923			if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4924				fprintf(stderr,
4925					"Debugging turned off\n");
4926			} else {
4927				fprintf(stderr,
4928					"Debugging enabled for "
4929					"%d:%d:%jx\n",
4930					bus, target, (uintmax_t)lun);
4931			}
4932		}
4933	}
4934	close(fd);
4935
4936	return (error);
4937}
4938
4939static int
4940tagcontrol(struct cam_device *device, int argc, char **argv,
4941	   char *combinedopt)
4942{
4943	int c;
4944	union ccb *ccb;
4945	int numtags = -1;
4946	int retval = 0;
4947	int quiet = 0;
4948	char pathstr[1024];
4949
4950	ccb = cam_getccb(device);
4951
4952	if (ccb == NULL) {
4953		warnx("tagcontrol: error allocating ccb");
4954		return (1);
4955	}
4956
4957	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4958		switch(c) {
4959		case 'N':
4960			numtags = strtol(optarg, NULL, 0);
4961			if (numtags < 0) {
4962				warnx("tag count %d is < 0", numtags);
4963				retval = 1;
4964				goto tagcontrol_bailout;
4965			}
4966			break;
4967		case 'q':
4968			quiet++;
4969			break;
4970		default:
4971			break;
4972		}
4973	}
4974
4975	cam_path_string(device, pathstr, sizeof(pathstr));
4976
4977	if (numtags >= 0) {
4978		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs);
4979		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4980		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4981		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4982		ccb->crs.openings = numtags;
4983
4984
4985		if (cam_send_ccb(device, ccb) < 0) {
4986			warn("error sending XPT_REL_SIMQ CCB");
4987			retval = 1;
4988			goto tagcontrol_bailout;
4989		}
4990
4991		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4992			warnx("XPT_REL_SIMQ CCB failed");
4993			cam_error_print(device, ccb, CAM_ESF_ALL,
4994					CAM_EPF_ALL, stderr);
4995			retval = 1;
4996			goto tagcontrol_bailout;
4997		}
4998
4999
5000		if (quiet == 0)
5001			fprintf(stdout, "%stagged openings now %d\n",
5002				pathstr, ccb->crs.openings);
5003	}
5004
5005	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgds);
5006
5007	ccb->ccb_h.func_code = XPT_GDEV_STATS;
5008
5009	if (cam_send_ccb(device, ccb) < 0) {
5010		warn("error sending XPT_GDEV_STATS CCB");
5011		retval = 1;
5012		goto tagcontrol_bailout;
5013	}
5014
5015	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5016		warnx("XPT_GDEV_STATS CCB failed");
5017		cam_error_print(device, ccb, CAM_ESF_ALL,
5018				CAM_EPF_ALL, stderr);
5019		retval = 1;
5020		goto tagcontrol_bailout;
5021	}
5022
5023	if (arglist & CAM_ARG_VERBOSE) {
5024		fprintf(stdout, "%s", pathstr);
5025		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
5026		fprintf(stdout, "%s", pathstr);
5027		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
5028		fprintf(stdout, "%s", pathstr);
5029		fprintf(stdout, "allocated     %d\n", ccb->cgds.allocated);
5030		fprintf(stdout, "%s", pathstr);
5031		fprintf(stdout, "queued        %d\n", ccb->cgds.queued);
5032		fprintf(stdout, "%s", pathstr);
5033		fprintf(stdout, "held          %d\n", ccb->cgds.held);
5034		fprintf(stdout, "%s", pathstr);
5035		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
5036		fprintf(stdout, "%s", pathstr);
5037		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
5038	} else {
5039		if (quiet == 0) {
5040			fprintf(stdout, "%s", pathstr);
5041			fprintf(stdout, "device openings: ");
5042		}
5043		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
5044			ccb->cgds.dev_active);
5045	}
5046
5047tagcontrol_bailout:
5048
5049	cam_freeccb(ccb);
5050	return (retval);
5051}
5052
5053static void
5054cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
5055{
5056	char pathstr[1024];
5057
5058	cam_path_string(device, pathstr, sizeof(pathstr));
5059
5060	if (cts->transport == XPORT_SPI) {
5061		struct ccb_trans_settings_spi *spi =
5062		    &cts->xport_specific.spi;
5063
5064		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
5065
5066			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
5067				spi->sync_period);
5068
5069			if (spi->sync_offset != 0) {
5070				u_int freq;
5071
5072				freq = scsi_calc_syncsrate(spi->sync_period);
5073				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
5074					pathstr, freq / 1000, freq % 1000);
5075			}
5076		}
5077
5078		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
5079			fprintf(stdout, "%soffset: %d\n", pathstr,
5080			    spi->sync_offset);
5081		}
5082
5083		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
5084			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
5085				(0x01 << spi->bus_width) * 8);
5086		}
5087
5088		if (spi->valid & CTS_SPI_VALID_DISC) {
5089			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
5090				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
5091				"enabled" : "disabled");
5092		}
5093	}
5094	if (cts->transport == XPORT_FC) {
5095		struct ccb_trans_settings_fc *fc =
5096		    &cts->xport_specific.fc;
5097
5098		if (fc->valid & CTS_FC_VALID_WWNN)
5099			fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr,
5100			    (long long) fc->wwnn);
5101		if (fc->valid & CTS_FC_VALID_WWPN)
5102			fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr,
5103			    (long long) fc->wwpn);
5104		if (fc->valid & CTS_FC_VALID_PORT)
5105			fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port);
5106		if (fc->valid & CTS_FC_VALID_SPEED)
5107			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
5108			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
5109	}
5110	if (cts->transport == XPORT_SAS) {
5111		struct ccb_trans_settings_sas *sas =
5112		    &cts->xport_specific.sas;
5113
5114		if (sas->valid & CTS_SAS_VALID_SPEED)
5115			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
5116			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
5117	}
5118	if (cts->transport == XPORT_ATA) {
5119		struct ccb_trans_settings_pata *pata =
5120		    &cts->xport_specific.ata;
5121
5122		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
5123			fprintf(stdout, "%sATA mode: %s\n", pathstr,
5124				ata_mode2string(pata->mode));
5125		}
5126		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
5127			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
5128				pata->atapi);
5129		}
5130		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
5131			fprintf(stdout, "%sPIO transaction length: %d\n",
5132				pathstr, pata->bytecount);
5133		}
5134	}
5135	if (cts->transport == XPORT_SATA) {
5136		struct ccb_trans_settings_sata *sata =
5137		    &cts->xport_specific.sata;
5138
5139		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
5140			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
5141				sata->revision);
5142		}
5143		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
5144			fprintf(stdout, "%sATA mode: %s\n", pathstr,
5145				ata_mode2string(sata->mode));
5146		}
5147		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
5148			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
5149				sata->atapi);
5150		}
5151		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
5152			fprintf(stdout, "%sPIO transaction length: %d\n",
5153				pathstr, sata->bytecount);
5154		}
5155		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
5156			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
5157				sata->pm_present);
5158		}
5159		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
5160			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
5161				sata->tags);
5162		}
5163		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
5164			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
5165				sata->caps);
5166		}
5167	}
5168	if (cts->protocol == PROTO_ATA) {
5169		struct ccb_trans_settings_ata *ata=
5170		    &cts->proto_specific.ata;
5171
5172		if (ata->valid & CTS_ATA_VALID_TQ) {
5173			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
5174				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
5175				"enabled" : "disabled");
5176		}
5177	}
5178	if (cts->protocol == PROTO_SCSI) {
5179		struct ccb_trans_settings_scsi *scsi=
5180		    &cts->proto_specific.scsi;
5181
5182		if (scsi->valid & CTS_SCSI_VALID_TQ) {
5183			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
5184				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
5185				"enabled" : "disabled");
5186		}
5187	}
5188
5189}
5190
5191/*
5192 * Get a path inquiry CCB for the specified device.
5193 */
5194static int
5195get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
5196{
5197	union ccb *ccb;
5198	int retval = 0;
5199
5200	ccb = cam_getccb(device);
5201	if (ccb == NULL) {
5202		warnx("get_cpi: couldn't allocate CCB");
5203		return (1);
5204	}
5205	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cpi);
5206	ccb->ccb_h.func_code = XPT_PATH_INQ;
5207	if (cam_send_ccb(device, ccb) < 0) {
5208		warn("get_cpi: error sending Path Inquiry CCB");
5209		retval = 1;
5210		goto get_cpi_bailout;
5211	}
5212	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5213		if (arglist & CAM_ARG_VERBOSE)
5214			cam_error_print(device, ccb, CAM_ESF_ALL,
5215					CAM_EPF_ALL, stderr);
5216		retval = 1;
5217		goto get_cpi_bailout;
5218	}
5219	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
5220
5221get_cpi_bailout:
5222	cam_freeccb(ccb);
5223	return (retval);
5224}
5225
5226/*
5227 * Get a get device CCB for the specified device.
5228 */
5229static int
5230get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
5231{
5232	union ccb *ccb;
5233	int retval = 0;
5234
5235	ccb = cam_getccb(device);
5236	if (ccb == NULL) {
5237		warnx("get_cgd: couldn't allocate CCB");
5238		return (1);
5239	}
5240	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd);
5241	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
5242	if (cam_send_ccb(device, ccb) < 0) {
5243		warn("get_cgd: error sending Get type information CCB");
5244		retval = 1;
5245		goto get_cgd_bailout;
5246	}
5247	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5248		if (arglist & CAM_ARG_VERBOSE)
5249			cam_error_print(device, ccb, CAM_ESF_ALL,
5250					CAM_EPF_ALL, stderr);
5251		retval = 1;
5252		goto get_cgd_bailout;
5253	}
5254	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
5255
5256get_cgd_bailout:
5257	cam_freeccb(ccb);
5258	return (retval);
5259}
5260
5261/*
5262 * Returns 1 if the device has the VPD page, 0 if it does not, and -1 on an
5263 * error.
5264 */
5265int
5266dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
5267		 int timeout, int verbosemode)
5268{
5269	union ccb *ccb = NULL;
5270	struct scsi_vpd_supported_page_list sup_pages;
5271	int i;
5272	int retval = 0;
5273
5274	ccb = cam_getccb(dev);
5275	if (ccb == NULL) {
5276		warn("Unable to allocate CCB");
5277		retval = -1;
5278		goto bailout;
5279	}
5280
5281	/* cam_getccb cleans up the header, caller has to zero the payload */
5282	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
5283
5284	bzero(&sup_pages, sizeof(sup_pages));
5285
5286	scsi_inquiry(&ccb->csio,
5287		     /*retries*/ retry_count,
5288		     /*cbfcnp*/ NULL,
5289		     /* tag_action */ MSG_SIMPLE_Q_TAG,
5290		     /* inq_buf */ (u_int8_t *)&sup_pages,
5291		     /* inq_len */ sizeof(sup_pages),
5292		     /* evpd */ 1,
5293		     /* page_code */ SVPD_SUPPORTED_PAGE_LIST,
5294		     /* sense_len */ SSD_FULL_SIZE,
5295		     /* timeout */ timeout ? timeout : 5000);
5296
5297	/* Disable freezing the device queue */
5298	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5299
5300	if (retry_count != 0)
5301		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5302
5303	if (cam_send_ccb(dev, ccb) < 0) {
5304		cam_freeccb(ccb);
5305		ccb = NULL;
5306		retval = -1;
5307		goto bailout;
5308	}
5309
5310	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5311		if (verbosemode != 0)
5312			cam_error_print(dev, ccb, CAM_ESF_ALL,
5313					CAM_EPF_ALL, stderr);
5314		retval = -1;
5315		goto bailout;
5316	}
5317
5318	for (i = 0; i < sup_pages.length; i++) {
5319		if (sup_pages.list[i] == page_id) {
5320			retval = 1;
5321			goto bailout;
5322		}
5323	}
5324bailout:
5325	if (ccb != NULL)
5326		cam_freeccb(ccb);
5327
5328	return (retval);
5329}
5330
5331/*
5332 * devtype is filled in with the type of device.
5333 * Returns 0 for success, non-zero for failure.
5334 */
5335int
5336get_device_type(struct cam_device *dev, int retry_count, int timeout,
5337		    int verbosemode, camcontrol_devtype *devtype)
5338{
5339	struct ccb_getdev cgd;
5340	int retval;
5341
5342	retval = get_cgd(dev, &cgd);
5343	if (retval != 0)
5344		goto bailout;
5345
5346	switch (cgd.protocol) {
5347	case PROTO_SCSI:
5348		break;
5349	case PROTO_ATA:
5350	case PROTO_ATAPI:
5351	case PROTO_SATAPM:
5352		*devtype = CC_DT_ATA;
5353		goto bailout;
5354		break; /*NOTREACHED*/
5355	case PROTO_NVME:
5356		*devtype = CC_DT_NVME;
5357		goto bailout;
5358		break; /*NOTREACHED*/
5359	default:
5360		*devtype = CC_DT_UNKNOWN;
5361		goto bailout;
5362		break; /*NOTREACHED*/
5363	}
5364
5365	if (retry_count == -1) {
5366		/*
5367		 * For a retry count of -1, used only the cached data to avoid
5368		 * I/O to the drive. Sending the identify command to the drive
5369		 * can cause issues for SATL attachaed drives since identify is
5370		 * not an NCQ command.
5371		 */
5372		if (cgd.ident_data.config != 0)
5373			*devtype = CC_DT_SATL;
5374		else
5375			*devtype = CC_DT_SCSI;
5376	} else {
5377		/*
5378		 * Check for the ATA Information VPD page (0x89).  If this is an
5379		 * ATA device behind a SCSI to ATA translation layer (SATL),
5380		 * this VPD page should be present.
5381		 *
5382		 * If that VPD page isn't present, or we get an error back from
5383		 * the INQUIRY command, we'll just treat it as a normal SCSI
5384		 * device.
5385		 */
5386		retval = dev_has_vpd_page(dev, SVPD_ATA_INFORMATION, retry_count,
5387		    timeout, verbosemode);
5388		if (retval == 1)
5389			*devtype = CC_DT_SATL;
5390		else
5391			*devtype = CC_DT_SCSI;
5392	}
5393	retval = 0;
5394
5395bailout:
5396	return (retval);
5397}
5398
5399int
5400build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
5401    uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features,
5402    uint16_t sector_count, uint64_t lba, uint8_t command, uint32_t auxiliary,
5403    uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage,
5404    size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout,
5405    int is48bit, camcontrol_devtype devtype)
5406{
5407	int retval = 0;
5408
5409	if (devtype == CC_DT_ATA) {
5410		cam_fill_ataio(&ccb->ataio,
5411		    /*retries*/ retry_count,
5412		    /*cbfcnp*/ NULL,
5413		    /*flags*/ flags,
5414		    /*tag_action*/ tag_action,
5415		    /*data_ptr*/ data_ptr,
5416		    /*dxfer_len*/ dxfer_len,
5417		    /*timeout*/ timeout);
5418		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5419			ata_48bit_cmd(&ccb->ataio, command, features, lba,
5420			    sector_count);
5421		else
5422			ata_28bit_cmd(&ccb->ataio, command, features, lba,
5423			    sector_count);
5424
5425		if (auxiliary != 0) {
5426			ccb->ataio.ata_flags |= ATA_FLAG_AUX;
5427			ccb->ataio.aux = auxiliary;
5428		}
5429
5430		if (ata_flags & AP_FLAG_CHK_COND)
5431			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
5432
5433		if ((protocol & AP_PROTO_MASK) == AP_PROTO_DMA)
5434			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
5435		else if ((protocol & AP_PROTO_MASK) == AP_PROTO_FPDMA)
5436			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
5437	} else {
5438		if (is48bit || lba > ATA_MAX_28BIT_LBA)
5439			protocol |= AP_EXTEND;
5440
5441		retval = scsi_ata_pass(&ccb->csio,
5442		    /*retries*/ retry_count,
5443		    /*cbfcnp*/ NULL,
5444		    /*flags*/ flags,
5445		    /*tag_action*/ tag_action,
5446		    /*protocol*/ protocol,
5447		    /*ata_flags*/ ata_flags,
5448		    /*features*/ features,
5449		    /*sector_count*/ sector_count,
5450		    /*lba*/ lba,
5451		    /*command*/ command,
5452		    /*device*/ 0,
5453		    /*icc*/ 0,
5454		    /*auxiliary*/ auxiliary,
5455		    /*control*/ 0,
5456		    /*data_ptr*/ data_ptr,
5457		    /*dxfer_len*/ dxfer_len,
5458		    /*cdb_storage*/ cdb_storage,
5459		    /*cdb_storage_len*/ cdb_storage_len,
5460		    /*minimum_cmd_size*/ 0,
5461		    /*sense_len*/ sense_len,
5462		    /*timeout*/ timeout);
5463	}
5464
5465	return (retval);
5466}
5467
5468/*
5469 * Returns: 0 -- success, 1 -- error, 2 -- lba truncated,
5470 *	    4 -- count truncated, 6 -- lba and count truncated.
5471 */
5472int
5473get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
5474	       uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
5475{
5476	int retval;
5477
5478	switch (ccb->ccb_h.func_code) {
5479	case XPT_SCSI_IO: {
5480		uint8_t opcode;
5481		int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
5482		u_int sense_len;
5483
5484		/*
5485		 * In this case, we have SCSI ATA PASS-THROUGH command, 12
5486		 * or 16 byte, and need to see what
5487		 */
5488		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
5489			opcode = ccb->csio.cdb_io.cdb_ptr[0];
5490		else
5491			opcode = ccb->csio.cdb_io.cdb_bytes[0];
5492		if ((opcode != ATA_PASS_12)
5493		 && (opcode != ATA_PASS_16)) {
5494			warnx("%s: unsupported opcode %02x", __func__, opcode);
5495			return (1);
5496		}
5497
5498		retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
5499						&asc, &ascq);
5500		/* Note: the _ccb() variant returns 0 for an error */
5501		if (retval == 0)
5502			return (1);
5503
5504		sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
5505		switch (error_code) {
5506		case SSD_DESC_CURRENT_ERROR:
5507		case SSD_DESC_DEFERRED_ERROR: {
5508			struct scsi_sense_data_desc *sense;
5509			struct scsi_sense_ata_ret_desc *desc;
5510			uint8_t *desc_ptr;
5511
5512			sense = (struct scsi_sense_data_desc *)
5513			    &ccb->csio.sense_data;
5514
5515			desc_ptr = scsi_find_desc(sense, sense_len,
5516			    SSD_DESC_ATA);
5517			if (desc_ptr == NULL) {
5518				cam_error_print(dev, ccb, CAM_ESF_ALL,
5519				    CAM_EPF_ALL, stderr);
5520				return (1);
5521			}
5522			desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
5523
5524			*error = desc->error;
5525			*count = (desc->count_15_8 << 8) |
5526				  desc->count_7_0;
5527			*lba = ((uint64_t)desc->lba_47_40 << 40) |
5528			       ((uint64_t)desc->lba_39_32 << 32) |
5529			       ((uint64_t)desc->lba_31_24 << 24) |
5530			       (desc->lba_23_16 << 16) |
5531			       (desc->lba_15_8  <<  8) |
5532				desc->lba_7_0;
5533			*device = desc->device;
5534			*status = desc->status;
5535
5536			/*
5537			 * If the extend bit isn't set, the result is for a
5538			 * 12-byte ATA PASS-THROUGH command or a 16 or 32 byte
5539			 * command without the extend bit set.  This means
5540			 * that the device is supposed to return 28-bit
5541			 * status.  The count field is only 8 bits, and the
5542			 * LBA field is only 8 bits.
5543			 */
5544			if ((desc->flags & SSD_DESC_ATA_FLAG_EXTEND) == 0){
5545				*count &= 0xff;
5546				*lba &= 0x0fffffff;
5547			}
5548			break;
5549		}
5550		case SSD_CURRENT_ERROR:
5551		case SSD_DEFERRED_ERROR: {
5552			uint64_t val;
5553
5554			/*
5555			 * In my understanding of SAT-5 specification, saying:
5556			 * "without interpreting the contents of the STATUS",
5557			 * this should not happen if CK_COND was set, but it
5558			 * does at least for some devices, so try to revert.
5559			 */
5560			if ((sense_key == SSD_KEY_ABORTED_COMMAND) &&
5561			    (asc == 0) && (ascq == 0)) {
5562				*status = ATA_STATUS_ERROR;
5563				*error = ATA_ERROR_ABORT;
5564				*device = 0;
5565				*count = 0;
5566				*lba = 0;
5567				return (0);
5568			}
5569
5570			if ((sense_key != SSD_KEY_RECOVERED_ERROR) ||
5571			    (asc != 0x00) || (ascq != 0x1d))
5572				return (1);
5573
5574			val = 0;
5575			scsi_get_sense_info(&ccb->csio.sense_data, sense_len,
5576			    SSD_DESC_INFO, &val, NULL);
5577			*error = (val >> 24) & 0xff;
5578			*status = (val >> 16) & 0xff;
5579			*device = (val >> 8) & 0xff;
5580			*count = val & 0xff;
5581
5582			val = 0;
5583			scsi_get_sense_info(&ccb->csio.sense_data, sense_len,
5584			    SSD_DESC_COMMAND, &val, NULL);
5585			*lba = ((val >> 16) & 0xff) | (val & 0xff00) |
5586				((val & 0xff) << 16);
5587
5588			/* Report UPPER NONZERO bits as errors 2, 4 and 6. */
5589			return ((val >> 28) & 0x06);
5590		}
5591		default:
5592			return (1);
5593		}
5594
5595		break;
5596	}
5597	case XPT_ATA_IO: {
5598		struct ata_res *res;
5599
5600		/* Only some statuses return ATA result register set. */
5601		if (cam_ccb_status(ccb) != CAM_REQ_CMP &&
5602		    cam_ccb_status(ccb) != CAM_ATA_STATUS_ERROR)
5603			return (1);
5604
5605		res = &ccb->ataio.res;
5606		*error = res->error;
5607		*status = res->status;
5608		*device = res->device;
5609		*count = res->sector_count;
5610		*lba = (res->lba_high << 16) |
5611		       (res->lba_mid << 8) |
5612		       (res->lba_low);
5613		if (ccb->ataio.cmd.flags & CAM_ATAIO_48BIT) {
5614			*count |= (res->sector_count_exp << 8);
5615			*lba |= ((uint64_t)res->lba_low_exp << 24) |
5616				((uint64_t)res->lba_mid_exp << 32) |
5617				((uint64_t)res->lba_high_exp << 40);
5618		} else {
5619			*lba |= (res->device & 0xf) << 24;
5620		}
5621		break;
5622	}
5623	default:
5624		return (1);
5625	}
5626	return (0);
5627}
5628
5629static void
5630cpi_print(struct ccb_pathinq *cpi)
5631{
5632	char adapter_str[1024];
5633	uint64_t i;
5634
5635	snprintf(adapter_str, sizeof(adapter_str),
5636		 "%s%d:", cpi->dev_name, cpi->unit_number);
5637
5638	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
5639		cpi->version_num);
5640
5641	for (i = 1; i < UINT8_MAX; i = i << 1) {
5642		const char *str;
5643
5644		if ((i & cpi->hba_inquiry) == 0)
5645			continue;
5646
5647		fprintf(stdout, "%s supports ", adapter_str);
5648
5649		switch(i) {
5650		case PI_MDP_ABLE:
5651			str = "MDP message";
5652			break;
5653		case PI_WIDE_32:
5654			str = "32 bit wide SCSI";
5655			break;
5656		case PI_WIDE_16:
5657			str = "16 bit wide SCSI";
5658			break;
5659		case PI_SDTR_ABLE:
5660			str = "SDTR message";
5661			break;
5662		case PI_LINKED_CDB:
5663			str = "linked CDBs";
5664			break;
5665		case PI_TAG_ABLE:
5666			str = "tag queue messages";
5667			break;
5668		case PI_SOFT_RST:
5669			str = "soft reset alternative";
5670			break;
5671		case PI_SATAPM:
5672			str = "SATA Port Multiplier";
5673			break;
5674		default:
5675			str = "unknown PI bit set";
5676			break;
5677		}
5678		fprintf(stdout, "%s\n", str);
5679	}
5680
5681	for (i = 1; i < UINT32_MAX; i = i << 1) {
5682		const char *str;
5683
5684		if ((i & cpi->hba_misc) == 0)
5685			continue;
5686
5687		fprintf(stdout, "%s ", adapter_str);
5688
5689		switch(i) {
5690		case PIM_ATA_EXT:
5691			str = "can understand ata_ext requests";
5692			break;
5693		case PIM_EXTLUNS:
5694			str = "64bit extended LUNs supported";
5695			break;
5696		case PIM_SCANHILO:
5697			str = "bus scans from high ID to low ID";
5698			break;
5699		case PIM_NOREMOVE:
5700			str = "removable devices not included in scan";
5701			break;
5702		case PIM_NOINITIATOR:
5703			str = "initiator role not supported";
5704			break;
5705		case PIM_NOBUSRESET:
5706			str = "user has disabled initial BUS RESET or"
5707			      " controller is in target/mixed mode";
5708			break;
5709		case PIM_NO_6_BYTE:
5710			str = "do not send 6-byte commands";
5711			break;
5712		case PIM_SEQSCAN:
5713			str = "scan bus sequentially";
5714			break;
5715		case PIM_UNMAPPED:
5716			str = "unmapped I/O supported";
5717			break;
5718		case PIM_NOSCAN:
5719			str = "does its own scanning";
5720			break;
5721		default:
5722			str = "unknown PIM bit set";
5723			break;
5724		}
5725		fprintf(stdout, "%s\n", str);
5726	}
5727
5728	for (i = 1; i < UINT16_MAX; i = i << 1) {
5729		const char *str;
5730
5731		if ((i & cpi->target_sprt) == 0)
5732			continue;
5733
5734		fprintf(stdout, "%s supports ", adapter_str);
5735		switch(i) {
5736		case PIT_PROCESSOR:
5737			str = "target mode processor mode";
5738			break;
5739		case PIT_PHASE:
5740			str = "target mode phase cog. mode";
5741			break;
5742		case PIT_DISCONNECT:
5743			str = "disconnects in target mode";
5744			break;
5745		case PIT_TERM_IO:
5746			str = "terminate I/O message in target mode";
5747			break;
5748		case PIT_GRP_6:
5749			str = "group 6 commands in target mode";
5750			break;
5751		case PIT_GRP_7:
5752			str = "group 7 commands in target mode";
5753			break;
5754		default:
5755			str = "unknown PIT bit set";
5756			break;
5757		}
5758
5759		fprintf(stdout, "%s\n", str);
5760	}
5761	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
5762		cpi->hba_eng_cnt);
5763	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
5764		cpi->max_target);
5765	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
5766		cpi->max_lun);
5767	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
5768		adapter_str, cpi->hpath_id);
5769	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
5770		cpi->initiator_id);
5771	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
5772	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
5773	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
5774	    adapter_str, cpi->hba_vendor);
5775	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
5776	    adapter_str, cpi->hba_device);
5777	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
5778	    adapter_str, cpi->hba_subvendor);
5779	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
5780	    adapter_str, cpi->hba_subdevice);
5781	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
5782	fprintf(stdout, "%s base transfer speed: ", adapter_str);
5783	if (cpi->base_transfer_speed > 1000)
5784		fprintf(stdout, "%d.%03dMB/sec\n",
5785			cpi->base_transfer_speed / 1000,
5786			cpi->base_transfer_speed % 1000);
5787	else
5788		fprintf(stdout, "%dKB/sec\n",
5789			(cpi->base_transfer_speed % 1000) * 1000);
5790	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
5791	    adapter_str, cpi->maxio);
5792}
5793
5794static int
5795get_print_cts(struct cam_device *device, int user_settings, int quiet,
5796	      struct ccb_trans_settings *cts)
5797{
5798	int retval;
5799	union ccb *ccb;
5800
5801	retval = 0;
5802	ccb = cam_getccb(device);
5803
5804	if (ccb == NULL) {
5805		warnx("get_print_cts: error allocating ccb");
5806		return (1);
5807	}
5808
5809	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5810
5811	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
5812
5813	if (user_settings == 0)
5814		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
5815	else
5816		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
5817
5818	if (cam_send_ccb(device, ccb) < 0) {
5819		warn("error sending XPT_GET_TRAN_SETTINGS CCB");
5820		retval = 1;
5821		goto get_print_cts_bailout;
5822	}
5823
5824	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5825		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
5826		if (arglist & CAM_ARG_VERBOSE)
5827			cam_error_print(device, ccb, CAM_ESF_ALL,
5828					CAM_EPF_ALL, stderr);
5829		retval = 1;
5830		goto get_print_cts_bailout;
5831	}
5832
5833	if (quiet == 0)
5834		cts_print(device, &ccb->cts);
5835
5836	if (cts != NULL)
5837		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
5838
5839get_print_cts_bailout:
5840
5841	cam_freeccb(ccb);
5842
5843	return (retval);
5844}
5845
5846static int
5847ratecontrol(struct cam_device *device, int task_attr, int retry_count,
5848	    int timeout, int argc, char **argv, char *combinedopt)
5849{
5850	int c;
5851	union ccb *ccb;
5852	int user_settings = 0;
5853	int retval = 0;
5854	int disc_enable = -1, tag_enable = -1;
5855	int mode = -1;
5856	int offset = -1;
5857	double syncrate = -1;
5858	int bus_width = -1;
5859	int quiet = 0;
5860	int change_settings = 0, send_tur = 0;
5861	struct ccb_pathinq cpi;
5862
5863	ccb = cam_getccb(device);
5864	if (ccb == NULL) {
5865		warnx("ratecontrol: error allocating ccb");
5866		return (1);
5867	}
5868	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5869		switch(c){
5870		case 'a':
5871			send_tur = 1;
5872			break;
5873		case 'c':
5874			user_settings = 0;
5875			break;
5876		case 'D':
5877			if (strncasecmp(optarg, "enable", 6) == 0)
5878				disc_enable = 1;
5879			else if (strncasecmp(optarg, "disable", 7) == 0)
5880				disc_enable = 0;
5881			else {
5882				warnx("-D argument \"%s\" is unknown", optarg);
5883				retval = 1;
5884				goto ratecontrol_bailout;
5885			}
5886			change_settings = 1;
5887			break;
5888		case 'M':
5889			mode = ata_string2mode(optarg);
5890			if (mode < 0) {
5891				warnx("unknown mode '%s'", optarg);
5892				retval = 1;
5893				goto ratecontrol_bailout;
5894			}
5895			change_settings = 1;
5896			break;
5897		case 'O':
5898			offset = strtol(optarg, NULL, 0);
5899			if (offset < 0) {
5900				warnx("offset value %d is < 0", offset);
5901				retval = 1;
5902				goto ratecontrol_bailout;
5903			}
5904			change_settings = 1;
5905			break;
5906		case 'q':
5907			quiet++;
5908			break;
5909		case 'R':
5910			syncrate = atof(optarg);
5911			if (syncrate < 0) {
5912				warnx("sync rate %f is < 0", syncrate);
5913				retval = 1;
5914				goto ratecontrol_bailout;
5915			}
5916			change_settings = 1;
5917			break;
5918		case 'T':
5919			if (strncasecmp(optarg, "enable", 6) == 0)
5920				tag_enable = 1;
5921			else if (strncasecmp(optarg, "disable", 7) == 0)
5922				tag_enable = 0;
5923			else {
5924				warnx("-T argument \"%s\" is unknown", optarg);
5925				retval = 1;
5926				goto ratecontrol_bailout;
5927			}
5928			change_settings = 1;
5929			break;
5930		case 'U':
5931			user_settings = 1;
5932			break;
5933		case 'W':
5934			bus_width = strtol(optarg, NULL, 0);
5935			if (bus_width < 0) {
5936				warnx("bus width %d is < 0", bus_width);
5937				retval = 1;
5938				goto ratecontrol_bailout;
5939			}
5940			change_settings = 1;
5941			break;
5942		default:
5943			break;
5944		}
5945	}
5946	/*
5947	 * Grab path inquiry information, so we can determine whether
5948	 * or not the initiator is capable of the things that the user
5949	 * requests.
5950	 */
5951	if ((retval = get_cpi(device, &cpi)) != 0)
5952		goto ratecontrol_bailout;
5953	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
5954	if (quiet == 0) {
5955		fprintf(stdout, "%s parameters:\n",
5956		    user_settings ? "User" : "Current");
5957	}
5958	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5959	if (retval != 0)
5960		goto ratecontrol_bailout;
5961
5962	if (arglist & CAM_ARG_VERBOSE)
5963		cpi_print(&cpi);
5964
5965	if (change_settings) {
5966		int didsettings = 0;
5967		struct ccb_trans_settings_spi *spi = NULL;
5968		struct ccb_trans_settings_pata *pata = NULL;
5969		struct ccb_trans_settings_sata *sata = NULL;
5970		struct ccb_trans_settings_ata *ata = NULL;
5971		struct ccb_trans_settings_scsi *scsi = NULL;
5972
5973		if (ccb->cts.transport == XPORT_SPI)
5974			spi = &ccb->cts.xport_specific.spi;
5975		if (ccb->cts.transport == XPORT_ATA)
5976			pata = &ccb->cts.xport_specific.ata;
5977		if (ccb->cts.transport == XPORT_SATA)
5978			sata = &ccb->cts.xport_specific.sata;
5979		if (ccb->cts.protocol == PROTO_ATA)
5980			ata = &ccb->cts.proto_specific.ata;
5981		if (ccb->cts.protocol == PROTO_SCSI)
5982			scsi = &ccb->cts.proto_specific.scsi;
5983		ccb->cts.xport_specific.valid = 0;
5984		ccb->cts.proto_specific.valid = 0;
5985		if (spi && disc_enable != -1) {
5986			spi->valid |= CTS_SPI_VALID_DISC;
5987			if (disc_enable == 0)
5988				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5989			else
5990				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5991			didsettings++;
5992		}
5993		if (tag_enable != -1) {
5994			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5995				warnx("HBA does not support tagged queueing, "
5996				      "so you cannot modify tag settings");
5997				retval = 1;
5998				goto ratecontrol_bailout;
5999			}
6000			if (ata) {
6001				ata->valid |= CTS_SCSI_VALID_TQ;
6002				if (tag_enable == 0)
6003					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
6004				else
6005					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
6006				didsettings++;
6007			} else if (scsi) {
6008				scsi->valid |= CTS_SCSI_VALID_TQ;
6009				if (tag_enable == 0)
6010					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
6011				else
6012					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
6013				didsettings++;
6014			}
6015		}
6016		if (spi && offset != -1) {
6017			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6018				warnx("HBA is not capable of changing offset");
6019				retval = 1;
6020				goto ratecontrol_bailout;
6021			}
6022			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
6023			spi->sync_offset = offset;
6024			didsettings++;
6025		}
6026		if (spi && syncrate != -1) {
6027			int prelim_sync_period;
6028
6029			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6030				warnx("HBA is not capable of changing "
6031				      "transfer rates");
6032				retval = 1;
6033				goto ratecontrol_bailout;
6034			}
6035			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
6036			/*
6037			 * The sync rate the user gives us is in MHz.
6038			 * We need to translate it into KHz for this
6039			 * calculation.
6040			 */
6041			syncrate *= 1000;
6042			/*
6043			 * Next, we calculate a "preliminary" sync period
6044			 * in tenths of a nanosecond.
6045			 */
6046			if (syncrate == 0)
6047				prelim_sync_period = 0;
6048			else
6049				prelim_sync_period = 10000000 / syncrate;
6050			spi->sync_period =
6051				scsi_calc_syncparam(prelim_sync_period);
6052			didsettings++;
6053		}
6054		if (sata && syncrate != -1) {
6055			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6056				warnx("HBA is not capable of changing "
6057				      "transfer rates");
6058				retval = 1;
6059				goto ratecontrol_bailout;
6060			}
6061			if  (!user_settings) {
6062				warnx("You can modify only user rate "
6063				    "settings for SATA");
6064				retval = 1;
6065				goto ratecontrol_bailout;
6066			}
6067			sata->revision = ata_speed2revision(syncrate * 100);
6068			if (sata->revision < 0) {
6069				warnx("Invalid rate %f", syncrate);
6070				retval = 1;
6071				goto ratecontrol_bailout;
6072			}
6073			sata->valid |= CTS_SATA_VALID_REVISION;
6074			didsettings++;
6075		}
6076		if ((pata || sata) && mode != -1) {
6077			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
6078				warnx("HBA is not capable of changing "
6079				      "transfer rates");
6080				retval = 1;
6081				goto ratecontrol_bailout;
6082			}
6083			if  (!user_settings) {
6084				warnx("You can modify only user mode "
6085				    "settings for ATA/SATA");
6086				retval = 1;
6087				goto ratecontrol_bailout;
6088			}
6089			if (pata) {
6090				pata->mode = mode;
6091				pata->valid |= CTS_ATA_VALID_MODE;
6092			} else {
6093				sata->mode = mode;
6094				sata->valid |= CTS_SATA_VALID_MODE;
6095			}
6096			didsettings++;
6097		}
6098		/*
6099		 * The bus_width argument goes like this:
6100		 * 0 == 8 bit
6101		 * 1 == 16 bit
6102		 * 2 == 32 bit
6103		 * Therefore, if you shift the number of bits given on the
6104		 * command line right by 4, you should get the correct
6105		 * number.
6106		 */
6107		if (spi && bus_width != -1) {
6108			/*
6109			 * We might as well validate things here with a
6110			 * decipherable error message, rather than what
6111			 * will probably be an indecipherable error message
6112			 * by the time it gets back to us.
6113			 */
6114			if ((bus_width == 16)
6115			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
6116				warnx("HBA does not support 16 bit bus width");
6117				retval = 1;
6118				goto ratecontrol_bailout;
6119			} else if ((bus_width == 32)
6120				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
6121				warnx("HBA does not support 32 bit bus width");
6122				retval = 1;
6123				goto ratecontrol_bailout;
6124			} else if ((bus_width != 8)
6125				&& (bus_width != 16)
6126				&& (bus_width != 32)) {
6127				warnx("Invalid bus width %d", bus_width);
6128				retval = 1;
6129				goto ratecontrol_bailout;
6130			}
6131			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
6132			spi->bus_width = bus_width >> 4;
6133			didsettings++;
6134		}
6135		if  (didsettings == 0) {
6136			goto ratecontrol_bailout;
6137		}
6138		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
6139		if (cam_send_ccb(device, ccb) < 0) {
6140			warn("error sending XPT_SET_TRAN_SETTINGS CCB");
6141			retval = 1;
6142			goto ratecontrol_bailout;
6143		}
6144		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6145			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
6146			if (arglist & CAM_ARG_VERBOSE) {
6147				cam_error_print(device, ccb, CAM_ESF_ALL,
6148						CAM_EPF_ALL, stderr);
6149			}
6150			retval = 1;
6151			goto ratecontrol_bailout;
6152		}
6153	}
6154	if (send_tur) {
6155		retval = testunitready(device, task_attr, retry_count, timeout,
6156				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
6157		/*
6158		 * If the TUR didn't succeed, just bail.
6159		 */
6160		if (retval != 0) {
6161			if (quiet == 0)
6162				fprintf(stderr, "Test Unit Ready failed\n");
6163			goto ratecontrol_bailout;
6164		}
6165	}
6166	if ((change_settings || send_tur) && !quiet &&
6167	    (ccb->cts.transport == XPORT_ATA ||
6168	     ccb->cts.transport == XPORT_SATA || send_tur)) {
6169		fprintf(stdout, "New parameters:\n");
6170		retval = get_print_cts(device, user_settings, 0, NULL);
6171	}
6172
6173ratecontrol_bailout:
6174	cam_freeccb(ccb);
6175	return (retval);
6176}
6177
6178static int
6179scsiformat(struct cam_device *device, int argc, char **argv,
6180	   char *combinedopt, int task_attr, int retry_count, int timeout)
6181{
6182	union ccb *ccb;
6183	int c;
6184	int ycount = 0, quiet = 0;
6185	int error = 0, retval = 0;
6186	int use_timeout = 10800 * 1000;
6187	int immediate = 1;
6188	struct format_defect_list_header fh;
6189	u_int8_t *data_ptr = NULL;
6190	u_int32_t dxfer_len = 0;
6191	u_int8_t byte2 = 0;
6192	int num_warnings = 0;
6193	int reportonly = 0;
6194
6195	ccb = cam_getccb(device);
6196
6197	if (ccb == NULL) {
6198		warnx("scsiformat: error allocating ccb");
6199		return (1);
6200	}
6201
6202	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6203
6204	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6205		switch(c) {
6206		case 'q':
6207			quiet++;
6208			break;
6209		case 'r':
6210			reportonly = 1;
6211			break;
6212		case 'w':
6213			immediate = 0;
6214			break;
6215		case 'y':
6216			ycount++;
6217			break;
6218		}
6219	}
6220
6221	if (reportonly)
6222		goto doreport;
6223
6224	if (quiet == 0 && ycount == 0) {
6225		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6226			"following device:\n");
6227
6228		error = scsidoinquiry(device, argc, argv, combinedopt,
6229				      task_attr, retry_count, timeout);
6230
6231		if (error != 0) {
6232			warnx("scsiformat: error sending inquiry");
6233			goto scsiformat_bailout;
6234		}
6235	}
6236
6237	if (ycount == 0) {
6238		if (!get_confirmation()) {
6239			error = 1;
6240			goto scsiformat_bailout;
6241		}
6242	}
6243
6244	if (timeout != 0)
6245		use_timeout = timeout;
6246
6247	if (quiet == 0) {
6248		fprintf(stdout, "Current format timeout is %d seconds\n",
6249			use_timeout / 1000);
6250	}
6251
6252	/*
6253	 * If the user hasn't disabled questions and didn't specify a
6254	 * timeout on the command line, ask them if they want the current
6255	 * timeout.
6256	 */
6257	if ((ycount == 0)
6258	 && (timeout == 0)) {
6259		char str[1024];
6260		int new_timeout = 0;
6261
6262		fprintf(stdout, "Enter new timeout in seconds or press\n"
6263			"return to keep the current timeout [%d] ",
6264			use_timeout / 1000);
6265
6266		if (fgets(str, sizeof(str), stdin) != NULL) {
6267			if (str[0] != '\0')
6268				new_timeout = atoi(str);
6269		}
6270
6271		if (new_timeout != 0) {
6272			use_timeout = new_timeout * 1000;
6273			fprintf(stdout, "Using new timeout value %d\n",
6274				use_timeout / 1000);
6275		}
6276	}
6277
6278	/*
6279	 * Keep this outside the if block below to silence any unused
6280	 * variable warnings.
6281	 */
6282	bzero(&fh, sizeof(fh));
6283
6284	/*
6285	 * If we're in immediate mode, we've got to include the format
6286	 * header
6287	 */
6288	if (immediate != 0) {
6289		fh.byte2 = FU_DLH_IMMED;
6290		data_ptr = (u_int8_t *)&fh;
6291		dxfer_len = sizeof(fh);
6292		byte2 = FU_FMT_DATA;
6293	} else if (quiet == 0) {
6294		fprintf(stdout, "Formatting...");
6295		fflush(stdout);
6296	}
6297
6298	scsi_format_unit(&ccb->csio,
6299			 /* retries */ retry_count,
6300			 /* cbfcnp */ NULL,
6301			 /* tag_action */ task_attr,
6302			 /* byte2 */ byte2,
6303			 /* ileave */ 0,
6304			 /* data_ptr */ data_ptr,
6305			 /* dxfer_len */ dxfer_len,
6306			 /* sense_len */ SSD_FULL_SIZE,
6307			 /* timeout */ use_timeout);
6308
6309	/* Disable freezing the device queue */
6310	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6311
6312	if (arglist & CAM_ARG_ERR_RECOVER)
6313		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6314
6315	if (((retval = cam_send_ccb(device, ccb)) < 0)
6316	 || ((immediate == 0)
6317	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
6318		const char errstr[] = "error sending format command";
6319
6320		if (retval < 0)
6321			warn(errstr);
6322		else
6323			warnx(errstr);
6324
6325		if (arglist & CAM_ARG_VERBOSE) {
6326			cam_error_print(device, ccb, CAM_ESF_ALL,
6327					CAM_EPF_ALL, stderr);
6328		}
6329		error = 1;
6330		goto scsiformat_bailout;
6331	}
6332
6333	/*
6334	 * If we ran in non-immediate mode, we already checked for errors
6335	 * above and printed out any necessary information.  If we're in
6336	 * immediate mode, we need to loop through and get status
6337	 * information periodically.
6338	 */
6339	if (immediate == 0) {
6340		if (quiet == 0) {
6341			fprintf(stdout, "Format Complete\n");
6342		}
6343		goto scsiformat_bailout;
6344	}
6345
6346doreport:
6347	do {
6348		cam_status status;
6349
6350		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6351
6352		/*
6353		 * There's really no need to do error recovery or
6354		 * retries here, since we're just going to sit in a
6355		 * loop and wait for the device to finish formatting.
6356		 */
6357		scsi_test_unit_ready(&ccb->csio,
6358				     /* retries */ 0,
6359				     /* cbfcnp */ NULL,
6360				     /* tag_action */ task_attr,
6361				     /* sense_len */ SSD_FULL_SIZE,
6362				     /* timeout */ 5000);
6363
6364		/* Disable freezing the device queue */
6365		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6366
6367		retval = cam_send_ccb(device, ccb);
6368
6369		/*
6370		 * If we get an error from the ioctl, bail out.  SCSI
6371		 * errors are expected.
6372		 */
6373		if (retval < 0) {
6374			warn("error sending TEST UNIT READY command");
6375			error = 1;
6376			goto scsiformat_bailout;
6377		}
6378
6379		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6380
6381		if ((status != CAM_REQ_CMP)
6382		 && (status == CAM_SCSI_STATUS_ERROR)
6383		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6384			struct scsi_sense_data *sense;
6385			int error_code, sense_key, asc, ascq;
6386
6387			sense = &ccb->csio.sense_data;
6388			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6389			    ccb->csio.sense_resid, &error_code, &sense_key,
6390			    &asc, &ascq, /*show_errors*/ 1);
6391
6392			/*
6393			 * According to the SCSI-2 and SCSI-3 specs, a
6394			 * drive that is in the middle of a format should
6395			 * return NOT READY with an ASC of "logical unit
6396			 * not ready, format in progress".  The sense key
6397			 * specific bytes will then be a progress indicator.
6398			 */
6399			if ((sense_key == SSD_KEY_NOT_READY)
6400			 && (asc == 0x04) && (ascq == 0x04)) {
6401				uint8_t sks[3];
6402
6403				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6404				     ccb->csio.sense_resid, sks) == 0)
6405				 && (quiet == 0)) {
6406					uint32_t val;
6407					u_int64_t percentage;
6408
6409					val = scsi_2btoul(&sks[1]);
6410					percentage = 10000ull * val;
6411
6412					fprintf(stdout,
6413						"\rFormatting:  %ju.%02u %% "
6414						"(%u/%d) done",
6415						(uintmax_t)(percentage /
6416						(0x10000 * 100)),
6417						(unsigned)((percentage /
6418						0x10000) % 100),
6419						val, 0x10000);
6420					fflush(stdout);
6421				} else if ((quiet == 0)
6422					&& (++num_warnings <= 1)) {
6423					warnx("Unexpected SCSI Sense Key "
6424					      "Specific value returned "
6425					      "during format:");
6426					scsi_sense_print(device, &ccb->csio,
6427							 stderr);
6428					warnx("Unable to print status "
6429					      "information, but format will "
6430					      "proceed.");
6431					warnx("will exit when format is "
6432					      "complete");
6433				}
6434				sleep(1);
6435			} else {
6436				warnx("Unexpected SCSI error during format");
6437				cam_error_print(device, ccb, CAM_ESF_ALL,
6438						CAM_EPF_ALL, stderr);
6439				error = 1;
6440				goto scsiformat_bailout;
6441			}
6442
6443		} else if (status != CAM_REQ_CMP) {
6444			warnx("Unexpected CAM status %#x", status);
6445			if (arglist & CAM_ARG_VERBOSE)
6446				cam_error_print(device, ccb, CAM_ESF_ALL,
6447						CAM_EPF_ALL, stderr);
6448			error = 1;
6449			goto scsiformat_bailout;
6450		}
6451
6452	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6453
6454	if (quiet == 0)
6455		fprintf(stdout, "\nFormat Complete\n");
6456
6457scsiformat_bailout:
6458
6459	cam_freeccb(ccb);
6460
6461	return (error);
6462}
6463
6464static int
6465sanitize_wait_ata(struct cam_device *device, union ccb *ccb, int quiet,
6466    camcontrol_devtype devtype)
6467{
6468	int retval;
6469	uint8_t error = 0, ata_device = 0, status = 0;
6470	uint16_t count = 0;
6471	uint64_t lba = 0;
6472	u_int val, perc;
6473
6474	do {
6475		retval = build_ata_cmd(ccb,
6476			     /*retries*/ 0,
6477			     /*flags*/ CAM_DIR_NONE,
6478			     /*tag_action*/ MSG_SIMPLE_Q_TAG,
6479			     /*protocol*/ AP_PROTO_NON_DATA,
6480			     /*ata_flags*/ AP_FLAG_CHK_COND,
6481			     /*features*/ 0x00, /* SANITIZE STATUS EXT */
6482			     /*sector_count*/ 0,
6483			     /*lba*/ 0,
6484			     /*command*/ ATA_SANITIZE,
6485			     /*auxiliary*/ 0,
6486			     /*data_ptr*/ NULL,
6487			     /*dxfer_len*/ 0,
6488			     /*cdb_storage*/ NULL,
6489			     /*cdb_storage_len*/ 0,
6490			     /*sense_len*/ SSD_FULL_SIZE,
6491			     /*timeout*/ 10000,
6492			     /*is48bit*/ 1,
6493			     /*devtype*/ devtype);
6494		if (retval != 0) {
6495			warnx("%s: build_ata_cmd() failed, likely "
6496			    "programmer error", __func__);
6497			return (1);
6498		}
6499
6500		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6501		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6502		retval = cam_send_ccb(device, ccb);
6503		if (retval != 0) {
6504			warn("error sending SANITIZE STATUS EXT command");
6505			return (1);
6506		}
6507
6508		retval = get_ata_status(device, ccb, &error, &count, &lba,
6509		    &ata_device, &status);
6510		if (retval != 0) {
6511			warnx("Can't get SANITIZE STATUS EXT status, "
6512			    "sanitize may still run.");
6513			return (retval);
6514		}
6515		if (status & ATA_STATUS_ERROR) {
6516			warnx("SANITIZE STATUS EXT failed, "
6517			    "sanitize may still run.");
6518			return (1);
6519		}
6520		if (count & 0x4000) {
6521			if (quiet == 0) {
6522				val = lba & 0xffff;
6523				perc = 10000 * val;
6524				fprintf(stdout,
6525				    "Sanitizing: %u.%02u%% (%d/%d)\r",
6526				    (perc / (0x10000 * 100)),
6527				    ((perc / 0x10000) % 100),
6528				    val, 0x10000);
6529				fflush(stdout);
6530			}
6531			sleep(1);
6532		} else if ((count & 0x8000) == 0) {
6533			warnx("Sanitize complete with an error.     ");
6534			return (1);
6535		} else
6536			break;
6537	} while (1);
6538	return (0);
6539}
6540
6541static int
6542sanitize_wait_scsi(struct cam_device *device, union ccb *ccb, int task_attr, int quiet)
6543{
6544	int warnings = 0, retval;
6545	cam_status status;
6546	u_int val, perc;
6547
6548	do {
6549		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6550
6551		/*
6552		 * There's really no need to do error recovery or
6553		 * retries here, since we're just going to sit in a
6554		 * loop and wait for the device to finish sanitizing.
6555		 */
6556		scsi_test_unit_ready(&ccb->csio,
6557				     /* retries */ 0,
6558				     /* cbfcnp */ NULL,
6559				     /* tag_action */ task_attr,
6560				     /* sense_len */ SSD_FULL_SIZE,
6561				     /* timeout */ 5000);
6562
6563		/* Disable freezing the device queue */
6564		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6565
6566		retval = cam_send_ccb(device, ccb);
6567
6568		/*
6569		 * If we get an error from the ioctl, bail out.  SCSI
6570		 * errors are expected.
6571		 */
6572		if (retval < 0) {
6573			warn("error sending TEST UNIT READY command");
6574			return (1);
6575		}
6576
6577		status = ccb->ccb_h.status & CAM_STATUS_MASK;
6578		if ((status == CAM_SCSI_STATUS_ERROR) &&
6579		    ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
6580			struct scsi_sense_data *sense;
6581			int error_code, sense_key, asc, ascq;
6582
6583			sense = &ccb->csio.sense_data;
6584			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6585			    ccb->csio.sense_resid, &error_code, &sense_key,
6586			    &asc, &ascq, /*show_errors*/ 1);
6587
6588			/*
6589			 * According to the SCSI-3 spec, a drive that is in the
6590			 * middle of a sanitize should return NOT READY with an
6591			 * ASC of "logical unit not ready, sanitize in
6592			 * progress". The sense key specific bytes will then
6593			 * be a progress indicator.
6594			 */
6595			if ((sense_key == SSD_KEY_NOT_READY)
6596			 && (asc == 0x04) && (ascq == 0x1b)) {
6597				uint8_t sks[3];
6598
6599				if ((scsi_get_sks(sense, ccb->csio.sense_len -
6600				     ccb->csio.sense_resid, sks) == 0)
6601				 && (quiet == 0)) {
6602					val = scsi_2btoul(&sks[1]);
6603					perc = 10000 * val;
6604					fprintf(stdout,
6605					    "Sanitizing: %u.%02u%% (%d/%d)\r",
6606					    (perc / (0x10000 * 100)),
6607					    ((perc / 0x10000) % 100),
6608					    val, 0x10000);
6609					fflush(stdout);
6610				} else if ((quiet == 0) && (++warnings <= 1)) {
6611					warnx("Unexpected SCSI Sense Key "
6612					      "Specific value returned "
6613					      "during sanitize:");
6614					scsi_sense_print(device, &ccb->csio,
6615							 stderr);
6616					warnx("Unable to print status "
6617					      "information, but sanitze will "
6618					      "proceed.");
6619					warnx("will exit when sanitize is "
6620					      "complete");
6621				}
6622				sleep(1);
6623			} else {
6624				warnx("Unexpected SCSI error during sanitize");
6625				cam_error_print(device, ccb, CAM_ESF_ALL,
6626						CAM_EPF_ALL, stderr);
6627				return (1);
6628			}
6629
6630		} else if (status != CAM_REQ_CMP && status != CAM_REQUEUE_REQ) {
6631			warnx("Unexpected CAM status %#x", status);
6632			if (arglist & CAM_ARG_VERBOSE)
6633				cam_error_print(device, ccb, CAM_ESF_ALL,
6634						CAM_EPF_ALL, stderr);
6635			return (1);
6636		}
6637	} while ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
6638	return (0);
6639}
6640
6641static int
6642sanitize(struct cam_device *device, int argc, char **argv,
6643	     char *combinedopt, int task_attr, int retry_count, int timeout)
6644{
6645	union ccb *ccb;
6646	u_int8_t action = 0;
6647	int c;
6648	int ycount = 0, quiet = 0;
6649	int error = 0;
6650	int use_timeout;
6651	int immediate = 1;
6652	int invert = 0;
6653	int passes = 0;
6654	int ause = 0;
6655	int fd = -1;
6656	const char *pattern = NULL;
6657	u_int8_t *data_ptr = NULL;
6658	u_int32_t dxfer_len = 0;
6659	uint8_t byte2;
6660	uint16_t feature, count;
6661	uint64_t lba;
6662	int reportonly = 0;
6663	camcontrol_devtype dt;
6664
6665	/*
6666	 * Get the device type, request no I/O be done to do this.
6667	 */
6668	error = get_device_type(device, -1, 0, 0, &dt);
6669	if (error != 0 || (unsigned)dt > CC_DT_UNKNOWN) {
6670		warnx("sanitize: can't get device type");
6671		return (1);
6672	}
6673
6674	ccb = cam_getccb(device);
6675
6676	if (ccb == NULL) {
6677		warnx("sanitize: error allocating ccb");
6678		return (1);
6679	}
6680
6681	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
6682
6683	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6684		switch(c) {
6685		case 'a':
6686			if (strcasecmp(optarg, "overwrite") == 0)
6687				action = SSZ_SERVICE_ACTION_OVERWRITE;
6688			else if (strcasecmp(optarg, "block") == 0)
6689				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
6690			else if (strcasecmp(optarg, "crypto") == 0)
6691				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
6692			else if (strcasecmp(optarg, "exitfailure") == 0)
6693				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
6694			else {
6695				warnx("invalid service operation \"%s\"",
6696				      optarg);
6697				error = 1;
6698				goto sanitize_bailout;
6699			}
6700			break;
6701		case 'c':
6702			passes = strtol(optarg, NULL, 0);
6703			if (passes < 1 || passes > 31) {
6704				warnx("invalid passes value %d", passes);
6705				error = 1;
6706				goto sanitize_bailout;
6707			}
6708			break;
6709		case 'I':
6710			invert = 1;
6711			break;
6712		case 'P':
6713			pattern = optarg;
6714			break;
6715		case 'q':
6716			quiet++;
6717			break;
6718		case 'U':
6719			ause = 1;
6720			break;
6721		case 'r':
6722			reportonly = 1;
6723			break;
6724		case 'w':
6725			/* ATA supports only immediate commands. */
6726			if (dt == CC_DT_SCSI)
6727				immediate = 0;
6728			break;
6729		case 'y':
6730			ycount++;
6731			break;
6732		}
6733	}
6734
6735	if (reportonly)
6736		goto doreport;
6737
6738	if (action == 0) {
6739		warnx("an action is required");
6740		error = 1;
6741		goto sanitize_bailout;
6742	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6743		struct scsi_sanitize_parameter_list *pl;
6744		struct stat sb;
6745		ssize_t sz, amt;
6746
6747		if (pattern == NULL) {
6748			warnx("overwrite action requires -P argument");
6749			error = 1;
6750			goto sanitize_bailout;
6751		}
6752		fd = open(pattern, O_RDONLY);
6753		if (fd < 0) {
6754			warn("cannot open pattern file %s", pattern);
6755			error = 1;
6756			goto sanitize_bailout;
6757		}
6758		if (fstat(fd, &sb) < 0) {
6759			warn("cannot stat pattern file %s", pattern);
6760			error = 1;
6761			goto sanitize_bailout;
6762		}
6763		sz = sb.st_size;
6764		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
6765			warnx("pattern file size exceeds maximum value %d",
6766			      SSZPL_MAX_PATTERN_LENGTH);
6767			error = 1;
6768			goto sanitize_bailout;
6769		}
6770		dxfer_len = sizeof(*pl) + sz;
6771		data_ptr = calloc(1, dxfer_len);
6772		if (data_ptr == NULL) {
6773			warnx("cannot allocate parameter list buffer");
6774			error = 1;
6775			goto sanitize_bailout;
6776		}
6777
6778		amt = read(fd, data_ptr + sizeof(*pl), sz);
6779		if (amt < 0) {
6780			warn("cannot read pattern file");
6781			error = 1;
6782			goto sanitize_bailout;
6783		} else if (amt != sz) {
6784			warnx("short pattern file read");
6785			error = 1;
6786			goto sanitize_bailout;
6787		}
6788
6789		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
6790		if (passes == 0)
6791			pl->byte1 = 1;
6792		else
6793			pl->byte1 = passes;
6794		if (invert != 0)
6795			pl->byte1 |= SSZPL_INVERT;
6796		scsi_ulto2b(sz, pl->length);
6797	} else {
6798		const char *arg;
6799
6800		if (passes != 0)
6801			arg = "-c";
6802		else if (invert != 0)
6803			arg = "-I";
6804		else if (pattern != NULL)
6805			arg = "-P";
6806		else
6807			arg = NULL;
6808		if (arg != NULL) {
6809			warnx("%s argument only valid with overwrite "
6810			      "operation", arg);
6811			error = 1;
6812			goto sanitize_bailout;
6813		}
6814	}
6815
6816	if (quiet == 0 && ycount == 0) {
6817		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
6818			"following device:\n");
6819
6820		if (dt == CC_DT_SCSI) {
6821			error = scsidoinquiry(device, argc, argv, combinedopt,
6822					      task_attr, retry_count, timeout);
6823		} else if (dt == CC_DT_ATA || dt == CC_DT_SATL) {
6824			struct ata_params *ident_buf;
6825			error = ata_do_identify(device, retry_count, timeout,
6826						ccb, &ident_buf);
6827			if (error == 0) {
6828				printf("%s%d: ", device->device_name,
6829				    device->dev_unit_num);
6830				ata_print_ident(ident_buf);
6831				free(ident_buf);
6832			}
6833		} else
6834			error = 1;
6835
6836		if (error != 0) {
6837			warnx("sanitize: error sending inquiry");
6838			goto sanitize_bailout;
6839		}
6840	}
6841
6842	if (ycount == 0) {
6843		if (!get_confirmation()) {
6844			error = 1;
6845			goto sanitize_bailout;
6846		}
6847	}
6848
6849	if (timeout != 0)
6850		use_timeout = timeout;
6851	else
6852		use_timeout = (immediate ? 10 : 10800) * 1000;
6853
6854	if (immediate == 0 && quiet == 0) {
6855		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
6856			use_timeout / 1000);
6857	}
6858
6859	/*
6860	 * If the user hasn't disabled questions and didn't specify a
6861	 * timeout on the command line, ask them if they want the current
6862	 * timeout.
6863	 */
6864	if (immediate == 0 && ycount == 0 && timeout == 0) {
6865		char str[1024];
6866		int new_timeout = 0;
6867
6868		fprintf(stdout, "Enter new timeout in seconds or press\n"
6869			"return to keep the current timeout [%d] ",
6870			use_timeout / 1000);
6871
6872		if (fgets(str, sizeof(str), stdin) != NULL) {
6873			if (str[0] != '\0')
6874				new_timeout = atoi(str);
6875		}
6876
6877		if (new_timeout != 0) {
6878			use_timeout = new_timeout * 1000;
6879			fprintf(stdout, "Using new timeout value %d\n",
6880				use_timeout / 1000);
6881		}
6882	}
6883
6884	if (dt == CC_DT_SCSI) {
6885		byte2 = action;
6886		if (ause != 0)
6887			byte2 |= SSZ_UNRESTRICTED_EXIT;
6888		if (immediate != 0)
6889			byte2 |= SSZ_IMMED;
6890		scsi_sanitize(&ccb->csio,
6891			      /* retries */ retry_count,
6892			      /* cbfcnp */ NULL,
6893			      /* tag_action */ task_attr,
6894			      /* byte2 */ byte2,
6895			      /* control */ 0,
6896			      /* data_ptr */ data_ptr,
6897			      /* dxfer_len */ dxfer_len,
6898			      /* sense_len */ SSD_FULL_SIZE,
6899			      /* timeout */ use_timeout);
6900
6901		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6902		if (arglist & CAM_ARG_ERR_RECOVER)
6903			ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6904		if (cam_send_ccb(device, ccb) < 0) {
6905			warn("error sending sanitize command");
6906			error = 1;
6907			goto sanitize_bailout;
6908		}
6909	} else if (dt == CC_DT_ATA || dt == CC_DT_SATL) {
6910		if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
6911			feature = 0x14; /* OVERWRITE EXT */
6912			lba = 0x4F5700000000 | scsi_4btoul(data_ptr + 4);
6913			count = (passes == 0) ? 1 : (passes >= 16) ? 0 : passes;
6914			if (invert)
6915				count |= 0x80; /* INVERT PATTERN */
6916			if (ause)
6917				count |= 0x10; /* FAILURE MODE */
6918		} else if (action == SSZ_SERVICE_ACTION_BLOCK_ERASE) {
6919			feature = 0x12; /* BLOCK ERASE EXT */
6920			lba = 0x0000426B4572;
6921			count = 0;
6922			if (ause)
6923				count |= 0x10; /* FAILURE MODE */
6924		} else if (action == SSZ_SERVICE_ACTION_CRYPTO_ERASE) {
6925			feature = 0x11; /* CRYPTO SCRAMBLE EXT */
6926			lba = 0x000043727970;
6927			count = 0;
6928			if (ause)
6929				count |= 0x10; /* FAILURE MODE */
6930		} else if (action == SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE) {
6931			feature = 0x00; /* SANITIZE STATUS EXT */
6932			lba = 0;
6933			count = 1; /* CLEAR SANITIZE OPERATION FAILED */
6934		} else {
6935			error = 1;
6936			goto sanitize_bailout;
6937		}
6938
6939		error = ata_do_cmd(device,
6940				   ccb,
6941				   retry_count,
6942				   /*flags*/CAM_DIR_NONE,
6943				   /*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
6944				   /*ata_flags*/0,
6945				   /*tag_action*/MSG_SIMPLE_Q_TAG,
6946				   /*command*/ATA_SANITIZE,
6947				   /*features*/feature,
6948				   /*lba*/lba,
6949				   /*sector_count*/count,
6950				   /*data_ptr*/NULL,
6951				   /*dxfer_len*/0,
6952				   /*timeout*/ use_timeout,
6953				   /*is48bit*/1);
6954	}
6955
6956	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6957		struct scsi_sense_data *sense;
6958		int error_code, sense_key, asc, ascq;
6959
6960		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
6961		    CAM_SCSI_STATUS_ERROR) {
6962			sense = &ccb->csio.sense_data;
6963			scsi_extract_sense_len(sense, ccb->csio.sense_len -
6964			    ccb->csio.sense_resid, &error_code, &sense_key,
6965			    &asc, &ascq, /*show_errors*/ 1);
6966
6967			if (sense_key == SSD_KEY_ILLEGAL_REQUEST &&
6968			    asc == 0x20 && ascq == 0x00)
6969				warnx("sanitize is not supported by "
6970				      "this device");
6971			else
6972				warnx("error sanitizing this device");
6973		} else
6974			warnx("error sanitizing this device");
6975
6976		if (arglist & CAM_ARG_VERBOSE) {
6977			cam_error_print(device, ccb, CAM_ESF_ALL,
6978					CAM_EPF_ALL, stderr);
6979		}
6980		error = 1;
6981		goto sanitize_bailout;
6982	}
6983
6984	/*
6985	 * If we ran in non-immediate mode, we already checked for errors
6986	 * above and printed out any necessary information.  If we're in
6987	 * immediate mode, we need to loop through and get status
6988	 * information periodically.
6989	 */
6990	if (immediate == 0) {
6991		if (quiet == 0) {
6992			fprintf(stdout, "Sanitize Complete\n");
6993		}
6994		goto sanitize_bailout;
6995	}
6996
6997doreport:
6998	if (dt == CC_DT_SCSI) {
6999		error = sanitize_wait_scsi(device, ccb, task_attr, quiet);
7000	} else if (dt == CC_DT_ATA || dt == CC_DT_SATL) {
7001		error = sanitize_wait_ata(device, ccb, quiet, dt);
7002	} else
7003		error = 1;
7004	if (error == 0 && quiet == 0)
7005		fprintf(stdout, "Sanitize Complete                      \n");
7006
7007sanitize_bailout:
7008	if (fd >= 0)
7009		close(fd);
7010	if (data_ptr != NULL)
7011		free(data_ptr);
7012	cam_freeccb(ccb);
7013
7014	return (error);
7015}
7016
7017static int
7018scsireportluns(struct cam_device *device, int argc, char **argv,
7019	       char *combinedopt, int task_attr, int retry_count, int timeout)
7020{
7021	union ccb *ccb;
7022	int c, countonly, lunsonly;
7023	struct scsi_report_luns_data *lundata;
7024	int alloc_len;
7025	uint8_t report_type;
7026	uint32_t list_len, i, j;
7027	int retval;
7028
7029	retval = 0;
7030	lundata = NULL;
7031	report_type = RPL_REPORT_DEFAULT;
7032	ccb = cam_getccb(device);
7033
7034	if (ccb == NULL) {
7035		warnx("%s: error allocating ccb", __func__);
7036		return (1);
7037	}
7038
7039	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
7040
7041	countonly = 0;
7042	lunsonly = 0;
7043
7044	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7045		switch (c) {
7046		case 'c':
7047			countonly++;
7048			break;
7049		case 'l':
7050			lunsonly++;
7051			break;
7052		case 'r':
7053			if (strcasecmp(optarg, "default") == 0)
7054				report_type = RPL_REPORT_DEFAULT;
7055			else if (strcasecmp(optarg, "wellknown") == 0)
7056				report_type = RPL_REPORT_WELLKNOWN;
7057			else if (strcasecmp(optarg, "all") == 0)
7058				report_type = RPL_REPORT_ALL;
7059			else {
7060				warnx("%s: invalid report type \"%s\"",
7061				      __func__, optarg);
7062				retval = 1;
7063				goto bailout;
7064			}
7065			break;
7066		default:
7067			break;
7068		}
7069	}
7070
7071	if ((countonly != 0)
7072	 && (lunsonly != 0)) {
7073		warnx("%s: you can only specify one of -c or -l", __func__);
7074		retval = 1;
7075		goto bailout;
7076	}
7077	/*
7078	 * According to SPC-4, the allocation length must be at least 16
7079	 * bytes -- enough for the header and one LUN.
7080	 */
7081	alloc_len = sizeof(*lundata) + 8;
7082
7083retry:
7084
7085	lundata = malloc(alloc_len);
7086
7087	if (lundata == NULL) {
7088		warn("%s: error mallocing %d bytes", __func__, alloc_len);
7089		retval = 1;
7090		goto bailout;
7091	}
7092
7093	scsi_report_luns(&ccb->csio,
7094			 /*retries*/ retry_count,
7095			 /*cbfcnp*/ NULL,
7096			 /*tag_action*/ task_attr,
7097			 /*select_report*/ report_type,
7098			 /*rpl_buf*/ lundata,
7099			 /*alloc_len*/ alloc_len,
7100			 /*sense_len*/ SSD_FULL_SIZE,
7101			 /*timeout*/ timeout ? timeout : 5000);
7102
7103	/* Disable freezing the device queue */
7104	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7105
7106	if (arglist & CAM_ARG_ERR_RECOVER)
7107		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7108
7109	if (cam_send_ccb(device, ccb) < 0) {
7110		warn("error sending REPORT LUNS command");
7111		retval = 1;
7112		goto bailout;
7113	}
7114
7115	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7116		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7117		retval = 1;
7118		goto bailout;
7119	}
7120
7121
7122	list_len = scsi_4btoul(lundata->length);
7123
7124	/*
7125	 * If we need to list the LUNs, and our allocation
7126	 * length was too short, reallocate and retry.
7127	 */
7128	if ((countonly == 0)
7129	 && (list_len > (alloc_len - sizeof(*lundata)))) {
7130		alloc_len = list_len + sizeof(*lundata);
7131		free(lundata);
7132		goto retry;
7133	}
7134
7135	if (lunsonly == 0)
7136		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
7137			((list_len / 8) > 1) ? "s" : "");
7138
7139	if (countonly != 0)
7140		goto bailout;
7141
7142	for (i = 0; i < (list_len / 8); i++) {
7143		int no_more;
7144
7145		no_more = 0;
7146		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
7147			if (j != 0)
7148				fprintf(stdout, ",");
7149			switch (lundata->luns[i].lundata[j] &
7150				RPL_LUNDATA_ATYP_MASK) {
7151			case RPL_LUNDATA_ATYP_PERIPH:
7152				if ((lundata->luns[i].lundata[j] &
7153				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
7154					fprintf(stdout, "%d:",
7155						lundata->luns[i].lundata[j] &
7156						RPL_LUNDATA_PERIPH_BUS_MASK);
7157				else if ((j == 0)
7158				      && ((lundata->luns[i].lundata[j+2] &
7159					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
7160					no_more = 1;
7161
7162				fprintf(stdout, "%d",
7163					lundata->luns[i].lundata[j+1]);
7164				break;
7165			case RPL_LUNDATA_ATYP_FLAT: {
7166				uint8_t tmplun[2];
7167				tmplun[0] = lundata->luns[i].lundata[j] &
7168					RPL_LUNDATA_FLAT_LUN_MASK;
7169				tmplun[1] = lundata->luns[i].lundata[j+1];
7170
7171				fprintf(stdout, "%d", scsi_2btoul(tmplun));
7172				no_more = 1;
7173				break;
7174			}
7175			case RPL_LUNDATA_ATYP_LUN:
7176				fprintf(stdout, "%d:%d:%d",
7177					(lundata->luns[i].lundata[j+1] &
7178					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
7179					lundata->luns[i].lundata[j] &
7180					RPL_LUNDATA_LUN_TARG_MASK,
7181					lundata->luns[i].lundata[j+1] &
7182					RPL_LUNDATA_LUN_LUN_MASK);
7183				break;
7184			case RPL_LUNDATA_ATYP_EXTLUN: {
7185				int field_len_code, eam_code;
7186
7187				eam_code = lundata->luns[i].lundata[j] &
7188					RPL_LUNDATA_EXT_EAM_MASK;
7189				field_len_code = (lundata->luns[i].lundata[j] &
7190					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
7191
7192				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
7193				 && (field_len_code == 0x00)) {
7194					fprintf(stdout, "%d",
7195						lundata->luns[i].lundata[j+1]);
7196				} else if ((eam_code ==
7197					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
7198					&& (field_len_code == 0x03)) {
7199					uint8_t tmp_lun[8];
7200
7201					/*
7202					 * This format takes up all 8 bytes.
7203					 * If we aren't starting at offset 0,
7204					 * that's a bug.
7205					 */
7206					if (j != 0) {
7207						fprintf(stdout, "Invalid "
7208							"offset %d for "
7209							"Extended LUN not "
7210							"specified format", j);
7211						no_more = 1;
7212						break;
7213					}
7214					bzero(tmp_lun, sizeof(tmp_lun));
7215					bcopy(&lundata->luns[i].lundata[j+1],
7216					      &tmp_lun[1], sizeof(tmp_lun) - 1);
7217					fprintf(stdout, "%#jx",
7218					       (intmax_t)scsi_8btou64(tmp_lun));
7219					no_more = 1;
7220				} else {
7221					fprintf(stderr, "Unknown Extended LUN"
7222						"Address method %#x, length "
7223						"code %#x", eam_code,
7224						field_len_code);
7225					no_more = 1;
7226				}
7227				break;
7228			}
7229			default:
7230				fprintf(stderr, "Unknown LUN address method "
7231					"%#x\n", lundata->luns[i].lundata[0] &
7232					RPL_LUNDATA_ATYP_MASK);
7233				break;
7234			}
7235			/*
7236			 * For the flat addressing method, there are no
7237			 * other levels after it.
7238			 */
7239			if (no_more != 0)
7240				break;
7241		}
7242		fprintf(stdout, "\n");
7243	}
7244
7245bailout:
7246
7247	cam_freeccb(ccb);
7248
7249	free(lundata);
7250
7251	return (retval);
7252}
7253
7254static int
7255scsireadcapacity(struct cam_device *device, int argc, char **argv,
7256		 char *combinedopt, int task_attr, int retry_count, int timeout)
7257{
7258	union ccb *ccb;
7259	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten, longonly;
7260	struct scsi_read_capacity_data rcap;
7261	struct scsi_read_capacity_data_long rcaplong;
7262	uint64_t maxsector;
7263	uint32_t block_len;
7264	int retval;
7265	int c;
7266
7267	blocksizeonly = 0;
7268	humanize = 0;
7269	longonly = 0;
7270	numblocks = 0;
7271	quiet = 0;
7272	sizeonly = 0;
7273	baseten = 0;
7274	retval = 0;
7275
7276	ccb = cam_getccb(device);
7277
7278	if (ccb == NULL) {
7279		warnx("%s: error allocating ccb", __func__);
7280		return (1);
7281	}
7282
7283	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
7284
7285	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7286		switch (c) {
7287		case 'b':
7288			blocksizeonly++;
7289			break;
7290		case 'h':
7291			humanize++;
7292			baseten = 0;
7293			break;
7294		case 'H':
7295			humanize++;
7296			baseten++;
7297			break;
7298		case 'l':
7299			longonly++;
7300			break;
7301		case 'N':
7302			numblocks++;
7303			break;
7304		case 'q':
7305			quiet++;
7306			break;
7307		case 's':
7308			sizeonly++;
7309			break;
7310		default:
7311			break;
7312		}
7313	}
7314
7315	if ((blocksizeonly != 0)
7316	 && (numblocks != 0)) {
7317		warnx("%s: you can only specify one of -b or -N", __func__);
7318		retval = 1;
7319		goto bailout;
7320	}
7321
7322	if ((blocksizeonly != 0)
7323	 && (sizeonly != 0)) {
7324		warnx("%s: you can only specify one of -b or -s", __func__);
7325		retval = 1;
7326		goto bailout;
7327	}
7328
7329	if ((humanize != 0)
7330	 && (quiet != 0)) {
7331		warnx("%s: you can only specify one of -h/-H or -q", __func__);
7332		retval = 1;
7333		goto bailout;
7334	}
7335
7336	if ((humanize != 0)
7337	 && (blocksizeonly != 0)) {
7338		warnx("%s: you can only specify one of -h/-H or -b", __func__);
7339		retval = 1;
7340		goto bailout;
7341	}
7342
7343	if (longonly != 0)
7344		goto long_only;
7345
7346	scsi_read_capacity(&ccb->csio,
7347			   /*retries*/ retry_count,
7348			   /*cbfcnp*/ NULL,
7349			   /*tag_action*/ task_attr,
7350			   &rcap,
7351			   SSD_FULL_SIZE,
7352			   /*timeout*/ timeout ? timeout : 5000);
7353
7354	/* Disable freezing the device queue */
7355	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7356
7357	if (arglist & CAM_ARG_ERR_RECOVER)
7358		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7359
7360	if (cam_send_ccb(device, ccb) < 0) {
7361		warn("error sending READ CAPACITY command");
7362		retval = 1;
7363		goto bailout;
7364	}
7365
7366	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7367		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7368		retval = 1;
7369		goto bailout;
7370	}
7371
7372	maxsector = scsi_4btoul(rcap.addr);
7373	block_len = scsi_4btoul(rcap.length);
7374
7375	/*
7376	 * A last block of 2^32-1 means that the true capacity is over 2TB,
7377	 * and we need to issue the long READ CAPACITY to get the real
7378	 * capacity.  Otherwise, we're all set.
7379	 */
7380	if (maxsector != 0xffffffff)
7381		goto do_print;
7382
7383long_only:
7384	scsi_read_capacity_16(&ccb->csio,
7385			      /*retries*/ retry_count,
7386			      /*cbfcnp*/ NULL,
7387			      /*tag_action*/ task_attr,
7388			      /*lba*/ 0,
7389			      /*reladdr*/ 0,
7390			      /*pmi*/ 0,
7391			      /*rcap_buf*/ (uint8_t *)&rcaplong,
7392			      /*rcap_buf_len*/ sizeof(rcaplong),
7393			      /*sense_len*/ SSD_FULL_SIZE,
7394			      /*timeout*/ timeout ? timeout : 5000);
7395
7396	/* Disable freezing the device queue */
7397	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7398
7399	if (arglist & CAM_ARG_ERR_RECOVER)
7400		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7401
7402	if (cam_send_ccb(device, ccb) < 0) {
7403		warn("error sending READ CAPACITY (16) command");
7404		retval = 1;
7405		goto bailout;
7406	}
7407
7408	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7409		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7410		retval = 1;
7411		goto bailout;
7412	}
7413
7414	maxsector = scsi_8btou64(rcaplong.addr);
7415	block_len = scsi_4btoul(rcaplong.length);
7416
7417do_print:
7418	if (blocksizeonly == 0) {
7419		/*
7420		 * Humanize implies !quiet, and also implies numblocks.
7421		 */
7422		if (humanize != 0) {
7423			char tmpstr[6];
7424			int64_t tmpbytes;
7425			int ret;
7426
7427			tmpbytes = (maxsector + 1) * block_len;
7428			ret = humanize_number(tmpstr, sizeof(tmpstr),
7429					      tmpbytes, "", HN_AUTOSCALE,
7430					      HN_B | HN_DECIMAL |
7431					      ((baseten != 0) ?
7432					      HN_DIVISOR_1000 : 0));
7433			if (ret == -1) {
7434				warnx("%s: humanize_number failed!", __func__);
7435				retval = 1;
7436				goto bailout;
7437			}
7438			fprintf(stdout, "Device Size: %s%s", tmpstr,
7439				(sizeonly == 0) ?  ", " : "\n");
7440		} else if (numblocks != 0) {
7441			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7442				"Blocks: " : "", (uintmax_t)maxsector + 1,
7443				(sizeonly == 0) ? ", " : "\n");
7444		} else {
7445			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
7446				"Last Block: " : "", (uintmax_t)maxsector,
7447				(sizeonly == 0) ? ", " : "\n");
7448		}
7449	}
7450	if (sizeonly == 0)
7451		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
7452			"Block Length: " : "", block_len, (quiet == 0) ?
7453			" bytes" : "");
7454bailout:
7455	cam_freeccb(ccb);
7456
7457	return (retval);
7458}
7459
7460static int
7461smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
7462       int retry_count, int timeout)
7463{
7464	int c, error = 0;
7465	union ccb *ccb;
7466	uint8_t *smp_request = NULL, *smp_response = NULL;
7467	int request_size = 0, response_size = 0;
7468	int fd_request = 0, fd_response = 0;
7469	char *datastr = NULL;
7470	struct get_hook hook;
7471	int retval;
7472	int flags = 0;
7473
7474	/*
7475	 * Note that at the moment we don't support sending SMP CCBs to
7476	 * devices that aren't probed by CAM.
7477	 */
7478	ccb = cam_getccb(device);
7479	if (ccb == NULL) {
7480		warnx("%s: error allocating CCB", __func__);
7481		return (1);
7482	}
7483
7484	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7485
7486	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7487		switch (c) {
7488		case 'R':
7489			arglist |= CAM_ARG_CMD_IN;
7490			response_size = strtol(optarg, NULL, 0);
7491			if (response_size <= 0) {
7492				warnx("invalid number of response bytes %d",
7493				      response_size);
7494				error = 1;
7495				goto smpcmd_bailout;
7496			}
7497			hook.argc = argc - optind;
7498			hook.argv = argv + optind;
7499			hook.got = 0;
7500			optind++;
7501			datastr = cget(&hook, NULL);
7502			/*
7503			 * If the user supplied "-" instead of a format, he
7504			 * wants the data to be written to stdout.
7505			 */
7506			if ((datastr != NULL)
7507			 && (datastr[0] == '-'))
7508				fd_response = 1;
7509
7510			smp_response = (u_int8_t *)malloc(response_size);
7511			if (smp_response == NULL) {
7512				warn("can't malloc memory for SMP response");
7513				error = 1;
7514				goto smpcmd_bailout;
7515			}
7516			break;
7517		case 'r':
7518			arglist |= CAM_ARG_CMD_OUT;
7519			request_size = strtol(optarg, NULL, 0);
7520			if (request_size <= 0) {
7521				warnx("invalid number of request bytes %d",
7522				      request_size);
7523				error = 1;
7524				goto smpcmd_bailout;
7525			}
7526			hook.argc = argc - optind;
7527			hook.argv = argv + optind;
7528			hook.got = 0;
7529			datastr = cget(&hook, NULL);
7530			smp_request = (u_int8_t *)malloc(request_size);
7531			if (smp_request == NULL) {
7532				warn("can't malloc memory for SMP request");
7533				error = 1;
7534				goto smpcmd_bailout;
7535			}
7536			bzero(smp_request, request_size);
7537			/*
7538			 * If the user supplied "-" instead of a format, he
7539			 * wants the data to be read from stdin.
7540			 */
7541			if ((datastr != NULL)
7542			 && (datastr[0] == '-'))
7543				fd_request = 1;
7544			else
7545				buff_encode_visit(smp_request, request_size,
7546						  datastr,
7547						  iget, &hook);
7548			optind += hook.got;
7549			break;
7550		default:
7551			break;
7552		}
7553	}
7554
7555	/*
7556	 * If fd_data is set, and we're writing to the device, we need to
7557	 * read the data the user wants written from stdin.
7558	 */
7559	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
7560		ssize_t amt_read;
7561		int amt_to_read = request_size;
7562		u_int8_t *buf_ptr = smp_request;
7563
7564		for (amt_read = 0; amt_to_read > 0;
7565		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
7566			if (amt_read == -1) {
7567				warn("error reading data from stdin");
7568				error = 1;
7569				goto smpcmd_bailout;
7570			}
7571			amt_to_read -= amt_read;
7572			buf_ptr += amt_read;
7573		}
7574	}
7575
7576	if (((arglist & CAM_ARG_CMD_IN) == 0)
7577	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
7578		warnx("%s: need both the request (-r) and response (-R) "
7579		      "arguments", __func__);
7580		error = 1;
7581		goto smpcmd_bailout;
7582	}
7583
7584	flags |= CAM_DEV_QFRZDIS;
7585
7586	cam_fill_smpio(&ccb->smpio,
7587		       /*retries*/ retry_count,
7588		       /*cbfcnp*/ NULL,
7589		       /*flags*/ flags,
7590		       /*smp_request*/ smp_request,
7591		       /*smp_request_len*/ request_size,
7592		       /*smp_response*/ smp_response,
7593		       /*smp_response_len*/ response_size,
7594		       /*timeout*/ timeout ? timeout : 5000);
7595
7596	ccb->smpio.flags = SMP_FLAG_NONE;
7597
7598	if (((retval = cam_send_ccb(device, ccb)) < 0)
7599	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7600		const char warnstr[] = "error sending command";
7601
7602		if (retval < 0)
7603			warn(warnstr);
7604		else
7605			warnx(warnstr);
7606
7607		if (arglist & CAM_ARG_VERBOSE) {
7608			cam_error_print(device, ccb, CAM_ESF_ALL,
7609					CAM_EPF_ALL, stderr);
7610		}
7611	}
7612
7613	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
7614	 && (response_size > 0)) {
7615		if (fd_response == 0) {
7616			buff_decode_visit(smp_response, response_size,
7617					  datastr, arg_put, NULL);
7618			fprintf(stdout, "\n");
7619		} else {
7620			ssize_t amt_written;
7621			int amt_to_write = response_size;
7622			u_int8_t *buf_ptr = smp_response;
7623
7624			for (amt_written = 0; (amt_to_write > 0) &&
7625			     (amt_written = write(STDOUT_FILENO, buf_ptr,
7626						  amt_to_write)) > 0;){
7627				amt_to_write -= amt_written;
7628				buf_ptr += amt_written;
7629			}
7630			if (amt_written == -1) {
7631				warn("error writing data to stdout");
7632				error = 1;
7633				goto smpcmd_bailout;
7634			} else if ((amt_written == 0)
7635				&& (amt_to_write > 0)) {
7636				warnx("only wrote %u bytes out of %u",
7637				      response_size - amt_to_write,
7638				      response_size);
7639			}
7640		}
7641	}
7642smpcmd_bailout:
7643	if (ccb != NULL)
7644		cam_freeccb(ccb);
7645
7646	if (smp_request != NULL)
7647		free(smp_request);
7648
7649	if (smp_response != NULL)
7650		free(smp_response);
7651
7652	return (error);
7653}
7654
7655static int
7656smpreportgeneral(struct cam_device *device, int argc, char **argv,
7657		 char *combinedopt, int retry_count, int timeout)
7658{
7659	union ccb *ccb;
7660	struct smp_report_general_request *request = NULL;
7661	struct smp_report_general_response *response = NULL;
7662	struct sbuf *sb = NULL;
7663	int error = 0;
7664	int c, long_response = 0;
7665	int retval;
7666
7667	/*
7668	 * Note that at the moment we don't support sending SMP CCBs to
7669	 * devices that aren't probed by CAM.
7670	 */
7671	ccb = cam_getccb(device);
7672	if (ccb == NULL) {
7673		warnx("%s: error allocating CCB", __func__);
7674		return (1);
7675	}
7676
7677	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7678
7679	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7680		switch (c) {
7681		case 'l':
7682			long_response = 1;
7683			break;
7684		default:
7685			break;
7686		}
7687	}
7688	request = malloc(sizeof(*request));
7689	if (request == NULL) {
7690		warn("%s: unable to allocate %zd bytes", __func__,
7691		     sizeof(*request));
7692		error = 1;
7693		goto bailout;
7694	}
7695
7696	response = malloc(sizeof(*response));
7697	if (response == NULL) {
7698		warn("%s: unable to allocate %zd bytes", __func__,
7699		     sizeof(*response));
7700		error = 1;
7701		goto bailout;
7702	}
7703
7704try_long:
7705	smp_report_general(&ccb->smpio,
7706			   retry_count,
7707			   /*cbfcnp*/ NULL,
7708			   request,
7709			   /*request_len*/ sizeof(*request),
7710			   (uint8_t *)response,
7711			   /*response_len*/ sizeof(*response),
7712			   /*long_response*/ long_response,
7713			   timeout);
7714
7715	if (((retval = cam_send_ccb(device, ccb)) < 0)
7716	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7717		const char warnstr[] = "error sending command";
7718
7719		if (retval < 0)
7720			warn(warnstr);
7721		else
7722			warnx(warnstr);
7723
7724		if (arglist & CAM_ARG_VERBOSE) {
7725			cam_error_print(device, ccb, CAM_ESF_ALL,
7726					CAM_EPF_ALL, stderr);
7727		}
7728		error = 1;
7729		goto bailout;
7730	}
7731
7732	/*
7733	 * If the device supports the long response bit, try again and see
7734	 * if we can get all of the data.
7735	 */
7736	if ((response->long_response & SMP_RG_LONG_RESPONSE)
7737	 && (long_response == 0)) {
7738		ccb->ccb_h.status = CAM_REQ_INPROG;
7739		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7740		long_response = 1;
7741		goto try_long;
7742	}
7743
7744	/*
7745	 * XXX KDM detect and decode SMP errors here.
7746	 */
7747	sb = sbuf_new_auto();
7748	if (sb == NULL) {
7749		warnx("%s: error allocating sbuf", __func__);
7750		goto bailout;
7751	}
7752
7753	smp_report_general_sbuf(response, sizeof(*response), sb);
7754
7755	if (sbuf_finish(sb) != 0) {
7756		warnx("%s: sbuf_finish", __func__);
7757		goto bailout;
7758	}
7759
7760	printf("%s", sbuf_data(sb));
7761
7762bailout:
7763	if (ccb != NULL)
7764		cam_freeccb(ccb);
7765
7766	if (request != NULL)
7767		free(request);
7768
7769	if (response != NULL)
7770		free(response);
7771
7772	if (sb != NULL)
7773		sbuf_delete(sb);
7774
7775	return (error);
7776}
7777
7778static struct camcontrol_opts phy_ops[] = {
7779	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
7780	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
7781	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
7782	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
7783	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
7784	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
7785	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
7786	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
7787	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
7788	{NULL, 0, 0, NULL}
7789};
7790
7791static int
7792smpphycontrol(struct cam_device *device, int argc, char **argv,
7793	      char *combinedopt, int retry_count, int timeout)
7794{
7795	union ccb *ccb;
7796	struct smp_phy_control_request *request = NULL;
7797	struct smp_phy_control_response *response = NULL;
7798	int long_response = 0;
7799	int retval = 0;
7800	int phy = -1;
7801	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
7802	int phy_op_set = 0;
7803	uint64_t attached_dev_name = 0;
7804	int dev_name_set = 0;
7805	uint32_t min_plr = 0, max_plr = 0;
7806	uint32_t pp_timeout_val = 0;
7807	int slumber_partial = 0;
7808	int set_pp_timeout_val = 0;
7809	int c;
7810
7811	/*
7812	 * Note that at the moment we don't support sending SMP CCBs to
7813	 * devices that aren't probed by CAM.
7814	 */
7815	ccb = cam_getccb(device);
7816	if (ccb == NULL) {
7817		warnx("%s: error allocating CCB", __func__);
7818		return (1);
7819	}
7820
7821	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
7822
7823	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7824		switch (c) {
7825		case 'a':
7826		case 'A':
7827		case 's':
7828		case 'S': {
7829			int enable = -1;
7830
7831			if (strcasecmp(optarg, "enable") == 0)
7832				enable = 1;
7833			else if (strcasecmp(optarg, "disable") == 0)
7834				enable = 2;
7835			else {
7836				warnx("%s: Invalid argument %s", __func__,
7837				      optarg);
7838				retval = 1;
7839				goto bailout;
7840			}
7841			switch (c) {
7842			case 's':
7843				slumber_partial |= enable <<
7844						   SMP_PC_SAS_SLUMBER_SHIFT;
7845				break;
7846			case 'S':
7847				slumber_partial |= enable <<
7848						   SMP_PC_SAS_PARTIAL_SHIFT;
7849				break;
7850			case 'a':
7851				slumber_partial |= enable <<
7852						   SMP_PC_SATA_SLUMBER_SHIFT;
7853				break;
7854			case 'A':
7855				slumber_partial |= enable <<
7856						   SMP_PC_SATA_PARTIAL_SHIFT;
7857				break;
7858			default:
7859				warnx("%s: programmer error", __func__);
7860				retval = 1;
7861				goto bailout;
7862				break; /*NOTREACHED*/
7863			}
7864			break;
7865		}
7866		case 'd':
7867			attached_dev_name = (uintmax_t)strtoumax(optarg,
7868								 NULL,0);
7869			dev_name_set = 1;
7870			break;
7871		case 'l':
7872			long_response = 1;
7873			break;
7874		case 'm':
7875			/*
7876			 * We don't do extensive checking here, so this
7877			 * will continue to work when new speeds come out.
7878			 */
7879			min_plr = strtoul(optarg, NULL, 0);
7880			if ((min_plr == 0)
7881			 || (min_plr > 0xf)) {
7882				warnx("%s: invalid link rate %x",
7883				      __func__, min_plr);
7884				retval = 1;
7885				goto bailout;
7886			}
7887			break;
7888		case 'M':
7889			/*
7890			 * We don't do extensive checking here, so this
7891			 * will continue to work when new speeds come out.
7892			 */
7893			max_plr = strtoul(optarg, NULL, 0);
7894			if ((max_plr == 0)
7895			 || (max_plr > 0xf)) {
7896				warnx("%s: invalid link rate %x",
7897				      __func__, max_plr);
7898				retval = 1;
7899				goto bailout;
7900			}
7901			break;
7902		case 'o': {
7903			camcontrol_optret optreturn;
7904			cam_argmask argnums;
7905			const char *subopt;
7906
7907			if (phy_op_set != 0) {
7908				warnx("%s: only one phy operation argument "
7909				      "(-o) allowed", __func__);
7910				retval = 1;
7911				goto bailout;
7912			}
7913
7914			phy_op_set = 1;
7915
7916			/*
7917			 * Allow the user to specify the phy operation
7918			 * numerically, as well as with a name.  This will
7919			 * future-proof it a bit, so options that are added
7920			 * in future specs can be used.
7921			 */
7922			if (isdigit(optarg[0])) {
7923				phy_operation = strtoul(optarg, NULL, 0);
7924				if ((phy_operation == 0)
7925				 || (phy_operation > 0xff)) {
7926					warnx("%s: invalid phy operation %#x",
7927					      __func__, phy_operation);
7928					retval = 1;
7929					goto bailout;
7930				}
7931				break;
7932			}
7933			optreturn = getoption(phy_ops, optarg, &phy_operation,
7934					      &argnums, &subopt);
7935
7936			if (optreturn == CC_OR_AMBIGUOUS) {
7937				warnx("%s: ambiguous option %s", __func__,
7938				      optarg);
7939				usage(0);
7940				retval = 1;
7941				goto bailout;
7942			} else if (optreturn == CC_OR_NOT_FOUND) {
7943				warnx("%s: option %s not found", __func__,
7944				      optarg);
7945				usage(0);
7946				retval = 1;
7947				goto bailout;
7948			}
7949			break;
7950		}
7951		case 'p':
7952			phy = atoi(optarg);
7953			break;
7954		case 'T':
7955			pp_timeout_val = strtoul(optarg, NULL, 0);
7956			if (pp_timeout_val > 15) {
7957				warnx("%s: invalid partial pathway timeout "
7958				      "value %u, need a value less than 16",
7959				      __func__, pp_timeout_val);
7960				retval = 1;
7961				goto bailout;
7962			}
7963			set_pp_timeout_val = 1;
7964			break;
7965		default:
7966			break;
7967		}
7968	}
7969
7970	if (phy == -1) {
7971		warnx("%s: a PHY (-p phy) argument is required",__func__);
7972		retval = 1;
7973		goto bailout;
7974	}
7975
7976	if (((dev_name_set != 0)
7977	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
7978	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
7979	  && (dev_name_set == 0))) {
7980		warnx("%s: -d name and -o setdevname arguments both "
7981		      "required to set device name", __func__);
7982		retval = 1;
7983		goto bailout;
7984	}
7985
7986	request = malloc(sizeof(*request));
7987	if (request == NULL) {
7988		warn("%s: unable to allocate %zd bytes", __func__,
7989		     sizeof(*request));
7990		retval = 1;
7991		goto bailout;
7992	}
7993
7994	response = malloc(sizeof(*response));
7995	if (response == NULL) {
7996		warn("%s: unable to allocate %zd bytes", __func__,
7997		     sizeof(*response));
7998		retval = 1;
7999		goto bailout;
8000	}
8001
8002	smp_phy_control(&ccb->smpio,
8003			retry_count,
8004			/*cbfcnp*/ NULL,
8005			request,
8006			sizeof(*request),
8007			(uint8_t *)response,
8008			sizeof(*response),
8009			long_response,
8010			/*expected_exp_change_count*/ 0,
8011			phy,
8012			phy_operation,
8013			(set_pp_timeout_val != 0) ? 1 : 0,
8014			attached_dev_name,
8015			min_plr,
8016			max_plr,
8017			slumber_partial,
8018			pp_timeout_val,
8019			timeout);
8020
8021	if (((retval = cam_send_ccb(device, ccb)) < 0)
8022	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8023		const char warnstr[] = "error sending command";
8024
8025		if (retval < 0)
8026			warn(warnstr);
8027		else
8028			warnx(warnstr);
8029
8030		if (arglist & CAM_ARG_VERBOSE) {
8031			/*
8032			 * Use CAM_EPF_NORMAL so we only get one line of
8033			 * SMP command decoding.
8034			 */
8035			cam_error_print(device, ccb, CAM_ESF_ALL,
8036					CAM_EPF_NORMAL, stderr);
8037		}
8038		retval = 1;
8039		goto bailout;
8040	}
8041
8042	/* XXX KDM print out something here for success? */
8043bailout:
8044	if (ccb != NULL)
8045		cam_freeccb(ccb);
8046
8047	if (request != NULL)
8048		free(request);
8049
8050	if (response != NULL)
8051		free(response);
8052
8053	return (retval);
8054}
8055
8056static int
8057smpmaninfo(struct cam_device *device, int argc, char **argv,
8058	   char *combinedopt, int retry_count, int timeout)
8059{
8060	union ccb *ccb;
8061	struct smp_report_manuf_info_request request;
8062	struct smp_report_manuf_info_response response;
8063	struct sbuf *sb = NULL;
8064	int long_response = 0;
8065	int retval = 0;
8066	int c;
8067
8068	/*
8069	 * Note that at the moment we don't support sending SMP CCBs to
8070	 * devices that aren't probed by CAM.
8071	 */
8072	ccb = cam_getccb(device);
8073	if (ccb == NULL) {
8074		warnx("%s: error allocating CCB", __func__);
8075		return (1);
8076	}
8077
8078	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8079
8080	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8081		switch (c) {
8082		case 'l':
8083			long_response = 1;
8084			break;
8085		default:
8086			break;
8087		}
8088	}
8089	bzero(&request, sizeof(request));
8090	bzero(&response, sizeof(response));
8091
8092	smp_report_manuf_info(&ccb->smpio,
8093			      retry_count,
8094			      /*cbfcnp*/ NULL,
8095			      &request,
8096			      sizeof(request),
8097			      (uint8_t *)&response,
8098			      sizeof(response),
8099			      long_response,
8100			      timeout);
8101
8102	if (((retval = cam_send_ccb(device, ccb)) < 0)
8103	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8104		const char warnstr[] = "error sending command";
8105
8106		if (retval < 0)
8107			warn(warnstr);
8108		else
8109			warnx(warnstr);
8110
8111		if (arglist & CAM_ARG_VERBOSE) {
8112			cam_error_print(device, ccb, CAM_ESF_ALL,
8113					CAM_EPF_ALL, stderr);
8114		}
8115		retval = 1;
8116		goto bailout;
8117	}
8118
8119	sb = sbuf_new_auto();
8120	if (sb == NULL) {
8121		warnx("%s: error allocating sbuf", __func__);
8122		goto bailout;
8123	}
8124
8125	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
8126
8127	if (sbuf_finish(sb) != 0) {
8128		warnx("%s: sbuf_finish", __func__);
8129		goto bailout;
8130	}
8131
8132	printf("%s", sbuf_data(sb));
8133
8134bailout:
8135
8136	if (ccb != NULL)
8137		cam_freeccb(ccb);
8138
8139	if (sb != NULL)
8140		sbuf_delete(sb);
8141
8142	return (retval);
8143}
8144
8145static int
8146getdevid(struct cam_devitem *item)
8147{
8148	int retval = 0;
8149	union ccb *ccb = NULL;
8150
8151	struct cam_device *dev;
8152
8153	dev = cam_open_btl(item->dev_match.path_id,
8154			   item->dev_match.target_id,
8155			   item->dev_match.target_lun, O_RDWR, NULL);
8156
8157	if (dev == NULL) {
8158		warnx("%s", cam_errbuf);
8159		retval = 1;
8160		goto bailout;
8161	}
8162
8163	item->device_id_len = 0;
8164
8165	ccb = cam_getccb(dev);
8166	if (ccb == NULL) {
8167		warnx("%s: error allocating CCB", __func__);
8168		retval = 1;
8169		goto bailout;
8170	}
8171
8172	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
8173
8174	/*
8175	 * On the first try, we just probe for the size of the data, and
8176	 * then allocate that much memory and try again.
8177	 */
8178retry:
8179	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
8180	ccb->ccb_h.flags = CAM_DIR_IN;
8181	ccb->cdai.flags = CDAI_FLAG_NONE;
8182	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
8183	ccb->cdai.bufsiz = item->device_id_len;
8184	if (item->device_id_len != 0)
8185		ccb->cdai.buf = (uint8_t *)item->device_id;
8186
8187	if (cam_send_ccb(dev, ccb) < 0) {
8188		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
8189		retval = 1;
8190		goto bailout;
8191	}
8192
8193	if (ccb->ccb_h.status != CAM_REQ_CMP) {
8194		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
8195		retval = 1;
8196		goto bailout;
8197	}
8198
8199	if (item->device_id_len == 0) {
8200		/*
8201		 * This is our first time through.  Allocate the buffer,
8202		 * and then go back to get the data.
8203		 */
8204		if (ccb->cdai.provsiz == 0) {
8205			warnx("%s: invalid .provsiz field returned with "
8206			     "XPT_GDEV_ADVINFO CCB", __func__);
8207			retval = 1;
8208			goto bailout;
8209		}
8210		item->device_id_len = ccb->cdai.provsiz;
8211		item->device_id = malloc(item->device_id_len);
8212		if (item->device_id == NULL) {
8213			warn("%s: unable to allocate %d bytes", __func__,
8214			     item->device_id_len);
8215			retval = 1;
8216			goto bailout;
8217		}
8218		ccb->ccb_h.status = CAM_REQ_INPROG;
8219		goto retry;
8220	}
8221
8222bailout:
8223	if (dev != NULL)
8224		cam_close_device(dev);
8225
8226	if (ccb != NULL)
8227		cam_freeccb(ccb);
8228
8229	return (retval);
8230}
8231
8232/*
8233 * XXX KDM merge this code with getdevtree()?
8234 */
8235static int
8236buildbusdevlist(struct cam_devlist *devlist)
8237{
8238	union ccb ccb;
8239	int bufsize, fd = -1;
8240	struct dev_match_pattern *patterns;
8241	struct cam_devitem *item = NULL;
8242	int skip_device = 0;
8243	int retval = 0;
8244
8245	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
8246		warn("couldn't open %s", XPT_DEVICE);
8247		return (1);
8248	}
8249
8250	bzero(&ccb, sizeof(union ccb));
8251
8252	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
8253	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
8254	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
8255
8256	ccb.ccb_h.func_code = XPT_DEV_MATCH;
8257	bufsize = sizeof(struct dev_match_result) * 100;
8258	ccb.cdm.match_buf_len = bufsize;
8259	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
8260	if (ccb.cdm.matches == NULL) {
8261		warnx("can't malloc memory for matches");
8262		close(fd);
8263		return (1);
8264	}
8265	ccb.cdm.num_matches = 0;
8266	ccb.cdm.num_patterns = 2;
8267	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
8268		ccb.cdm.num_patterns;
8269
8270	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
8271	if (patterns == NULL) {
8272		warnx("can't malloc memory for patterns");
8273		retval = 1;
8274		goto bailout;
8275	}
8276
8277	ccb.cdm.patterns = patterns;
8278	bzero(patterns, ccb.cdm.pattern_buf_len);
8279
8280	patterns[0].type = DEV_MATCH_DEVICE;
8281	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
8282	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
8283	patterns[1].type = DEV_MATCH_PERIPH;
8284	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
8285	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
8286
8287	/*
8288	 * We do the ioctl multiple times if necessary, in case there are
8289	 * more than 100 nodes in the EDT.
8290	 */
8291	do {
8292		unsigned int i;
8293
8294		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
8295			warn("error sending CAMIOCOMMAND ioctl");
8296			retval = 1;
8297			goto bailout;
8298		}
8299
8300		if ((ccb.ccb_h.status != CAM_REQ_CMP)
8301		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
8302		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
8303			warnx("got CAM error %#x, CDM error %d\n",
8304			      ccb.ccb_h.status, ccb.cdm.status);
8305			retval = 1;
8306			goto bailout;
8307		}
8308
8309		for (i = 0; i < ccb.cdm.num_matches; i++) {
8310			switch (ccb.cdm.matches[i].type) {
8311			case DEV_MATCH_DEVICE: {
8312				struct device_match_result *dev_result;
8313
8314				dev_result =
8315				     &ccb.cdm.matches[i].result.device_result;
8316
8317				if (dev_result->flags &
8318				    DEV_RESULT_UNCONFIGURED) {
8319					skip_device = 1;
8320					break;
8321				} else
8322					skip_device = 0;
8323
8324				item = malloc(sizeof(*item));
8325				if (item == NULL) {
8326					warn("%s: unable to allocate %zd bytes",
8327					     __func__, sizeof(*item));
8328					retval = 1;
8329					goto bailout;
8330				}
8331				bzero(item, sizeof(*item));
8332				bcopy(dev_result, &item->dev_match,
8333				      sizeof(*dev_result));
8334				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
8335						   links);
8336
8337				if (getdevid(item) != 0) {
8338					retval = 1;
8339					goto bailout;
8340				}
8341				break;
8342			}
8343			case DEV_MATCH_PERIPH: {
8344				struct periph_match_result *periph_result;
8345
8346				periph_result =
8347				      &ccb.cdm.matches[i].result.periph_result;
8348
8349				if (skip_device != 0)
8350					break;
8351				item->num_periphs++;
8352				item->periph_matches = realloc(
8353					item->periph_matches,
8354					item->num_periphs *
8355					sizeof(struct periph_match_result));
8356				if (item->periph_matches == NULL) {
8357					warn("%s: error allocating periph "
8358					     "list", __func__);
8359					retval = 1;
8360					goto bailout;
8361				}
8362				bcopy(periph_result, &item->periph_matches[
8363				      item->num_periphs - 1],
8364				      sizeof(*periph_result));
8365				break;
8366			}
8367			default:
8368				fprintf(stderr, "%s: unexpected match "
8369					"type %d\n", __func__,
8370					ccb.cdm.matches[i].type);
8371				retval = 1;
8372				goto bailout;
8373				break; /*NOTREACHED*/
8374			}
8375		}
8376	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
8377		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
8378bailout:
8379
8380	if (fd != -1)
8381		close(fd);
8382
8383	free(patterns);
8384
8385	free(ccb.cdm.matches);
8386
8387	if (retval != 0)
8388		freebusdevlist(devlist);
8389
8390	return (retval);
8391}
8392
8393static void
8394freebusdevlist(struct cam_devlist *devlist)
8395{
8396	struct cam_devitem *item, *item2;
8397
8398	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
8399		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
8400			      links);
8401		free(item->device_id);
8402		free(item->periph_matches);
8403		free(item);
8404	}
8405}
8406
8407static struct cam_devitem *
8408findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
8409{
8410	struct cam_devitem *item;
8411
8412	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
8413		struct scsi_vpd_id_descriptor *idd;
8414
8415		/*
8416		 * XXX KDM look for LUN IDs as well?
8417		 */
8418		idd = scsi_get_devid(item->device_id,
8419					   item->device_id_len,
8420					   scsi_devid_is_sas_target);
8421		if (idd == NULL)
8422			continue;
8423
8424		if (scsi_8btou64(idd->identifier) == sasaddr)
8425			return (item);
8426	}
8427
8428	return (NULL);
8429}
8430
8431static int
8432smpphylist(struct cam_device *device, int argc, char **argv,
8433	   char *combinedopt, int retry_count, int timeout)
8434{
8435	struct smp_report_general_request *rgrequest = NULL;
8436	struct smp_report_general_response *rgresponse = NULL;
8437	struct smp_discover_request *disrequest = NULL;
8438	struct smp_discover_response *disresponse = NULL;
8439	struct cam_devlist devlist;
8440	union ccb *ccb;
8441	int long_response = 0;
8442	int num_phys = 0;
8443	int quiet = 0;
8444	int retval;
8445	int i, c;
8446
8447	/*
8448	 * Note that at the moment we don't support sending SMP CCBs to
8449	 * devices that aren't probed by CAM.
8450	 */
8451	ccb = cam_getccb(device);
8452	if (ccb == NULL) {
8453		warnx("%s: error allocating CCB", __func__);
8454		return (1);
8455	}
8456
8457	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8458	STAILQ_INIT(&devlist.dev_queue);
8459
8460	rgrequest = malloc(sizeof(*rgrequest));
8461	if (rgrequest == NULL) {
8462		warn("%s: unable to allocate %zd bytes", __func__,
8463		     sizeof(*rgrequest));
8464		retval = 1;
8465		goto bailout;
8466	}
8467
8468	rgresponse = malloc(sizeof(*rgresponse));
8469	if (rgresponse == NULL) {
8470		warn("%s: unable to allocate %zd bytes", __func__,
8471		     sizeof(*rgresponse));
8472		retval = 1;
8473		goto bailout;
8474	}
8475
8476	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8477		switch (c) {
8478		case 'l':
8479			long_response = 1;
8480			break;
8481		case 'q':
8482			quiet = 1;
8483			break;
8484		default:
8485			break;
8486		}
8487	}
8488
8489	smp_report_general(&ccb->smpio,
8490			   retry_count,
8491			   /*cbfcnp*/ NULL,
8492			   rgrequest,
8493			   /*request_len*/ sizeof(*rgrequest),
8494			   (uint8_t *)rgresponse,
8495			   /*response_len*/ sizeof(*rgresponse),
8496			   /*long_response*/ long_response,
8497			   timeout);
8498
8499	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8500
8501	if (((retval = cam_send_ccb(device, ccb)) < 0)
8502	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
8503		const char warnstr[] = "error sending command";
8504
8505		if (retval < 0)
8506			warn(warnstr);
8507		else
8508			warnx(warnstr);
8509
8510		if (arglist & CAM_ARG_VERBOSE) {
8511			cam_error_print(device, ccb, CAM_ESF_ALL,
8512					CAM_EPF_ALL, stderr);
8513		}
8514		retval = 1;
8515		goto bailout;
8516	}
8517
8518	num_phys = rgresponse->num_phys;
8519
8520	if (num_phys == 0) {
8521		if (quiet == 0)
8522			fprintf(stdout, "%s: No Phys reported\n", __func__);
8523		retval = 1;
8524		goto bailout;
8525	}
8526
8527	devlist.path_id = device->path_id;
8528
8529	retval = buildbusdevlist(&devlist);
8530	if (retval != 0)
8531		goto bailout;
8532
8533	if (quiet == 0) {
8534		fprintf(stdout, "%d PHYs:\n", num_phys);
8535		fprintf(stdout, "PHY  Attached SAS Address\n");
8536	}
8537
8538	disrequest = malloc(sizeof(*disrequest));
8539	if (disrequest == NULL) {
8540		warn("%s: unable to allocate %zd bytes", __func__,
8541		     sizeof(*disrequest));
8542		retval = 1;
8543		goto bailout;
8544	}
8545
8546	disresponse = malloc(sizeof(*disresponse));
8547	if (disresponse == NULL) {
8548		warn("%s: unable to allocate %zd bytes", __func__,
8549		     sizeof(*disresponse));
8550		retval = 1;
8551		goto bailout;
8552	}
8553
8554	for (i = 0; i < num_phys; i++) {
8555		struct cam_devitem *item;
8556		struct device_match_result *dev_match;
8557		char vendor[16], product[48], revision[16];
8558		char tmpstr[256];
8559		int j;
8560
8561		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->smpio);
8562
8563		ccb->ccb_h.status = CAM_REQ_INPROG;
8564		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8565
8566		smp_discover(&ccb->smpio,
8567			     retry_count,
8568			     /*cbfcnp*/ NULL,
8569			     disrequest,
8570			     sizeof(*disrequest),
8571			     (uint8_t *)disresponse,
8572			     sizeof(*disresponse),
8573			     long_response,
8574			     /*ignore_zone_group*/ 0,
8575			     /*phy*/ i,
8576			     timeout);
8577
8578		if (((retval = cam_send_ccb(device, ccb)) < 0)
8579		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
8580		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
8581			const char warnstr[] = "error sending command";
8582
8583			if (retval < 0)
8584				warn(warnstr);
8585			else
8586				warnx(warnstr);
8587
8588			if (arglist & CAM_ARG_VERBOSE) {
8589				cam_error_print(device, ccb, CAM_ESF_ALL,
8590						CAM_EPF_ALL, stderr);
8591			}
8592			retval = 1;
8593			goto bailout;
8594		}
8595
8596		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
8597			if (quiet == 0)
8598				fprintf(stdout, "%3d  <vacant>\n", i);
8599			continue;
8600		}
8601
8602		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
8603			item = NULL;
8604		} else {
8605			item = findsasdevice(&devlist,
8606			    scsi_8btou64(disresponse->attached_sas_address));
8607		}
8608
8609		if ((quiet == 0)
8610		 || (item != NULL)) {
8611			fprintf(stdout, "%3d  0x%016jx", i,
8612				(uintmax_t)scsi_8btou64(
8613				disresponse->attached_sas_address));
8614			if (item == NULL) {
8615				fprintf(stdout, "\n");
8616				continue;
8617			}
8618		} else if (quiet != 0)
8619			continue;
8620
8621		dev_match = &item->dev_match;
8622
8623		if (dev_match->protocol == PROTO_SCSI) {
8624			cam_strvis(vendor, dev_match->inq_data.vendor,
8625				   sizeof(dev_match->inq_data.vendor),
8626				   sizeof(vendor));
8627			cam_strvis(product, dev_match->inq_data.product,
8628				   sizeof(dev_match->inq_data.product),
8629				   sizeof(product));
8630			cam_strvis(revision, dev_match->inq_data.revision,
8631				   sizeof(dev_match->inq_data.revision),
8632				   sizeof(revision));
8633			sprintf(tmpstr, "<%s %s %s>", vendor, product,
8634				revision);
8635		} else if ((dev_match->protocol == PROTO_ATA)
8636			|| (dev_match->protocol == PROTO_SATAPM)) {
8637			cam_strvis(product, dev_match->ident_data.model,
8638				   sizeof(dev_match->ident_data.model),
8639				   sizeof(product));
8640			cam_strvis(revision, dev_match->ident_data.revision,
8641				   sizeof(dev_match->ident_data.revision),
8642				   sizeof(revision));
8643			sprintf(tmpstr, "<%s %s>", product, revision);
8644		} else {
8645			sprintf(tmpstr, "<>");
8646		}
8647		fprintf(stdout, "   %-33s ", tmpstr);
8648
8649		/*
8650		 * If we have 0 periphs, that's a bug...
8651		 */
8652		if (item->num_periphs == 0) {
8653			fprintf(stdout, "\n");
8654			continue;
8655		}
8656
8657		fprintf(stdout, "(");
8658		for (j = 0; j < item->num_periphs; j++) {
8659			if (j > 0)
8660				fprintf(stdout, ",");
8661
8662			fprintf(stdout, "%s%d",
8663				item->periph_matches[j].periph_name,
8664				item->periph_matches[j].unit_number);
8665
8666		}
8667		fprintf(stdout, ")\n");
8668	}
8669bailout:
8670	if (ccb != NULL)
8671		cam_freeccb(ccb);
8672
8673	free(rgrequest);
8674
8675	free(rgresponse);
8676
8677	free(disrequest);
8678
8679	free(disresponse);
8680
8681	freebusdevlist(&devlist);
8682
8683	return (retval);
8684}
8685
8686static int
8687atapm_proc_resp(struct cam_device *device, union ccb *ccb)
8688{
8689	uint8_t error = 0, ata_device = 0, status = 0;
8690	uint16_t count = 0;
8691	uint64_t lba = 0;
8692	int retval;
8693
8694	retval = get_ata_status(device, ccb, &error, &count, &lba, &ata_device,
8695	    &status);
8696	if (retval == 1) {
8697		if (arglist & CAM_ARG_VERBOSE) {
8698			cam_error_print(device, ccb, CAM_ESF_ALL,
8699					CAM_EPF_ALL, stderr);
8700		}
8701		warnx("Can't get ATA command status");
8702		return (retval);
8703	}
8704
8705	if (status & ATA_STATUS_ERROR) {
8706		cam_error_print(device, ccb, CAM_ESF_ALL,
8707		    CAM_EPF_ALL, stderr);
8708	        return (1);
8709	}
8710
8711	printf("%s%d: ", device->device_name, device->dev_unit_num);
8712	switch (count) {
8713	case 0x00:
8714		printf("Standby mode\n");
8715		break;
8716	case 0x01:
8717		printf("Standby_y mode\n");
8718		break;
8719	case 0x40:
8720		printf("NV Cache Power Mode and the spindle is spun down or spinning down\n");
8721		break;
8722	case 0x41:
8723		printf("NV Cache Power Mode and the spindle is spun up or spinning up\n");
8724		break;
8725	case 0x80:
8726		printf("Idle mode\n");
8727		break;
8728	case 0x81:
8729		printf("Idle_a mode\n");
8730		break;
8731	case 0x82:
8732		printf("Idle_b mode\n");
8733		break;
8734	case 0x83:
8735		printf("Idle_c mode\n");
8736		break;
8737	case 0xff:
8738		printf("Active or Idle mode\n");
8739		break;
8740	default:
8741		printf("Unknown mode 0x%02x\n", count);
8742		break;
8743	}
8744
8745	return (0);
8746}
8747
8748static int
8749atapm(struct cam_device *device, int argc, char **argv,
8750		 char *combinedopt, int retry_count, int timeout)
8751{
8752	union ccb *ccb;
8753	int retval = 0;
8754	int t = -1;
8755	int c;
8756	u_int8_t ata_flags = 0;
8757	u_char cmd, sc;
8758
8759	ccb = cam_getccb(device);
8760
8761	if (ccb == NULL) {
8762		warnx("%s: error allocating ccb", __func__);
8763		return (1);
8764	}
8765
8766	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8767		switch (c) {
8768		case 't':
8769			t = atoi(optarg);
8770			break;
8771		default:
8772			break;
8773		}
8774	}
8775	if (strcmp(argv[1], "idle") == 0) {
8776		if (t == -1)
8777			cmd = ATA_IDLE_IMMEDIATE;
8778		else
8779			cmd = ATA_IDLE_CMD;
8780	} else if (strcmp(argv[1], "standby") == 0) {
8781		if (t == -1)
8782			cmd = ATA_STANDBY_IMMEDIATE;
8783		else
8784			cmd = ATA_STANDBY_CMD;
8785	} else if (strcmp(argv[1], "powermode") == 0) {
8786		cmd = ATA_CHECK_POWER_MODE;
8787		ata_flags = AP_FLAG_CHK_COND;
8788		t = -1;
8789	} else {
8790		cmd = ATA_SLEEP;
8791		t = -1;
8792	}
8793
8794	if (t < 0)
8795		sc = 0;
8796	else if (t <= (240 * 5))
8797		sc = (t + 4) / 5;
8798	else if (t <= (252 * 5))
8799		/* special encoding for 21 minutes */
8800		sc = 252;
8801	else if (t <= (11 * 30 * 60))
8802		sc = (t - 1) / (30 * 60) + 241;
8803	else
8804		sc = 253;
8805
8806	retval = ata_do_cmd(device,
8807	    ccb,
8808	    /*retries*/retry_count,
8809	    /*flags*/CAM_DIR_NONE,
8810	    /*protocol*/AP_PROTO_NON_DATA,
8811	    /*ata_flags*/ata_flags,
8812	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8813	    /*command*/cmd,
8814	    /*features*/0,
8815	    /*lba*/0,
8816	    /*sector_count*/sc,
8817	    /*data_ptr*/NULL,
8818	    /*dxfer_len*/0,
8819	    /*timeout*/timeout ? timeout : 30 * 1000,
8820	    /*force48bit*/0);
8821
8822	cam_freeccb(ccb);
8823
8824	if (retval || cmd != ATA_CHECK_POWER_MODE)
8825		return (retval);
8826
8827	return (atapm_proc_resp(device, ccb));
8828}
8829
8830static int
8831ataaxm(struct cam_device *device, int argc, char **argv,
8832		 char *combinedopt, int retry_count, int timeout)
8833{
8834	union ccb *ccb;
8835	int retval = 0;
8836	int l = -1;
8837	int c;
8838	u_char cmd, sc;
8839
8840	ccb = cam_getccb(device);
8841
8842	if (ccb == NULL) {
8843		warnx("%s: error allocating ccb", __func__);
8844		return (1);
8845	}
8846
8847	while ((c = getopt(argc, argv, combinedopt)) != -1) {
8848		switch (c) {
8849		case 'l':
8850			l = atoi(optarg);
8851			break;
8852		default:
8853			break;
8854		}
8855	}
8856	sc = 0;
8857	if (strcmp(argv[1], "apm") == 0) {
8858		if (l == -1)
8859			cmd = 0x85;
8860		else {
8861			cmd = 0x05;
8862			sc = l;
8863		}
8864	} else /* aam */ {
8865		if (l == -1)
8866			cmd = 0xC2;
8867		else {
8868			cmd = 0x42;
8869			sc = l;
8870		}
8871	}
8872
8873	retval = ata_do_cmd(device,
8874	    ccb,
8875	    /*retries*/retry_count,
8876	    /*flags*/CAM_DIR_NONE,
8877	    /*protocol*/AP_PROTO_NON_DATA,
8878	    /*ata_flags*/0,
8879	    /*tag_action*/MSG_SIMPLE_Q_TAG,
8880	    /*command*/ATA_SETFEATURES,
8881	    /*features*/cmd,
8882	    /*lba*/0,
8883	    /*sector_count*/sc,
8884	    /*data_ptr*/NULL,
8885	    /*dxfer_len*/0,
8886	    /*timeout*/timeout ? timeout : 30 * 1000,
8887	    /*force48bit*/0);
8888
8889	cam_freeccb(ccb);
8890	return (retval);
8891}
8892
8893int
8894scsigetopcodes(struct cam_device *device, int opcode_set, int opcode,
8895	       int show_sa_errors, int sa_set, int service_action,
8896	       int timeout_desc, int task_attr, int retry_count, int timeout,
8897	       int verbosemode, uint32_t *fill_len, uint8_t **data_ptr)
8898{
8899	union ccb *ccb = NULL;
8900	uint8_t *buf = NULL;
8901	uint32_t alloc_len = 0, num_opcodes;
8902	uint32_t valid_len = 0;
8903	uint32_t avail_len = 0;
8904	struct scsi_report_supported_opcodes_all *all_hdr;
8905	struct scsi_report_supported_opcodes_one *one;
8906	int options = 0;
8907	int retval = 0;
8908
8909	/*
8910	 * Make it clear that we haven't yet allocated or filled anything.
8911	 */
8912	*fill_len = 0;
8913	*data_ptr = NULL;
8914
8915	ccb = cam_getccb(device);
8916	if (ccb == NULL) {
8917		warnx("couldn't allocate CCB");
8918		retval = 1;
8919		goto bailout;
8920	}
8921
8922	/* cam_getccb cleans up the header, caller has to zero the payload */
8923	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
8924
8925	if (opcode_set != 0) {
8926		options |= RSO_OPTIONS_OC;
8927		num_opcodes = 1;
8928		alloc_len = sizeof(*one) + CAM_MAX_CDBLEN;
8929	} else {
8930		num_opcodes = 256;
8931		alloc_len = sizeof(*all_hdr) + (num_opcodes *
8932		    sizeof(struct scsi_report_supported_opcodes_descr));
8933	}
8934
8935	if (timeout_desc != 0) {
8936		options |= RSO_RCTD;
8937		alloc_len += num_opcodes *
8938		    sizeof(struct scsi_report_supported_opcodes_timeout);
8939	}
8940
8941	if (sa_set != 0) {
8942		options |= RSO_OPTIONS_OC_SA;
8943		if (show_sa_errors != 0)
8944			options &= ~RSO_OPTIONS_OC;
8945	}
8946
8947retry_alloc:
8948	if (buf != NULL) {
8949		free(buf);
8950		buf = NULL;
8951	}
8952
8953	buf = malloc(alloc_len);
8954	if (buf == NULL) {
8955		warn("Unable to allocate %u bytes", alloc_len);
8956		retval = 1;
8957		goto bailout;
8958	}
8959	bzero(buf, alloc_len);
8960
8961	scsi_report_supported_opcodes(&ccb->csio,
8962				      /*retries*/ retry_count,
8963				      /*cbfcnp*/ NULL,
8964				      /*tag_action*/ task_attr,
8965				      /*options*/ options,
8966				      /*req_opcode*/ opcode,
8967				      /*req_service_action*/ service_action,
8968				      /*data_ptr*/ buf,
8969				      /*dxfer_len*/ alloc_len,
8970				      /*sense_len*/ SSD_FULL_SIZE,
8971				      /*timeout*/ timeout ? timeout : 10000);
8972
8973	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
8974
8975	if (retry_count != 0)
8976		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
8977
8978	if (cam_send_ccb(device, ccb) < 0) {
8979		warn("error sending REPORT SUPPORTED OPERATION CODES command");
8980		retval = 1;
8981		goto bailout;
8982	}
8983
8984	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
8985		if (verbosemode != 0)
8986			cam_error_print(device, ccb, CAM_ESF_ALL,
8987					CAM_EPF_ALL, stderr);
8988		retval = 1;
8989		goto bailout;
8990	}
8991
8992	valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
8993
8994	if (((options & RSO_OPTIONS_MASK) == RSO_OPTIONS_ALL)
8995	 && (valid_len >= sizeof(*all_hdr))) {
8996		all_hdr = (struct scsi_report_supported_opcodes_all *)buf;
8997		avail_len = scsi_4btoul(all_hdr->length) + sizeof(*all_hdr);
8998	} else if (((options & RSO_OPTIONS_MASK) != RSO_OPTIONS_ALL)
8999		&& (valid_len >= sizeof(*one))) {
9000		uint32_t cdb_length;
9001
9002		one = (struct scsi_report_supported_opcodes_one *)buf;
9003		cdb_length = scsi_2btoul(one->cdb_length);
9004		avail_len = sizeof(*one) + cdb_length;
9005		if (one->support & RSO_ONE_CTDP) {
9006			struct scsi_report_supported_opcodes_timeout *td;
9007
9008			td = (struct scsi_report_supported_opcodes_timeout *)
9009			    &buf[avail_len];
9010			if (valid_len >= (avail_len + sizeof(td->length))) {
9011				avail_len += scsi_2btoul(td->length) +
9012				    sizeof(td->length);
9013			} else {
9014				avail_len += sizeof(*td);
9015			}
9016		}
9017	}
9018
9019	/*
9020	 * avail_len could be zero if we didn't get enough data back from
9021	 * thet target to determine
9022	 */
9023	if ((avail_len != 0)
9024	 && (avail_len > valid_len)) {
9025		alloc_len = avail_len;
9026		goto retry_alloc;
9027	}
9028
9029	*fill_len = valid_len;
9030	*data_ptr = buf;
9031bailout:
9032	if (retval != 0)
9033		free(buf);
9034
9035	cam_freeccb(ccb);
9036
9037	return (retval);
9038}
9039
9040static int
9041scsiprintoneopcode(struct cam_device *device, int req_opcode, int sa_set,
9042		   int req_sa, uint8_t *buf, uint32_t valid_len)
9043{
9044	struct scsi_report_supported_opcodes_one *one;
9045	struct scsi_report_supported_opcodes_timeout *td;
9046	uint32_t cdb_len = 0, td_len = 0;
9047	const char *op_desc = NULL;
9048	unsigned int i;
9049	int retval = 0;
9050
9051	one = (struct scsi_report_supported_opcodes_one *)buf;
9052
9053	/*
9054	 * If we don't have the full single opcode descriptor, no point in
9055	 * continuing.
9056	 */
9057	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9058	    cdb_length)) {
9059		warnx("Only %u bytes returned, not enough to verify support",
9060		      valid_len);
9061		retval = 1;
9062		goto bailout;
9063	}
9064
9065	op_desc = scsi_op_desc(req_opcode, &device->inq_data);
9066
9067	printf("%s (0x%02x)", op_desc != NULL ? op_desc : "UNKNOWN",
9068	       req_opcode);
9069	if (sa_set != 0)
9070		printf(", SA 0x%x", req_sa);
9071	printf(": ");
9072
9073	switch (one->support & RSO_ONE_SUP_MASK) {
9074	case RSO_ONE_SUP_UNAVAIL:
9075		printf("No command support information currently available\n");
9076		break;
9077	case RSO_ONE_SUP_NOT_SUP:
9078		printf("Command not supported\n");
9079		retval = 1;
9080		goto bailout;
9081		break; /*NOTREACHED*/
9082	case RSO_ONE_SUP_AVAIL:
9083		printf("Command is supported, complies with a SCSI standard\n");
9084		break;
9085	case RSO_ONE_SUP_VENDOR:
9086		printf("Command is supported, vendor-specific "
9087		       "implementation\n");
9088		break;
9089	default:
9090		printf("Unknown command support flags 0x%#x\n",
9091		       one->support & RSO_ONE_SUP_MASK);
9092		break;
9093	}
9094
9095	/*
9096	 * If we don't have the CDB length, it isn't exactly an error, the
9097	 * command probably isn't supported.
9098	 */
9099	if (valid_len < __offsetof(struct scsi_report_supported_opcodes_one,
9100	    cdb_usage))
9101		goto bailout;
9102
9103	cdb_len = scsi_2btoul(one->cdb_length);
9104
9105	/*
9106	 * If our valid data doesn't include the full reported length,
9107	 * return.  The caller should have detected this and adjusted his
9108	 * allocation length to get all of the available data.
9109	 */
9110	if (valid_len < sizeof(*one) + cdb_len) {
9111		retval = 1;
9112		goto bailout;
9113	}
9114
9115	/*
9116	 * If all we have is the opcode, there is no point in printing out
9117	 * the usage bitmap.
9118	 */
9119	if (cdb_len <= 1) {
9120		retval = 1;
9121		goto bailout;
9122	}
9123
9124	printf("CDB usage bitmap:");
9125	for (i = 0; i < cdb_len; i++) {
9126		printf(" %02x", one->cdb_usage[i]);
9127	}
9128	printf("\n");
9129
9130	/*
9131	 * If we don't have a timeout descriptor, we're done.
9132	 */
9133	if ((one->support & RSO_ONE_CTDP) == 0)
9134		goto bailout;
9135
9136	/*
9137	 * If we don't have enough valid length to include the timeout
9138	 * descriptor length, we're done.
9139	 */
9140	if (valid_len < (sizeof(*one) + cdb_len + sizeof(td->length)))
9141		goto bailout;
9142
9143	td = (struct scsi_report_supported_opcodes_timeout *)
9144	    &buf[sizeof(*one) + cdb_len];
9145	td_len = scsi_2btoul(td->length);
9146	td_len += sizeof(td->length);
9147
9148	/*
9149	 * If we don't have the full timeout descriptor, we're done.
9150	 */
9151	if (td_len < sizeof(*td))
9152		goto bailout;
9153
9154	/*
9155	 * If we don't have enough valid length to contain the full timeout
9156	 * descriptor, we're done.
9157	 */
9158	if (valid_len < (sizeof(*one) + cdb_len + td_len))
9159		goto bailout;
9160
9161	printf("Timeout information:\n");
9162	printf("Command-specific:    0x%02x\n", td->cmd_specific);
9163	printf("Nominal timeout:     %u seconds\n",
9164	       scsi_4btoul(td->nominal_time));
9165	printf("Recommended timeout: %u seconds\n",
9166	       scsi_4btoul(td->recommended_time));
9167
9168bailout:
9169	return (retval);
9170}
9171
9172static int
9173scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf,
9174		 uint32_t valid_len)
9175{
9176	struct scsi_report_supported_opcodes_all *hdr;
9177	struct scsi_report_supported_opcodes_descr *desc;
9178	uint32_t avail_len = 0, used_len = 0;
9179	uint8_t *cur_ptr;
9180	int retval = 0;
9181
9182	if (valid_len < sizeof(*hdr)) {
9183		warnx("%s: not enough returned data (%u bytes) opcode list",
9184		      __func__, valid_len);
9185		retval = 1;
9186		goto bailout;
9187	}
9188	hdr = (struct scsi_report_supported_opcodes_all *)buf;
9189	avail_len = scsi_4btoul(hdr->length);
9190	avail_len += sizeof(hdr->length);
9191	/*
9192	 * Take the lesser of the amount of data the drive claims is
9193	 * available, and the amount of data the HBA says was returned.
9194	 */
9195	avail_len = MIN(avail_len, valid_len);
9196
9197	used_len = sizeof(hdr->length);
9198
9199	printf("%-6s %4s %8s ",
9200	       "Opcode", "SA", "CDB len" );
9201
9202	if (td_req != 0)
9203		printf("%5s %6s %6s ", "CS", "Nom", "Rec");
9204	printf(" Description\n");
9205
9206	while ((avail_len - used_len) > sizeof(*desc)) {
9207		struct scsi_report_supported_opcodes_timeout *td;
9208		uint32_t td_len;
9209		const char *op_desc = NULL;
9210
9211		cur_ptr = &buf[used_len];
9212		desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
9213
9214		op_desc = scsi_op_desc(desc->opcode, &device->inq_data);
9215		if (op_desc == NULL)
9216			op_desc = "UNKNOWN";
9217
9218		printf("0x%02x   %#4x %8u ", desc->opcode,
9219		       scsi_2btoul(desc->service_action),
9220		       scsi_2btoul(desc->cdb_length));
9221
9222		used_len += sizeof(*desc);
9223
9224		if ((desc->flags & RSO_CTDP) == 0) {
9225			printf(" %s\n", op_desc);
9226			continue;
9227		}
9228
9229		/*
9230		 * If we don't have enough space to fit a timeout
9231		 * descriptor, then we're done.
9232		 */
9233		if (avail_len - used_len < sizeof(*td)) {
9234			used_len = avail_len;
9235			printf(" %s\n", op_desc);
9236			continue;
9237		}
9238		cur_ptr = &buf[used_len];
9239		td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
9240		td_len = scsi_2btoul(td->length);
9241		td_len += sizeof(td->length);
9242
9243		used_len += td_len;
9244		/*
9245		 * If the given timeout descriptor length is less than what
9246		 * we understand, skip it.
9247		 */
9248		if (td_len < sizeof(*td)) {
9249			printf(" %s\n", op_desc);
9250			continue;
9251		}
9252
9253		printf(" 0x%02x %6u %6u  %s\n", td->cmd_specific,
9254		       scsi_4btoul(td->nominal_time),
9255		       scsi_4btoul(td->recommended_time), op_desc);
9256	}
9257bailout:
9258	return (retval);
9259}
9260
9261static int
9262scsiopcodes(struct cam_device *device, int argc, char **argv,
9263	    char *combinedopt, int task_attr, int retry_count, int timeout,
9264	    int verbosemode)
9265{
9266	int c;
9267	uint32_t opcode = 0, service_action = 0;
9268	int td_set = 0, opcode_set = 0, sa_set = 0;
9269	int show_sa_errors = 1;
9270	uint32_t valid_len = 0;
9271	uint8_t *buf = NULL;
9272	char *endptr;
9273	int retval = 0;
9274
9275	while ((c = getopt(argc, argv, combinedopt)) != -1) {
9276		switch (c) {
9277		case 'N':
9278			show_sa_errors = 0;
9279			break;
9280		case 'o':
9281			opcode = strtoul(optarg, &endptr, 0);
9282			if (*endptr != '\0') {
9283				warnx("Invalid opcode \"%s\", must be a number",
9284				      optarg);
9285				retval = 1;
9286				goto bailout;
9287			}
9288			if (opcode > 0xff) {
9289				warnx("Invalid opcode 0x%#x, must be between"
9290				      "0 and 0xff inclusive", opcode);
9291				retval = 1;
9292				goto bailout;
9293			}
9294			opcode_set = 1;
9295			break;
9296		case 's':
9297			service_action = strtoul(optarg, &endptr, 0);
9298			if (*endptr != '\0') {
9299				warnx("Invalid service action \"%s\", must "
9300				      "be a number", optarg);
9301				retval = 1;
9302				goto bailout;
9303			}
9304			if (service_action > 0xffff) {
9305				warnx("Invalid service action 0x%#x, must "
9306				      "be between 0 and 0xffff inclusive",
9307				      service_action);
9308				retval = 1;
9309			}
9310			sa_set = 1;
9311			break;
9312		case 'T':
9313			td_set = 1;
9314			break;
9315		default:
9316			break;
9317		}
9318	}
9319
9320	if ((sa_set != 0)
9321	 && (opcode_set == 0)) {
9322		warnx("You must specify an opcode with -o if a service "
9323		      "action is given");
9324		retval = 1;
9325		goto bailout;
9326	}
9327	retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors,
9328				sa_set, service_action, td_set, task_attr,
9329				retry_count, timeout, verbosemode, &valid_len,
9330				&buf);
9331	if (retval != 0)
9332		goto bailout;
9333
9334	if ((opcode_set != 0)
9335	 || (sa_set != 0)) {
9336		retval = scsiprintoneopcode(device, opcode, sa_set,
9337					    service_action, buf, valid_len);
9338	} else {
9339		retval = scsiprintopcodes(device, td_set, buf, valid_len);
9340	}
9341
9342bailout:
9343	free(buf);
9344
9345	return (retval);
9346}
9347
9348#endif /* MINIMALISTIC */
9349
9350static int
9351reprobe(struct cam_device *device)
9352{
9353	union ccb *ccb;
9354	int retval = 0;
9355
9356	ccb = cam_getccb(device);
9357
9358	if (ccb == NULL) {
9359		warnx("%s: error allocating ccb", __func__);
9360		return (1);
9361	}
9362
9363	CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
9364
9365	ccb->ccb_h.func_code = XPT_REPROBE_LUN;
9366
9367	if (cam_send_ccb(device, ccb) < 0) {
9368		warn("error sending XPT_REPROBE_LUN CCB");
9369		retval = 1;
9370		goto bailout;
9371	}
9372
9373	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
9374		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
9375		retval = 1;
9376		goto bailout;
9377	}
9378
9379bailout:
9380	cam_freeccb(ccb);
9381
9382	return (retval);
9383}
9384
9385void
9386usage(int printlong)
9387{
9388
9389	fprintf(printlong ? stdout : stderr,
9390"usage:  camcontrol <command>  [device id][generic args][command args]\n"
9391"        camcontrol devlist    [-b] [-v]\n"
9392#ifndef MINIMALISTIC
9393"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
9394"        camcontrol tur        [dev_id][generic args]\n"
9395"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
9396"        camcontrol identify   [dev_id][generic args] [-v]\n"
9397"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
9398"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
9399"                              [-q] [-s] [-l]\n"
9400"        camcontrol start      [dev_id][generic args]\n"
9401"        camcontrol stop       [dev_id][generic args]\n"
9402"        camcontrol load       [dev_id][generic args]\n"
9403"        camcontrol eject      [dev_id][generic args]\n"
9404"        camcontrol reprobe    [dev_id][generic args]\n"
9405#endif /* MINIMALISTIC */
9406"        camcontrol rescan     <all | bus[:target:lun] | dev_id>\n"
9407"        camcontrol reset      <all | bus[:target:lun] | dev_id>\n"
9408#ifndef MINIMALISTIC
9409"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
9410"                              [-q][-s][-S offset][-X]\n"
9411"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
9412"                              [-P pagectl][-e | -b][-d]\n"
9413"        camcontrol cmd        [dev_id][generic args]\n"
9414"                              <-a cmd [args] | -c cmd [args]>\n"
9415"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
9416"        camcontrol smpcmd     [dev_id][generic args]\n"
9417"                              <-r len fmt [args]> <-R len fmt [args]>\n"
9418"        camcontrol smprg      [dev_id][generic args][-l]\n"
9419"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
9420"                              [-o operation][-d name][-m rate][-M rate]\n"
9421"                              [-T pp_timeout][-a enable|disable]\n"
9422"                              [-A enable|disable][-s enable|disable]\n"
9423"                              [-S enable|disable]\n"
9424"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
9425"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
9426"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
9427"                              <all|dev_id|bus[:target[:lun]]|off>\n"
9428"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
9429"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
9430"                              [-D <enable|disable>][-M mode][-O offset]\n"
9431"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
9432"                              [-U][-W bus_width]\n"
9433"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
9434"        camcontrol sanitize   [dev_id][generic args]\n"
9435"                              [-a overwrite|block|crypto|exitfailure]\n"
9436"                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
9437"                              [-y]\n"
9438"        camcontrol idle       [dev_id][generic args][-t time]\n"
9439"        camcontrol standby    [dev_id][generic args][-t time]\n"
9440"        camcontrol sleep      [dev_id][generic args]\n"
9441"        camcontrol powermode  [dev_id][generic args]\n"
9442"        camcontrol apm        [dev_id][generic args][-l level]\n"
9443"        camcontrol aam        [dev_id][generic args][-l level]\n"
9444"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-q]\n"
9445"                              [-s][-y]\n"
9446"        camcontrol security   [dev_id][generic args]\n"
9447"                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
9448"                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
9449"                              [-U <user|master>] [-y]\n"
9450"        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
9451"                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
9452"        camcontrol ama        [dev_id][generic args] [-f] [-q] [-s max_sectors]\n"
9453"        camcontrol persist    [dev_id][generic args] <-i action|-o action>\n"
9454"                              [-a][-I tid][-k key][-K sa_key][-p][-R rtp]\n"
9455"                              [-s scope][-S][-T type][-U]\n"
9456"        camcontrol attrib     [dev_id][generic args] <-r action|-w attr>\n"
9457"                              [-a attr_num][-c][-e elem][-F form1,form1]\n"
9458"                              [-p part][-s start][-T type][-V vol]\n"
9459"        camcontrol opcodes    [dev_id][generic args][-o opcode][-s SA]\n"
9460"                              [-N][-T]\n"
9461"        camcontrol zone       [dev_id][generic args]<-c cmd> [-a] [-l LBA]\n"
9462"                              [-o rep_opts] [-P print_opts]\n"
9463"        camcontrol epc        [dev_id][generic_args]<-c cmd> [-d] [-D] [-e]\n"
9464"                              [-H] [-p power_cond] [-P] [-r rst_src] [-s]\n"
9465"                              [-S power_src] [-T timer]\n"
9466"        camcontrol timestamp  [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
9467"                              <-s <-f format -T time | -U >>\n"
9468"        camcontrol devtype    [dev_id]\n"
9469"                              \n"
9470#endif /* MINIMALISTIC */
9471"        camcontrol help\n");
9472	if (!printlong)
9473		return;
9474#ifndef MINIMALISTIC
9475	fprintf(stdout,
9476"Specify one of the following options:\n"
9477"devlist     list all CAM devices\n"
9478"periphlist  list all CAM peripheral drivers attached to a device\n"
9479"tur         send a test unit ready to the named device\n"
9480"inquiry     send a SCSI inquiry command to the named device\n"
9481"identify    send a ATA identify command to the named device\n"
9482"reportluns  send a SCSI report luns command to the device\n"
9483"readcap     send a SCSI read capacity command to the device\n"
9484"start       send a Start Unit command to the device\n"
9485"stop        send a Stop Unit command to the device\n"
9486"load        send a Start Unit command to the device with the load bit set\n"
9487"eject       send a Stop Unit command to the device with the eject bit set\n"
9488"reprobe     update capacity information of the given device\n"
9489"rescan      rescan all buses, the given bus, bus:target:lun or device\n"
9490"reset       reset all buses, the given bus, bus:target:lun or device\n"
9491"defects     read the defect list of the specified device\n"
9492"modepage    display or edit (-e) the given mode page\n"
9493"cmd         send the given SCSI command, may need -i or -o as well\n"
9494"smpcmd      send the given SMP command, requires -o and -i\n"
9495"smprg       send the SMP Report General command\n"
9496"smppc       send the SMP PHY Control command, requires -p\n"
9497"smpphylist  display phys attached to a SAS expander\n"
9498"smpmaninfo  send the SMP Report Manufacturer Info command\n"
9499"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
9500"tags        report or set the number of transaction slots for a device\n"
9501"negotiate   report or set device negotiation parameters\n"
9502"format      send the SCSI FORMAT UNIT command to the named device\n"
9503"sanitize    send the SCSI SANITIZE command to the named device\n"
9504"idle        send the ATA IDLE command to the named device\n"
9505"standby     send the ATA STANDBY command to the named device\n"
9506"sleep       send the ATA SLEEP command to the named device\n"
9507"powermode   send the ATA CHECK POWER MODE command to the named device\n"
9508"fwdownload  program firmware of the named device with the given image\n"
9509"security    report or send ATA security commands to the named device\n"
9510"persist     send the SCSI PERSISTENT RESERVE IN or OUT commands\n"
9511"attrib      send the SCSI READ or WRITE ATTRIBUTE commands\n"
9512"opcodes     send the SCSI REPORT SUPPORTED OPCODES command\n"
9513"zone        manage Zoned Block (Shingled) devices\n"
9514"epc         send ATA Extended Power Conditions commands\n"
9515"timestamp   report or set the device's timestamp\n"
9516"devtype     report the type of device\n"
9517"help        this message\n"
9518"Device Identifiers:\n"
9519"bus:target        specify the bus and target, lun defaults to 0\n"
9520"bus:target:lun    specify the bus, target and lun\n"
9521"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
9522"Generic arguments:\n"
9523"-v                be verbose, print out sense information\n"
9524"-t timeout        command timeout in seconds, overrides default timeout\n"
9525"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
9526"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
9527"-E                have the kernel attempt to perform SCSI error recovery\n"
9528"-C count          specify the SCSI command retry count (needs -E to work)\n"
9529"-Q task_attr      specify ordered, simple or head tag type for SCSI cmds\n"
9530"modepage arguments:\n"
9531"-l                list all available mode pages\n"
9532"-m page           specify the mode page to view or edit\n"
9533"-e                edit the specified mode page\n"
9534"-b                force view to binary mode\n"
9535"-d                disable block descriptors for mode sense\n"
9536"-P pgctl          page control field 0-3\n"
9537"defects arguments:\n"
9538"-f format         specify defect list format (block, bfi or phys)\n"
9539"-G                get the grown defect list\n"
9540"-P                get the permanent defect list\n"
9541"inquiry arguments:\n"
9542"-D                get the standard inquiry data\n"
9543"-S                get the serial number\n"
9544"-R                get the transfer rate, etc.\n"
9545"reportluns arguments:\n"
9546"-c                only report a count of available LUNs\n"
9547"-l                only print out luns, and not a count\n"
9548"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
9549"readcap arguments\n"
9550"-b                only report the blocksize\n"
9551"-h                human readable device size, base 2\n"
9552"-H                human readable device size, base 10\n"
9553"-N                print the number of blocks instead of last block\n"
9554"-q                quiet, print numbers only\n"
9555"-s                only report the last block/device size\n"
9556"cmd arguments:\n"
9557"-c cdb [args]     specify the SCSI CDB\n"
9558"-i len fmt        specify input data and input data format\n"
9559"-o len fmt [args] specify output data and output data fmt\n"
9560"smpcmd arguments:\n"
9561"-r len fmt [args] specify the SMP command to be sent\n"
9562"-R len fmt [args] specify SMP response format\n"
9563"smprg arguments:\n"
9564"-l                specify the long response format\n"
9565"smppc arguments:\n"
9566"-p phy            specify the PHY to operate on\n"
9567"-l                specify the long request/response format\n"
9568"-o operation      specify the phy control operation\n"
9569"-d name           set the attached device name\n"
9570"-m rate           set the minimum physical link rate\n"
9571"-M rate           set the maximum physical link rate\n"
9572"-T pp_timeout     set the partial pathway timeout value\n"
9573"-a enable|disable enable or disable SATA slumber\n"
9574"-A enable|disable enable or disable SATA partial phy power\n"
9575"-s enable|disable enable or disable SAS slumber\n"
9576"-S enable|disable enable or disable SAS partial phy power\n"
9577"smpphylist arguments:\n"
9578"-l                specify the long response format\n"
9579"-q                only print phys with attached devices\n"
9580"smpmaninfo arguments:\n"
9581"-l                specify the long response format\n"
9582"debug arguments:\n"
9583"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
9584"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
9585"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
9586"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
9587"tags arguments:\n"
9588"-N tags           specify the number of tags to use for this device\n"
9589"-q                be quiet, don't report the number of tags\n"
9590"-v                report a number of tag-related parameters\n"
9591"negotiate arguments:\n"
9592"-a                send a test unit ready after negotiation\n"
9593"-c                report/set current negotiation settings\n"
9594"-D <arg>          \"enable\" or \"disable\" disconnection\n"
9595"-M mode           set ATA mode\n"
9596"-O offset         set command delay offset\n"
9597"-q                be quiet, don't report anything\n"
9598"-R syncrate       synchronization rate in MHz\n"
9599"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
9600"-U                report/set user negotiation settings\n"
9601"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
9602"-v                also print a Path Inquiry CCB for the controller\n"
9603"format arguments:\n"
9604"-q                be quiet, don't print status messages\n"
9605"-r                run in report only mode\n"
9606"-w                don't send immediate format command\n"
9607"-y                don't ask any questions\n"
9608"sanitize arguments:\n"
9609"-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
9610"-c passes         overwrite passes to perform (1 to 31)\n"
9611"-I                invert overwrite pattern after each pass\n"
9612"-P pattern        path to overwrite pattern file\n"
9613"-q                be quiet, don't print status messages\n"
9614"-r                run in report only mode\n"
9615"-U                run operation in unrestricted completion exit mode\n"
9616"-w                don't send immediate sanitize command\n"
9617"-y                don't ask any questions\n"
9618"idle/standby arguments:\n"
9619"-t <arg>          number of seconds before respective state.\n"
9620"fwdownload arguments:\n"
9621"-f fw_image       path to firmware image file\n"
9622"-q                don't print informational messages, only errors\n"
9623"-s                run in simulation mode\n"
9624"-v                print info for every firmware segment sent to device\n"
9625"-y                don't ask any questions\n"
9626"security arguments:\n"
9627"-d pwd            disable security using the given password for the selected\n"
9628"                  user\n"
9629"-e pwd            erase the device using the given pwd for the selected user\n"
9630"-f                freeze the security configuration of the specified device\n"
9631"-h pwd            enhanced erase the device using the given pwd for the\n"
9632"                  selected user\n"
9633"-k pwd            unlock the device using the given pwd for the selected\n"
9634"                  user\n"
9635"-l <high|maximum> specifies which security level to set: high or maximum\n"
9636"-q                be quiet, do not print any status messages\n"
9637"-s pwd            password the device (enable security) using the given\n"
9638"                  pwd for the selected user\n"
9639"-T timeout        overrides the timeout (seconds) used for erase operation\n"
9640"-U <user|master>  specifies which user to set: user or master\n"
9641"-y                don't ask any questions\n"
9642"hpa arguments:\n"
9643"-f                freeze the HPA configuration of the device\n"
9644"-l                lock the HPA configuration of the device\n"
9645"-P                make the HPA max sectors persist\n"
9646"-p pwd            Set the HPA configuration password required for unlock\n"
9647"                  calls\n"
9648"-q                be quiet, do not print any status messages\n"
9649"-s sectors        configures the maximum user accessible sectors of the\n"
9650"                  device\n"
9651"-U pwd            unlock the HPA configuration of the device\n"
9652"-y                don't ask any questions\n"
9653"ama arguments:\n"
9654"-f                freeze the AMA configuration of the device\n"
9655"-q                be quiet, do not print any status messages\n"
9656"-s sectors        configures the maximum user accessible sectors of the\n"
9657"                  device\n"
9658"persist arguments:\n"
9659"-i action         specify read_keys, read_reservation, report_cap, or\n"
9660"                  read_full_status\n"
9661"-o action         specify register, register_ignore, reserve, release,\n"
9662"                  clear, preempt, preempt_abort, register_move, replace_lost\n"
9663"-a                set the All Target Ports (ALL_TG_PT) bit\n"
9664"-I tid            specify a Transport ID, e.g.: sas,0x1234567812345678\n"
9665"-k key            specify the Reservation Key\n"
9666"-K sa_key         specify the Service Action Reservation Key\n"
9667"-p                set the Activate Persist Through Power Loss bit\n"
9668"-R rtp            specify the Relative Target Port\n"
9669"-s scope          specify the scope: lun, extent, element or a number\n"
9670"-S                specify Transport ID for register, requires -I\n"
9671"-T res_type       specify the reservation type: read_shared, wr_ex, rd_ex,\n"
9672"                  ex_ac, wr_ex_ro, ex_ac_ro, wr_ex_ar, ex_ac_ar\n"
9673"-U                unregister the current initiator for register_move\n"
9674"attrib arguments:\n"
9675"-r action         specify attr_values, attr_list, lv_list, part_list, or\n"
9676"                  supp_attr\n"
9677"-w attr           specify an attribute to write, one -w argument per attr\n"
9678"-a attr_num       only display this attribute number\n"
9679"-c                get cached attributes\n"
9680"-e elem_addr      request attributes for the given element in a changer\n"
9681"-F form1,form2    output format, comma separated list: text_esc, text_raw,\n"
9682"                  nonascii_esc, nonascii_trim, nonascii_raw, field_all,\n"
9683"                  field_none, field_desc, field_num, field_size, field_rw\n"
9684"-p partition      request attributes for the given partition\n"
9685"-s start_attr     request attributes starting at the given number\n"
9686"-T elem_type      specify the element type (used with -e)\n"
9687"-V logical_vol    specify the logical volume ID\n"
9688"opcodes arguments:\n"
9689"-o opcode         specify the individual opcode to list\n"
9690"-s service_action specify the service action for the opcode\n"
9691"-N                do not return SCSI error for unsupported SA\n"
9692"-T                request nominal and recommended timeout values\n"
9693"zone arguments:\n"
9694"-c cmd            required: rz, open, close, finish, or rwp\n"
9695"-a                apply the action to all zones\n"
9696"-l LBA            specify the zone starting LBA\n"
9697"-o rep_opts       report zones options: all, empty, imp_open, exp_open,\n"
9698"                  closed, full, ro, offline, reset, nonseq, nonwp\n"
9699"-P print_opt      report zones printing:  normal, summary, script\n"
9700"epc arguments:\n"
9701"-c cmd            required: restore, goto, timer, state, enable, disable,\n"
9702"                  source, status, list\n"
9703"-d                disable power mode (timer, state)\n"
9704"-D                delayed entry (goto)\n"
9705"-e                enable power mode (timer, state)\n"
9706"-H                hold power mode (goto)\n"
9707"-p power_cond     Idle_a, Idle_b, Idle_c, Standby_y, Standby_z (timer,\n"
9708"                  state, goto)\n"
9709"-P                only display power mode (status)\n"
9710"-r rst_src        restore settings from: default, saved (restore)\n"
9711"-s                save mode (timer, state, restore)\n"
9712"-S power_src      set power source: battery, nonbattery (source)\n"
9713"-T timer          set timer, seconds, .1 sec resolution (timer)\n"
9714"timestamp arguments:\n"
9715"-r                report the timestamp of the device\n"
9716"-f format         report the timestamp of the device with the given\n"
9717"                  strftime(3) format string\n"
9718"-m                report the timestamp of the device as milliseconds since\n"
9719"                  January 1st, 1970\n"
9720"-U                report the time with UTC instead of the local time zone\n"
9721"-s                set the timestamp of the device\n"
9722"-f format         the format of the time string passed into strptime(3)\n"
9723"-T time           the time value passed into strptime(3)\n"
9724"-U                set the timestamp of the device to UTC time\n"
9725);
9726#endif /* MINIMALISTIC */
9727}
9728
9729int
9730main(int argc, char **argv)
9731{
9732	int c;
9733	char *device = NULL;
9734	int unit = 0;
9735	struct cam_device *cam_dev = NULL;
9736	int timeout = 0, retry_count = 1;
9737	camcontrol_optret optreturn;
9738	char *tstr;
9739	const char *mainopt = "C:En:Q:t:u:v";
9740	const char *subopt = NULL;
9741	char combinedopt[256];
9742	int error = 0, optstart = 2;
9743	int task_attr = MSG_SIMPLE_Q_TAG;
9744	int devopen = 1;
9745#ifndef MINIMALISTIC
9746	path_id_t bus;
9747	target_id_t target;
9748	lun_id_t lun;
9749#endif /* MINIMALISTIC */
9750
9751	cmdlist = CAM_CMD_NONE;
9752	arglist = CAM_ARG_NONE;
9753
9754	if (argc < 2) {
9755		usage(0);
9756		exit(1);
9757	}
9758
9759	/*
9760	 * Get the base option.
9761	 */
9762	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
9763
9764	if (optreturn == CC_OR_AMBIGUOUS) {
9765		warnx("ambiguous option %s", argv[1]);
9766		usage(0);
9767		exit(1);
9768	} else if (optreturn == CC_OR_NOT_FOUND) {
9769		warnx("option %s not found", argv[1]);
9770		usage(0);
9771		exit(1);
9772	}
9773
9774	/*
9775	 * Ahh, getopt(3) is a pain.
9776	 *
9777	 * This is a gross hack.  There really aren't many other good
9778	 * options (excuse the pun) for parsing options in a situation like
9779	 * this.  getopt is kinda braindead, so you end up having to run
9780	 * through the options twice, and give each invocation of getopt
9781	 * the option string for the other invocation.
9782	 *
9783	 * You would think that you could just have two groups of options.
9784	 * The first group would get parsed by the first invocation of
9785	 * getopt, and the second group would get parsed by the second
9786	 * invocation of getopt.  It doesn't quite work out that way.  When
9787	 * the first invocation of getopt finishes, it leaves optind pointing
9788	 * to the argument _after_ the first argument in the second group.
9789	 * So when the second invocation of getopt comes around, it doesn't
9790	 * recognize the first argument it gets and then bails out.
9791	 *
9792	 * A nice alternative would be to have a flag for getopt that says
9793	 * "just keep parsing arguments even when you encounter an unknown
9794	 * argument", but there isn't one.  So there's no real clean way to
9795	 * easily parse two sets of arguments without having one invocation
9796	 * of getopt know about the other.
9797	 *
9798	 * Without this hack, the first invocation of getopt would work as
9799	 * long as the generic arguments are first, but the second invocation
9800	 * (in the subfunction) would fail in one of two ways.  In the case
9801	 * where you don't set optreset, it would fail because optind may be
9802	 * pointing to the argument after the one it should be pointing at.
9803	 * In the case where you do set optreset, and reset optind, it would
9804	 * fail because getopt would run into the first set of options, which
9805	 * it doesn't understand.
9806	 *
9807	 * All of this would "sort of" work if you could somehow figure out
9808	 * whether optind had been incremented one option too far.  The
9809	 * mechanics of that, however, are more daunting than just giving
9810	 * both invocations all of the expect options for either invocation.
9811	 *
9812	 * Needless to say, I wouldn't mind if someone invented a better
9813	 * (non-GPL!) command line parsing interface than getopt.  I
9814	 * wouldn't mind if someone added more knobs to getopt to make it
9815	 * work better.  Who knows, I may talk myself into doing it someday,
9816	 * if the standards weenies let me.  As it is, it just leads to
9817	 * hackery like this and causes people to avoid it in some cases.
9818	 *
9819	 * KDM, September 8th, 1998
9820	 */
9821	if (subopt != NULL)
9822		sprintf(combinedopt, "%s%s", mainopt, subopt);
9823	else
9824		sprintf(combinedopt, "%s", mainopt);
9825
9826	/*
9827	 * For these options we do not parse optional device arguments and
9828	 * we do not open a passthrough device.
9829	 */
9830	if ((cmdlist == CAM_CMD_RESCAN)
9831	 || (cmdlist == CAM_CMD_RESET)
9832	 || (cmdlist == CAM_CMD_DEVTREE)
9833	 || (cmdlist == CAM_CMD_USAGE)
9834	 || (cmdlist == CAM_CMD_DEBUG))
9835		devopen = 0;
9836
9837#ifndef MINIMALISTIC
9838	if ((devopen == 1)
9839	 && (argc > 2 && argv[2][0] != '-')) {
9840		char name[30];
9841		int rv;
9842
9843		if (isdigit(argv[2][0])) {
9844			/* device specified as bus:target[:lun] */
9845			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
9846			if (rv < 2)
9847				errx(1, "numeric device specification must "
9848				     "be either bus:target, or "
9849				     "bus:target:lun");
9850			/* default to 0 if lun was not specified */
9851			if ((arglist & CAM_ARG_LUN) == 0) {
9852				lun = 0;
9853				arglist |= CAM_ARG_LUN;
9854			}
9855			optstart++;
9856		} else {
9857			if (cam_get_device(argv[2], name, sizeof name, &unit)
9858			    == -1)
9859				errx(1, "%s", cam_errbuf);
9860			device = strdup(name);
9861			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
9862			optstart++;
9863		}
9864	}
9865#endif /* MINIMALISTIC */
9866	/*
9867	 * Start getopt processing at argv[2/3], since we've already
9868	 * accepted argv[1..2] as the command name, and as a possible
9869	 * device name.
9870	 */
9871	optind = optstart;
9872
9873	/*
9874	 * Now we run through the argument list looking for generic
9875	 * options, and ignoring options that possibly belong to
9876	 * subfunctions.
9877	 */
9878	while ((c = getopt(argc, argv, combinedopt))!= -1){
9879		switch(c) {
9880			case 'C':
9881				retry_count = strtol(optarg, NULL, 0);
9882				if (retry_count < 0)
9883					errx(1, "retry count %d is < 0",
9884					     retry_count);
9885				arglist |= CAM_ARG_RETRIES;
9886				break;
9887			case 'E':
9888				arglist |= CAM_ARG_ERR_RECOVER;
9889				break;
9890			case 'n':
9891				arglist |= CAM_ARG_DEVICE;
9892				tstr = optarg;
9893				while (isspace(*tstr) && (*tstr != '\0'))
9894					tstr++;
9895				device = (char *)strdup(tstr);
9896				break;
9897			case 'Q': {
9898				char *endptr;
9899				int table_entry = 0;
9900
9901				tstr = optarg;
9902				while (isspace(*tstr) && (*tstr != '\0'))
9903					tstr++;
9904				if (isdigit(*tstr)) {
9905					task_attr = strtol(tstr, &endptr, 0);
9906					if (*endptr != '\0') {
9907						errx(1, "Invalid queue option "
9908						    "%s", tstr);
9909					}
9910				} else {
9911					size_t table_size;
9912					scsi_nv_status status;
9913
9914					table_size = sizeof(task_attrs) /
9915						     sizeof(task_attrs[0]);
9916					status = scsi_get_nv(task_attrs,
9917					    table_size, tstr, &table_entry,
9918					    SCSI_NV_FLAG_IG_CASE);
9919					if (status == SCSI_NV_FOUND)
9920						task_attr = task_attrs[
9921						    table_entry].value;
9922					else {
9923						errx(1, "%s option %s",
9924						  (status == SCSI_NV_AMBIGUOUS)?
9925						    "ambiguous" : "invalid",
9926						    tstr);
9927					}
9928				}
9929				break;
9930			}
9931			case 't':
9932				timeout = strtol(optarg, NULL, 0);
9933				if (timeout < 0)
9934					errx(1, "invalid timeout %d", timeout);
9935				/* Convert the timeout from seconds to ms */
9936				timeout *= 1000;
9937				arglist |= CAM_ARG_TIMEOUT;
9938				break;
9939			case 'u':
9940				arglist |= CAM_ARG_UNIT;
9941				unit = strtol(optarg, NULL, 0);
9942				break;
9943			case 'v':
9944				arglist |= CAM_ARG_VERBOSE;
9945				break;
9946			default:
9947				break;
9948		}
9949	}
9950
9951#ifndef MINIMALISTIC
9952	/*
9953	 * For most commands we'll want to open the passthrough device
9954	 * associated with the specified device.  In the case of the rescan
9955	 * commands, we don't use a passthrough device at all, just the
9956	 * transport layer device.
9957	 */
9958	if (devopen == 1) {
9959		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
9960		 && (((arglist & CAM_ARG_DEVICE) == 0)
9961		  || ((arglist & CAM_ARG_UNIT) == 0))) {
9962			errx(1, "subcommand \"%s\" requires a valid device "
9963			     "identifier", argv[1]);
9964		}
9965
9966		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
9967				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
9968				cam_open_spec_device(device,unit,O_RDWR,NULL)))
9969		     == NULL)
9970			errx(1,"%s", cam_errbuf);
9971	}
9972#endif /* MINIMALISTIC */
9973
9974	/*
9975	 * Reset optind to 2, and reset getopt, so these routines can parse
9976	 * the arguments again.
9977	 */
9978	optind = optstart;
9979	optreset = 1;
9980
9981	switch(cmdlist) {
9982#ifndef MINIMALISTIC
9983	case CAM_CMD_DEVLIST:
9984		error = getdevlist(cam_dev);
9985		break;
9986	case CAM_CMD_HPA:
9987		error = atahpa(cam_dev, retry_count, timeout,
9988			       argc, argv, combinedopt);
9989		break;
9990	case CAM_CMD_AMA:
9991		error = ataama(cam_dev, retry_count, timeout,
9992			       argc, argv, combinedopt);
9993		break;
9994#endif /* MINIMALISTIC */
9995	case CAM_CMD_DEVTREE:
9996		error = getdevtree(argc, argv, combinedopt);
9997		break;
9998	case CAM_CMD_DEVTYPE:
9999		error = getdevtype(cam_dev);
10000		break;
10001#ifndef MINIMALISTIC
10002	case CAM_CMD_TUR:
10003		error = testunitready(cam_dev, task_attr, retry_count,
10004		    timeout, 0);
10005		break;
10006	case CAM_CMD_INQUIRY:
10007		error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
10008				      task_attr, retry_count, timeout);
10009		break;
10010	case CAM_CMD_IDENTIFY:
10011		error = ataidentify(cam_dev, retry_count, timeout);
10012		break;
10013	case CAM_CMD_STARTSTOP:
10014		error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
10015				  arglist & CAM_ARG_EJECT, task_attr,
10016				  retry_count, timeout);
10017		break;
10018#endif /* MINIMALISTIC */
10019	case CAM_CMD_RESCAN:
10020		error = dorescan_or_reset(argc, argv, 1);
10021		break;
10022	case CAM_CMD_RESET:
10023		error = dorescan_or_reset(argc, argv, 0);
10024		break;
10025#ifndef MINIMALISTIC
10026	case CAM_CMD_READ_DEFECTS:
10027		error = readdefects(cam_dev, argc, argv, combinedopt,
10028				    task_attr, retry_count, timeout);
10029		break;
10030	case CAM_CMD_MODE_PAGE:
10031		modepage(cam_dev, argc, argv, combinedopt,
10032			 task_attr, retry_count, timeout);
10033		break;
10034	case CAM_CMD_SCSI_CMD:
10035		error = scsicmd(cam_dev, argc, argv, combinedopt,
10036				task_attr, retry_count, timeout);
10037		break;
10038	case CAM_CMD_SMP_CMD:
10039		error = smpcmd(cam_dev, argc, argv, combinedopt,
10040			       retry_count, timeout);
10041		break;
10042	case CAM_CMD_SMP_RG:
10043		error = smpreportgeneral(cam_dev, argc, argv,
10044					 combinedopt, retry_count,
10045					 timeout);
10046		break;
10047	case CAM_CMD_SMP_PC:
10048		error = smpphycontrol(cam_dev, argc, argv, combinedopt,
10049				      retry_count, timeout);
10050		break;
10051	case CAM_CMD_SMP_PHYLIST:
10052		error = smpphylist(cam_dev, argc, argv, combinedopt,
10053				   retry_count, timeout);
10054		break;
10055	case CAM_CMD_SMP_MANINFO:
10056		error = smpmaninfo(cam_dev, argc, argv, combinedopt,
10057				   retry_count, timeout);
10058		break;
10059	case CAM_CMD_DEBUG:
10060		error = camdebug(argc, argv, combinedopt);
10061		break;
10062	case CAM_CMD_TAG:
10063		error = tagcontrol(cam_dev, argc, argv, combinedopt);
10064		break;
10065	case CAM_CMD_RATE:
10066		error = ratecontrol(cam_dev, task_attr, retry_count,
10067				    timeout, argc, argv, combinedopt);
10068		break;
10069	case CAM_CMD_FORMAT:
10070		error = scsiformat(cam_dev, argc, argv,
10071				   combinedopt, task_attr, retry_count,
10072				   timeout);
10073		break;
10074	case CAM_CMD_REPORTLUNS:
10075		error = scsireportluns(cam_dev, argc, argv,
10076				       combinedopt, task_attr,
10077				       retry_count, timeout);
10078		break;
10079	case CAM_CMD_READCAP:
10080		error = scsireadcapacity(cam_dev, argc, argv,
10081					 combinedopt, task_attr,
10082					 retry_count, timeout);
10083		break;
10084	case CAM_CMD_IDLE:
10085	case CAM_CMD_STANDBY:
10086	case CAM_CMD_SLEEP:
10087	case CAM_CMD_POWER_MODE:
10088		error = atapm(cam_dev, argc, argv,
10089			      combinedopt, retry_count, timeout);
10090		break;
10091	case CAM_CMD_APM:
10092	case CAM_CMD_AAM:
10093		error = ataaxm(cam_dev, argc, argv,
10094			      combinedopt, retry_count, timeout);
10095		break;
10096	case CAM_CMD_SECURITY:
10097		error = atasecurity(cam_dev, retry_count, timeout,
10098				    argc, argv, combinedopt);
10099		break;
10100	case CAM_CMD_DOWNLOAD_FW:
10101		error = fwdownload(cam_dev, argc, argv, combinedopt,
10102		    arglist & CAM_ARG_VERBOSE, task_attr, retry_count,
10103		    timeout);
10104		break;
10105	case CAM_CMD_SANITIZE:
10106		error = sanitize(cam_dev, argc, argv, combinedopt, task_attr,
10107				 retry_count, timeout);
10108		break;
10109	case CAM_CMD_PERSIST:
10110		error = scsipersist(cam_dev, argc, argv, combinedopt,
10111		    task_attr, retry_count, timeout,
10112		    arglist & CAM_ARG_VERBOSE,
10113		    arglist & CAM_ARG_ERR_RECOVER);
10114		break;
10115	case CAM_CMD_ATTRIB:
10116		error = scsiattrib(cam_dev, argc, argv, combinedopt,
10117		    task_attr, retry_count, timeout,
10118		    arglist & CAM_ARG_VERBOSE,
10119		    arglist & CAM_ARG_ERR_RECOVER);
10120		break;
10121	case CAM_CMD_OPCODES:
10122		error = scsiopcodes(cam_dev, argc, argv, combinedopt,
10123		    task_attr, retry_count, timeout,
10124		    arglist & CAM_ARG_VERBOSE);
10125		break;
10126	case CAM_CMD_REPROBE:
10127		error = reprobe(cam_dev);
10128		break;
10129	case CAM_CMD_ZONE:
10130		error = zone(cam_dev, argc, argv, combinedopt,
10131		    task_attr, retry_count, timeout,
10132		    arglist & CAM_ARG_VERBOSE);
10133		break;
10134	case CAM_CMD_EPC:
10135		error = epc(cam_dev, argc, argv, combinedopt,
10136		    retry_count, timeout, arglist & CAM_ARG_VERBOSE);
10137		break;
10138	case CAM_CMD_TIMESTAMP:
10139		error = timestamp(cam_dev, argc, argv, combinedopt,
10140		    task_attr, retry_count, timeout,
10141		    arglist & CAM_ARG_VERBOSE);
10142		break;
10143#endif /* MINIMALISTIC */
10144	case CAM_CMD_USAGE:
10145		usage(1);
10146		break;
10147	default:
10148		usage(0);
10149		error = 1;
10150		break;
10151	}
10152
10153	if (cam_dev != NULL)
10154		cam_close_device(cam_dev);
10155
10156	exit(error);
10157}
10158