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