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
66typedef enum {
67	CAM_CMD_NONE		= 0x00000000,
68	CAM_CMD_DEVLIST		= 0x00000001,
69	CAM_CMD_TUR		= 0x00000002,
70	CAM_CMD_INQUIRY		= 0x00000003,
71	CAM_CMD_STARTSTOP	= 0x00000004,
72	CAM_CMD_RESCAN		= 0x00000005,
73	CAM_CMD_READ_DEFECTS	= 0x00000006,
74	CAM_CMD_MODE_PAGE	= 0x00000007,
75	CAM_CMD_SCSI_CMD	= 0x00000008,
76	CAM_CMD_DEVTREE		= 0x00000009,
77	CAM_CMD_USAGE		= 0x0000000a,
78	CAM_CMD_DEBUG		= 0x0000000b,
79	CAM_CMD_RESET		= 0x0000000c,
80	CAM_CMD_FORMAT		= 0x0000000d,
81	CAM_CMD_TAG		= 0x0000000e,
82	CAM_CMD_RATE		= 0x0000000f,
83	CAM_CMD_DETACH		= 0x00000010,
84	CAM_CMD_REPORTLUNS	= 0x00000011,
85	CAM_CMD_READCAP		= 0x00000012,
86	CAM_CMD_IDENTIFY	= 0x00000013,
87	CAM_CMD_IDLE		= 0x00000014,
88	CAM_CMD_STANDBY		= 0x00000015,
89	CAM_CMD_SLEEP		= 0x00000016,
90	CAM_CMD_SMP_CMD		= 0x00000017,
91	CAM_CMD_SMP_RG		= 0x00000018,
92	CAM_CMD_SMP_PC		= 0x00000019,
93	CAM_CMD_SMP_PHYLIST	= 0x0000001a,
94	CAM_CMD_SMP_MANINFO	= 0x0000001b,
95	CAM_CMD_DOWNLOAD_FW	= 0x0000001c,
96	CAM_CMD_SECURITY	= 0x0000001d,
97	CAM_CMD_HPA		= 0x0000001e,
98	CAM_CMD_SANITIZE	= 0x0000001f,
99} cam_cmdmask;
100
101typedef enum {
102	CAM_ARG_NONE		= 0x00000000,
103	CAM_ARG_VERBOSE		= 0x00000001,
104	CAM_ARG_DEVICE		= 0x00000002,
105	CAM_ARG_BUS		= 0x00000004,
106	CAM_ARG_TARGET		= 0x00000008,
107	CAM_ARG_LUN		= 0x00000010,
108	CAM_ARG_EJECT		= 0x00000020,
109	CAM_ARG_UNIT		= 0x00000040,
110	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
111	CAM_ARG_FORMAT_BFI	= 0x00000100,
112	CAM_ARG_FORMAT_PHYS	= 0x00000200,
113	CAM_ARG_PLIST		= 0x00000400,
114	CAM_ARG_GLIST		= 0x00000800,
115	CAM_ARG_GET_SERIAL	= 0x00001000,
116	CAM_ARG_GET_STDINQ	= 0x00002000,
117	CAM_ARG_GET_XFERRATE	= 0x00004000,
118	CAM_ARG_INQ_MASK	= 0x00007000,
119	CAM_ARG_MODE_EDIT	= 0x00008000,
120	CAM_ARG_PAGE_CNTL	= 0x00010000,
121	CAM_ARG_TIMEOUT		= 0x00020000,
122	CAM_ARG_CMD_IN		= 0x00040000,
123	CAM_ARG_CMD_OUT		= 0x00080000,
124	CAM_ARG_DBD		= 0x00100000,
125	CAM_ARG_ERR_RECOVER	= 0x00200000,
126	CAM_ARG_RETRIES		= 0x00400000,
127	CAM_ARG_START_UNIT	= 0x00800000,
128	CAM_ARG_DEBUG_INFO	= 0x01000000,
129	CAM_ARG_DEBUG_TRACE	= 0x02000000,
130	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
131	CAM_ARG_DEBUG_CDB	= 0x08000000,
132	CAM_ARG_DEBUG_XPT	= 0x10000000,
133	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
134	CAM_ARG_DEBUG_PROBE	= 0x40000000,
135} cam_argmask;
136
137struct camcontrol_opts {
138	const char	*optname;
139	uint32_t	cmdnum;
140	cam_argmask	argnum;
141	const char	*subopt;
142};
143
144#ifndef MINIMALISTIC
145struct ata_res_pass16 {
146	u_int16_t reserved[5];
147	u_int8_t flags;
148	u_int8_t error;
149	u_int8_t sector_count_exp;
150	u_int8_t sector_count;
151	u_int8_t lba_low_exp;
152	u_int8_t lba_low;
153	u_int8_t lba_mid_exp;
154	u_int8_t lba_mid;
155	u_int8_t lba_high_exp;
156	u_int8_t lba_high;
157	u_int8_t device;
158	u_int8_t status;
159};
160
161struct ata_set_max_pwd
162{
163	u_int16_t reserved1;
164	u_int8_t password[32];
165	u_int16_t reserved2[239];
166};
167
168static const char scsicmd_opts[] = "a:c:dfi:o:r";
169static const char readdefect_opts[] = "f:GP";
170static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
171static const char smprg_opts[] = "l";
172static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:";
173static const char smpphylist_opts[] = "lq";
174static char pwd_opt;
175#endif
176
177static struct camcontrol_opts option_table[] = {
178#ifndef MINIMALISTIC
179	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
180	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
181	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
182	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
183	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
184	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
185	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
186	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
187	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
188#endif /* MINIMALISTIC */
189	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
190	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
191#ifndef MINIMALISTIC
192	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
193	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
194	{"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"},
195	{"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
196	{"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts},
197	{"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
198	{"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts},
199	{"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
200	{"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts},
201	{"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"},
202	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
203	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
204#endif /* MINIMALISTIC */
205	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
206#ifndef MINIMALISTIC
207	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
208	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
209	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
210	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
211	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
212	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXcp"},
213	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
214	{"sanitize", CAM_CMD_SANITIZE, CAM_ARG_NONE, "a:c:IP:qrUwy"},
215	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
216	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
217	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
218	{"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"},
219	{"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"},
220	{"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"},
221#endif /* MINIMALISTIC */
222	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
223	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
224	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
225	{NULL, 0, 0, NULL}
226};
227
228typedef enum {
229	CC_OR_NOT_FOUND,
230	CC_OR_AMBIGUOUS,
231	CC_OR_FOUND
232} camcontrol_optret;
233
234struct cam_devitem {
235	struct device_match_result dev_match;
236	int num_periphs;
237	struct periph_match_result *periph_matches;
238	struct scsi_vpd_device_id *device_id;
239	int device_id_len;
240	STAILQ_ENTRY(cam_devitem) links;
241};
242
243struct cam_devlist {
244	STAILQ_HEAD(, cam_devitem) dev_queue;
245	path_id_t path_id;
246};
247
248static cam_cmdmask cmdlist;
249static cam_argmask arglist;
250
251camcontrol_optret getoption(struct camcontrol_opts *table, char *arg,
252			    uint32_t *cmdnum, cam_argmask *argnum,
253			    const char **subopt);
254#ifndef MINIMALISTIC
255static int getdevlist(struct cam_device *device);
256#endif /* MINIMALISTIC */
257static int getdevtree(void);
258#ifndef MINIMALISTIC
259static int testunitready(struct cam_device *device, int retry_count,
260			 int timeout, int quiet);
261static int scsistart(struct cam_device *device, int startstop, int loadeject,
262		     int retry_count, int timeout);
263static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
264static int scsiserial(struct cam_device *device, int retry_count, int timeout);
265static int camxferrate(struct cam_device *device);
266#endif /* MINIMALISTIC */
267static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target,
268		     lun_id_t *lun, cam_argmask *arglst);
269static int dorescan_or_reset(int argc, char **argv, int rescan);
270static int rescan_or_reset_bus(path_id_t bus, int rescan);
271static int scanlun_or_reset_dev(path_id_t bus, target_id_t target,
272    lun_id_t lun, int scan);
273#ifndef MINIMALISTIC
274static int readdefects(struct cam_device *device, int argc, char **argv,
275		       char *combinedopt, int retry_count, int timeout);
276static void modepage(struct cam_device *device, int argc, char **argv,
277		     char *combinedopt, int retry_count, int timeout);
278static int scsicmd(struct cam_device *device, int argc, char **argv,
279		   char *combinedopt, int retry_count, int timeout);
280static int smpcmd(struct cam_device *device, int argc, char **argv,
281		  char *combinedopt, int retry_count, int timeout);
282static int smpreportgeneral(struct cam_device *device, int argc, char **argv,
283			    char *combinedopt, int retry_count, int timeout);
284static int smpphycontrol(struct cam_device *device, int argc, char **argv,
285			 char *combinedopt, int retry_count, int timeout);
286static int smpmaninfo(struct cam_device *device, int argc, char **argv,
287		      char *combinedopt, int retry_count, int timeout);
288static int getdevid(struct cam_devitem *item);
289static int buildbusdevlist(struct cam_devlist *devlist);
290static void freebusdevlist(struct cam_devlist *devlist);
291static struct cam_devitem *findsasdevice(struct cam_devlist *devlist,
292					 uint64_t sasaddr);
293static int smpphylist(struct cam_device *device, int argc, char **argv,
294		      char *combinedopt, int retry_count, int timeout);
295static int tagcontrol(struct cam_device *device, int argc, char **argv,
296		      char *combinedopt);
297static void cts_print(struct cam_device *device,
298		      struct ccb_trans_settings *cts);
299static void cpi_print(struct ccb_pathinq *cpi);
300static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
301static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
302static int get_print_cts(struct cam_device *device, int user_settings,
303			 int quiet, struct ccb_trans_settings *cts);
304static int ratecontrol(struct cam_device *device, int retry_count,
305		       int timeout, int argc, char **argv, char *combinedopt);
306static int scsiformat(struct cam_device *device, int argc, char **argv,
307		      char *combinedopt, int retry_count, int timeout);
308static int scsisanitize(struct cam_device *device, int argc, char **argv,
309			char *combinedopt, int retry_count, int timeout);
310static int scsireportluns(struct cam_device *device, int argc, char **argv,
311			  char *combinedopt, int retry_count, int timeout);
312static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
313			    char *combinedopt, int retry_count, int timeout);
314static int atapm(struct cam_device *device, int argc, char **argv,
315		 char *combinedopt, int retry_count, int timeout);
316static int atasecurity(struct cam_device *device, int retry_count, int timeout,
317		       int argc, char **argv, char *combinedopt);
318static int atahpa(struct cam_device *device, int retry_count, int timeout,
319		  int argc, char **argv, char *combinedopt);
320
321#endif /* MINIMALISTIC */
322#ifndef min
323#define min(a,b) (((a)<(b))?(a):(b))
324#endif
325#ifndef max
326#define max(a,b) (((a)>(b))?(a):(b))
327#endif
328
329camcontrol_optret
330getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum,
331	  cam_argmask *argnum, const char **subopt)
332{
333	struct camcontrol_opts *opts;
334	int num_matches = 0;
335
336	for (opts = table; (opts != NULL) && (opts->optname != NULL);
337	     opts++) {
338		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
339			*cmdnum = opts->cmdnum;
340			*argnum = opts->argnum;
341			*subopt = opts->subopt;
342			if (++num_matches > 1)
343				return(CC_OR_AMBIGUOUS);
344		}
345	}
346
347	if (num_matches > 0)
348		return(CC_OR_FOUND);
349	else
350		return(CC_OR_NOT_FOUND);
351}
352
353#ifndef MINIMALISTIC
354static int
355getdevlist(struct cam_device *device)
356{
357	union ccb *ccb;
358	char status[32];
359	int error = 0;
360
361	ccb = cam_getccb(device);
362
363	ccb->ccb_h.func_code = XPT_GDEVLIST;
364	ccb->ccb_h.flags = CAM_DIR_NONE;
365	ccb->ccb_h.retry_count = 1;
366	ccb->cgdl.index = 0;
367	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
368	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
369		if (cam_send_ccb(device, ccb) < 0) {
370			perror("error getting device list");
371			cam_freeccb(ccb);
372			return(1);
373		}
374
375		status[0] = '\0';
376
377		switch (ccb->cgdl.status) {
378			case CAM_GDEVLIST_MORE_DEVS:
379				strcpy(status, "MORE");
380				break;
381			case CAM_GDEVLIST_LAST_DEVICE:
382				strcpy(status, "LAST");
383				break;
384			case CAM_GDEVLIST_LIST_CHANGED:
385				strcpy(status, "CHANGED");
386				break;
387			case CAM_GDEVLIST_ERROR:
388				strcpy(status, "ERROR");
389				error = 1;
390				break;
391		}
392
393		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
394			ccb->cgdl.periph_name,
395			ccb->cgdl.unit_number,
396			ccb->cgdl.generation,
397			ccb->cgdl.index,
398			status);
399
400		/*
401		 * If the list has changed, we need to start over from the
402		 * beginning.
403		 */
404		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
405			ccb->cgdl.index = 0;
406	}
407
408	cam_freeccb(ccb);
409
410	return(error);
411}
412#endif /* MINIMALISTIC */
413
414static int
415getdevtree(void)
416{
417	union ccb ccb;
418	int bufsize, fd;
419	unsigned int i;
420	int need_close = 0;
421	int error = 0;
422	int skip_device = 0;
423
424	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
425		warn("couldn't open %s", XPT_DEVICE);
426		return(1);
427	}
428
429	bzero(&ccb, sizeof(union ccb));
430
431	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
432	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
433	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
434
435	ccb.ccb_h.func_code = XPT_DEV_MATCH;
436	bufsize = sizeof(struct dev_match_result) * 100;
437	ccb.cdm.match_buf_len = bufsize;
438	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
439	if (ccb.cdm.matches == NULL) {
440		warnx("can't malloc memory for matches");
441		close(fd);
442		return(1);
443	}
444	ccb.cdm.num_matches = 0;
445
446	/*
447	 * We fetch all nodes, since we display most of them in the default
448	 * case, and all in the verbose case.
449	 */
450	ccb.cdm.num_patterns = 0;
451	ccb.cdm.pattern_buf_len = 0;
452
453	/*
454	 * We do the ioctl multiple times if necessary, in case there are
455	 * more than 100 nodes in the EDT.
456	 */
457	do {
458		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
459			warn("error sending CAMIOCOMMAND ioctl");
460			error = 1;
461			break;
462		}
463
464		if ((ccb.ccb_h.status != CAM_REQ_CMP)
465		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
466		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
467			warnx("got CAM error %#x, CDM error %d\n",
468			      ccb.ccb_h.status, ccb.cdm.status);
469			error = 1;
470			break;
471		}
472
473		for (i = 0; i < ccb.cdm.num_matches; i++) {
474			switch (ccb.cdm.matches[i].type) {
475			case DEV_MATCH_BUS: {
476				struct bus_match_result *bus_result;
477
478				/*
479				 * Only print the bus information if the
480				 * user turns on the verbose flag.
481				 */
482				if ((arglist & CAM_ARG_VERBOSE) == 0)
483					break;
484
485				bus_result =
486					&ccb.cdm.matches[i].result.bus_result;
487
488				if (need_close) {
489					fprintf(stdout, ")\n");
490					need_close = 0;
491				}
492
493				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
494					bus_result->path_id,
495					bus_result->dev_name,
496					bus_result->unit_number,
497					bus_result->bus_id);
498				break;
499			}
500			case DEV_MATCH_DEVICE: {
501				struct device_match_result *dev_result;
502				char vendor[16], product[48], revision[16];
503				char fw[5], tmpstr[256];
504
505				dev_result =
506				     &ccb.cdm.matches[i].result.device_result;
507
508				if ((dev_result->flags
509				     & DEV_RESULT_UNCONFIGURED)
510				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
511					skip_device = 1;
512					break;
513				} else
514					skip_device = 0;
515
516				if (dev_result->protocol == PROTO_SCSI) {
517				    cam_strvis(vendor, dev_result->inq_data.vendor,
518					   sizeof(dev_result->inq_data.vendor),
519					   sizeof(vendor));
520				    cam_strvis(product,
521					   dev_result->inq_data.product,
522					   sizeof(dev_result->inq_data.product),
523					   sizeof(product));
524				    cam_strvis(revision,
525					   dev_result->inq_data.revision,
526					  sizeof(dev_result->inq_data.revision),
527					   sizeof(revision));
528				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
529					revision);
530				} else if (dev_result->protocol == PROTO_ATA ||
531				    dev_result->protocol == PROTO_SATAPM) {
532				    cam_strvis(product,
533					   dev_result->ident_data.model,
534					   sizeof(dev_result->ident_data.model),
535					   sizeof(product));
536				    cam_strvis(revision,
537					   dev_result->ident_data.revision,
538					  sizeof(dev_result->ident_data.revision),
539					   sizeof(revision));
540				    sprintf(tmpstr, "<%s %s>", product,
541					revision);
542				} else if (dev_result->protocol == PROTO_SEMB) {
543					struct sep_identify_data *sid;
544
545					sid = (struct sep_identify_data *)
546					    &dev_result->ident_data;
547					cam_strvis(vendor, sid->vendor_id,
548					    sizeof(sid->vendor_id),
549					    sizeof(vendor));
550					cam_strvis(product, sid->product_id,
551					    sizeof(sid->product_id),
552					    sizeof(product));
553					cam_strvis(revision, sid->product_rev,
554					    sizeof(sid->product_rev),
555					    sizeof(revision));
556					cam_strvis(fw, sid->firmware_rev,
557					    sizeof(sid->firmware_rev),
558					    sizeof(fw));
559					sprintf(tmpstr, "<%s %s %s %s>",
560					    vendor, product, revision, fw);
561				} else {
562				    sprintf(tmpstr, "<>");
563				}
564				if (need_close) {
565					fprintf(stdout, ")\n");
566					need_close = 0;
567				}
568
569				fprintf(stdout, "%-33s  at scbus%d "
570					"target %d lun %d (",
571					tmpstr,
572					dev_result->path_id,
573					dev_result->target_id,
574					dev_result->target_lun);
575
576				need_close = 1;
577
578				break;
579			}
580			case DEV_MATCH_PERIPH: {
581				struct periph_match_result *periph_result;
582
583				periph_result =
584				      &ccb.cdm.matches[i].result.periph_result;
585
586				if (skip_device != 0)
587					break;
588
589				if (need_close > 1)
590					fprintf(stdout, ",");
591
592				fprintf(stdout, "%s%d",
593					periph_result->periph_name,
594					periph_result->unit_number);
595
596				need_close++;
597				break;
598			}
599			default:
600				fprintf(stdout, "unknown match type\n");
601				break;
602			}
603		}
604
605	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
606		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
607
608	if (need_close)
609		fprintf(stdout, ")\n");
610
611	close(fd);
612
613	return(error);
614}
615
616#ifndef MINIMALISTIC
617static int
618testunitready(struct cam_device *device, int retry_count, int timeout,
619	      int quiet)
620{
621	int error = 0;
622	union ccb *ccb;
623
624	ccb = cam_getccb(device);
625
626	scsi_test_unit_ready(&ccb->csio,
627			     /* retries */ retry_count,
628			     /* cbfcnp */ NULL,
629			     /* tag_action */ MSG_SIMPLE_Q_TAG,
630			     /* sense_len */ SSD_FULL_SIZE,
631			     /* timeout */ timeout ? timeout : 5000);
632
633	/* Disable freezing the device queue */
634	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
635
636	if (arglist & CAM_ARG_ERR_RECOVER)
637		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
638
639	if (cam_send_ccb(device, ccb) < 0) {
640		if (quiet == 0)
641			perror("error sending test unit ready");
642
643		if (arglist & CAM_ARG_VERBOSE) {
644			cam_error_print(device, ccb, CAM_ESF_ALL,
645					CAM_EPF_ALL, stderr);
646		}
647
648		cam_freeccb(ccb);
649		return(1);
650	}
651
652	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
653		if (quiet == 0)
654			fprintf(stdout, "Unit is ready\n");
655	} else {
656		if (quiet == 0)
657			fprintf(stdout, "Unit is not ready\n");
658		error = 1;
659
660		if (arglist & CAM_ARG_VERBOSE) {
661			cam_error_print(device, ccb, CAM_ESF_ALL,
662					CAM_EPF_ALL, stderr);
663		}
664	}
665
666	cam_freeccb(ccb);
667
668	return(error);
669}
670
671static int
672scsistart(struct cam_device *device, int startstop, int loadeject,
673	  int retry_count, int timeout)
674{
675	union ccb *ccb;
676	int error = 0;
677
678	ccb = cam_getccb(device);
679
680	/*
681	 * If we're stopping, send an ordered tag so the drive in question
682	 * will finish any previously queued writes before stopping.  If
683	 * the device isn't capable of tagged queueing, or if tagged
684	 * queueing is turned off, the tag action is a no-op.
685	 */
686	scsi_start_stop(&ccb->csio,
687			/* retries */ retry_count,
688			/* cbfcnp */ NULL,
689			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
690						     MSG_ORDERED_Q_TAG,
691			/* start/stop */ startstop,
692			/* load_eject */ loadeject,
693			/* immediate */ 0,
694			/* sense_len */ SSD_FULL_SIZE,
695			/* timeout */ timeout ? timeout : 120000);
696
697	/* Disable freezing the device queue */
698	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
699
700	if (arglist & CAM_ARG_ERR_RECOVER)
701		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
702
703	if (cam_send_ccb(device, ccb) < 0) {
704		perror("error sending start unit");
705
706		if (arglist & CAM_ARG_VERBOSE) {
707			cam_error_print(device, ccb, CAM_ESF_ALL,
708					CAM_EPF_ALL, stderr);
709		}
710
711		cam_freeccb(ccb);
712		return(1);
713	}
714
715	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
716		if (startstop) {
717			fprintf(stdout, "Unit started successfully");
718			if (loadeject)
719				fprintf(stdout,", Media loaded\n");
720			else
721				fprintf(stdout,"\n");
722		} else {
723			fprintf(stdout, "Unit stopped successfully");
724			if (loadeject)
725				fprintf(stdout, ", Media ejected\n");
726			else
727				fprintf(stdout, "\n");
728		}
729	else {
730		error = 1;
731		if (startstop)
732			fprintf(stdout,
733				"Error received from start unit command\n");
734		else
735			fprintf(stdout,
736				"Error received from stop unit command\n");
737
738		if (arglist & CAM_ARG_VERBOSE) {
739			cam_error_print(device, ccb, CAM_ESF_ALL,
740					CAM_EPF_ALL, stderr);
741		}
742	}
743
744	cam_freeccb(ccb);
745
746	return(error);
747}
748
749int
750scsidoinquiry(struct cam_device *device, int argc, char **argv,
751	      char *combinedopt, int retry_count, int timeout)
752{
753	int c;
754	int error = 0;
755
756	while ((c = getopt(argc, argv, combinedopt)) != -1) {
757		switch(c) {
758		case 'D':
759			arglist |= CAM_ARG_GET_STDINQ;
760			break;
761		case 'R':
762			arglist |= CAM_ARG_GET_XFERRATE;
763			break;
764		case 'S':
765			arglist |= CAM_ARG_GET_SERIAL;
766			break;
767		default:
768			break;
769		}
770	}
771
772	/*
773	 * If the user didn't specify any inquiry options, he wants all of
774	 * them.
775	 */
776	if ((arglist & CAM_ARG_INQ_MASK) == 0)
777		arglist |= CAM_ARG_INQ_MASK;
778
779	if (arglist & CAM_ARG_GET_STDINQ)
780		error = scsiinquiry(device, retry_count, timeout);
781
782	if (error != 0)
783		return(error);
784
785	if (arglist & CAM_ARG_GET_SERIAL)
786		scsiserial(device, retry_count, timeout);
787
788	if (error != 0)
789		return(error);
790
791	if (arglist & CAM_ARG_GET_XFERRATE)
792		error = camxferrate(device);
793
794	return(error);
795}
796
797static int
798scsiinquiry(struct cam_device *device, int retry_count, int timeout)
799{
800	union ccb *ccb;
801	struct scsi_inquiry_data *inq_buf;
802	int error = 0;
803
804	ccb = cam_getccb(device);
805
806	if (ccb == NULL) {
807		warnx("couldn't allocate CCB");
808		return(1);
809	}
810
811	/* cam_getccb cleans up the header, caller has to zero the payload */
812	bzero(&(&ccb->ccb_h)[1],
813	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
814
815	inq_buf = (struct scsi_inquiry_data *)malloc(
816		sizeof(struct scsi_inquiry_data));
817
818	if (inq_buf == NULL) {
819		cam_freeccb(ccb);
820		warnx("can't malloc memory for inquiry\n");
821		return(1);
822	}
823	bzero(inq_buf, sizeof(*inq_buf));
824
825	/*
826	 * Note that although the size of the inquiry buffer is the full
827	 * 256 bytes specified in the SCSI spec, we only tell the device
828	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
829	 * two reasons for this:
830	 *
831	 *  - The SCSI spec says that when a length field is only 1 byte,
832	 *    a value of 0 will be interpreted as 256.  Therefore
833	 *    scsi_inquiry() will convert an inq_len (which is passed in as
834	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
835	 *    to 0.  Evidently, very few devices meet the spec in that
836	 *    regard.  Some devices, like many Seagate disks, take the 0 as
837	 *    0, and don't return any data.  One Pioneer DVD-R drive
838	 *    returns more data than the command asked for.
839	 *
840	 *    So, since there are numerous devices that just don't work
841	 *    right with the full inquiry size, we don't send the full size.
842	 *
843	 *  - The second reason not to use the full inquiry data length is
844	 *    that we don't need it here.  The only reason we issue a
845	 *    standard inquiry is to get the vendor name, device name,
846	 *    and revision so scsi_print_inquiry() can print them.
847	 *
848	 * If, at some point in the future, more inquiry data is needed for
849	 * some reason, this code should use a procedure similar to the
850	 * probe code.  i.e., issue a short inquiry, and determine from
851	 * the additional length passed back from the device how much
852	 * inquiry data the device supports.  Once the amount the device
853	 * supports is determined, issue an inquiry for that amount and no
854	 * more.
855	 *
856	 * KDM, 2/18/2000
857	 */
858	scsi_inquiry(&ccb->csio,
859		     /* retries */ retry_count,
860		     /* cbfcnp */ NULL,
861		     /* tag_action */ MSG_SIMPLE_Q_TAG,
862		     /* inq_buf */ (u_int8_t *)inq_buf,
863		     /* inq_len */ SHORT_INQUIRY_LENGTH,
864		     /* evpd */ 0,
865		     /* page_code */ 0,
866		     /* sense_len */ SSD_FULL_SIZE,
867		     /* timeout */ timeout ? timeout : 5000);
868
869	/* Disable freezing the device queue */
870	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
871
872	if (arglist & CAM_ARG_ERR_RECOVER)
873		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
874
875	if (cam_send_ccb(device, ccb) < 0) {
876		perror("error sending SCSI inquiry");
877
878		if (arglist & CAM_ARG_VERBOSE) {
879			cam_error_print(device, ccb, CAM_ESF_ALL,
880					CAM_EPF_ALL, stderr);
881		}
882
883		cam_freeccb(ccb);
884		return(1);
885	}
886
887	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
888		error = 1;
889
890		if (arglist & CAM_ARG_VERBOSE) {
891			cam_error_print(device, ccb, CAM_ESF_ALL,
892					CAM_EPF_ALL, stderr);
893		}
894	}
895
896	cam_freeccb(ccb);
897
898	if (error != 0) {
899		free(inq_buf);
900		return(error);
901	}
902
903	fprintf(stdout, "%s%d: ", device->device_name,
904		device->dev_unit_num);
905	scsi_print_inquiry(inq_buf);
906
907	free(inq_buf);
908
909	return(0);
910}
911
912static int
913scsiserial(struct cam_device *device, int retry_count, int timeout)
914{
915	union ccb *ccb;
916	struct scsi_vpd_unit_serial_number *serial_buf;
917	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
918	int error = 0;
919
920	ccb = cam_getccb(device);
921
922	if (ccb == NULL) {
923		warnx("couldn't allocate CCB");
924		return(1);
925	}
926
927	/* cam_getccb cleans up the header, caller has to zero the payload */
928	bzero(&(&ccb->ccb_h)[1],
929	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
930
931	serial_buf = (struct scsi_vpd_unit_serial_number *)
932		malloc(sizeof(*serial_buf));
933
934	if (serial_buf == NULL) {
935		cam_freeccb(ccb);
936		warnx("can't malloc memory for serial number");
937		return(1);
938	}
939
940	scsi_inquiry(&ccb->csio,
941		     /*retries*/ retry_count,
942		     /*cbfcnp*/ NULL,
943		     /* tag_action */ MSG_SIMPLE_Q_TAG,
944		     /* inq_buf */ (u_int8_t *)serial_buf,
945		     /* inq_len */ sizeof(*serial_buf),
946		     /* evpd */ 1,
947		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
948		     /* sense_len */ SSD_FULL_SIZE,
949		     /* timeout */ timeout ? timeout : 5000);
950
951	/* Disable freezing the device queue */
952	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
953
954	if (arglist & CAM_ARG_ERR_RECOVER)
955		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
956
957	if (cam_send_ccb(device, ccb) < 0) {
958		warn("error getting serial number");
959
960		if (arglist & CAM_ARG_VERBOSE) {
961			cam_error_print(device, ccb, CAM_ESF_ALL,
962					CAM_EPF_ALL, stderr);
963		}
964
965		cam_freeccb(ccb);
966		free(serial_buf);
967		return(1);
968	}
969
970	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
971		error = 1;
972
973		if (arglist & CAM_ARG_VERBOSE) {
974			cam_error_print(device, ccb, CAM_ESF_ALL,
975					CAM_EPF_ALL, stderr);
976		}
977	}
978
979	cam_freeccb(ccb);
980
981	if (error != 0) {
982		free(serial_buf);
983		return(error);
984	}
985
986	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
987	serial_num[serial_buf->length] = '\0';
988
989	if ((arglist & CAM_ARG_GET_STDINQ)
990	 || (arglist & CAM_ARG_GET_XFERRATE))
991		fprintf(stdout, "%s%d: Serial Number ",
992			device->device_name, device->dev_unit_num);
993
994	fprintf(stdout, "%.60s\n", serial_num);
995
996	free(serial_buf);
997
998	return(0);
999}
1000
1001static int
1002camxferrate(struct cam_device *device)
1003{
1004	struct ccb_pathinq cpi;
1005	u_int32_t freq = 0;
1006	u_int32_t speed = 0;
1007	union ccb *ccb;
1008	u_int mb;
1009	int retval = 0;
1010
1011	if ((retval = get_cpi(device, &cpi)) != 0)
1012		return (1);
1013
1014	ccb = cam_getccb(device);
1015
1016	if (ccb == NULL) {
1017		warnx("couldn't allocate CCB");
1018		return(1);
1019	}
1020
1021	bzero(&(&ccb->ccb_h)[1],
1022	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
1023
1024	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
1025	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
1026
1027	if (((retval = cam_send_ccb(device, ccb)) < 0)
1028	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1029		const char error_string[] = "error getting transfer settings";
1030
1031		if (retval < 0)
1032			warn(error_string);
1033		else
1034			warnx(error_string);
1035
1036		if (arglist & CAM_ARG_VERBOSE)
1037			cam_error_print(device, ccb, CAM_ESF_ALL,
1038					CAM_EPF_ALL, stderr);
1039
1040		retval = 1;
1041
1042		goto xferrate_bailout;
1043
1044	}
1045
1046	speed = cpi.base_transfer_speed;
1047	freq = 0;
1048	if (ccb->cts.transport == XPORT_SPI) {
1049		struct ccb_trans_settings_spi *spi =
1050		    &ccb->cts.xport_specific.spi;
1051
1052		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
1053			freq = scsi_calc_syncsrate(spi->sync_period);
1054			speed = freq;
1055		}
1056		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1057			speed *= (0x01 << spi->bus_width);
1058		}
1059	} else if (ccb->cts.transport == XPORT_FC) {
1060		struct ccb_trans_settings_fc *fc =
1061		    &ccb->cts.xport_specific.fc;
1062
1063		if (fc->valid & CTS_FC_VALID_SPEED)
1064			speed = fc->bitrate;
1065	} else if (ccb->cts.transport == XPORT_SAS) {
1066		struct ccb_trans_settings_sas *sas =
1067		    &ccb->cts.xport_specific.sas;
1068
1069		if (sas->valid & CTS_SAS_VALID_SPEED)
1070			speed = sas->bitrate;
1071	} else if (ccb->cts.transport == XPORT_ATA) {
1072		struct ccb_trans_settings_pata *pata =
1073		    &ccb->cts.xport_specific.ata;
1074
1075		if (pata->valid & CTS_ATA_VALID_MODE)
1076			speed = ata_mode2speed(pata->mode);
1077	} else if (ccb->cts.transport == XPORT_SATA) {
1078		struct	ccb_trans_settings_sata *sata =
1079		    &ccb->cts.xport_specific.sata;
1080
1081		if (sata->valid & CTS_SATA_VALID_REVISION)
1082			speed = ata_revision2speed(sata->revision);
1083	}
1084
1085	mb = speed / 1000;
1086	if (mb > 0) {
1087		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
1088			device->device_name, device->dev_unit_num,
1089			mb, speed % 1000);
1090	} else {
1091		fprintf(stdout, "%s%d: %dKB/s transfers",
1092			device->device_name, device->dev_unit_num,
1093			speed);
1094	}
1095
1096	if (ccb->cts.transport == XPORT_SPI) {
1097		struct ccb_trans_settings_spi *spi =
1098		    &ccb->cts.xport_specific.spi;
1099
1100		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1101		 && (spi->sync_offset != 0))
1102			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
1103				freq % 1000, spi->sync_offset);
1104
1105		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
1106		 && (spi->bus_width > 0)) {
1107			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1108			 && (spi->sync_offset != 0)) {
1109				fprintf(stdout, ", ");
1110			} else {
1111				fprintf(stdout, " (");
1112			}
1113			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1114		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1115		 && (spi->sync_offset != 0)) {
1116			fprintf(stdout, ")");
1117		}
1118	} else if (ccb->cts.transport == XPORT_ATA) {
1119		struct ccb_trans_settings_pata *pata =
1120		    &ccb->cts.xport_specific.ata;
1121
1122		printf(" (");
1123		if (pata->valid & CTS_ATA_VALID_MODE)
1124			printf("%s, ", ata_mode2string(pata->mode));
1125		if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
1126			printf("ATAPI %dbytes, ", pata->atapi);
1127		if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
1128			printf("PIO %dbytes", pata->bytecount);
1129		printf(")");
1130	} else if (ccb->cts.transport == XPORT_SATA) {
1131		struct ccb_trans_settings_sata *sata =
1132		    &ccb->cts.xport_specific.sata;
1133
1134		printf(" (");
1135		if (sata->valid & CTS_SATA_VALID_REVISION)
1136			printf("SATA %d.x, ", sata->revision);
1137		else
1138			printf("SATA, ");
1139		if (sata->valid & CTS_SATA_VALID_MODE)
1140			printf("%s, ", ata_mode2string(sata->mode));
1141		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1142			printf("ATAPI %dbytes, ", sata->atapi);
1143		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1144			printf("PIO %dbytes", sata->bytecount);
1145		printf(")");
1146	}
1147
1148	if (ccb->cts.protocol == PROTO_SCSI) {
1149		struct ccb_trans_settings_scsi *scsi =
1150		    &ccb->cts.proto_specific.scsi;
1151		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1152			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1153				fprintf(stdout, ", Command Queueing Enabled");
1154			}
1155		}
1156	}
1157
1158        fprintf(stdout, "\n");
1159
1160xferrate_bailout:
1161
1162	cam_freeccb(ccb);
1163
1164	return(retval);
1165}
1166
1167static void
1168atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
1169{
1170	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1171				((u_int32_t)parm->lba_size_2 << 16);
1172
1173	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1174				((u_int64_t)parm->lba_size48_2 << 16) |
1175				((u_int64_t)parm->lba_size48_3 << 32) |
1176				((u_int64_t)parm->lba_size48_4 << 48);
1177
1178	if (header) {
1179		printf("\nFeature                      "
1180		       "Support  Enabled   Value\n");
1181	}
1182
1183	printf("Host Protected Area (HPA)      ");
1184	if (parm->support.command1 & ATA_SUPPORT_PROTECTED) {
1185		u_int64_t lba = lbasize48 ? lbasize48 : lbasize;
1186		printf("yes      %s     %ju/%ju\n", (hpasize > lba) ? "yes" : "no ",
1187		        lba, hpasize);
1188
1189		printf("HPA - Security                 ");
1190		if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY)
1191			printf("yes\n");
1192		else
1193			printf("no\n");
1194	} else {
1195		printf("no\n");
1196	}
1197}
1198
1199static int
1200atasata(struct ata_params *parm)
1201{
1202
1203
1204	if (parm->satacapabilities != 0xffff &&
1205	    parm->satacapabilities != 0x0000)
1206		return 1;
1207
1208	return 0;
1209}
1210
1211static void
1212atacapprint(struct ata_params *parm)
1213{
1214	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1215				((u_int32_t)parm->lba_size_2 << 16);
1216
1217	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1218				((u_int64_t)parm->lba_size48_2 << 16) |
1219				((u_int64_t)parm->lba_size48_3 << 32) |
1220				((u_int64_t)parm->lba_size48_4 << 48);
1221
1222	printf("\n");
1223	printf("protocol              ");
1224	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1225	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1226		if (parm->satacapabilities & ATA_SATA_GEN3)
1227			printf(" SATA 3.x\n");
1228		else if (parm->satacapabilities & ATA_SATA_GEN2)
1229			printf(" SATA 2.x\n");
1230		else if (parm->satacapabilities & ATA_SATA_GEN1)
1231			printf(" SATA 1.x\n");
1232		else
1233			printf(" SATA\n");
1234	}
1235	else
1236		printf("\n");
1237	printf("device model          %.40s\n", parm->model);
1238	printf("firmware revision     %.8s\n", parm->revision);
1239	printf("serial number         %.20s\n", parm->serial);
1240	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1241		printf("WWN                   %04x%04x%04x%04x\n",
1242		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1243	}
1244	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1245		printf("media serial number   %.30s\n",
1246		    parm->media_serial);
1247	}
1248
1249	printf("cylinders             %d\n", parm->cylinders);
1250	printf("heads                 %d\n", parm->heads);
1251	printf("sectors/track         %d\n", parm->sectors);
1252	printf("sector size           logical %u, physical %lu, offset %lu\n",
1253	    ata_logical_sector_size(parm),
1254	    (unsigned long)ata_physical_sector_size(parm),
1255	    (unsigned long)ata_logical_sector_offset(parm));
1256
1257	if (parm->config == ATA_PROTO_CFA ||
1258	    (parm->support.command2 & ATA_SUPPORT_CFA))
1259		printf("CFA supported\n");
1260
1261	printf("LBA%ssupported         ",
1262		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1263	if (lbasize)
1264		printf("%d sectors\n", lbasize);
1265	else
1266		printf("\n");
1267
1268	printf("LBA48%ssupported       ",
1269		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1270	if (lbasize48)
1271		printf("%ju sectors\n", (uintmax_t)lbasize48);
1272	else
1273		printf("\n");
1274
1275	printf("PIO supported         PIO");
1276	switch (ata_max_pmode(parm)) {
1277	case ATA_PIO4:
1278		printf("4");
1279		break;
1280	case ATA_PIO3:
1281		printf("3");
1282		break;
1283	case ATA_PIO2:
1284		printf("2");
1285		break;
1286	case ATA_PIO1:
1287		printf("1");
1288		break;
1289	default:
1290		printf("0");
1291	}
1292	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1293		printf(" w/o IORDY");
1294	printf("\n");
1295
1296	printf("DMA%ssupported         ",
1297		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1298	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1299		if (parm->mwdmamodes & 0xff) {
1300			printf("WDMA");
1301			if (parm->mwdmamodes & 0x04)
1302				printf("2");
1303			else if (parm->mwdmamodes & 0x02)
1304				printf("1");
1305			else if (parm->mwdmamodes & 0x01)
1306				printf("0");
1307			printf(" ");
1308		}
1309		if ((parm->atavalid & ATA_FLAG_88) &&
1310		    (parm->udmamodes & 0xff)) {
1311			printf("UDMA");
1312			if (parm->udmamodes & 0x40)
1313				printf("6");
1314			else if (parm->udmamodes & 0x20)
1315				printf("5");
1316			else if (parm->udmamodes & 0x10)
1317				printf("4");
1318			else if (parm->udmamodes & 0x08)
1319				printf("3");
1320			else if (parm->udmamodes & 0x04)
1321				printf("2");
1322			else if (parm->udmamodes & 0x02)
1323				printf("1");
1324			else if (parm->udmamodes & 0x01)
1325				printf("0");
1326			printf(" ");
1327		}
1328	}
1329	printf("\n");
1330
1331	if (parm->media_rotation_rate == 1) {
1332		printf("media RPM             non-rotating\n");
1333	} else if (parm->media_rotation_rate >= 0x0401 &&
1334	    parm->media_rotation_rate <= 0xFFFE) {
1335		printf("media RPM             %d\n",
1336			parm->media_rotation_rate);
1337	}
1338
1339	printf("\nFeature                      "
1340		"Support  Enabled   Value           Vendor\n");
1341	printf("read ahead                     %s	%s\n",
1342		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1343		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1344	printf("write cache                    %s	%s\n",
1345		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1346		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1347	printf("flush cache                    %s	%s\n",
1348		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1349		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1350	printf("overlap                        %s\n",
1351		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1352	printf("Tagged Command Queuing (TCQ)   %s	%s",
1353		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1354		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1355		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1356			printf("	%d tags\n",
1357			    ATA_QUEUE_LEN(parm->queue) + 1);
1358		} else
1359			printf("\n");
1360	printf("Native Command Queuing (NCQ)   ");
1361	if (parm->satacapabilities != 0xffff &&
1362	    (parm->satacapabilities & ATA_SUPPORT_NCQ)) {
1363		printf("yes		%d tags\n",
1364		    ATA_QUEUE_LEN(parm->queue) + 1);
1365	} else
1366		printf("no\n");
1367
1368	printf("NCQ Queue Management           %s\n", atasata(parm) &&
1369		parm->satacapabilities2 & ATA_SUPPORT_NCQ_QMANAGEMENT ?
1370		"yes" : "no");
1371	printf("NCQ Streaming                  %s\n", atasata(parm) &&
1372		parm->satacapabilities2 & ATA_SUPPORT_NCQ_STREAM ?
1373		"yes" : "no");
1374	printf("Receive & Send FPDMA Queued    %s\n", atasata(parm) &&
1375		parm->satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED ?
1376		"yes" : "no");
1377
1378	printf("SMART                          %s	%s\n",
1379		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1380		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1381	printf("microcode download             %s	%s\n",
1382		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1383		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1384	printf("security                       %s	%s\n",
1385		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1386		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1387	printf("power management               %s	%s\n",
1388		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1389		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1390	printf("advanced power management      %s	%s",
1391		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1392		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no");
1393		if (parm->support.command2 & ATA_SUPPORT_APM) {
1394			printf("	%d/0x%02X\n",
1395			    parm->apm_value, parm->apm_value);
1396		} else
1397			printf("\n");
1398	printf("automatic acoustic management  %s	%s",
1399		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1400		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no");
1401		if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) {
1402			printf("	%d/0x%02X	%d/0x%02X\n",
1403			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1404			    ATA_ACOUSTIC_CURRENT(parm->acoustic),
1405			    ATA_ACOUSTIC_VENDOR(parm->acoustic),
1406			    ATA_ACOUSTIC_VENDOR(parm->acoustic));
1407		} else
1408			printf("\n");
1409	printf("media status notification      %s	%s\n",
1410		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1411		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1412	printf("power-up in Standby            %s	%s\n",
1413		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1414		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1415	printf("write-read-verify              %s	%s",
1416		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1417		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no");
1418		if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) {
1419			printf("	%d/0x%x\n",
1420			    parm->wrv_mode, parm->wrv_mode);
1421		} else
1422			printf("\n");
1423	printf("unload                         %s	%s\n",
1424		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1425		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1426	printf("general purpose logging        %s	%s\n",
1427		parm->support.extension & ATA_SUPPORT_GENLOG ? "yes" : "no",
1428		parm->enabled.extension & ATA_SUPPORT_GENLOG ? "yes" : "no");
1429	printf("free-fall                      %s	%s\n",
1430		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1431		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1432	printf("Data Set Management (DSM/TRIM) ");
1433	if (parm->support_dsm & ATA_SUPPORT_DSM_TRIM) {
1434		printf("yes\n");
1435		printf("DSM - max 512byte blocks       ");
1436		if (parm->max_dsm_blocks == 0x00)
1437			printf("yes              not specified\n");
1438		else
1439			printf("yes              %d\n",
1440				parm->max_dsm_blocks);
1441
1442		printf("DSM - deterministic read       ");
1443		if (parm->support3 & ATA_SUPPORT_DRAT) {
1444			if (parm->support3 & ATA_SUPPORT_RZAT)
1445				printf("yes              zeroed\n");
1446			else
1447				printf("yes              any value\n");
1448		} else {
1449			printf("no\n");
1450		}
1451	} else {
1452		printf("no\n");
1453	}
1454}
1455
1456static int
1457scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
1458{
1459	struct ata_pass_16 *ata_pass_16;
1460	struct ata_cmd ata_cmd;
1461
1462	ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
1463	ata_cmd.command = ata_pass_16->command;
1464	ata_cmd.control = ata_pass_16->control;
1465	ata_cmd.features = ata_pass_16->features;
1466
1467	if (arglist & CAM_ARG_VERBOSE) {
1468		warnx("sending ATA %s via pass_16 with timeout of %u msecs",
1469		      ata_op_string(&ata_cmd),
1470		      ccb->csio.ccb_h.timeout);
1471	}
1472
1473	/* Disable freezing the device queue */
1474	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1475
1476	if (arglist & CAM_ARG_ERR_RECOVER)
1477		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1478
1479	if (cam_send_ccb(device, ccb) < 0) {
1480		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1481			warn("error sending ATA %s via pass_16",
1482			     ata_op_string(&ata_cmd));
1483		}
1484
1485		if (arglist & CAM_ARG_VERBOSE) {
1486			cam_error_print(device, ccb, CAM_ESF_ALL,
1487					CAM_EPF_ALL, stderr);
1488		}
1489
1490		return (1);
1491	}
1492
1493	if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
1494	    (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1495		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1496			warnx("ATA %s via pass_16 failed",
1497			      ata_op_string(&ata_cmd));
1498		}
1499		if (arglist & CAM_ARG_VERBOSE) {
1500			cam_error_print(device, ccb, CAM_ESF_ALL,
1501					CAM_EPF_ALL, stderr);
1502		}
1503
1504		return (1);
1505	}
1506
1507	return (0);
1508}
1509
1510
1511static int
1512ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
1513{
1514	if (arglist & CAM_ARG_VERBOSE) {
1515		warnx("sending ATA %s with timeout of %u msecs",
1516		      ata_op_string(&(ccb->ataio.cmd)),
1517		      ccb->ataio.ccb_h.timeout);
1518	}
1519
1520	/* Disable freezing the device queue */
1521	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1522
1523	if (arglist & CAM_ARG_ERR_RECOVER)
1524		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1525
1526	if (cam_send_ccb(device, ccb) < 0) {
1527		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1528			warn("error sending ATA %s",
1529			     ata_op_string(&(ccb->ataio.cmd)));
1530		}
1531
1532		if (arglist & CAM_ARG_VERBOSE) {
1533			cam_error_print(device, ccb, CAM_ESF_ALL,
1534					CAM_EPF_ALL, stderr);
1535		}
1536
1537		return (1);
1538	}
1539
1540	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1541		if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
1542			warnx("ATA %s failed: %d",
1543			      ata_op_string(&(ccb->ataio.cmd)), quiet);
1544		}
1545
1546		if (arglist & CAM_ARG_VERBOSE) {
1547			cam_error_print(device, ccb, CAM_ESF_ALL,
1548					CAM_EPF_ALL, stderr);
1549		}
1550
1551		return (1);
1552	}
1553
1554	return (0);
1555}
1556
1557static int
1558ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
1559	       u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1560	       u_int8_t tag_action, u_int8_t command, u_int8_t features,
1561	       u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1562	       u_int16_t dxfer_len, int timeout, int quiet)
1563{
1564	if (data_ptr != NULL) {
1565		ata_flags |= AP_FLAG_BYT_BLOK_BYTES |
1566			    AP_FLAG_TLEN_SECT_CNT;
1567		if (flags & CAM_DIR_OUT)
1568			ata_flags |= AP_FLAG_TDIR_TO_DEV;
1569		else
1570			ata_flags |= AP_FLAG_TDIR_FROM_DEV;
1571	} else {
1572		ata_flags |= AP_FLAG_TLEN_NO_DATA;
1573	}
1574
1575	bzero(&(&ccb->ccb_h)[1],
1576	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1577
1578	scsi_ata_pass_16(&ccb->csio,
1579			 retries,
1580			 NULL,
1581			 flags,
1582			 tag_action,
1583			 protocol,
1584			 ata_flags,
1585			 features,
1586			 sector_count,
1587			 lba,
1588			 command,
1589			 /*control*/0,
1590			 data_ptr,
1591			 dxfer_len,
1592			 /*sense_len*/SSD_FULL_SIZE,
1593			 timeout);
1594
1595	return scsi_cam_pass_16_send(device, ccb, quiet);
1596}
1597
1598static int
1599ata_try_pass_16(struct cam_device *device)
1600{
1601	struct ccb_pathinq cpi;
1602
1603	if (get_cpi(device, &cpi) != 0) {
1604		warnx("couldn't get CPI");
1605		return (-1);
1606	}
1607
1608	if (cpi.protocol == PROTO_SCSI) {
1609		/* possibly compatible with pass_16 */
1610		return (1);
1611	}
1612
1613	/* likely not compatible with pass_16 */
1614	return (0);
1615}
1616
1617static int
1618ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries,
1619		 u_int32_t flags, u_int8_t protocol, u_int8_t tag_action,
1620		 u_int8_t command, u_int8_t features, u_int32_t lba,
1621		 u_int8_t sector_count, u_int8_t *data_ptr, u_int16_t dxfer_len,
1622		 int timeout, int quiet)
1623{
1624
1625
1626	switch (ata_try_pass_16(device)) {
1627	case -1:
1628		return (1);
1629	case 1:
1630		/* Try using SCSI Passthrough */
1631		return ata_do_pass_16(device, ccb, retries, flags, protocol,
1632				      0, tag_action, command, features, lba,
1633				      sector_count, data_ptr, dxfer_len,
1634				      timeout, quiet);
1635	}
1636
1637	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1638	      sizeof(struct ccb_hdr));
1639	cam_fill_ataio(&ccb->ataio,
1640		       retries,
1641		       NULL,
1642		       flags,
1643		       tag_action,
1644		       data_ptr,
1645		       dxfer_len,
1646		       timeout);
1647
1648	ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1649	return ata_cam_send(device, ccb, quiet);
1650}
1651
1652static int
1653ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
1654	   u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
1655	   u_int8_t tag_action, u_int8_t command, u_int8_t features,
1656	   u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr,
1657	   u_int16_t dxfer_len, int timeout, int force48bit)
1658{
1659	int retval;
1660
1661	retval = ata_try_pass_16(device);
1662	if (retval == -1)
1663		return (1);
1664
1665	if (retval == 1) {
1666		int error;
1667
1668		/* Try using SCSI Passthrough */
1669		error = ata_do_pass_16(device, ccb, retries, flags, protocol,
1670				      ata_flags, tag_action, command, features,
1671				      lba, sector_count, data_ptr, dxfer_len,
1672				      timeout, 0);
1673
1674		if (ata_flags & AP_FLAG_CHK_COND) {
1675			/* Decode ata_res from sense data */
1676			struct ata_res_pass16 *res_pass16;
1677			struct ata_res *res;
1678			u_int i;
1679			u_int16_t *ptr;
1680
1681			/* sense_data is 4 byte aligned */
1682			ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
1683			for (i = 0; i < sizeof(*res_pass16) / 2; i++)
1684				ptr[i] = le16toh(ptr[i]);
1685
1686			/* sense_data is 4 byte aligned */
1687			res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
1688			    &ccb->csio.sense_data;
1689			res = &ccb->ataio.res;
1690			res->flags = res_pass16->flags;
1691			res->status = res_pass16->status;
1692			res->error = res_pass16->error;
1693			res->lba_low = res_pass16->lba_low;
1694			res->lba_mid = res_pass16->lba_mid;
1695			res->lba_high = res_pass16->lba_high;
1696			res->device = res_pass16->device;
1697			res->lba_low_exp = res_pass16->lba_low_exp;
1698			res->lba_mid_exp = res_pass16->lba_mid_exp;
1699			res->lba_high_exp = res_pass16->lba_high_exp;
1700			res->sector_count = res_pass16->sector_count;
1701			res->sector_count_exp = res_pass16->sector_count_exp;
1702		}
1703
1704		return (error);
1705	}
1706
1707	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) -
1708	      sizeof(struct ccb_hdr));
1709	cam_fill_ataio(&ccb->ataio,
1710		       retries,
1711		       NULL,
1712		       flags,
1713		       tag_action,
1714		       data_ptr,
1715		       dxfer_len,
1716		       timeout);
1717
1718	if (force48bit || lba > ATA_MAX_28BIT_LBA)
1719		ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1720	else
1721		ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count);
1722
1723	if (ata_flags & AP_FLAG_CHK_COND)
1724		ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
1725
1726	return ata_cam_send(device, ccb, 0);
1727}
1728
1729static void
1730dump_data(uint16_t *ptr, uint32_t len)
1731{
1732	u_int i;
1733
1734	for (i = 0; i < len / 2; i++) {
1735		if ((i % 8) == 0)
1736			printf(" %3d: ", i);
1737		printf("%04hx ", ptr[i]);
1738		if ((i % 8) == 7)
1739			printf("\n");
1740	}
1741	if ((i % 8) != 7)
1742		printf("\n");
1743}
1744
1745static int
1746atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
1747		 int is48bit, u_int64_t *hpasize)
1748{
1749	struct ata_res *res;
1750
1751	res = &ccb->ataio.res;
1752	if (res->status & ATA_STATUS_ERROR) {
1753		if (arglist & CAM_ARG_VERBOSE) {
1754			cam_error_print(device, ccb, CAM_ESF_ALL,
1755					CAM_EPF_ALL, stderr);
1756			printf("error = 0x%02x, sector_count = 0x%04x, "
1757			       "device = 0x%02x, status = 0x%02x\n",
1758			       res->error, res->sector_count,
1759			       res->device, res->status);
1760		}
1761
1762		if (res->error & ATA_ERROR_ID_NOT_FOUND) {
1763			warnx("Max address has already been set since "
1764			      "last power-on or hardware reset");
1765		}
1766
1767		return (1);
1768	}
1769
1770	if (arglist & CAM_ARG_VERBOSE) {
1771		fprintf(stdout, "%s%d: Raw native max data:\n",
1772			device->device_name, device->dev_unit_num);
1773		/* res is 4 byte aligned */
1774		dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
1775
1776		printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
1777		       "status = 0x%02x\n", res->error, res->sector_count,
1778		       res->device, res->status);
1779	}
1780
1781	if (hpasize != NULL) {
1782		if (is48bit) {
1783			*hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
1784			    (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
1785			    ((res->lba_high << 16) | (res->lba_mid << 8) |
1786			    res->lba_low)) + 1;
1787		} else {
1788			*hpasize = (((res->device & 0x0f) << 24) |
1789			    (res->lba_high << 16) | (res->lba_mid << 8) |
1790			    res->lba_low) + 1;
1791		}
1792	}
1793
1794	return (0);
1795}
1796
1797static int
1798ata_read_native_max(struct cam_device *device, int retry_count,
1799		      u_int32_t timeout, union ccb *ccb,
1800		      struct ata_params *parm, u_int64_t *hpasize)
1801{
1802	int error;
1803	u_int cmd, is48bit;
1804	u_int8_t protocol;
1805
1806	is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
1807	protocol = AP_PROTO_NON_DATA;
1808
1809	if (is48bit) {
1810		cmd = ATA_READ_NATIVE_MAX_ADDRESS48;
1811		protocol |= AP_EXTEND;
1812	} else {
1813		cmd = ATA_READ_NATIVE_MAX_ADDRESS;
1814	}
1815
1816	error = ata_do_cmd(device,
1817			   ccb,
1818			   retry_count,
1819			   /*flags*/CAM_DIR_NONE,
1820			   /*protocol*/protocol,
1821			   /*ata_flags*/AP_FLAG_CHK_COND,
1822			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1823			   /*command*/cmd,
1824			   /*features*/0,
1825			   /*lba*/0,
1826			   /*sector_count*/0,
1827			   /*data_ptr*/NULL,
1828			   /*dxfer_len*/0,
1829			   timeout ? timeout : 1000,
1830			   is48bit);
1831
1832	if (error)
1833		return (error);
1834
1835	return atahpa_proc_resp(device, ccb, is48bit, hpasize);
1836}
1837
1838static int
1839atahpa_set_max(struct cam_device *device, int retry_count,
1840	      u_int32_t timeout, union ccb *ccb,
1841	      int is48bit, u_int64_t maxsize, int persist)
1842{
1843	int error;
1844	u_int cmd;
1845	u_int8_t protocol;
1846
1847	protocol = AP_PROTO_NON_DATA;
1848
1849	if (is48bit) {
1850		cmd = ATA_SET_MAX_ADDRESS48;
1851		protocol |= AP_EXTEND;
1852	} else {
1853		cmd = ATA_SET_MAX_ADDRESS;
1854	}
1855
1856	/* lba's are zero indexed so the max lba is requested max - 1 */
1857	if (maxsize)
1858		maxsize--;
1859
1860	error = ata_do_cmd(device,
1861			   ccb,
1862			   retry_count,
1863			   /*flags*/CAM_DIR_NONE,
1864			   /*protocol*/protocol,
1865			   /*ata_flags*/AP_FLAG_CHK_COND,
1866			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1867			   /*command*/cmd,
1868			   /*features*/ATA_HPA_FEAT_MAX_ADDR,
1869			   /*lba*/maxsize,
1870			   /*sector_count*/persist,
1871			   /*data_ptr*/NULL,
1872			   /*dxfer_len*/0,
1873			   timeout ? timeout : 1000,
1874			   is48bit);
1875
1876	if (error)
1877		return (error);
1878
1879	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1880}
1881
1882static int
1883atahpa_password(struct cam_device *device, int retry_count,
1884		u_int32_t timeout, union ccb *ccb,
1885		int is48bit, struct ata_set_max_pwd *pwd)
1886{
1887	int error;
1888	u_int cmd;
1889	u_int8_t protocol;
1890
1891	protocol = AP_PROTO_PIO_OUT;
1892	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1893
1894	error = ata_do_cmd(device,
1895			   ccb,
1896			   retry_count,
1897			   /*flags*/CAM_DIR_OUT,
1898			   /*protocol*/protocol,
1899			   /*ata_flags*/AP_FLAG_CHK_COND,
1900			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1901			   /*command*/cmd,
1902			   /*features*/ATA_HPA_FEAT_SET_PWD,
1903			   /*lba*/0,
1904			   /*sector_count*/0,
1905			   /*data_ptr*/(u_int8_t*)pwd,
1906			   /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1907			   timeout ? timeout : 1000,
1908			   is48bit);
1909
1910	if (error)
1911		return (error);
1912
1913	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1914}
1915
1916static int
1917atahpa_lock(struct cam_device *device, int retry_count,
1918	    u_int32_t timeout, union ccb *ccb, int is48bit)
1919{
1920	int error;
1921	u_int cmd;
1922	u_int8_t protocol;
1923
1924	protocol = AP_PROTO_NON_DATA;
1925	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1926
1927	error = ata_do_cmd(device,
1928			   ccb,
1929			   retry_count,
1930			   /*flags*/CAM_DIR_NONE,
1931			   /*protocol*/protocol,
1932			   /*ata_flags*/AP_FLAG_CHK_COND,
1933			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1934			   /*command*/cmd,
1935			   /*features*/ATA_HPA_FEAT_LOCK,
1936			   /*lba*/0,
1937			   /*sector_count*/0,
1938			   /*data_ptr*/NULL,
1939			   /*dxfer_len*/0,
1940			   timeout ? timeout : 1000,
1941			   is48bit);
1942
1943	if (error)
1944		return (error);
1945
1946	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1947}
1948
1949static int
1950atahpa_unlock(struct cam_device *device, int retry_count,
1951	      u_int32_t timeout, union ccb *ccb,
1952	      int is48bit, struct ata_set_max_pwd *pwd)
1953{
1954	int error;
1955	u_int cmd;
1956	u_int8_t protocol;
1957
1958	protocol = AP_PROTO_PIO_OUT;
1959	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1960
1961	error = ata_do_cmd(device,
1962			   ccb,
1963			   retry_count,
1964			   /*flags*/CAM_DIR_OUT,
1965			   /*protocol*/protocol,
1966			   /*ata_flags*/AP_FLAG_CHK_COND,
1967			   /*tag_action*/MSG_SIMPLE_Q_TAG,
1968			   /*command*/cmd,
1969			   /*features*/ATA_HPA_FEAT_UNLOCK,
1970			   /*lba*/0,
1971			   /*sector_count*/0,
1972			   /*data_ptr*/(u_int8_t*)pwd,
1973			   /*dxfer_len*/sizeof(struct ata_set_max_pwd),
1974			   timeout ? timeout : 1000,
1975			   is48bit);
1976
1977	if (error)
1978		return (error);
1979
1980	return atahpa_proc_resp(device, ccb, is48bit, NULL);
1981}
1982
1983static int
1984atahpa_freeze_lock(struct cam_device *device, int retry_count,
1985		   u_int32_t timeout, union ccb *ccb, int is48bit)
1986{
1987	int error;
1988	u_int cmd;
1989	u_int8_t protocol;
1990
1991	protocol = AP_PROTO_NON_DATA;
1992	cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
1993
1994	error = ata_do_cmd(device,
1995			   ccb,
1996			   retry_count,
1997			   /*flags*/CAM_DIR_NONE,
1998			   /*protocol*/protocol,
1999			   /*ata_flags*/AP_FLAG_CHK_COND,
2000			   /*tag_action*/MSG_SIMPLE_Q_TAG,
2001			   /*command*/cmd,
2002			   /*features*/ATA_HPA_FEAT_FREEZE,
2003			   /*lba*/0,
2004			   /*sector_count*/0,
2005			   /*data_ptr*/NULL,
2006			   /*dxfer_len*/0,
2007			   timeout ? timeout : 1000,
2008			   is48bit);
2009
2010	if (error)
2011		return (error);
2012
2013	return atahpa_proc_resp(device, ccb, is48bit, NULL);
2014}
2015
2016
2017static int
2018ata_do_identify(struct cam_device *device, int retry_count, int timeout,
2019		union ccb *ccb, struct ata_params** ident_bufp)
2020{
2021	struct ata_params *ident_buf;
2022	struct ccb_pathinq cpi;
2023	struct ccb_getdev cgd;
2024	u_int i, error;
2025	int16_t *ptr;
2026	u_int8_t command, retry_command;
2027
2028	if (get_cpi(device, &cpi) != 0) {
2029		warnx("couldn't get CPI");
2030		return (-1);
2031	}
2032
2033	/* Neither PROTO_ATAPI or PROTO_SATAPM are used in cpi.protocol */
2034	if (cpi.protocol == PROTO_ATA) {
2035		if (get_cgd(device, &cgd) != 0) {
2036			warnx("couldn't get CGD");
2037			return (-1);
2038		}
2039
2040		command = (cgd.protocol == PROTO_ATA) ?
2041		    ATA_ATA_IDENTIFY : ATA_ATAPI_IDENTIFY;
2042		retry_command = 0;
2043	} else {
2044		/* We don't know which for sure so try both */
2045		command = ATA_ATA_IDENTIFY;
2046		retry_command = ATA_ATAPI_IDENTIFY;
2047	}
2048
2049	ptr = (uint16_t *)calloc(1, sizeof(struct ata_params));
2050	if (ptr == NULL) {
2051		warnx("can't calloc memory for identify\n");
2052		return (1);
2053	}
2054
2055	error = ata_do_28bit_cmd(device,
2056				 ccb,
2057				 /*retries*/retry_count,
2058				 /*flags*/CAM_DIR_IN,
2059				 /*protocol*/AP_PROTO_PIO_IN,
2060				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2061				 /*command*/command,
2062				 /*features*/0,
2063				 /*lba*/0,
2064				 /*sector_count*/(u_int8_t)sizeof(struct ata_params),
2065				 /*data_ptr*/(u_int8_t *)ptr,
2066				 /*dxfer_len*/sizeof(struct ata_params),
2067				 /*timeout*/timeout ? timeout : 30 * 1000,
2068				 /*quiet*/1);
2069
2070	if (error != 0) {
2071		if (retry_command == 0) {
2072			free(ptr);
2073			return (1);
2074		}
2075		error = ata_do_28bit_cmd(device,
2076					 ccb,
2077					 /*retries*/retry_count,
2078					 /*flags*/CAM_DIR_IN,
2079					 /*protocol*/AP_PROTO_PIO_IN,
2080					 /*tag_action*/MSG_SIMPLE_Q_TAG,
2081					 /*command*/retry_command,
2082					 /*features*/0,
2083					 /*lba*/0,
2084					 /*sector_count*/(u_int8_t)
2085					     sizeof(struct ata_params),
2086					 /*data_ptr*/(u_int8_t *)ptr,
2087					 /*dxfer_len*/sizeof(struct ata_params),
2088					 /*timeout*/timeout ? timeout : 30 * 1000,
2089					 /*quiet*/0);
2090
2091		if (error != 0) {
2092			free(ptr);
2093			return (1);
2094		}
2095	}
2096
2097	error = 1;
2098	for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
2099		ptr[i] = le16toh(ptr[i]);
2100		if (ptr[i] != 0)
2101			error = 0;
2102	}
2103
2104	if (arglist & CAM_ARG_VERBOSE) {
2105		fprintf(stdout, "%s%d: Raw identify data:\n",
2106		    device->device_name, device->dev_unit_num);
2107		dump_data(ptr, sizeof(struct ata_params));
2108	}
2109
2110	/* check for invalid (all zero) response */
2111	if (error != 0) {
2112		warnx("Invalid identify response detected");
2113		free(ptr);
2114		return (error);
2115	}
2116
2117	ident_buf = (struct ata_params *)ptr;
2118	if (strncmp(ident_buf->model, "FX", 2) &&
2119	    strncmp(ident_buf->model, "NEC", 3) &&
2120	    strncmp(ident_buf->model, "Pioneer", 7) &&
2121	    strncmp(ident_buf->model, "SHARP", 5)) {
2122		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
2123		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
2124		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
2125		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2126	}
2127	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
2128	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
2129	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
2130	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
2131	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
2132	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
2133	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
2134	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
2135	    sizeof(ident_buf->media_serial));
2136
2137	*ident_bufp = ident_buf;
2138
2139	return (0);
2140}
2141
2142
2143static int
2144ataidentify(struct cam_device *device, int retry_count, int timeout)
2145{
2146	union ccb *ccb;
2147	struct ata_params *ident_buf;
2148	u_int64_t hpasize;
2149
2150	if ((ccb = cam_getccb(device)) == NULL) {
2151		warnx("couldn't allocate CCB");
2152		return (1);
2153	}
2154
2155	if (ata_do_identify(device, retry_count, timeout, ccb, &ident_buf) != 0) {
2156		cam_freeccb(ccb);
2157		return (1);
2158	}
2159
2160	if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
2161		if (ata_read_native_max(device, retry_count, timeout, ccb,
2162					ident_buf, &hpasize) != 0) {
2163			cam_freeccb(ccb);
2164			return (1);
2165		}
2166	} else {
2167		hpasize = 0;
2168	}
2169
2170	printf("%s%d: ", device->device_name, device->dev_unit_num);
2171	ata_print_ident(ident_buf);
2172	camxferrate(device);
2173	atacapprint(ident_buf);
2174	atahpa_print(ident_buf, hpasize, 0);
2175
2176	free(ident_buf);
2177	cam_freeccb(ccb);
2178
2179	return (0);
2180}
2181#endif /* MINIMALISTIC */
2182
2183
2184#ifndef MINIMALISTIC
2185enum {
2186	ATA_SECURITY_ACTION_PRINT,
2187	ATA_SECURITY_ACTION_FREEZE,
2188	ATA_SECURITY_ACTION_UNLOCK,
2189	ATA_SECURITY_ACTION_DISABLE,
2190	ATA_SECURITY_ACTION_ERASE,
2191	ATA_SECURITY_ACTION_ERASE_ENHANCED,
2192	ATA_SECURITY_ACTION_SET_PASSWORD
2193} atasecurity_action;
2194
2195static void
2196atasecurity_print_time(u_int16_t tw)
2197{
2198
2199	if (tw == 0)
2200		printf("unspecified");
2201	else if (tw >= 255)
2202		printf("> 508 min");
2203	else
2204		printf("%i min", 2 * tw);
2205}
2206
2207static u_int32_t
2208atasecurity_erase_timeout_msecs(u_int16_t timeout)
2209{
2210
2211	if (timeout == 0)
2212		return 2 * 3600 * 1000; /* default: two hours */
2213	else if (timeout > 255)
2214		return (508 + 60) * 60 * 1000; /* spec says > 508 minutes */
2215
2216	return ((2 * timeout) + 5) * 60 * 1000; /* add a 5min margin */
2217}
2218
2219
2220static void
2221atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
2222{
2223	struct ata_cmd cmd;
2224
2225	bzero(&cmd, sizeof(cmd));
2226	cmd.command = command;
2227	printf("Issuing %s", ata_op_string(&cmd));
2228
2229	if (pwd != NULL) {
2230		char pass[sizeof(pwd->password)+1];
2231
2232		/* pwd->password may not be null terminated */
2233		pass[sizeof(pwd->password)] = '\0';
2234		strncpy(pass, pwd->password, sizeof(pwd->password));
2235		printf(" password='%s', user='%s'",
2236			pass,
2237			(pwd->ctrl & ATA_SECURITY_PASSWORD_MASTER) ?
2238			"master" : "user");
2239
2240		if (command == ATA_SECURITY_SET_PASSWORD) {
2241			printf(", mode='%s'",
2242			       (pwd->ctrl & ATA_SECURITY_LEVEL_MAXIMUM) ?
2243			       "maximum" : "high");
2244		}
2245	}
2246
2247	printf("\n");
2248}
2249
2250static int
2251atasecurity_freeze(struct cam_device *device, union ccb *ccb,
2252		   int retry_count, u_int32_t timeout, int quiet)
2253{
2254
2255	if (quiet == 0)
2256		atasecurity_notify(ATA_SECURITY_FREEZE_LOCK, NULL);
2257
2258	return ata_do_28bit_cmd(device,
2259				ccb,
2260				retry_count,
2261				/*flags*/CAM_DIR_NONE,
2262				/*protocol*/AP_PROTO_NON_DATA,
2263				/*tag_action*/MSG_SIMPLE_Q_TAG,
2264				/*command*/ATA_SECURITY_FREEZE_LOCK,
2265				/*features*/0,
2266				/*lba*/0,
2267				/*sector_count*/0,
2268				/*data_ptr*/NULL,
2269				/*dxfer_len*/0,
2270				/*timeout*/timeout,
2271				/*quiet*/0);
2272}
2273
2274static int
2275atasecurity_unlock(struct cam_device *device, union ccb *ccb,
2276		   int retry_count, u_int32_t timeout,
2277		   struct ata_security_password *pwd, int quiet)
2278{
2279
2280	if (quiet == 0)
2281		atasecurity_notify(ATA_SECURITY_UNLOCK, pwd);
2282
2283	return ata_do_28bit_cmd(device,
2284				ccb,
2285				retry_count,
2286				/*flags*/CAM_DIR_OUT,
2287				/*protocol*/AP_PROTO_PIO_OUT,
2288				/*tag_action*/MSG_SIMPLE_Q_TAG,
2289				/*command*/ATA_SECURITY_UNLOCK,
2290				/*features*/0,
2291				/*lba*/0,
2292				/*sector_count*/0,
2293				/*data_ptr*/(u_int8_t *)pwd,
2294				/*dxfer_len*/sizeof(*pwd),
2295				/*timeout*/timeout,
2296				/*quiet*/0);
2297}
2298
2299static int
2300atasecurity_disable(struct cam_device *device, union ccb *ccb,
2301		    int retry_count, u_int32_t timeout,
2302		    struct ata_security_password *pwd, int quiet)
2303{
2304
2305	if (quiet == 0)
2306		atasecurity_notify(ATA_SECURITY_DISABLE_PASSWORD, pwd);
2307	return ata_do_28bit_cmd(device,
2308				ccb,
2309				retry_count,
2310				/*flags*/CAM_DIR_OUT,
2311				/*protocol*/AP_PROTO_PIO_OUT,
2312				/*tag_action*/MSG_SIMPLE_Q_TAG,
2313				/*command*/ATA_SECURITY_DISABLE_PASSWORD,
2314				/*features*/0,
2315				/*lba*/0,
2316				/*sector_count*/0,
2317				/*data_ptr*/(u_int8_t *)pwd,
2318				/*dxfer_len*/sizeof(*pwd),
2319				/*timeout*/timeout,
2320				/*quiet*/0);
2321}
2322
2323
2324static int
2325atasecurity_erase_confirm(struct cam_device *device,
2326			  struct ata_params* ident_buf)
2327{
2328
2329	printf("\nYou are about to ERASE ALL DATA from the following"
2330	       " device:\n%s%d,%s%d: ", device->device_name,
2331	       device->dev_unit_num, device->given_dev_name,
2332	       device->given_unit_number);
2333	ata_print_ident(ident_buf);
2334
2335	for(;;) {
2336		char str[50];
2337		printf("\nAre you SURE you want to ERASE ALL DATA? (yes/no) ");
2338
2339		if (fgets(str, sizeof(str), stdin) != NULL) {
2340			if (strncasecmp(str, "yes", 3) == 0) {
2341				return (1);
2342			} else if (strncasecmp(str, "no", 2) == 0) {
2343				return (0);
2344			} else {
2345				printf("Please answer \"yes\" or "
2346				       "\"no\"\n");
2347			}
2348		}
2349	}
2350
2351	/* NOTREACHED */
2352	return (0);
2353}
2354
2355static int
2356atasecurity_erase(struct cam_device *device, union ccb *ccb,
2357		  int retry_count, u_int32_t timeout,
2358		  u_int32_t erase_timeout,
2359		  struct ata_security_password *pwd, int quiet)
2360{
2361	int error;
2362
2363	if (quiet == 0)
2364		atasecurity_notify(ATA_SECURITY_ERASE_PREPARE, NULL);
2365
2366	error = ata_do_28bit_cmd(device,
2367				 ccb,
2368				 retry_count,
2369				 /*flags*/CAM_DIR_NONE,
2370				 /*protocol*/AP_PROTO_NON_DATA,
2371				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2372				 /*command*/ATA_SECURITY_ERASE_PREPARE,
2373				 /*features*/0,
2374				 /*lba*/0,
2375				 /*sector_count*/0,
2376				 /*data_ptr*/NULL,
2377				 /*dxfer_len*/0,
2378				 /*timeout*/timeout,
2379				 /*quiet*/0);
2380
2381	if (error != 0)
2382		return error;
2383
2384	if (quiet == 0)
2385		atasecurity_notify(ATA_SECURITY_ERASE_UNIT, pwd);
2386
2387	error = ata_do_28bit_cmd(device,
2388				 ccb,
2389				 retry_count,
2390				 /*flags*/CAM_DIR_OUT,
2391				 /*protocol*/AP_PROTO_PIO_OUT,
2392				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2393				 /*command*/ATA_SECURITY_ERASE_UNIT,
2394				 /*features*/0,
2395				 /*lba*/0,
2396				 /*sector_count*/0,
2397				 /*data_ptr*/(u_int8_t *)pwd,
2398				 /*dxfer_len*/sizeof(*pwd),
2399				 /*timeout*/erase_timeout,
2400				 /*quiet*/0);
2401
2402	if (error == 0 && quiet == 0)
2403		printf("\nErase Complete\n");
2404
2405	return error;
2406}
2407
2408static int
2409atasecurity_set_password(struct cam_device *device, union ccb *ccb,
2410			 int retry_count, u_int32_t timeout,
2411			 struct ata_security_password *pwd, int quiet)
2412{
2413
2414	if (quiet == 0)
2415		atasecurity_notify(ATA_SECURITY_SET_PASSWORD, pwd);
2416
2417	return ata_do_28bit_cmd(device,
2418				 ccb,
2419				 retry_count,
2420				 /*flags*/CAM_DIR_OUT,
2421				 /*protocol*/AP_PROTO_PIO_OUT,
2422				 /*tag_action*/MSG_SIMPLE_Q_TAG,
2423				 /*command*/ATA_SECURITY_SET_PASSWORD,
2424				 /*features*/0,
2425				 /*lba*/0,
2426				 /*sector_count*/0,
2427				 /*data_ptr*/(u_int8_t *)pwd,
2428				 /*dxfer_len*/sizeof(*pwd),
2429				 /*timeout*/timeout,
2430				 /*quiet*/0);
2431}
2432
2433static void
2434atasecurity_print(struct ata_params *parm)
2435{
2436
2437	printf("\nSecurity Option           Value\n");
2438	if (arglist & CAM_ARG_VERBOSE) {
2439		printf("status                    %04x\n",
2440		       parm->security_status);
2441	}
2442	printf("supported                 %s\n",
2443		parm->security_status & ATA_SECURITY_SUPPORTED ? "yes" : "no");
2444	if (!(parm->security_status & ATA_SECURITY_SUPPORTED))
2445		return;
2446	printf("enabled                   %s\n",
2447		parm->security_status & ATA_SECURITY_ENABLED ? "yes" : "no");
2448	printf("drive locked              %s\n",
2449		parm->security_status & ATA_SECURITY_LOCKED ? "yes" : "no");
2450	printf("security config frozen    %s\n",
2451		parm->security_status & ATA_SECURITY_FROZEN ? "yes" : "no");
2452	printf("count expired             %s\n",
2453		parm->security_status & ATA_SECURITY_COUNT_EXP ? "yes" : "no");
2454	printf("security level            %s\n",
2455		parm->security_status & ATA_SECURITY_LEVEL ? "maximum" : "high");
2456	printf("enhanced erase supported  %s\n",
2457		parm->security_status & ATA_SECURITY_ENH_SUPP ? "yes" : "no");
2458	printf("erase time                ");
2459	atasecurity_print_time(parm->erase_time);
2460	printf("\n");
2461	printf("enhanced erase time       ");
2462	atasecurity_print_time(parm->enhanced_erase_time);
2463	printf("\n");
2464	printf("master password rev       %04x%s\n",
2465		parm->master_passwd_revision,
2466		parm->master_passwd_revision == 0x0000 ||
2467		parm->master_passwd_revision == 0xFFFF ?  " (unsupported)" : "");
2468}
2469
2470/*
2471 * Validates and copies the password in optarg to the passed buffer.
2472 * If the password in optarg is the same length as the buffer then
2473 * the data will still be copied but no null termination will occur.
2474 */
2475static int
2476ata_getpwd(u_int8_t *passwd, int max, char opt)
2477{
2478	int len;
2479
2480	len = strlen(optarg);
2481	if (len > max) {
2482		warnx("-%c password is too long", opt);
2483		return (1);
2484	} else if (len == 0) {
2485		warnx("-%c password is missing", opt);
2486		return (1);
2487	} else if (optarg[0] == '-'){
2488		warnx("-%c password starts with '-' (generic arg?)", opt);
2489		return (1);
2490	} else if (strlen(passwd) != 0 && strcmp(passwd, optarg) != 0) {
2491		warnx("-%c password conflicts with existing password from -%c",
2492		      opt, pwd_opt);
2493		return (1);
2494	}
2495
2496	/* Callers pass in a buffer which does NOT need to be terminated */
2497	strncpy(passwd, optarg, max);
2498	pwd_opt = opt;
2499
2500	return (0);
2501}
2502
2503enum {
2504	ATA_HPA_ACTION_PRINT,
2505	ATA_HPA_ACTION_SET_MAX,
2506	ATA_HPA_ACTION_SET_PWD,
2507	ATA_HPA_ACTION_LOCK,
2508	ATA_HPA_ACTION_UNLOCK,
2509	ATA_HPA_ACTION_FREEZE_LOCK
2510};
2511
2512static int
2513atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf,
2514		   u_int64_t maxsize, int persist)
2515{
2516	printf("\nYou are about to configure HPA to limit the user accessible\n"
2517	       "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize,
2518	       persist ? "persistently" : "temporarily",
2519	       device->device_name, device->dev_unit_num,
2520	       device->given_dev_name, device->given_unit_number);
2521	ata_print_ident(ident_buf);
2522
2523	for(;;) {
2524		char str[50];
2525		printf("\nAre you SURE you want to configure HPA? (yes/no) ");
2526
2527		if (NULL != fgets(str, sizeof(str), stdin)) {
2528			if (0 == strncasecmp(str, "yes", 3)) {
2529				return (1);
2530			} else if (0 == strncasecmp(str, "no", 2)) {
2531				return (0);
2532			} else {
2533				printf("Please answer \"yes\" or "
2534				       "\"no\"\n");
2535			}
2536		}
2537	}
2538
2539	/* NOTREACHED */
2540	return (0);
2541}
2542
2543static int
2544atahpa(struct cam_device *device, int retry_count, int timeout,
2545       int argc, char **argv, char *combinedopt)
2546{
2547	union ccb *ccb;
2548	struct ata_params *ident_buf;
2549	struct ccb_getdev cgd;
2550	struct ata_set_max_pwd pwd;
2551	int error, confirm, quiet, c, action, actions, setpwd, persist;
2552	int security, is48bit, pwdsize;
2553	u_int64_t hpasize, maxsize;
2554
2555	actions = 0;
2556	setpwd = 0;
2557	confirm = 0;
2558	quiet = 0;
2559	maxsize = 0;
2560	persist = 0;
2561	security = 0;
2562
2563	memset(&pwd, 0, sizeof(pwd));
2564
2565	/* default action is to print hpa information */
2566	action = ATA_HPA_ACTION_PRINT;
2567	pwdsize = sizeof(pwd.password);
2568
2569	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2570		switch(c){
2571		case 's':
2572			action = ATA_HPA_ACTION_SET_MAX;
2573			maxsize = strtoumax(optarg, NULL, 0);
2574			actions++;
2575			break;
2576
2577		case 'p':
2578			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2579				return (1);
2580			action = ATA_HPA_ACTION_SET_PWD;
2581			security = 1;
2582			actions++;
2583			break;
2584
2585		case 'l':
2586			action = ATA_HPA_ACTION_LOCK;
2587			security = 1;
2588			actions++;
2589			break;
2590
2591		case 'U':
2592			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2593				return (1);
2594			action = ATA_HPA_ACTION_UNLOCK;
2595			security = 1;
2596			actions++;
2597			break;
2598
2599		case 'f':
2600			action = ATA_HPA_ACTION_FREEZE_LOCK;
2601			security = 1;
2602			actions++;
2603			break;
2604
2605		case 'P':
2606			persist = 1;
2607			break;
2608
2609		case 'y':
2610			confirm++;
2611			break;
2612
2613		case 'q':
2614			quiet++;
2615			break;
2616		}
2617	}
2618
2619	if (actions > 1) {
2620		warnx("too many hpa actions specified");
2621		return (1);
2622	}
2623
2624	if (get_cgd(device, &cgd) != 0) {
2625		warnx("couldn't get CGD");
2626		return (1);
2627	}
2628
2629	ccb = cam_getccb(device);
2630	if (ccb == NULL) {
2631		warnx("couldn't allocate CCB");
2632		return (1);
2633	}
2634
2635	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2636	if (error != 0) {
2637		cam_freeccb(ccb);
2638		return (1);
2639	}
2640
2641	if (quiet == 0) {
2642		printf("%s%d: ", device->device_name, device->dev_unit_num);
2643		ata_print_ident(ident_buf);
2644		camxferrate(device);
2645	}
2646
2647	if (action == ATA_HPA_ACTION_PRINT) {
2648		error = ata_read_native_max(device, retry_count, timeout, ccb,
2649					    ident_buf, &hpasize);
2650		if (error == 0)
2651			atahpa_print(ident_buf, hpasize, 1);
2652
2653		cam_freeccb(ccb);
2654		free(ident_buf);
2655		return (error);
2656	}
2657
2658	if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) {
2659		warnx("HPA is not supported by this device");
2660		cam_freeccb(ccb);
2661		free(ident_buf);
2662		return (1);
2663	}
2664
2665	if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) {
2666		warnx("HPA Security is not supported by this device");
2667		cam_freeccb(ccb);
2668		free(ident_buf);
2669		return (1);
2670	}
2671
2672	is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48;
2673
2674	/*
2675	 * The ATA spec requires:
2676	 * 1. Read native max addr is called directly before set max addr
2677	 * 2. Read native max addr is NOT called before any other set max call
2678	 */
2679	switch(action) {
2680	case ATA_HPA_ACTION_SET_MAX:
2681		if (confirm == 0 &&
2682		    atahpa_set_confirm(device, ident_buf, maxsize,
2683		    persist) == 0) {
2684			cam_freeccb(ccb);
2685			free(ident_buf);
2686			return (1);
2687		}
2688
2689		error = ata_read_native_max(device, retry_count, timeout,
2690					    ccb, ident_buf, &hpasize);
2691		if (error == 0) {
2692			error = atahpa_set_max(device, retry_count, timeout,
2693					       ccb, is48bit, maxsize, persist);
2694			if (error == 0) {
2695				/* redo identify to get new lba values */
2696				error = ata_do_identify(device, retry_count,
2697							timeout, ccb,
2698							&ident_buf);
2699				atahpa_print(ident_buf, hpasize, 1);
2700			}
2701		}
2702		break;
2703
2704	case ATA_HPA_ACTION_SET_PWD:
2705		error = atahpa_password(device, retry_count, timeout,
2706					ccb, is48bit, &pwd);
2707		if (error == 0)
2708			printf("HPA password has been set\n");
2709		break;
2710
2711	case ATA_HPA_ACTION_LOCK:
2712		error = atahpa_lock(device, retry_count, timeout,
2713				    ccb, is48bit);
2714		if (error == 0)
2715			printf("HPA has been locked\n");
2716		break;
2717
2718	case ATA_HPA_ACTION_UNLOCK:
2719		error = atahpa_unlock(device, retry_count, timeout,
2720				      ccb, is48bit, &pwd);
2721		if (error == 0)
2722			printf("HPA has been unlocked\n");
2723		break;
2724
2725	case ATA_HPA_ACTION_FREEZE_LOCK:
2726		error = atahpa_freeze_lock(device, retry_count, timeout,
2727					   ccb, is48bit);
2728		if (error == 0)
2729			printf("HPA has been frozen\n");
2730		break;
2731
2732	default:
2733		errx(1, "Option currently not supported");
2734	}
2735
2736	cam_freeccb(ccb);
2737	free(ident_buf);
2738
2739	return (error);
2740}
2741
2742static int
2743atasecurity(struct cam_device *device, int retry_count, int timeout,
2744	    int argc, char **argv, char *combinedopt)
2745{
2746	union ccb *ccb;
2747	struct ata_params *ident_buf;
2748	int error, confirm, quiet, c, action, actions, setpwd;
2749	int security_enabled, erase_timeout, pwdsize;
2750	struct ata_security_password pwd;
2751
2752	actions = 0;
2753	setpwd = 0;
2754	erase_timeout = 0;
2755	confirm = 0;
2756	quiet = 0;
2757
2758	memset(&pwd, 0, sizeof(pwd));
2759
2760	/* default action is to print security information */
2761	action = ATA_SECURITY_ACTION_PRINT;
2762
2763	/* user is master by default as its safer that way */
2764	pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2765	pwdsize = sizeof(pwd.password);
2766
2767	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2768		switch(c){
2769		case 'f':
2770			action = ATA_SECURITY_ACTION_FREEZE;
2771			actions++;
2772			break;
2773
2774		case 'U':
2775			if (strcasecmp(optarg, "user") == 0) {
2776				pwd.ctrl |= ATA_SECURITY_PASSWORD_USER;
2777				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_MASTER;
2778			} else if (strcasecmp(optarg, "master") == 0) {
2779				pwd.ctrl |= ATA_SECURITY_PASSWORD_MASTER;
2780				pwd.ctrl &= ~ATA_SECURITY_PASSWORD_USER;
2781			} else {
2782				warnx("-U argument '%s' is invalid (must be "
2783				      "'user' or 'master')", optarg);
2784				return (1);
2785			}
2786			break;
2787
2788		case 'l':
2789			if (strcasecmp(optarg, "high") == 0) {
2790				pwd.ctrl |= ATA_SECURITY_LEVEL_HIGH;
2791				pwd.ctrl &= ~ATA_SECURITY_LEVEL_MAXIMUM;
2792			} else if (strcasecmp(optarg, "maximum") == 0) {
2793				pwd.ctrl |= ATA_SECURITY_LEVEL_MAXIMUM;
2794				pwd.ctrl &= ~ATA_SECURITY_LEVEL_HIGH;
2795			} else {
2796				warnx("-l argument '%s' is unknown (must be "
2797				      "'high' or 'maximum')", optarg);
2798				return (1);
2799			}
2800			break;
2801
2802		case 'k':
2803			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2804				return (1);
2805			action = ATA_SECURITY_ACTION_UNLOCK;
2806			actions++;
2807			break;
2808
2809		case 'd':
2810			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2811				return (1);
2812			action = ATA_SECURITY_ACTION_DISABLE;
2813			actions++;
2814			break;
2815
2816		case 'e':
2817			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2818				return (1);
2819			action = ATA_SECURITY_ACTION_ERASE;
2820			actions++;
2821			break;
2822
2823		case 'h':
2824			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2825				return (1);
2826			pwd.ctrl |= ATA_SECURITY_ERASE_ENHANCED;
2827			action = ATA_SECURITY_ACTION_ERASE_ENHANCED;
2828			actions++;
2829			break;
2830
2831		case 's':
2832			if (ata_getpwd(pwd.password, pwdsize, c) != 0)
2833				return (1);
2834			setpwd = 1;
2835			if (action == ATA_SECURITY_ACTION_PRINT)
2836				action = ATA_SECURITY_ACTION_SET_PASSWORD;
2837			/*
2838			 * Don't increment action as this can be combined
2839			 * with other actions.
2840			 */
2841			break;
2842
2843		case 'y':
2844			confirm++;
2845			break;
2846
2847		case 'q':
2848			quiet++;
2849			break;
2850
2851		case 'T':
2852			erase_timeout = atoi(optarg) * 1000;
2853			break;
2854		}
2855	}
2856
2857	if (actions > 1) {
2858		warnx("too many security actions specified");
2859		return (1);
2860	}
2861
2862	if ((ccb = cam_getccb(device)) == NULL) {
2863		warnx("couldn't allocate CCB");
2864		return (1);
2865	}
2866
2867	error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf);
2868	if (error != 0) {
2869		cam_freeccb(ccb);
2870		return (1);
2871	}
2872
2873	if (quiet == 0) {
2874		printf("%s%d: ", device->device_name, device->dev_unit_num);
2875		ata_print_ident(ident_buf);
2876		camxferrate(device);
2877	}
2878
2879	if (action == ATA_SECURITY_ACTION_PRINT) {
2880		atasecurity_print(ident_buf);
2881		free(ident_buf);
2882		cam_freeccb(ccb);
2883		return (0);
2884	}
2885
2886	if ((ident_buf->support.command1 & ATA_SUPPORT_SECURITY) == 0) {
2887		warnx("Security not supported");
2888		free(ident_buf);
2889		cam_freeccb(ccb);
2890		return (1);
2891	}
2892
2893	/* default timeout 15 seconds the same as linux hdparm */
2894	timeout = timeout ? timeout : 15 * 1000;
2895
2896	security_enabled = ident_buf->security_status & ATA_SECURITY_ENABLED;
2897
2898	/* first set the password if requested */
2899	if (setpwd == 1) {
2900		/* confirm we can erase before setting the password if erasing */
2901		if (confirm == 0 &&
2902		    (action == ATA_SECURITY_ACTION_ERASE_ENHANCED ||
2903		    action == ATA_SECURITY_ACTION_ERASE) &&
2904		    atasecurity_erase_confirm(device, ident_buf) == 0) {
2905			cam_freeccb(ccb);
2906			free(ident_buf);
2907			return (error);
2908		}
2909
2910		if (pwd.ctrl & ATA_SECURITY_PASSWORD_MASTER) {
2911			pwd.revision = ident_buf->master_passwd_revision;
2912			if (pwd.revision != 0 && pwd.revision != 0xfff &&
2913			    --pwd.revision == 0) {
2914				pwd.revision = 0xfffe;
2915			}
2916		}
2917		error = atasecurity_set_password(device, ccb, retry_count,
2918						 timeout, &pwd, quiet);
2919		if (error != 0) {
2920			cam_freeccb(ccb);
2921			free(ident_buf);
2922			return (error);
2923		}
2924		security_enabled = 1;
2925	}
2926
2927	switch(action) {
2928	case ATA_SECURITY_ACTION_FREEZE:
2929		error = atasecurity_freeze(device, ccb, retry_count,
2930					   timeout, quiet);
2931		break;
2932
2933	case ATA_SECURITY_ACTION_UNLOCK:
2934		if (security_enabled) {
2935			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2936				error = atasecurity_unlock(device, ccb,
2937					retry_count, timeout, &pwd, quiet);
2938			} else {
2939				warnx("Can't unlock, drive is not locked");
2940				error = 1;
2941			}
2942		} else {
2943			warnx("Can't unlock, security is disabled");
2944			error = 1;
2945		}
2946		break;
2947
2948	case ATA_SECURITY_ACTION_DISABLE:
2949		if (security_enabled) {
2950			/* First unlock the drive if its locked */
2951			if (ident_buf->security_status & ATA_SECURITY_LOCKED) {
2952				error = atasecurity_unlock(device, ccb,
2953							   retry_count,
2954							   timeout,
2955							   &pwd,
2956							   quiet);
2957			}
2958
2959			if (error == 0) {
2960				error = atasecurity_disable(device,
2961							    ccb,
2962							    retry_count,
2963							    timeout,
2964							    &pwd,
2965							    quiet);
2966			}
2967		} else {
2968			warnx("Can't disable security (already disabled)");
2969			error = 1;
2970		}
2971		break;
2972
2973	case ATA_SECURITY_ACTION_ERASE:
2974		if (security_enabled) {
2975			if (erase_timeout == 0) {
2976				erase_timeout = atasecurity_erase_timeout_msecs(
2977				    ident_buf->erase_time);
2978			}
2979
2980			error = atasecurity_erase(device, ccb, retry_count,
2981					          timeout, erase_timeout, &pwd,
2982						  quiet);
2983		} else {
2984			warnx("Can't secure erase (security is disabled)");
2985			error = 1;
2986		}
2987		break;
2988
2989	case ATA_SECURITY_ACTION_ERASE_ENHANCED:
2990		if (security_enabled) {
2991			if (ident_buf->security_status & ATA_SECURITY_ENH_SUPP) {
2992				if (erase_timeout == 0) {
2993					erase_timeout =
2994					    atasecurity_erase_timeout_msecs(
2995						ident_buf->enhanced_erase_time);
2996				}
2997
2998				error = atasecurity_erase(device, ccb,
2999							  retry_count, timeout,
3000							  erase_timeout, &pwd,
3001							  quiet);
3002			} else {
3003				warnx("Enhanced erase is not supported");
3004				error = 1;
3005			}
3006		} else {
3007			warnx("Can't secure erase (enhanced), "
3008			      "(security is disabled)");
3009			error = 1;
3010		}
3011		break;
3012	}
3013
3014	cam_freeccb(ccb);
3015	free(ident_buf);
3016
3017	return (error);
3018}
3019#endif /* MINIMALISTIC */
3020
3021/*
3022 * Parse out a bus, or a bus, target and lun in the following
3023 * format:
3024 * bus
3025 * bus:target
3026 * bus:target:lun
3027 *
3028 * Returns the number of parsed components, or 0.
3029 */
3030static int
3031parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun,
3032    cam_argmask *arglst)
3033{
3034	char *tmpstr;
3035	int convs = 0;
3036
3037	while (isspace(*tstr) && (*tstr != '\0'))
3038		tstr++;
3039
3040	tmpstr = (char *)strtok(tstr, ":");
3041	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3042		*bus = strtol(tmpstr, NULL, 0);
3043		*arglst |= CAM_ARG_BUS;
3044		convs++;
3045		tmpstr = (char *)strtok(NULL, ":");
3046		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3047			*target = strtol(tmpstr, NULL, 0);
3048			*arglst |= CAM_ARG_TARGET;
3049			convs++;
3050			tmpstr = (char *)strtok(NULL, ":");
3051			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
3052				*lun = strtol(tmpstr, NULL, 0);
3053				*arglst |= CAM_ARG_LUN;
3054				convs++;
3055			}
3056		}
3057	}
3058
3059	return convs;
3060}
3061
3062static int
3063dorescan_or_reset(int argc, char **argv, int rescan)
3064{
3065	static const char must[] =
3066		"you must specify \"all\", a bus, or a bus:target:lun to %s";
3067	int rv, error = 0;
3068	path_id_t bus = CAM_BUS_WILDCARD;
3069	target_id_t target = CAM_TARGET_WILDCARD;
3070	lun_id_t lun = CAM_LUN_WILDCARD;
3071	char *tstr;
3072
3073	if (argc < 3) {
3074		warnx(must, rescan? "rescan" : "reset");
3075		return(1);
3076	}
3077
3078	tstr = argv[optind];
3079	while (isspace(*tstr) && (*tstr != '\0'))
3080		tstr++;
3081	if (strncasecmp(tstr, "all", strlen("all")) == 0)
3082		arglist |= CAM_ARG_BUS;
3083	else {
3084		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
3085		if (rv != 1 && rv != 3) {
3086			warnx(must, rescan? "rescan" : "reset");
3087			return(1);
3088		}
3089	}
3090
3091	if ((arglist & CAM_ARG_BUS)
3092	    && (arglist & CAM_ARG_TARGET)
3093	    && (arglist & CAM_ARG_LUN))
3094		error = scanlun_or_reset_dev(bus, target, lun, rescan);
3095	else
3096		error = rescan_or_reset_bus(bus, rescan);
3097
3098	return(error);
3099}
3100
3101static int
3102rescan_or_reset_bus(path_id_t bus, int rescan)
3103{
3104	union ccb ccb, matchccb;
3105	int fd, retval;
3106	int bufsize;
3107
3108	retval = 0;
3109
3110	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3111		warnx("error opening transport layer device %s", XPT_DEVICE);
3112		warn("%s", XPT_DEVICE);
3113		return(1);
3114	}
3115
3116	if (bus != CAM_BUS_WILDCARD) {
3117		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
3118		ccb.ccb_h.path_id = bus;
3119		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3120		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3121		ccb.crcn.flags = CAM_FLAG_NONE;
3122
3123		/* run this at a low priority */
3124		ccb.ccb_h.pinfo.priority = 5;
3125
3126		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3127			warn("CAMIOCOMMAND ioctl failed");
3128			close(fd);
3129			return(1);
3130		}
3131
3132		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
3133			fprintf(stdout, "%s of bus %d was successful\n",
3134			    rescan ? "Re-scan" : "Reset", bus);
3135		} else {
3136			fprintf(stdout, "%s of bus %d returned error %#x\n",
3137				rescan ? "Re-scan" : "Reset", bus,
3138				ccb.ccb_h.status & CAM_STATUS_MASK);
3139			retval = 1;
3140		}
3141
3142		close(fd);
3143		return(retval);
3144
3145	}
3146
3147
3148	/*
3149	 * The right way to handle this is to modify the xpt so that it can
3150	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
3151	 * that isn't implemented, so instead we enumerate the busses and
3152	 * send the rescan or reset to those busses in the case where the
3153	 * given bus is -1 (wildcard).  We don't send a rescan or reset
3154	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
3155	 * no-op, sending a rescan to the xpt bus would result in a status of
3156	 * CAM_REQ_INVALID.
3157	 */
3158	bzero(&(&matchccb.ccb_h)[1],
3159	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
3160	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
3161	matchccb.ccb_h.path_id = CAM_BUS_WILDCARD;
3162	bufsize = sizeof(struct dev_match_result) * 20;
3163	matchccb.cdm.match_buf_len = bufsize;
3164	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
3165	if (matchccb.cdm.matches == NULL) {
3166		warnx("can't malloc memory for matches");
3167		retval = 1;
3168		goto bailout;
3169	}
3170	matchccb.cdm.num_matches = 0;
3171
3172	matchccb.cdm.num_patterns = 1;
3173	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
3174
3175	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
3176		matchccb.cdm.pattern_buf_len);
3177	if (matchccb.cdm.patterns == NULL) {
3178		warnx("can't malloc memory for patterns");
3179		retval = 1;
3180		goto bailout;
3181	}
3182	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
3183	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
3184
3185	do {
3186		unsigned int i;
3187
3188		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
3189			warn("CAMIOCOMMAND ioctl failed");
3190			retval = 1;
3191			goto bailout;
3192		}
3193
3194		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
3195		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
3196		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
3197			warnx("got CAM error %#x, CDM error %d\n",
3198			      matchccb.ccb_h.status, matchccb.cdm.status);
3199			retval = 1;
3200			goto bailout;
3201		}
3202
3203		for (i = 0; i < matchccb.cdm.num_matches; i++) {
3204			struct bus_match_result *bus_result;
3205
3206			/* This shouldn't happen. */
3207			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
3208				continue;
3209
3210			bus_result = &matchccb.cdm.matches[i].result.bus_result;
3211
3212			/*
3213			 * We don't want to rescan or reset the xpt bus.
3214			 * See above.
3215			 */
3216			if (bus_result->path_id == CAM_XPT_PATH_ID)
3217				continue;
3218
3219			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
3220						       XPT_RESET_BUS;
3221			ccb.ccb_h.path_id = bus_result->path_id;
3222			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
3223			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
3224			ccb.crcn.flags = CAM_FLAG_NONE;
3225
3226			/* run this at a low priority */
3227			ccb.ccb_h.pinfo.priority = 5;
3228
3229			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
3230				warn("CAMIOCOMMAND ioctl failed");
3231				retval = 1;
3232				goto bailout;
3233			}
3234
3235			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
3236				fprintf(stdout, "%s of bus %d was successful\n",
3237					rescan? "Re-scan" : "Reset",
3238					bus_result->path_id);
3239			} else {
3240				/*
3241				 * Don't bail out just yet, maybe the other
3242				 * rescan or reset commands will complete
3243				 * successfully.
3244				 */
3245				fprintf(stderr, "%s of bus %d returned error "
3246					"%#x\n", rescan? "Re-scan" : "Reset",
3247					bus_result->path_id,
3248					ccb.ccb_h.status & CAM_STATUS_MASK);
3249				retval = 1;
3250			}
3251		}
3252	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
3253		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
3254
3255bailout:
3256
3257	if (fd != -1)
3258		close(fd);
3259
3260	if (matchccb.cdm.patterns != NULL)
3261		free(matchccb.cdm.patterns);
3262	if (matchccb.cdm.matches != NULL)
3263		free(matchccb.cdm.matches);
3264
3265	return(retval);
3266}
3267
3268static int
3269scanlun_or_reset_dev(path_id_t bus, target_id_t target, lun_id_t lun, int scan)
3270{
3271	union ccb ccb;
3272	struct cam_device *device;
3273	int fd;
3274
3275	device = NULL;
3276
3277	if (bus == CAM_BUS_WILDCARD) {
3278		warnx("invalid bus number %d", bus);
3279		return(1);
3280	}
3281
3282	if (target == CAM_TARGET_WILDCARD) {
3283		warnx("invalid target number %d", target);
3284		return(1);
3285	}
3286
3287	if (lun == CAM_LUN_WILDCARD) {
3288		warnx("invalid lun number %jx", (uintmax_t)lun);
3289		return(1);
3290	}
3291
3292	fd = -1;
3293
3294	bzero(&ccb, sizeof(union ccb));
3295
3296	if (scan) {
3297		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
3298			warnx("error opening transport layer device %s\n",
3299			    XPT_DEVICE);
3300			warn("%s", XPT_DEVICE);
3301			return(1);
3302		}
3303	} else {
3304		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
3305		if (device == NULL) {
3306			warnx("%s", cam_errbuf);
3307			return(1);
3308		}
3309	}
3310
3311	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
3312	ccb.ccb_h.path_id = bus;
3313	ccb.ccb_h.target_id = target;
3314	ccb.ccb_h.target_lun = lun;
3315	ccb.ccb_h.timeout = 5000;
3316	ccb.crcn.flags = CAM_FLAG_NONE;
3317
3318	/* run this at a low priority */
3319	ccb.ccb_h.pinfo.priority = 5;
3320
3321	if (scan) {
3322		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
3323			warn("CAMIOCOMMAND ioctl failed");
3324			close(fd);
3325			return(1);
3326		}
3327	} else {
3328		if (cam_send_ccb(device, &ccb) < 0) {
3329			warn("error sending XPT_RESET_DEV CCB");
3330			cam_close_device(device);
3331			return(1);
3332		}
3333	}
3334
3335	if (scan)
3336		close(fd);
3337	else
3338		cam_close_device(device);
3339
3340	/*
3341	 * An error code of CAM_BDR_SENT is normal for a BDR request.
3342	 */
3343	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
3344	 || ((!scan)
3345	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
3346		fprintf(stdout, "%s of %d:%d:%jx was successful\n",
3347		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun);
3348		return(0);
3349	} else {
3350		fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n",
3351		    scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun,
3352		    ccb.ccb_h.status & CAM_STATUS_MASK);
3353		return(1);
3354	}
3355}
3356
3357#ifndef MINIMALISTIC
3358static int
3359readdefects(struct cam_device *device, int argc, char **argv,
3360	    char *combinedopt, int retry_count, int timeout)
3361{
3362	union ccb *ccb = NULL;
3363	struct scsi_read_defect_data_10 *rdd_cdb;
3364	u_int8_t *defect_list = NULL;
3365	u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0;
3366	u_int32_t returned_length = 0;
3367	u_int32_t num_returned = 0;
3368	u_int8_t returned_format;
3369	unsigned int i;
3370	int c, error = 0;
3371	int lists_specified;
3372	int get_length = 1;
3373
3374	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3375		switch(c){
3376		case 'f':
3377		{
3378			char *tstr;
3379			tstr = optarg;
3380			while (isspace(*tstr) && (*tstr != '\0'))
3381				tstr++;
3382			if (strcmp(tstr, "block") == 0)
3383				arglist |= CAM_ARG_FORMAT_BLOCK;
3384			else if (strcmp(tstr, "bfi") == 0)
3385				arglist |= CAM_ARG_FORMAT_BFI;
3386			else if (strcmp(tstr, "phys") == 0)
3387				arglist |= CAM_ARG_FORMAT_PHYS;
3388			else {
3389				error = 1;
3390				warnx("invalid defect format %s", tstr);
3391				goto defect_bailout;
3392			}
3393			break;
3394		}
3395		case 'G':
3396			arglist |= CAM_ARG_GLIST;
3397			break;
3398		case 'P':
3399			arglist |= CAM_ARG_PLIST;
3400			break;
3401		default:
3402			break;
3403		}
3404	}
3405
3406	ccb = cam_getccb(device);
3407
3408	/*
3409	 * Eventually we should probably support the 12 byte READ DEFECT
3410	 * DATA command.  It supports a longer parameter list, which may be
3411	 * necessary on newer drives with lots of defects.  According to
3412	 * the SBC-3 spec, drives are supposed to return an illegal request
3413	 * if they have more defect data than will fit in 64K.
3414	 */
3415	defect_list = malloc(max_dlist_length);
3416	if (defect_list == NULL) {
3417		warnx("can't malloc memory for defect list");
3418		error = 1;
3419		goto defect_bailout;
3420	}
3421
3422	/*
3423	 * We start off asking for just the header to determine how much
3424	 * defect data is available.  Some Hitachi drives return an error
3425	 * if you ask for more data than the drive has.  Once we know the
3426	 * length, we retry the command with the returned length.
3427	 */
3428	dlist_length = sizeof(struct scsi_read_defect_data_hdr_10);
3429
3430	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
3431
3432retry:
3433
3434	lists_specified = 0;
3435
3436	/*
3437	 * cam_getccb() zeros the CCB header only.  So we need to zero the
3438	 * payload portion of the ccb.
3439	 */
3440	bzero(&(&ccb->ccb_h)[1],
3441	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3442
3443	cam_fill_csio(&ccb->csio,
3444		      /*retries*/ retry_count,
3445		      /*cbfcnp*/ NULL,
3446		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
3447					      CAM_PASS_ERR_RECOVER : 0),
3448		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
3449		      /*data_ptr*/ defect_list,
3450		      /*dxfer_len*/ dlist_length,
3451		      /*sense_len*/ SSD_FULL_SIZE,
3452		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
3453		      /*timeout*/ timeout ? timeout : 5000);
3454
3455	rdd_cdb->opcode = READ_DEFECT_DATA_10;
3456	if (arglist & CAM_ARG_FORMAT_BLOCK)
3457		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
3458	else if (arglist & CAM_ARG_FORMAT_BFI)
3459		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
3460	else if (arglist & CAM_ARG_FORMAT_PHYS)
3461		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
3462	else {
3463		error = 1;
3464		warnx("no defect list format specified");
3465		goto defect_bailout;
3466	}
3467	if (arglist & CAM_ARG_PLIST) {
3468		rdd_cdb->format |= SRDD10_PLIST;
3469		lists_specified++;
3470	}
3471
3472	if (arglist & CAM_ARG_GLIST) {
3473		rdd_cdb->format |= SRDD10_GLIST;
3474		lists_specified++;
3475	}
3476
3477	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
3478
3479	/* Disable freezing the device queue */
3480	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3481
3482	if (cam_send_ccb(device, ccb) < 0) {
3483		perror("error reading defect list");
3484
3485		if (arglist & CAM_ARG_VERBOSE) {
3486			cam_error_print(device, ccb, CAM_ESF_ALL,
3487					CAM_EPF_ALL, stderr);
3488		}
3489
3490		error = 1;
3491		goto defect_bailout;
3492	}
3493
3494	returned_length = scsi_2btoul(((struct
3495		scsi_read_defect_data_hdr_10 *)defect_list)->length);
3496
3497	if (get_length != 0) {
3498		get_length = 0;
3499
3500		if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
3501		     CAM_SCSI_STATUS_ERROR) {
3502			struct scsi_sense_data *sense;
3503			int error_code, sense_key, asc, ascq;
3504
3505			sense = &ccb->csio.sense_data;
3506			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3507			    ccb->csio.sense_resid, &error_code, &sense_key,
3508			    &asc, &ascq, /*show_errors*/ 1);
3509
3510			/*
3511			 * If the drive is reporting that it just doesn't
3512			 * support the defect list format, go ahead and use
3513			 * the length it reported.  Otherwise, the length
3514			 * may not be valid, so use the maximum.
3515			 */
3516			if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3517			 && (asc == 0x1c) && (ascq == 0x00)
3518			 && (returned_length > 0)) {
3519				dlist_length = returned_length +
3520				    sizeof(struct scsi_read_defect_data_hdr_10);
3521				dlist_length = min(dlist_length,
3522						   SRDD10_MAX_LENGTH);
3523			} else
3524				dlist_length = max_dlist_length;
3525		} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3526			    CAM_REQ_CMP){
3527			error = 1;
3528			warnx("Error reading defect header");
3529			if (arglist & CAM_ARG_VERBOSE)
3530				cam_error_print(device, ccb, CAM_ESF_ALL,
3531						CAM_EPF_ALL, stderr);
3532			goto defect_bailout;
3533		} else {
3534			dlist_length = returned_length +
3535			    sizeof(struct scsi_read_defect_data_hdr_10);
3536			dlist_length = min(dlist_length, SRDD10_MAX_LENGTH);
3537		}
3538
3539		goto retry;
3540	}
3541
3542	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
3543			defect_list)->format;
3544
3545	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
3546	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
3547	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3548		struct scsi_sense_data *sense;
3549		int error_code, sense_key, asc, ascq;
3550
3551		sense = &ccb->csio.sense_data;
3552		scsi_extract_sense_len(sense, ccb->csio.sense_len -
3553		    ccb->csio.sense_resid, &error_code, &sense_key, &asc,
3554		    &ascq, /*show_errors*/ 1);
3555
3556		/*
3557		 * According to the SCSI spec, if the disk doesn't support
3558		 * the requested format, it will generally return a sense
3559		 * key of RECOVERED ERROR, and an additional sense code
3560		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
3561		 * also check to make sure that the returned length is
3562		 * greater than 0, and then print out whatever format the
3563		 * disk gave us.
3564		 */
3565		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
3566		 && (asc == 0x1c) && (ascq == 0x00)
3567		 && (returned_length > 0)) {
3568			warnx("requested defect format not available");
3569			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
3570			case SRDD10_BLOCK_FORMAT:
3571				warnx("Device returned block format");
3572				break;
3573			case SRDD10_BYTES_FROM_INDEX_FORMAT:
3574				warnx("Device returned bytes from index"
3575				      " format");
3576				break;
3577			case SRDD10_PHYSICAL_SECTOR_FORMAT:
3578				warnx("Device returned physical sector format");
3579				break;
3580			default:
3581				error = 1;
3582				warnx("Device returned unknown defect"
3583				     " data format %#x", returned_format);
3584				goto defect_bailout;
3585				break; /* NOTREACHED */
3586			}
3587		} else {
3588			error = 1;
3589			warnx("Error returned from read defect data command");
3590			if (arglist & CAM_ARG_VERBOSE)
3591				cam_error_print(device, ccb, CAM_ESF_ALL,
3592						CAM_EPF_ALL, stderr);
3593			goto defect_bailout;
3594		}
3595	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3596		error = 1;
3597		warnx("Error returned from read defect data command");
3598		if (arglist & CAM_ARG_VERBOSE)
3599			cam_error_print(device, ccb, CAM_ESF_ALL,
3600					CAM_EPF_ALL, stderr);
3601		goto defect_bailout;
3602	}
3603
3604	/*
3605	 * XXX KDM  I should probably clean up the printout format for the
3606	 * disk defects.
3607	 */
3608	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
3609		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
3610		{
3611			struct scsi_defect_desc_phys_sector *dlist;
3612
3613			dlist = (struct scsi_defect_desc_phys_sector *)
3614				(defect_list +
3615				sizeof(struct scsi_read_defect_data_hdr_10));
3616
3617			num_returned = returned_length /
3618				sizeof(struct scsi_defect_desc_phys_sector);
3619
3620			fprintf(stderr, "Got %d defect", num_returned);
3621
3622			if ((lists_specified == 0) || (num_returned == 0)) {
3623				fprintf(stderr, "s.\n");
3624				break;
3625			} else if (num_returned == 1)
3626				fprintf(stderr, ":\n");
3627			else
3628				fprintf(stderr, "s:\n");
3629
3630			for (i = 0; i < num_returned; i++) {
3631				fprintf(stdout, "%d:%d:%d\n",
3632					scsi_3btoul(dlist[i].cylinder),
3633					dlist[i].head,
3634					scsi_4btoul(dlist[i].sector));
3635			}
3636			break;
3637		}
3638		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
3639		{
3640			struct scsi_defect_desc_bytes_from_index *dlist;
3641
3642			dlist = (struct scsi_defect_desc_bytes_from_index *)
3643				(defect_list +
3644				sizeof(struct scsi_read_defect_data_hdr_10));
3645
3646			num_returned = returned_length /
3647			      sizeof(struct scsi_defect_desc_bytes_from_index);
3648
3649			fprintf(stderr, "Got %d defect", num_returned);
3650
3651			if ((lists_specified == 0) || (num_returned == 0)) {
3652				fprintf(stderr, "s.\n");
3653				break;
3654			} else if (num_returned == 1)
3655				fprintf(stderr, ":\n");
3656			else
3657				fprintf(stderr, "s:\n");
3658
3659			for (i = 0; i < num_returned; i++) {
3660				fprintf(stdout, "%d:%d:%d\n",
3661					scsi_3btoul(dlist[i].cylinder),
3662					dlist[i].head,
3663					scsi_4btoul(dlist[i].bytes_from_index));
3664			}
3665			break;
3666		}
3667		case SRDDH10_BLOCK_FORMAT:
3668		{
3669			struct scsi_defect_desc_block *dlist;
3670
3671			dlist = (struct scsi_defect_desc_block *)(defect_list +
3672				sizeof(struct scsi_read_defect_data_hdr_10));
3673
3674			num_returned = returned_length /
3675			      sizeof(struct scsi_defect_desc_block);
3676
3677			fprintf(stderr, "Got %d defect", num_returned);
3678
3679			if ((lists_specified == 0) || (num_returned == 0)) {
3680				fprintf(stderr, "s.\n");
3681				break;
3682			} else if (num_returned == 1)
3683				fprintf(stderr, ":\n");
3684			else
3685				fprintf(stderr, "s:\n");
3686
3687			for (i = 0; i < num_returned; i++)
3688				fprintf(stdout, "%u\n",
3689					scsi_4btoul(dlist[i].address));
3690			break;
3691		}
3692		default:
3693			fprintf(stderr, "Unknown defect format %d\n",
3694				returned_format & SRDDH10_DLIST_FORMAT_MASK);
3695			error = 1;
3696			break;
3697	}
3698defect_bailout:
3699
3700	if (defect_list != NULL)
3701		free(defect_list);
3702
3703	if (ccb != NULL)
3704		cam_freeccb(ccb);
3705
3706	return(error);
3707}
3708#endif /* MINIMALISTIC */
3709
3710#if 0
3711void
3712reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
3713{
3714	union ccb *ccb;
3715
3716	ccb = cam_getccb(device);
3717
3718	cam_freeccb(ccb);
3719}
3720#endif
3721
3722#ifndef MINIMALISTIC
3723void
3724mode_sense(struct cam_device *device, int mode_page, int page_control,
3725	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
3726{
3727	union ccb *ccb;
3728	int retval;
3729
3730	ccb = cam_getccb(device);
3731
3732	if (ccb == NULL)
3733		errx(1, "mode_sense: couldn't allocate CCB");
3734
3735	bzero(&(&ccb->ccb_h)[1],
3736	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3737
3738	scsi_mode_sense(&ccb->csio,
3739			/* retries */ retry_count,
3740			/* cbfcnp */ NULL,
3741			/* tag_action */ MSG_SIMPLE_Q_TAG,
3742			/* dbd */ dbd,
3743			/* page_code */ page_control << 6,
3744			/* page */ mode_page,
3745			/* param_buf */ data,
3746			/* param_len */ datalen,
3747			/* sense_len */ SSD_FULL_SIZE,
3748			/* timeout */ timeout ? timeout : 5000);
3749
3750	if (arglist & CAM_ARG_ERR_RECOVER)
3751		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3752
3753	/* Disable freezing the device queue */
3754	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3755
3756	if (((retval = cam_send_ccb(device, ccb)) < 0)
3757	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3758		if (arglist & CAM_ARG_VERBOSE) {
3759			cam_error_print(device, ccb, CAM_ESF_ALL,
3760					CAM_EPF_ALL, stderr);
3761		}
3762		cam_freeccb(ccb);
3763		cam_close_device(device);
3764		if (retval < 0)
3765			err(1, "error sending mode sense command");
3766		else
3767			errx(1, "error sending mode sense command");
3768	}
3769
3770	cam_freeccb(ccb);
3771}
3772
3773void
3774mode_select(struct cam_device *device, int save_pages, int retry_count,
3775	   int timeout, u_int8_t *data, int datalen)
3776{
3777	union ccb *ccb;
3778	int retval;
3779
3780	ccb = cam_getccb(device);
3781
3782	if (ccb == NULL)
3783		errx(1, "mode_select: couldn't allocate CCB");
3784
3785	bzero(&(&ccb->ccb_h)[1],
3786	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3787
3788	scsi_mode_select(&ccb->csio,
3789			 /* retries */ retry_count,
3790			 /* cbfcnp */ NULL,
3791			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3792			 /* scsi_page_fmt */ 1,
3793			 /* save_pages */ save_pages,
3794			 /* param_buf */ data,
3795			 /* param_len */ datalen,
3796			 /* sense_len */ SSD_FULL_SIZE,
3797			 /* timeout */ timeout ? timeout : 5000);
3798
3799	if (arglist & CAM_ARG_ERR_RECOVER)
3800		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3801
3802	/* Disable freezing the device queue */
3803	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3804
3805	if (((retval = cam_send_ccb(device, ccb)) < 0)
3806	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
3807		if (arglist & CAM_ARG_VERBOSE) {
3808			cam_error_print(device, ccb, CAM_ESF_ALL,
3809					CAM_EPF_ALL, stderr);
3810		}
3811		cam_freeccb(ccb);
3812		cam_close_device(device);
3813
3814		if (retval < 0)
3815			err(1, "error sending mode select command");
3816		else
3817			errx(1, "error sending mode select command");
3818
3819	}
3820
3821	cam_freeccb(ccb);
3822}
3823
3824void
3825modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
3826	 int retry_count, int timeout)
3827{
3828	int c, mode_page = -1, page_control = 0;
3829	int binary = 0, list = 0;
3830
3831	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3832		switch(c) {
3833		case 'b':
3834			binary = 1;
3835			break;
3836		case 'd':
3837			arglist |= CAM_ARG_DBD;
3838			break;
3839		case 'e':
3840			arglist |= CAM_ARG_MODE_EDIT;
3841			break;
3842		case 'l':
3843			list = 1;
3844			break;
3845		case 'm':
3846			mode_page = strtol(optarg, NULL, 0);
3847			if (mode_page < 0)
3848				errx(1, "invalid mode page %d", mode_page);
3849			break;
3850		case 'P':
3851			page_control = strtol(optarg, NULL, 0);
3852			if ((page_control < 0) || (page_control > 3))
3853				errx(1, "invalid page control field %d",
3854				     page_control);
3855			arglist |= CAM_ARG_PAGE_CNTL;
3856			break;
3857		default:
3858			break;
3859		}
3860	}
3861
3862	if (mode_page == -1 && list == 0)
3863		errx(1, "you must specify a mode page!");
3864
3865	if (list) {
3866		mode_list(device, page_control, arglist & CAM_ARG_DBD,
3867		    retry_count, timeout);
3868	} else {
3869		mode_edit(device, mode_page, page_control,
3870		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
3871		    retry_count, timeout);
3872	}
3873}
3874
3875static int
3876scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
3877	int retry_count, int timeout)
3878{
3879	union ccb *ccb;
3880	u_int32_t flags = CAM_DIR_NONE;
3881	u_int8_t *data_ptr = NULL;
3882	u_int8_t cdb[20];
3883	u_int8_t atacmd[12];
3884	struct get_hook hook;
3885	int c, data_bytes = 0;
3886	int cdb_len = 0;
3887	int atacmd_len = 0;
3888	int dmacmd = 0;
3889	int fpdmacmd = 0;
3890	int need_res = 0;
3891	char *datastr = NULL, *tstr, *resstr = NULL;
3892	int error = 0;
3893	int fd_data = 0, fd_res = 0;
3894	int retval;
3895
3896	ccb = cam_getccb(device);
3897
3898	if (ccb == NULL) {
3899		warnx("scsicmd: error allocating ccb");
3900		return(1);
3901	}
3902
3903	bzero(&(&ccb->ccb_h)[1],
3904	      sizeof(union ccb) - sizeof(struct ccb_hdr));
3905
3906	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3907		switch(c) {
3908		case 'a':
3909			tstr = optarg;
3910			while (isspace(*tstr) && (*tstr != '\0'))
3911				tstr++;
3912			hook.argc = argc - optind;
3913			hook.argv = argv + optind;
3914			hook.got = 0;
3915			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
3916						    iget, &hook);
3917			/*
3918			 * Increment optind by the number of arguments the
3919			 * encoding routine processed.  After each call to
3920			 * getopt(3), optind points to the argument that
3921			 * getopt should process _next_.  In this case,
3922			 * that means it points to the first command string
3923			 * argument, if there is one.  Once we increment
3924			 * this, it should point to either the next command
3925			 * line argument, or it should be past the end of
3926			 * the list.
3927			 */
3928			optind += hook.got;
3929			break;
3930		case 'c':
3931			tstr = optarg;
3932			while (isspace(*tstr) && (*tstr != '\0'))
3933				tstr++;
3934			hook.argc = argc - optind;
3935			hook.argv = argv + optind;
3936			hook.got = 0;
3937			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
3938						    iget, &hook);
3939			/*
3940			 * Increment optind by the number of arguments the
3941			 * encoding routine processed.  After each call to
3942			 * getopt(3), optind points to the argument that
3943			 * getopt should process _next_.  In this case,
3944			 * that means it points to the first command string
3945			 * argument, if there is one.  Once we increment
3946			 * this, it should point to either the next command
3947			 * line argument, or it should be past the end of
3948			 * the list.
3949			 */
3950			optind += hook.got;
3951			break;
3952		case 'd':
3953			dmacmd = 1;
3954			break;
3955		case 'f':
3956			fpdmacmd = 1;
3957			break;
3958		case 'i':
3959			if (arglist & CAM_ARG_CMD_OUT) {
3960				warnx("command must either be "
3961				      "read or write, not both");
3962				error = 1;
3963				goto scsicmd_bailout;
3964			}
3965			arglist |= CAM_ARG_CMD_IN;
3966			flags = CAM_DIR_IN;
3967			data_bytes = strtol(optarg, NULL, 0);
3968			if (data_bytes <= 0) {
3969				warnx("invalid number of input bytes %d",
3970				      data_bytes);
3971				error = 1;
3972				goto scsicmd_bailout;
3973			}
3974			hook.argc = argc - optind;
3975			hook.argv = argv + optind;
3976			hook.got = 0;
3977			optind++;
3978			datastr = cget(&hook, NULL);
3979			/*
3980			 * If the user supplied "-" instead of a format, he
3981			 * wants the data to be written to stdout.
3982			 */
3983			if ((datastr != NULL)
3984			 && (datastr[0] == '-'))
3985				fd_data = 1;
3986
3987			data_ptr = (u_int8_t *)malloc(data_bytes);
3988			if (data_ptr == NULL) {
3989				warnx("can't malloc memory for data_ptr");
3990				error = 1;
3991				goto scsicmd_bailout;
3992			}
3993			break;
3994		case 'o':
3995			if (arglist & CAM_ARG_CMD_IN) {
3996				warnx("command must either be "
3997				      "read or write, not both");
3998				error = 1;
3999				goto scsicmd_bailout;
4000			}
4001			arglist |= CAM_ARG_CMD_OUT;
4002			flags = CAM_DIR_OUT;
4003			data_bytes = strtol(optarg, NULL, 0);
4004			if (data_bytes <= 0) {
4005				warnx("invalid number of output bytes %d",
4006				      data_bytes);
4007				error = 1;
4008				goto scsicmd_bailout;
4009			}
4010			hook.argc = argc - optind;
4011			hook.argv = argv + optind;
4012			hook.got = 0;
4013			datastr = cget(&hook, NULL);
4014			data_ptr = (u_int8_t *)malloc(data_bytes);
4015			if (data_ptr == NULL) {
4016				warnx("can't malloc memory for data_ptr");
4017				error = 1;
4018				goto scsicmd_bailout;
4019			}
4020			bzero(data_ptr, data_bytes);
4021			/*
4022			 * If the user supplied "-" instead of a format, he
4023			 * wants the data to be read from stdin.
4024			 */
4025			if ((datastr != NULL)
4026			 && (datastr[0] == '-'))
4027				fd_data = 1;
4028			else
4029				buff_encode_visit(data_ptr, data_bytes, datastr,
4030						  iget, &hook);
4031			optind += hook.got;
4032			break;
4033		case 'r':
4034			need_res = 1;
4035			hook.argc = argc - optind;
4036			hook.argv = argv + optind;
4037			hook.got = 0;
4038			resstr = cget(&hook, NULL);
4039			if ((resstr != NULL) && (resstr[0] == '-'))
4040				fd_res = 1;
4041			optind += hook.got;
4042			break;
4043		default:
4044			break;
4045		}
4046	}
4047
4048	/*
4049	 * If fd_data is set, and we're writing to the device, we need to
4050	 * read the data the user wants written from stdin.
4051	 */
4052	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4053		ssize_t amt_read;
4054		int amt_to_read = data_bytes;
4055		u_int8_t *buf_ptr = data_ptr;
4056
4057		for (amt_read = 0; amt_to_read > 0;
4058		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4059			if (amt_read == -1) {
4060				warn("error reading data from stdin");
4061				error = 1;
4062				goto scsicmd_bailout;
4063			}
4064			amt_to_read -= amt_read;
4065			buf_ptr += amt_read;
4066		}
4067	}
4068
4069	if (arglist & CAM_ARG_ERR_RECOVER)
4070		flags |= CAM_PASS_ERR_RECOVER;
4071
4072	/* Disable freezing the device queue */
4073	flags |= CAM_DEV_QFRZDIS;
4074
4075	if (cdb_len) {
4076		/*
4077		 * This is taken from the SCSI-3 draft spec.
4078		 * (T10/1157D revision 0.3)
4079		 * The top 3 bits of an opcode are the group code.
4080		 * The next 5 bits are the command code.
4081		 * Group 0:  six byte commands
4082		 * Group 1:  ten byte commands
4083		 * Group 2:  ten byte commands
4084		 * Group 3:  reserved
4085		 * Group 4:  sixteen byte commands
4086		 * Group 5:  twelve byte commands
4087		 * Group 6:  vendor specific
4088		 * Group 7:  vendor specific
4089		 */
4090		switch((cdb[0] >> 5) & 0x7) {
4091			case 0:
4092				cdb_len = 6;
4093				break;
4094			case 1:
4095			case 2:
4096				cdb_len = 10;
4097				break;
4098			case 3:
4099			case 6:
4100			case 7:
4101			        /* computed by buff_encode_visit */
4102				break;
4103			case 4:
4104				cdb_len = 16;
4105				break;
4106			case 5:
4107				cdb_len = 12;
4108				break;
4109		}
4110
4111		/*
4112		 * We should probably use csio_build_visit or something like that
4113		 * here, but it's easier to encode arguments as you go.  The
4114		 * alternative would be skipping the CDB argument and then encoding
4115		 * it here, since we've got the data buffer argument by now.
4116		 */
4117		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
4118
4119		cam_fill_csio(&ccb->csio,
4120		      /*retries*/ retry_count,
4121		      /*cbfcnp*/ NULL,
4122		      /*flags*/ flags,
4123		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4124		      /*data_ptr*/ data_ptr,
4125		      /*dxfer_len*/ data_bytes,
4126		      /*sense_len*/ SSD_FULL_SIZE,
4127		      /*cdb_len*/ cdb_len,
4128		      /*timeout*/ timeout ? timeout : 5000);
4129	} else {
4130		atacmd_len = 12;
4131		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
4132		if (need_res)
4133			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
4134		if (dmacmd)
4135			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
4136		if (fpdmacmd)
4137			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
4138
4139		cam_fill_ataio(&ccb->ataio,
4140		      /*retries*/ retry_count,
4141		      /*cbfcnp*/ NULL,
4142		      /*flags*/ flags,
4143		      /*tag_action*/ 0,
4144		      /*data_ptr*/ data_ptr,
4145		      /*dxfer_len*/ data_bytes,
4146		      /*timeout*/ timeout ? timeout : 5000);
4147	}
4148
4149	if (((retval = cam_send_ccb(device, ccb)) < 0)
4150	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4151		const char warnstr[] = "error sending command";
4152
4153		if (retval < 0)
4154			warn(warnstr);
4155		else
4156			warnx(warnstr);
4157
4158		if (arglist & CAM_ARG_VERBOSE) {
4159			cam_error_print(device, ccb, CAM_ESF_ALL,
4160					CAM_EPF_ALL, stderr);
4161		}
4162
4163		error = 1;
4164		goto scsicmd_bailout;
4165	}
4166
4167	if (atacmd_len && need_res) {
4168		if (fd_res == 0) {
4169			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
4170					  arg_put, NULL);
4171			fprintf(stdout, "\n");
4172		} else {
4173			fprintf(stdout,
4174			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
4175			    ccb->ataio.res.status,
4176			    ccb->ataio.res.error,
4177			    ccb->ataio.res.lba_low,
4178			    ccb->ataio.res.lba_mid,
4179			    ccb->ataio.res.lba_high,
4180			    ccb->ataio.res.device,
4181			    ccb->ataio.res.lba_low_exp,
4182			    ccb->ataio.res.lba_mid_exp,
4183			    ccb->ataio.res.lba_high_exp,
4184			    ccb->ataio.res.sector_count,
4185			    ccb->ataio.res.sector_count_exp);
4186			fflush(stdout);
4187		}
4188	}
4189
4190	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4191	 && (arglist & CAM_ARG_CMD_IN)
4192	 && (data_bytes > 0)) {
4193		if (fd_data == 0) {
4194			buff_decode_visit(data_ptr, data_bytes, datastr,
4195					  arg_put, NULL);
4196			fprintf(stdout, "\n");
4197		} else {
4198			ssize_t amt_written;
4199			int amt_to_write = data_bytes;
4200			u_int8_t *buf_ptr = data_ptr;
4201
4202			for (amt_written = 0; (amt_to_write > 0) &&
4203			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
4204				amt_to_write -= amt_written;
4205				buf_ptr += amt_written;
4206			}
4207			if (amt_written == -1) {
4208				warn("error writing data to stdout");
4209				error = 1;
4210				goto scsicmd_bailout;
4211			} else if ((amt_written == 0)
4212				&& (amt_to_write > 0)) {
4213				warnx("only wrote %u bytes out of %u",
4214				      data_bytes - amt_to_write, data_bytes);
4215			}
4216		}
4217	}
4218
4219scsicmd_bailout:
4220
4221	if ((data_bytes > 0) && (data_ptr != NULL))
4222		free(data_ptr);
4223
4224	cam_freeccb(ccb);
4225
4226	return(error);
4227}
4228
4229static int
4230camdebug(int argc, char **argv, char *combinedopt)
4231{
4232	int c, fd;
4233	path_id_t bus = CAM_BUS_WILDCARD;
4234	target_id_t target = CAM_TARGET_WILDCARD;
4235	lun_id_t lun = CAM_LUN_WILDCARD;
4236	char *tstr, *tmpstr = NULL;
4237	union ccb ccb;
4238	int error = 0;
4239
4240	bzero(&ccb, sizeof(union ccb));
4241
4242	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4243		switch(c) {
4244		case 'I':
4245			arglist |= CAM_ARG_DEBUG_INFO;
4246			ccb.cdbg.flags |= CAM_DEBUG_INFO;
4247			break;
4248		case 'P':
4249			arglist |= CAM_ARG_DEBUG_PERIPH;
4250			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
4251			break;
4252		case 'S':
4253			arglist |= CAM_ARG_DEBUG_SUBTRACE;
4254			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
4255			break;
4256		case 'T':
4257			arglist |= CAM_ARG_DEBUG_TRACE;
4258			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
4259			break;
4260		case 'X':
4261			arglist |= CAM_ARG_DEBUG_XPT;
4262			ccb.cdbg.flags |= CAM_DEBUG_XPT;
4263			break;
4264		case 'c':
4265			arglist |= CAM_ARG_DEBUG_CDB;
4266			ccb.cdbg.flags |= CAM_DEBUG_CDB;
4267			break;
4268		case 'p':
4269			arglist |= CAM_ARG_DEBUG_PROBE;
4270			ccb.cdbg.flags |= CAM_DEBUG_PROBE;
4271			break;
4272		default:
4273			break;
4274		}
4275	}
4276
4277	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
4278		warnx("error opening transport layer device %s", XPT_DEVICE);
4279		warn("%s", XPT_DEVICE);
4280		return(1);
4281	}
4282	argc -= optind;
4283	argv += optind;
4284
4285	if (argc <= 0) {
4286		warnx("you must specify \"off\", \"all\" or a bus,");
4287		warnx("bus:target, or bus:target:lun");
4288		close(fd);
4289		return(1);
4290	}
4291
4292	tstr = *argv;
4293
4294	while (isspace(*tstr) && (*tstr != '\0'))
4295		tstr++;
4296
4297	if (strncmp(tstr, "off", 3) == 0) {
4298		ccb.cdbg.flags = CAM_DEBUG_NONE;
4299		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
4300			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
4301			     CAM_ARG_DEBUG_XPT|CAM_ARG_DEBUG_PROBE);
4302	} else if (strncmp(tstr, "all", 3) != 0) {
4303		tmpstr = (char *)strtok(tstr, ":");
4304		if ((tmpstr != NULL) && (*tmpstr != '\0')){
4305			bus = strtol(tmpstr, NULL, 0);
4306			arglist |= CAM_ARG_BUS;
4307			tmpstr = (char *)strtok(NULL, ":");
4308			if ((tmpstr != NULL) && (*tmpstr != '\0')){
4309				target = strtol(tmpstr, NULL, 0);
4310				arglist |= CAM_ARG_TARGET;
4311				tmpstr = (char *)strtok(NULL, ":");
4312				if ((tmpstr != NULL) && (*tmpstr != '\0')){
4313					lun = strtol(tmpstr, NULL, 0);
4314					arglist |= CAM_ARG_LUN;
4315				}
4316			}
4317		} else {
4318			error = 1;
4319			warnx("you must specify \"all\", \"off\", or a bus,");
4320			warnx("bus:target, or bus:target:lun to debug");
4321		}
4322	}
4323
4324	if (error == 0) {
4325
4326		ccb.ccb_h.func_code = XPT_DEBUG;
4327		ccb.ccb_h.path_id = bus;
4328		ccb.ccb_h.target_id = target;
4329		ccb.ccb_h.target_lun = lun;
4330
4331		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
4332			warn("CAMIOCOMMAND ioctl failed");
4333			error = 1;
4334		}
4335
4336		if (error == 0) {
4337			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
4338			     CAM_FUNC_NOTAVAIL) {
4339				warnx("CAM debugging not available");
4340				warnx("you need to put options CAMDEBUG in"
4341				      " your kernel config file!");
4342				error = 1;
4343			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
4344				    CAM_REQ_CMP) {
4345				warnx("XPT_DEBUG CCB failed with status %#x",
4346				      ccb.ccb_h.status);
4347				error = 1;
4348			} else {
4349				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
4350					fprintf(stderr,
4351						"Debugging turned off\n");
4352				} else {
4353					fprintf(stderr,
4354						"Debugging enabled for "
4355						"%d:%d:%jx\n",
4356						bus, target, (uintmax_t)lun);
4357				}
4358			}
4359		}
4360		close(fd);
4361	}
4362
4363	return(error);
4364}
4365
4366static int
4367tagcontrol(struct cam_device *device, int argc, char **argv,
4368	   char *combinedopt)
4369{
4370	int c;
4371	union ccb *ccb;
4372	int numtags = -1;
4373	int retval = 0;
4374	int quiet = 0;
4375	char pathstr[1024];
4376
4377	ccb = cam_getccb(device);
4378
4379	if (ccb == NULL) {
4380		warnx("tagcontrol: error allocating ccb");
4381		return(1);
4382	}
4383
4384	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4385		switch(c) {
4386		case 'N':
4387			numtags = strtol(optarg, NULL, 0);
4388			if (numtags < 0) {
4389				warnx("tag count %d is < 0", numtags);
4390				retval = 1;
4391				goto tagcontrol_bailout;
4392			}
4393			break;
4394		case 'q':
4395			quiet++;
4396			break;
4397		default:
4398			break;
4399		}
4400	}
4401
4402	cam_path_string(device, pathstr, sizeof(pathstr));
4403
4404	if (numtags >= 0) {
4405		bzero(&(&ccb->ccb_h)[1],
4406		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
4407		ccb->ccb_h.func_code = XPT_REL_SIMQ;
4408		ccb->ccb_h.flags = CAM_DEV_QFREEZE;
4409		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
4410		ccb->crs.openings = numtags;
4411
4412
4413		if (cam_send_ccb(device, ccb) < 0) {
4414			perror("error sending XPT_REL_SIMQ CCB");
4415			retval = 1;
4416			goto tagcontrol_bailout;
4417		}
4418
4419		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4420			warnx("XPT_REL_SIMQ CCB failed");
4421			cam_error_print(device, ccb, CAM_ESF_ALL,
4422					CAM_EPF_ALL, stderr);
4423			retval = 1;
4424			goto tagcontrol_bailout;
4425		}
4426
4427
4428		if (quiet == 0)
4429			fprintf(stdout, "%stagged openings now %d\n",
4430				pathstr, ccb->crs.openings);
4431	}
4432
4433	bzero(&(&ccb->ccb_h)[1],
4434	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
4435
4436	ccb->ccb_h.func_code = XPT_GDEV_STATS;
4437
4438	if (cam_send_ccb(device, ccb) < 0) {
4439		perror("error sending XPT_GDEV_STATS CCB");
4440		retval = 1;
4441		goto tagcontrol_bailout;
4442	}
4443
4444	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4445		warnx("XPT_GDEV_STATS CCB failed");
4446		cam_error_print(device, ccb, CAM_ESF_ALL,
4447				CAM_EPF_ALL, stderr);
4448		retval = 1;
4449		goto tagcontrol_bailout;
4450	}
4451
4452	if (arglist & CAM_ARG_VERBOSE) {
4453		fprintf(stdout, "%s", pathstr);
4454		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
4455		fprintf(stdout, "%s", pathstr);
4456		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
4457		fprintf(stdout, "%s", pathstr);
4458		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
4459		fprintf(stdout, "%s", pathstr);
4460		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
4461		fprintf(stdout, "%s", pathstr);
4462		fprintf(stdout, "held          %d\n", ccb->cgds.held);
4463		fprintf(stdout, "%s", pathstr);
4464		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
4465		fprintf(stdout, "%s", pathstr);
4466		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
4467	} else {
4468		if (quiet == 0) {
4469			fprintf(stdout, "%s", pathstr);
4470			fprintf(stdout, "device openings: ");
4471		}
4472		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
4473			ccb->cgds.dev_active);
4474	}
4475
4476tagcontrol_bailout:
4477
4478	cam_freeccb(ccb);
4479	return(retval);
4480}
4481
4482static void
4483cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
4484{
4485	char pathstr[1024];
4486
4487	cam_path_string(device, pathstr, sizeof(pathstr));
4488
4489	if (cts->transport == XPORT_SPI) {
4490		struct ccb_trans_settings_spi *spi =
4491		    &cts->xport_specific.spi;
4492
4493		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
4494
4495			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
4496				spi->sync_period);
4497
4498			if (spi->sync_offset != 0) {
4499				u_int freq;
4500
4501				freq = scsi_calc_syncsrate(spi->sync_period);
4502				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
4503					pathstr, freq / 1000, freq % 1000);
4504			}
4505		}
4506
4507		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
4508			fprintf(stdout, "%soffset: %d\n", pathstr,
4509			    spi->sync_offset);
4510		}
4511
4512		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
4513			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
4514				(0x01 << spi->bus_width) * 8);
4515		}
4516
4517		if (spi->valid & CTS_SPI_VALID_DISC) {
4518			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
4519				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
4520				"enabled" : "disabled");
4521		}
4522	}
4523	if (cts->transport == XPORT_FC) {
4524		struct ccb_trans_settings_fc *fc =
4525		    &cts->xport_specific.fc;
4526
4527		if (fc->valid & CTS_FC_VALID_WWNN)
4528			fprintf(stdout, "%sWWNN: 0x%llx", pathstr,
4529			    (long long) fc->wwnn);
4530		if (fc->valid & CTS_FC_VALID_WWPN)
4531			fprintf(stdout, "%sWWPN: 0x%llx", pathstr,
4532			    (long long) fc->wwpn);
4533		if (fc->valid & CTS_FC_VALID_PORT)
4534			fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port);
4535		if (fc->valid & CTS_FC_VALID_SPEED)
4536			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4537			    pathstr, fc->bitrate / 1000, fc->bitrate % 1000);
4538	}
4539	if (cts->transport == XPORT_SAS) {
4540		struct ccb_trans_settings_sas *sas =
4541		    &cts->xport_specific.sas;
4542
4543		if (sas->valid & CTS_SAS_VALID_SPEED)
4544			fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n",
4545			    pathstr, sas->bitrate / 1000, sas->bitrate % 1000);
4546	}
4547	if (cts->transport == XPORT_ATA) {
4548		struct ccb_trans_settings_pata *pata =
4549		    &cts->xport_specific.ata;
4550
4551		if ((pata->valid & CTS_ATA_VALID_MODE) != 0) {
4552			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4553				ata_mode2string(pata->mode));
4554		}
4555		if ((pata->valid & CTS_ATA_VALID_ATAPI) != 0) {
4556			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4557				pata->atapi);
4558		}
4559		if ((pata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
4560			fprintf(stdout, "%sPIO transaction length: %d\n",
4561				pathstr, pata->bytecount);
4562		}
4563	}
4564	if (cts->transport == XPORT_SATA) {
4565		struct ccb_trans_settings_sata *sata =
4566		    &cts->xport_specific.sata;
4567
4568		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
4569			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
4570				sata->revision);
4571		}
4572		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
4573			fprintf(stdout, "%sATA mode: %s\n", pathstr,
4574				ata_mode2string(sata->mode));
4575		}
4576		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
4577			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
4578				sata->atapi);
4579		}
4580		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
4581			fprintf(stdout, "%sPIO transaction length: %d\n",
4582				pathstr, sata->bytecount);
4583		}
4584		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
4585			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
4586				sata->pm_present);
4587		}
4588		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
4589			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
4590				sata->tags);
4591		}
4592		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
4593			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
4594				sata->caps);
4595		}
4596	}
4597	if (cts->protocol == PROTO_ATA) {
4598		struct ccb_trans_settings_ata *ata=
4599		    &cts->proto_specific.ata;
4600
4601		if (ata->valid & CTS_ATA_VALID_TQ) {
4602			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4603				(ata->flags & CTS_ATA_FLAGS_TAG_ENB) ?
4604				"enabled" : "disabled");
4605		}
4606	}
4607	if (cts->protocol == PROTO_SCSI) {
4608		struct ccb_trans_settings_scsi *scsi=
4609		    &cts->proto_specific.scsi;
4610
4611		if (scsi->valid & CTS_SCSI_VALID_TQ) {
4612			fprintf(stdout, "%stagged queueing: %s\n", pathstr,
4613				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
4614				"enabled" : "disabled");
4615		}
4616	}
4617
4618}
4619
4620/*
4621 * Get a path inquiry CCB for the specified device.
4622 */
4623static int
4624get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
4625{
4626	union ccb *ccb;
4627	int retval = 0;
4628
4629	ccb = cam_getccb(device);
4630	if (ccb == NULL) {
4631		warnx("get_cpi: couldn't allocate CCB");
4632		return(1);
4633	}
4634	bzero(&(&ccb->ccb_h)[1],
4635	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4636	ccb->ccb_h.func_code = XPT_PATH_INQ;
4637	if (cam_send_ccb(device, ccb) < 0) {
4638		warn("get_cpi: error sending Path Inquiry CCB");
4639		if (arglist & CAM_ARG_VERBOSE)
4640			cam_error_print(device, ccb, CAM_ESF_ALL,
4641					CAM_EPF_ALL, stderr);
4642		retval = 1;
4643		goto get_cpi_bailout;
4644	}
4645	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4646		if (arglist & CAM_ARG_VERBOSE)
4647			cam_error_print(device, ccb, CAM_ESF_ALL,
4648					CAM_EPF_ALL, stderr);
4649		retval = 1;
4650		goto get_cpi_bailout;
4651	}
4652	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
4653
4654get_cpi_bailout:
4655	cam_freeccb(ccb);
4656	return(retval);
4657}
4658
4659/*
4660 * Get a get device CCB for the specified device.
4661 */
4662static int
4663get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
4664{
4665	union ccb *ccb;
4666	int retval = 0;
4667
4668	ccb = cam_getccb(device);
4669	if (ccb == NULL) {
4670		warnx("get_cgd: couldn't allocate CCB");
4671		return(1);
4672	}
4673	bzero(&(&ccb->ccb_h)[1],
4674	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
4675	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
4676	if (cam_send_ccb(device, ccb) < 0) {
4677		warn("get_cgd: error sending Path Inquiry CCB");
4678		if (arglist & CAM_ARG_VERBOSE)
4679			cam_error_print(device, ccb, CAM_ESF_ALL,
4680					CAM_EPF_ALL, stderr);
4681		retval = 1;
4682		goto get_cgd_bailout;
4683	}
4684	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4685		if (arglist & CAM_ARG_VERBOSE)
4686			cam_error_print(device, ccb, CAM_ESF_ALL,
4687					CAM_EPF_ALL, stderr);
4688		retval = 1;
4689		goto get_cgd_bailout;
4690	}
4691	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
4692
4693get_cgd_bailout:
4694	cam_freeccb(ccb);
4695	return(retval);
4696}
4697
4698/* return the type of disk (really the command type) */
4699static const char *
4700get_disk_type(struct cam_device *device)
4701{
4702	struct ccb_getdev	cgd;
4703
4704	(void) memset(&cgd, 0x0, sizeof(cgd));
4705	get_cgd(device, &cgd);
4706	switch(cgd.protocol) {
4707	case PROTO_SCSI:
4708		return "scsi";
4709	case PROTO_ATA:
4710	case PROTO_ATAPI:
4711	case PROTO_SATAPM:
4712		return "ata";
4713	default:
4714		return "unknown";
4715	}
4716}
4717
4718static void
4719cpi_print(struct ccb_pathinq *cpi)
4720{
4721	char adapter_str[1024];
4722	int i;
4723
4724	snprintf(adapter_str, sizeof(adapter_str),
4725		 "%s%d:", cpi->dev_name, cpi->unit_number);
4726
4727	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
4728		cpi->version_num);
4729
4730	for (i = 1; i < 0xff; i = i << 1) {
4731		const char *str;
4732
4733		if ((i & cpi->hba_inquiry) == 0)
4734			continue;
4735
4736		fprintf(stdout, "%s supports ", adapter_str);
4737
4738		switch(i) {
4739		case PI_MDP_ABLE:
4740			str = "MDP message";
4741			break;
4742		case PI_WIDE_32:
4743			str = "32 bit wide SCSI";
4744			break;
4745		case PI_WIDE_16:
4746			str = "16 bit wide SCSI";
4747			break;
4748		case PI_SDTR_ABLE:
4749			str = "SDTR message";
4750			break;
4751		case PI_LINKED_CDB:
4752			str = "linked CDBs";
4753			break;
4754		case PI_TAG_ABLE:
4755			str = "tag queue messages";
4756			break;
4757		case PI_SOFT_RST:
4758			str = "soft reset alternative";
4759			break;
4760		case PI_SATAPM:
4761			str = "SATA Port Multiplier";
4762			break;
4763		default:
4764			str = "unknown PI bit set";
4765			break;
4766		}
4767		fprintf(stdout, "%s\n", str);
4768	}
4769
4770	for (i = 1; i < 0xff; i = i << 1) {
4771		const char *str;
4772
4773		if ((i & cpi->hba_misc) == 0)
4774			continue;
4775
4776		fprintf(stdout, "%s ", adapter_str);
4777
4778		switch(i) {
4779		case PIM_SCANHILO:
4780			str = "bus scans from high ID to low ID";
4781			break;
4782		case PIM_NOREMOVE:
4783			str = "removable devices not included in scan";
4784			break;
4785		case PIM_NOINITIATOR:
4786			str = "initiator role not supported";
4787			break;
4788		case PIM_NOBUSRESET:
4789			str = "user has disabled initial BUS RESET or"
4790			      " controller is in target/mixed mode";
4791			break;
4792		case PIM_NO_6_BYTE:
4793			str = "do not send 6-byte commands";
4794			break;
4795		case PIM_SEQSCAN:
4796			str = "scan bus sequentially";
4797			break;
4798		default:
4799			str = "unknown PIM bit set";
4800			break;
4801		}
4802		fprintf(stdout, "%s\n", str);
4803	}
4804
4805	for (i = 1; i < 0xff; i = i << 1) {
4806		const char *str;
4807
4808		if ((i & cpi->target_sprt) == 0)
4809			continue;
4810
4811		fprintf(stdout, "%s supports ", adapter_str);
4812		switch(i) {
4813		case PIT_PROCESSOR:
4814			str = "target mode processor mode";
4815			break;
4816		case PIT_PHASE:
4817			str = "target mode phase cog. mode";
4818			break;
4819		case PIT_DISCONNECT:
4820			str = "disconnects in target mode";
4821			break;
4822		case PIT_TERM_IO:
4823			str = "terminate I/O message in target mode";
4824			break;
4825		case PIT_GRP_6:
4826			str = "group 6 commands in target mode";
4827			break;
4828		case PIT_GRP_7:
4829			str = "group 7 commands in target mode";
4830			break;
4831		default:
4832			str = "unknown PIT bit set";
4833			break;
4834		}
4835
4836		fprintf(stdout, "%s\n", str);
4837	}
4838	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
4839		cpi->hba_eng_cnt);
4840	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
4841		cpi->max_target);
4842	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
4843		cpi->max_lun);
4844	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
4845		adapter_str, cpi->hpath_id);
4846	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
4847		cpi->initiator_id);
4848	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
4849	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
4850	fprintf(stdout, "%s HBA vendor ID: 0x%04x\n",
4851	    adapter_str, cpi->hba_vendor);
4852	fprintf(stdout, "%s HBA device ID: 0x%04x\n",
4853	    adapter_str, cpi->hba_device);
4854	fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n",
4855	    adapter_str, cpi->hba_subvendor);
4856	fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n",
4857	    adapter_str, cpi->hba_subdevice);
4858	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
4859	fprintf(stdout, "%s base transfer speed: ", adapter_str);
4860	if (cpi->base_transfer_speed > 1000)
4861		fprintf(stdout, "%d.%03dMB/sec\n",
4862			cpi->base_transfer_speed / 1000,
4863			cpi->base_transfer_speed % 1000);
4864	else
4865		fprintf(stdout, "%dKB/sec\n",
4866			(cpi->base_transfer_speed % 1000) * 1000);
4867	fprintf(stdout, "%s maximum transfer size: %u bytes\n",
4868	    adapter_str, cpi->maxio);
4869}
4870
4871static int
4872get_print_cts(struct cam_device *device, int user_settings, int quiet,
4873	      struct ccb_trans_settings *cts)
4874{
4875	int retval;
4876	union ccb *ccb;
4877
4878	retval = 0;
4879	ccb = cam_getccb(device);
4880
4881	if (ccb == NULL) {
4882		warnx("get_print_cts: error allocating ccb");
4883		return(1);
4884	}
4885
4886	bzero(&(&ccb->ccb_h)[1],
4887	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
4888
4889	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
4890
4891	if (user_settings == 0)
4892		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
4893	else
4894		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
4895
4896	if (cam_send_ccb(device, ccb) < 0) {
4897		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
4898		if (arglist & CAM_ARG_VERBOSE)
4899			cam_error_print(device, ccb, CAM_ESF_ALL,
4900					CAM_EPF_ALL, stderr);
4901		retval = 1;
4902		goto get_print_cts_bailout;
4903	}
4904
4905	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4906		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
4907		if (arglist & CAM_ARG_VERBOSE)
4908			cam_error_print(device, ccb, CAM_ESF_ALL,
4909					CAM_EPF_ALL, stderr);
4910		retval = 1;
4911		goto get_print_cts_bailout;
4912	}
4913
4914	if (quiet == 0)
4915		cts_print(device, &ccb->cts);
4916
4917	if (cts != NULL)
4918		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
4919
4920get_print_cts_bailout:
4921
4922	cam_freeccb(ccb);
4923
4924	return(retval);
4925}
4926
4927static int
4928ratecontrol(struct cam_device *device, int retry_count, int timeout,
4929	    int argc, char **argv, char *combinedopt)
4930{
4931	int c;
4932	union ccb *ccb;
4933	int user_settings = 0;
4934	int retval = 0;
4935	int disc_enable = -1, tag_enable = -1;
4936	int mode = -1;
4937	int offset = -1;
4938	double syncrate = -1;
4939	int bus_width = -1;
4940	int quiet = 0;
4941	int change_settings = 0, send_tur = 0;
4942	struct ccb_pathinq cpi;
4943
4944	ccb = cam_getccb(device);
4945	if (ccb == NULL) {
4946		warnx("ratecontrol: error allocating ccb");
4947		return(1);
4948	}
4949	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4950		switch(c){
4951		case 'a':
4952			send_tur = 1;
4953			break;
4954		case 'c':
4955			user_settings = 0;
4956			break;
4957		case 'D':
4958			if (strncasecmp(optarg, "enable", 6) == 0)
4959				disc_enable = 1;
4960			else if (strncasecmp(optarg, "disable", 7) == 0)
4961				disc_enable = 0;
4962			else {
4963				warnx("-D argument \"%s\" is unknown", optarg);
4964				retval = 1;
4965				goto ratecontrol_bailout;
4966			}
4967			change_settings = 1;
4968			break;
4969		case 'M':
4970			mode = ata_string2mode(optarg);
4971			if (mode < 0) {
4972				warnx("unknown mode '%s'", optarg);
4973				retval = 1;
4974				goto ratecontrol_bailout;
4975			}
4976			change_settings = 1;
4977			break;
4978		case 'O':
4979			offset = strtol(optarg, NULL, 0);
4980			if (offset < 0) {
4981				warnx("offset value %d is < 0", offset);
4982				retval = 1;
4983				goto ratecontrol_bailout;
4984			}
4985			change_settings = 1;
4986			break;
4987		case 'q':
4988			quiet++;
4989			break;
4990		case 'R':
4991			syncrate = atof(optarg);
4992			if (syncrate < 0) {
4993				warnx("sync rate %f is < 0", syncrate);
4994				retval = 1;
4995				goto ratecontrol_bailout;
4996			}
4997			change_settings = 1;
4998			break;
4999		case 'T':
5000			if (strncasecmp(optarg, "enable", 6) == 0)
5001				tag_enable = 1;
5002			else if (strncasecmp(optarg, "disable", 7) == 0)
5003				tag_enable = 0;
5004			else {
5005				warnx("-T argument \"%s\" is unknown", optarg);
5006				retval = 1;
5007				goto ratecontrol_bailout;
5008			}
5009			change_settings = 1;
5010			break;
5011		case 'U':
5012			user_settings = 1;
5013			break;
5014		case 'W':
5015			bus_width = strtol(optarg, NULL, 0);
5016			if (bus_width < 0) {
5017				warnx("bus width %d is < 0", bus_width);
5018				retval = 1;
5019				goto ratecontrol_bailout;
5020			}
5021			change_settings = 1;
5022			break;
5023		default:
5024			break;
5025		}
5026	}
5027	bzero(&(&ccb->ccb_h)[1],
5028	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
5029	/*
5030	 * Grab path inquiry information, so we can determine whether
5031	 * or not the initiator is capable of the things that the user
5032	 * requests.
5033	 */
5034	ccb->ccb_h.func_code = XPT_PATH_INQ;
5035	if (cam_send_ccb(device, ccb) < 0) {
5036		perror("error sending XPT_PATH_INQ CCB");
5037		if (arglist & CAM_ARG_VERBOSE) {
5038			cam_error_print(device, ccb, CAM_ESF_ALL,
5039					CAM_EPF_ALL, stderr);
5040		}
5041		retval = 1;
5042		goto ratecontrol_bailout;
5043	}
5044	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5045		warnx("XPT_PATH_INQ CCB failed");
5046		if (arglist & CAM_ARG_VERBOSE) {
5047			cam_error_print(device, ccb, CAM_ESF_ALL,
5048					CAM_EPF_ALL, stderr);
5049		}
5050		retval = 1;
5051		goto ratecontrol_bailout;
5052	}
5053	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
5054	bzero(&(&ccb->ccb_h)[1],
5055	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
5056	if (quiet == 0) {
5057		fprintf(stdout, "%s parameters:\n",
5058		    user_settings ? "User" : "Current");
5059	}
5060	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
5061	if (retval != 0)
5062		goto ratecontrol_bailout;
5063
5064	if (arglist & CAM_ARG_VERBOSE)
5065		cpi_print(&cpi);
5066
5067	if (change_settings) {
5068		int didsettings = 0;
5069		struct ccb_trans_settings_spi *spi = NULL;
5070		struct ccb_trans_settings_pata *pata = NULL;
5071		struct ccb_trans_settings_sata *sata = NULL;
5072		struct ccb_trans_settings_ata *ata = NULL;
5073		struct ccb_trans_settings_scsi *scsi = NULL;
5074
5075		if (ccb->cts.transport == XPORT_SPI)
5076			spi = &ccb->cts.xport_specific.spi;
5077		if (ccb->cts.transport == XPORT_ATA)
5078			pata = &ccb->cts.xport_specific.ata;
5079		if (ccb->cts.transport == XPORT_SATA)
5080			sata = &ccb->cts.xport_specific.sata;
5081		if (ccb->cts.protocol == PROTO_ATA)
5082			ata = &ccb->cts.proto_specific.ata;
5083		if (ccb->cts.protocol == PROTO_SCSI)
5084			scsi = &ccb->cts.proto_specific.scsi;
5085		ccb->cts.xport_specific.valid = 0;
5086		ccb->cts.proto_specific.valid = 0;
5087		if (spi && disc_enable != -1) {
5088			spi->valid |= CTS_SPI_VALID_DISC;
5089			if (disc_enable == 0)
5090				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
5091			else
5092				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5093			didsettings++;
5094		}
5095		if (tag_enable != -1) {
5096			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
5097				warnx("HBA does not support tagged queueing, "
5098				      "so you cannot modify tag settings");
5099				retval = 1;
5100				goto ratecontrol_bailout;
5101			}
5102			if (ata) {
5103				ata->valid |= CTS_SCSI_VALID_TQ;
5104				if (tag_enable == 0)
5105					ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
5106				else
5107					ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
5108				didsettings++;
5109			} else if (scsi) {
5110				scsi->valid |= CTS_SCSI_VALID_TQ;
5111				if (tag_enable == 0)
5112					scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
5113				else
5114					scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5115				didsettings++;
5116			}
5117		}
5118		if (spi && offset != -1) {
5119			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5120				warnx("HBA is not capable of changing offset");
5121				retval = 1;
5122				goto ratecontrol_bailout;
5123			}
5124			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5125			spi->sync_offset = offset;
5126			didsettings++;
5127		}
5128		if (spi && syncrate != -1) {
5129			int prelim_sync_period;
5130
5131			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5132				warnx("HBA is not capable of changing "
5133				      "transfer rates");
5134				retval = 1;
5135				goto ratecontrol_bailout;
5136			}
5137			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5138			/*
5139			 * The sync rate the user gives us is in MHz.
5140			 * We need to translate it into KHz for this
5141			 * calculation.
5142			 */
5143			syncrate *= 1000;
5144			/*
5145			 * Next, we calculate a "preliminary" sync period
5146			 * in tenths of a nanosecond.
5147			 */
5148			if (syncrate == 0)
5149				prelim_sync_period = 0;
5150			else
5151				prelim_sync_period = 10000000 / syncrate;
5152			spi->sync_period =
5153				scsi_calc_syncparam(prelim_sync_period);
5154			didsettings++;
5155		}
5156		if (sata && syncrate != -1) {
5157			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5158				warnx("HBA is not capable of changing "
5159				      "transfer rates");
5160				retval = 1;
5161				goto ratecontrol_bailout;
5162			}
5163			if  (!user_settings) {
5164				warnx("You can modify only user rate "
5165				    "settings for SATA");
5166				retval = 1;
5167				goto ratecontrol_bailout;
5168			}
5169			sata->revision = ata_speed2revision(syncrate * 100);
5170			if (sata->revision < 0) {
5171				warnx("Invalid rate %f", syncrate);
5172				retval = 1;
5173				goto ratecontrol_bailout;
5174			}
5175			sata->valid |= CTS_SATA_VALID_REVISION;
5176			didsettings++;
5177		}
5178		if ((pata || sata) && mode != -1) {
5179			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
5180				warnx("HBA is not capable of changing "
5181				      "transfer rates");
5182				retval = 1;
5183				goto ratecontrol_bailout;
5184			}
5185			if  (!user_settings) {
5186				warnx("You can modify only user mode "
5187				    "settings for ATA/SATA");
5188				retval = 1;
5189				goto ratecontrol_bailout;
5190			}
5191			if (pata) {
5192				pata->mode = mode;
5193				pata->valid |= CTS_ATA_VALID_MODE;
5194			} else {
5195				sata->mode = mode;
5196				sata->valid |= CTS_SATA_VALID_MODE;
5197			}
5198			didsettings++;
5199		}
5200		/*
5201		 * The bus_width argument goes like this:
5202		 * 0 == 8 bit
5203		 * 1 == 16 bit
5204		 * 2 == 32 bit
5205		 * Therefore, if you shift the number of bits given on the
5206		 * command line right by 4, you should get the correct
5207		 * number.
5208		 */
5209		if (spi && bus_width != -1) {
5210			/*
5211			 * We might as well validate things here with a
5212			 * decipherable error message, rather than what
5213			 * will probably be an indecipherable error message
5214			 * by the time it gets back to us.
5215			 */
5216			if ((bus_width == 16)
5217			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
5218				warnx("HBA does not support 16 bit bus width");
5219				retval = 1;
5220				goto ratecontrol_bailout;
5221			} else if ((bus_width == 32)
5222				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
5223				warnx("HBA does not support 32 bit bus width");
5224				retval = 1;
5225				goto ratecontrol_bailout;
5226			} else if ((bus_width != 8)
5227				&& (bus_width != 16)
5228				&& (bus_width != 32)) {
5229				warnx("Invalid bus width %d", bus_width);
5230				retval = 1;
5231				goto ratecontrol_bailout;
5232			}
5233			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
5234			spi->bus_width = bus_width >> 4;
5235			didsettings++;
5236		}
5237		if  (didsettings == 0) {
5238			goto ratecontrol_bailout;
5239		}
5240		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
5241		if (cam_send_ccb(device, ccb) < 0) {
5242			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
5243			if (arglist & CAM_ARG_VERBOSE) {
5244				cam_error_print(device, ccb, CAM_ESF_ALL,
5245						CAM_EPF_ALL, stderr);
5246			}
5247			retval = 1;
5248			goto ratecontrol_bailout;
5249		}
5250		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5251			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
5252			if (arglist & CAM_ARG_VERBOSE) {
5253				cam_error_print(device, ccb, CAM_ESF_ALL,
5254						CAM_EPF_ALL, stderr);
5255			}
5256			retval = 1;
5257			goto ratecontrol_bailout;
5258		}
5259	}
5260	if (send_tur) {
5261		retval = testunitready(device, retry_count, timeout,
5262				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
5263		/*
5264		 * If the TUR didn't succeed, just bail.
5265		 */
5266		if (retval != 0) {
5267			if (quiet == 0)
5268				fprintf(stderr, "Test Unit Ready failed\n");
5269			goto ratecontrol_bailout;
5270		}
5271	}
5272	if ((change_settings || send_tur) && !quiet &&
5273	    (ccb->cts.transport == XPORT_ATA ||
5274	     ccb->cts.transport == XPORT_SATA || send_tur)) {
5275		fprintf(stdout, "New parameters:\n");
5276		retval = get_print_cts(device, user_settings, 0, NULL);
5277	}
5278
5279ratecontrol_bailout:
5280	cam_freeccb(ccb);
5281	return(retval);
5282}
5283
5284static int
5285scsiformat(struct cam_device *device, int argc, char **argv,
5286	   char *combinedopt, int retry_count, int timeout)
5287{
5288	union ccb *ccb;
5289	int c;
5290	int ycount = 0, quiet = 0;
5291	int error = 0, retval = 0;
5292	int use_timeout = 10800 * 1000;
5293	int immediate = 1;
5294	struct format_defect_list_header fh;
5295	u_int8_t *data_ptr = NULL;
5296	u_int32_t dxfer_len = 0;
5297	u_int8_t byte2 = 0;
5298	int num_warnings = 0;
5299	int reportonly = 0;
5300
5301	ccb = cam_getccb(device);
5302
5303	if (ccb == NULL) {
5304		warnx("scsiformat: error allocating ccb");
5305		return(1);
5306	}
5307
5308	bzero(&(&ccb->ccb_h)[1],
5309	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5310
5311	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5312		switch(c) {
5313		case 'q':
5314			quiet++;
5315			break;
5316		case 'r':
5317			reportonly = 1;
5318			break;
5319		case 'w':
5320			immediate = 0;
5321			break;
5322		case 'y':
5323			ycount++;
5324			break;
5325		}
5326	}
5327
5328	if (reportonly)
5329		goto doreport;
5330
5331	if (quiet == 0) {
5332		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5333			"following device:\n");
5334
5335		error = scsidoinquiry(device, argc, argv, combinedopt,
5336				      retry_count, timeout);
5337
5338		if (error != 0) {
5339			warnx("scsiformat: error sending inquiry");
5340			goto scsiformat_bailout;
5341		}
5342	}
5343
5344	if (ycount == 0) {
5345		if (!get_confirmation()) {
5346			error = 1;
5347			goto scsiformat_bailout;
5348		}
5349	}
5350
5351	if (timeout != 0)
5352		use_timeout = timeout;
5353
5354	if (quiet == 0) {
5355		fprintf(stdout, "Current format timeout is %d seconds\n",
5356			use_timeout / 1000);
5357	}
5358
5359	/*
5360	 * If the user hasn't disabled questions and didn't specify a
5361	 * timeout on the command line, ask them if they want the current
5362	 * timeout.
5363	 */
5364	if ((ycount == 0)
5365	 && (timeout == 0)) {
5366		char str[1024];
5367		int new_timeout = 0;
5368
5369		fprintf(stdout, "Enter new timeout in seconds or press\n"
5370			"return to keep the current timeout [%d] ",
5371			use_timeout / 1000);
5372
5373		if (fgets(str, sizeof(str), stdin) != NULL) {
5374			if (str[0] != '\0')
5375				new_timeout = atoi(str);
5376		}
5377
5378		if (new_timeout != 0) {
5379			use_timeout = new_timeout * 1000;
5380			fprintf(stdout, "Using new timeout value %d\n",
5381				use_timeout / 1000);
5382		}
5383	}
5384
5385	/*
5386	 * Keep this outside the if block below to silence any unused
5387	 * variable warnings.
5388	 */
5389	bzero(&fh, sizeof(fh));
5390
5391	/*
5392	 * If we're in immediate mode, we've got to include the format
5393	 * header
5394	 */
5395	if (immediate != 0) {
5396		fh.byte2 = FU_DLH_IMMED;
5397		data_ptr = (u_int8_t *)&fh;
5398		dxfer_len = sizeof(fh);
5399		byte2 = FU_FMT_DATA;
5400	} else if (quiet == 0) {
5401		fprintf(stdout, "Formatting...");
5402		fflush(stdout);
5403	}
5404
5405	scsi_format_unit(&ccb->csio,
5406			 /* retries */ retry_count,
5407			 /* cbfcnp */ NULL,
5408			 /* tag_action */ MSG_SIMPLE_Q_TAG,
5409			 /* byte2 */ byte2,
5410			 /* ileave */ 0,
5411			 /* data_ptr */ data_ptr,
5412			 /* dxfer_len */ dxfer_len,
5413			 /* sense_len */ SSD_FULL_SIZE,
5414			 /* timeout */ use_timeout);
5415
5416	/* Disable freezing the device queue */
5417	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5418
5419	if (arglist & CAM_ARG_ERR_RECOVER)
5420		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5421
5422	if (((retval = cam_send_ccb(device, ccb)) < 0)
5423	 || ((immediate == 0)
5424	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5425		const char errstr[] = "error sending format command";
5426
5427		if (retval < 0)
5428			warn(errstr);
5429		else
5430			warnx(errstr);
5431
5432		if (arglist & CAM_ARG_VERBOSE) {
5433			cam_error_print(device, ccb, CAM_ESF_ALL,
5434					CAM_EPF_ALL, stderr);
5435		}
5436		error = 1;
5437		goto scsiformat_bailout;
5438	}
5439
5440	/*
5441	 * If we ran in non-immediate mode, we already checked for errors
5442	 * above and printed out any necessary information.  If we're in
5443	 * immediate mode, we need to loop through and get status
5444	 * information periodically.
5445	 */
5446	if (immediate == 0) {
5447		if (quiet == 0) {
5448			fprintf(stdout, "Format Complete\n");
5449		}
5450		goto scsiformat_bailout;
5451	}
5452
5453doreport:
5454	do {
5455		cam_status status;
5456
5457		bzero(&(&ccb->ccb_h)[1],
5458		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5459
5460		/*
5461		 * There's really no need to do error recovery or
5462		 * retries here, since we're just going to sit in a
5463		 * loop and wait for the device to finish formatting.
5464		 */
5465		scsi_test_unit_ready(&ccb->csio,
5466				     /* retries */ 0,
5467				     /* cbfcnp */ NULL,
5468				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5469				     /* sense_len */ SSD_FULL_SIZE,
5470				     /* timeout */ 5000);
5471
5472		/* Disable freezing the device queue */
5473		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5474
5475		retval = cam_send_ccb(device, ccb);
5476
5477		/*
5478		 * If we get an error from the ioctl, bail out.  SCSI
5479		 * errors are expected.
5480		 */
5481		if (retval < 0) {
5482			warn("error sending CAMIOCOMMAND ioctl");
5483			if (arglist & CAM_ARG_VERBOSE) {
5484				cam_error_print(device, ccb, CAM_ESF_ALL,
5485						CAM_EPF_ALL, stderr);
5486			}
5487			error = 1;
5488			goto scsiformat_bailout;
5489		}
5490
5491		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5492
5493		if ((status != CAM_REQ_CMP)
5494		 && (status == CAM_SCSI_STATUS_ERROR)
5495		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5496			struct scsi_sense_data *sense;
5497			int error_code, sense_key, asc, ascq;
5498
5499			sense = &ccb->csio.sense_data;
5500			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5501			    ccb->csio.sense_resid, &error_code, &sense_key,
5502			    &asc, &ascq, /*show_errors*/ 1);
5503
5504			/*
5505			 * According to the SCSI-2 and SCSI-3 specs, a
5506			 * drive that is in the middle of a format should
5507			 * return NOT READY with an ASC of "logical unit
5508			 * not ready, format in progress".  The sense key
5509			 * specific bytes will then be a progress indicator.
5510			 */
5511			if ((sense_key == SSD_KEY_NOT_READY)
5512			 && (asc == 0x04) && (ascq == 0x04)) {
5513				uint8_t sks[3];
5514
5515				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5516				     ccb->csio.sense_resid, sks) == 0)
5517				 && (quiet == 0)) {
5518					int val;
5519					u_int64_t percentage;
5520
5521					val = scsi_2btoul(&sks[1]);
5522					percentage = 10000 * val;
5523
5524					fprintf(stdout,
5525						"\rFormatting:  %ju.%02u %% "
5526						"(%d/%d) done",
5527						(uintmax_t)(percentage /
5528						(0x10000 * 100)),
5529						(unsigned)((percentage /
5530						0x10000) % 100),
5531						val, 0x10000);
5532					fflush(stdout);
5533				} else if ((quiet == 0)
5534					&& (++num_warnings <= 1)) {
5535					warnx("Unexpected SCSI Sense Key "
5536					      "Specific value returned "
5537					      "during format:");
5538					scsi_sense_print(device, &ccb->csio,
5539							 stderr);
5540					warnx("Unable to print status "
5541					      "information, but format will "
5542					      "proceed.");
5543					warnx("will exit when format is "
5544					      "complete");
5545				}
5546				sleep(1);
5547			} else {
5548				warnx("Unexpected SCSI error during format");
5549				cam_error_print(device, ccb, CAM_ESF_ALL,
5550						CAM_EPF_ALL, stderr);
5551				error = 1;
5552				goto scsiformat_bailout;
5553			}
5554
5555		} else if (status != CAM_REQ_CMP) {
5556			warnx("Unexpected CAM status %#x", status);
5557			if (arglist & CAM_ARG_VERBOSE)
5558				cam_error_print(device, ccb, CAM_ESF_ALL,
5559						CAM_EPF_ALL, stderr);
5560			error = 1;
5561			goto scsiformat_bailout;
5562		}
5563
5564	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5565
5566	if (quiet == 0)
5567		fprintf(stdout, "\nFormat Complete\n");
5568
5569scsiformat_bailout:
5570
5571	cam_freeccb(ccb);
5572
5573	return(error);
5574}
5575
5576static int
5577scsisanitize(struct cam_device *device, int argc, char **argv,
5578	     char *combinedopt, int retry_count, int timeout)
5579{
5580	union ccb *ccb;
5581	u_int8_t action = 0;
5582	int c;
5583	int ycount = 0, quiet = 0;
5584	int error = 0, retval = 0;
5585	int use_timeout = 10800 * 1000;
5586	int immediate = 1;
5587	int invert = 0;
5588	int passes = 0;
5589	int ause = 0;
5590	int fd = -1;
5591	const char *pattern = NULL;
5592	u_int8_t *data_ptr = NULL;
5593	u_int32_t dxfer_len = 0;
5594	u_int8_t byte2 = 0;
5595	int num_warnings = 0;
5596	int reportonly = 0;
5597
5598	ccb = cam_getccb(device);
5599
5600	if (ccb == NULL) {
5601		warnx("scsisanitize: error allocating ccb");
5602		return(1);
5603	}
5604
5605	bzero(&(&ccb->ccb_h)[1],
5606	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5607
5608	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5609		switch(c) {
5610		case 'a':
5611			if (strcasecmp(optarg, "overwrite") == 0)
5612				action = SSZ_SERVICE_ACTION_OVERWRITE;
5613			else if (strcasecmp(optarg, "block") == 0)
5614				action = SSZ_SERVICE_ACTION_BLOCK_ERASE;
5615			else if (strcasecmp(optarg, "crypto") == 0)
5616				action = SSZ_SERVICE_ACTION_CRYPTO_ERASE;
5617			else if (strcasecmp(optarg, "exitfailure") == 0)
5618				action = SSZ_SERVICE_ACTION_EXIT_MODE_FAILURE;
5619			else {
5620				warnx("invalid service operation \"%s\"",
5621				      optarg);
5622				error = 1;
5623				goto scsisanitize_bailout;
5624			}
5625			break;
5626		case 'c':
5627			passes = strtol(optarg, NULL, 0);
5628			if (passes < 1 || passes > 31) {
5629				warnx("invalid passes value %d", passes);
5630				error = 1;
5631				goto scsisanitize_bailout;
5632			}
5633			break;
5634		case 'I':
5635			invert = 1;
5636			break;
5637		case 'P':
5638			pattern = optarg;
5639			break;
5640		case 'q':
5641			quiet++;
5642			break;
5643		case 'U':
5644			ause = 1;
5645			break;
5646		case 'r':
5647			reportonly = 1;
5648			break;
5649		case 'w':
5650			immediate = 0;
5651			break;
5652		case 'y':
5653			ycount++;
5654			break;
5655		}
5656	}
5657
5658	if (reportonly)
5659		goto doreport;
5660
5661	if (action == 0) {
5662		warnx("an action is required");
5663		error = 1;
5664		goto scsisanitize_bailout;
5665	} else if (action == SSZ_SERVICE_ACTION_OVERWRITE) {
5666		struct scsi_sanitize_parameter_list *pl;
5667		struct stat sb;
5668		ssize_t sz, amt;
5669
5670		if (pattern == NULL) {
5671			warnx("overwrite action requires -P argument");
5672			error = 1;
5673			goto scsisanitize_bailout;
5674		}
5675		fd = open(pattern, O_RDONLY);
5676		if (fd < 0) {
5677			warn("cannot open pattern file %s", pattern);
5678			error = 1;
5679			goto scsisanitize_bailout;
5680		}
5681		if (fstat(fd, &sb) < 0) {
5682			warn("cannot stat pattern file %s", pattern);
5683			error = 1;
5684			goto scsisanitize_bailout;
5685		}
5686		sz = sb.st_size;
5687		if (sz > SSZPL_MAX_PATTERN_LENGTH) {
5688			warnx("pattern file size exceeds maximum value %d",
5689			      SSZPL_MAX_PATTERN_LENGTH);
5690			error = 1;
5691			goto scsisanitize_bailout;
5692		}
5693		dxfer_len = sizeof(*pl) + sz;
5694		data_ptr = calloc(1, dxfer_len);
5695		if (data_ptr == NULL) {
5696			warnx("cannot allocate parameter list buffer");
5697			error = 1;
5698			goto scsisanitize_bailout;
5699		}
5700
5701		amt = read(fd, data_ptr + sizeof(*pl), sz);
5702		if (amt < 0) {
5703			warn("cannot read pattern file");
5704			error = 1;
5705			goto scsisanitize_bailout;
5706		} else if (amt != sz) {
5707			warnx("short pattern file read");
5708			error = 1;
5709			goto scsisanitize_bailout;
5710		}
5711
5712		pl = (struct scsi_sanitize_parameter_list *)data_ptr;
5713		if (passes == 0)
5714			pl->byte1 = 1;
5715		else
5716			pl->byte1 = passes;
5717		if (invert != 0)
5718			pl->byte1 |= SSZPL_INVERT;
5719		scsi_ulto2b(sz, pl->length);
5720	} else {
5721		const char *arg;
5722
5723		if (passes != 0)
5724			arg = "-c";
5725		else if (invert != 0)
5726			arg = "-I";
5727		else if (pattern != NULL)
5728			arg = "-P";
5729		else
5730			arg = NULL;
5731		if (arg != NULL) {
5732			warnx("%s argument only valid with overwrite "
5733			      "operation", arg);
5734			error = 1;
5735			goto scsisanitize_bailout;
5736		}
5737	}
5738
5739	if (quiet == 0) {
5740		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
5741			"following device:\n");
5742
5743		error = scsidoinquiry(device, argc, argv, combinedopt,
5744				      retry_count, timeout);
5745
5746		if (error != 0) {
5747			warnx("scsisanitize: error sending inquiry");
5748			goto scsisanitize_bailout;
5749		}
5750	}
5751
5752	if (ycount == 0) {
5753		if (!get_confirmation()) {
5754			error = 1;
5755			goto scsisanitize_bailout;
5756		}
5757	}
5758
5759	if (timeout != 0)
5760		use_timeout = timeout;
5761
5762	if (quiet == 0) {
5763		fprintf(stdout, "Current sanitize timeout is %d seconds\n",
5764			use_timeout / 1000);
5765	}
5766
5767	/*
5768	 * If the user hasn't disabled questions and didn't specify a
5769	 * timeout on the command line, ask them if they want the current
5770	 * timeout.
5771	 */
5772	if ((ycount == 0)
5773	 && (timeout == 0)) {
5774		char str[1024];
5775		int new_timeout = 0;
5776
5777		fprintf(stdout, "Enter new timeout in seconds or press\n"
5778			"return to keep the current timeout [%d] ",
5779			use_timeout / 1000);
5780
5781		if (fgets(str, sizeof(str), stdin) != NULL) {
5782			if (str[0] != '\0')
5783				new_timeout = atoi(str);
5784		}
5785
5786		if (new_timeout != 0) {
5787			use_timeout = new_timeout * 1000;
5788			fprintf(stdout, "Using new timeout value %d\n",
5789				use_timeout / 1000);
5790		}
5791	}
5792
5793	byte2 = action;
5794	if (ause != 0)
5795		byte2 |= SSZ_UNRESTRICTED_EXIT;
5796	if (immediate != 0)
5797		byte2 |= SSZ_IMMED;
5798
5799	scsi_sanitize(&ccb->csio,
5800		      /* retries */ retry_count,
5801		      /* cbfcnp */ NULL,
5802		      /* tag_action */ MSG_SIMPLE_Q_TAG,
5803		      /* byte2 */ byte2,
5804		      /* control */ 0,
5805		      /* data_ptr */ data_ptr,
5806		      /* dxfer_len */ dxfer_len,
5807		      /* sense_len */ SSD_FULL_SIZE,
5808		      /* timeout */ use_timeout);
5809
5810	/* Disable freezing the device queue */
5811	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5812
5813	if (arglist & CAM_ARG_ERR_RECOVER)
5814		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5815
5816	if (((retval = cam_send_ccb(device, ccb)) < 0)
5817	 || ((immediate == 0)
5818	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
5819		const char errstr[] = "error sending sanitize command";
5820
5821		if (retval < 0)
5822			warn(errstr);
5823		else
5824			warnx(errstr);
5825
5826		if (arglist & CAM_ARG_VERBOSE) {
5827			cam_error_print(device, ccb, CAM_ESF_ALL,
5828					CAM_EPF_ALL, stderr);
5829		}
5830		error = 1;
5831		goto scsisanitize_bailout;
5832	}
5833
5834	/*
5835	 * If we ran in non-immediate mode, we already checked for errors
5836	 * above and printed out any necessary information.  If we're in
5837	 * immediate mode, we need to loop through and get status
5838	 * information periodically.
5839	 */
5840	if (immediate == 0) {
5841		if (quiet == 0) {
5842			fprintf(stdout, "Sanitize Complete\n");
5843		}
5844		goto scsisanitize_bailout;
5845	}
5846
5847doreport:
5848	do {
5849		cam_status status;
5850
5851		bzero(&(&ccb->ccb_h)[1],
5852		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5853
5854		/*
5855		 * There's really no need to do error recovery or
5856		 * retries here, since we're just going to sit in a
5857		 * loop and wait for the device to finish sanitizing.
5858		 */
5859		scsi_test_unit_ready(&ccb->csio,
5860				     /* retries */ 0,
5861				     /* cbfcnp */ NULL,
5862				     /* tag_action */ MSG_SIMPLE_Q_TAG,
5863				     /* sense_len */ SSD_FULL_SIZE,
5864				     /* timeout */ 5000);
5865
5866		/* Disable freezing the device queue */
5867		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5868
5869		retval = cam_send_ccb(device, ccb);
5870
5871		/*
5872		 * If we get an error from the ioctl, bail out.  SCSI
5873		 * errors are expected.
5874		 */
5875		if (retval < 0) {
5876			warn("error sending CAMIOCOMMAND ioctl");
5877			if (arglist & CAM_ARG_VERBOSE) {
5878				cam_error_print(device, ccb, CAM_ESF_ALL,
5879						CAM_EPF_ALL, stderr);
5880			}
5881			error = 1;
5882			goto scsisanitize_bailout;
5883		}
5884
5885		status = ccb->ccb_h.status & CAM_STATUS_MASK;
5886
5887		if ((status != CAM_REQ_CMP)
5888		 && (status == CAM_SCSI_STATUS_ERROR)
5889		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
5890			struct scsi_sense_data *sense;
5891			int error_code, sense_key, asc, ascq;
5892
5893			sense = &ccb->csio.sense_data;
5894			scsi_extract_sense_len(sense, ccb->csio.sense_len -
5895			    ccb->csio.sense_resid, &error_code, &sense_key,
5896			    &asc, &ascq, /*show_errors*/ 1);
5897
5898			/*
5899			 * According to the SCSI-3 spec, a drive that is in the
5900			 * middle of a sanitize should return NOT READY with an
5901			 * ASC of "logical unit not ready, sanitize in
5902			 * progress". The sense key specific bytes will then
5903			 * be a progress indicator.
5904			 */
5905			if ((sense_key == SSD_KEY_NOT_READY)
5906			 && (asc == 0x04) && (ascq == 0x1b)) {
5907				uint8_t sks[3];
5908
5909				if ((scsi_get_sks(sense, ccb->csio.sense_len -
5910				     ccb->csio.sense_resid, sks) == 0)
5911				 && (quiet == 0)) {
5912					int val;
5913					u_int64_t percentage;
5914
5915					val = scsi_2btoul(&sks[1]);
5916					percentage = 10000 * val;
5917
5918					fprintf(stdout,
5919						"\rSanitizing:  %ju.%02u %% "
5920						"(%d/%d) done",
5921						(uintmax_t)(percentage /
5922						(0x10000 * 100)),
5923						(unsigned)((percentage /
5924						0x10000) % 100),
5925						val, 0x10000);
5926					fflush(stdout);
5927				} else if ((quiet == 0)
5928					&& (++num_warnings <= 1)) {
5929					warnx("Unexpected SCSI Sense Key "
5930					      "Specific value returned "
5931					      "during sanitize:");
5932					scsi_sense_print(device, &ccb->csio,
5933							 stderr);
5934					warnx("Unable to print status "
5935					      "information, but sanitze will "
5936					      "proceed.");
5937					warnx("will exit when sanitize is "
5938					      "complete");
5939				}
5940				sleep(1);
5941			} else {
5942				warnx("Unexpected SCSI error during sanitize");
5943				cam_error_print(device, ccb, CAM_ESF_ALL,
5944						CAM_EPF_ALL, stderr);
5945				error = 1;
5946				goto scsisanitize_bailout;
5947			}
5948
5949		} else if (status != CAM_REQ_CMP) {
5950			warnx("Unexpected CAM status %#x", status);
5951			if (arglist & CAM_ARG_VERBOSE)
5952				cam_error_print(device, ccb, CAM_ESF_ALL,
5953						CAM_EPF_ALL, stderr);
5954			error = 1;
5955			goto scsisanitize_bailout;
5956		}
5957	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
5958
5959	if (quiet == 0)
5960		fprintf(stdout, "\nSanitize Complete\n");
5961
5962scsisanitize_bailout:
5963	if (fd >= 0)
5964		close(fd);
5965	if (data_ptr != NULL)
5966		free(data_ptr);
5967	cam_freeccb(ccb);
5968
5969	return(error);
5970}
5971
5972static int
5973scsireportluns(struct cam_device *device, int argc, char **argv,
5974	       char *combinedopt, int retry_count, int timeout)
5975{
5976	union ccb *ccb;
5977	int c, countonly, lunsonly;
5978	struct scsi_report_luns_data *lundata;
5979	int alloc_len;
5980	uint8_t report_type;
5981	uint32_t list_len, i, j;
5982	int retval;
5983
5984	retval = 0;
5985	lundata = NULL;
5986	report_type = RPL_REPORT_DEFAULT;
5987	ccb = cam_getccb(device);
5988
5989	if (ccb == NULL) {
5990		warnx("%s: error allocating ccb", __func__);
5991		return (1);
5992	}
5993
5994	bzero(&(&ccb->ccb_h)[1],
5995	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
5996
5997	countonly = 0;
5998	lunsonly = 0;
5999
6000	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6001		switch (c) {
6002		case 'c':
6003			countonly++;
6004			break;
6005		case 'l':
6006			lunsonly++;
6007			break;
6008		case 'r':
6009			if (strcasecmp(optarg, "default") == 0)
6010				report_type = RPL_REPORT_DEFAULT;
6011			else if (strcasecmp(optarg, "wellknown") == 0)
6012				report_type = RPL_REPORT_WELLKNOWN;
6013			else if (strcasecmp(optarg, "all") == 0)
6014				report_type = RPL_REPORT_ALL;
6015			else {
6016				warnx("%s: invalid report type \"%s\"",
6017				      __func__, optarg);
6018				retval = 1;
6019				goto bailout;
6020			}
6021			break;
6022		default:
6023			break;
6024		}
6025	}
6026
6027	if ((countonly != 0)
6028	 && (lunsonly != 0)) {
6029		warnx("%s: you can only specify one of -c or -l", __func__);
6030		retval = 1;
6031		goto bailout;
6032	}
6033	/*
6034	 * According to SPC-4, the allocation length must be at least 16
6035	 * bytes -- enough for the header and one LUN.
6036	 */
6037	alloc_len = sizeof(*lundata) + 8;
6038
6039retry:
6040
6041	lundata = malloc(alloc_len);
6042
6043	if (lundata == NULL) {
6044		warn("%s: error mallocing %d bytes", __func__, alloc_len);
6045		retval = 1;
6046		goto bailout;
6047	}
6048
6049	scsi_report_luns(&ccb->csio,
6050			 /*retries*/ retry_count,
6051			 /*cbfcnp*/ NULL,
6052			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
6053			 /*select_report*/ report_type,
6054			 /*rpl_buf*/ lundata,
6055			 /*alloc_len*/ alloc_len,
6056			 /*sense_len*/ SSD_FULL_SIZE,
6057			 /*timeout*/ timeout ? timeout : 5000);
6058
6059	/* Disable freezing the device queue */
6060	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6061
6062	if (arglist & CAM_ARG_ERR_RECOVER)
6063		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6064
6065	if (cam_send_ccb(device, ccb) < 0) {
6066		warn("error sending REPORT LUNS command");
6067
6068		if (arglist & CAM_ARG_VERBOSE)
6069			cam_error_print(device, ccb, CAM_ESF_ALL,
6070					CAM_EPF_ALL, stderr);
6071
6072		retval = 1;
6073		goto bailout;
6074	}
6075
6076	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6077		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6078		retval = 1;
6079		goto bailout;
6080	}
6081
6082
6083	list_len = scsi_4btoul(lundata->length);
6084
6085	/*
6086	 * If we need to list the LUNs, and our allocation
6087	 * length was too short, reallocate and retry.
6088	 */
6089	if ((countonly == 0)
6090	 && (list_len > (alloc_len - sizeof(*lundata)))) {
6091		alloc_len = list_len + sizeof(*lundata);
6092		free(lundata);
6093		goto retry;
6094	}
6095
6096	if (lunsonly == 0)
6097		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
6098			((list_len / 8) > 1) ? "s" : "");
6099
6100	if (countonly != 0)
6101		goto bailout;
6102
6103	for (i = 0; i < (list_len / 8); i++) {
6104		int no_more;
6105
6106		no_more = 0;
6107		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
6108			if (j != 0)
6109				fprintf(stdout, ",");
6110			switch (lundata->luns[i].lundata[j] &
6111				RPL_LUNDATA_ATYP_MASK) {
6112			case RPL_LUNDATA_ATYP_PERIPH:
6113				if ((lundata->luns[i].lundata[j] &
6114				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
6115					fprintf(stdout, "%d:",
6116						lundata->luns[i].lundata[j] &
6117						RPL_LUNDATA_PERIPH_BUS_MASK);
6118				else if ((j == 0)
6119				      && ((lundata->luns[i].lundata[j+2] &
6120					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
6121					no_more = 1;
6122
6123				fprintf(stdout, "%d",
6124					lundata->luns[i].lundata[j+1]);
6125				break;
6126			case RPL_LUNDATA_ATYP_FLAT: {
6127				uint8_t tmplun[2];
6128				tmplun[0] = lundata->luns[i].lundata[j] &
6129					RPL_LUNDATA_FLAT_LUN_MASK;
6130				tmplun[1] = lundata->luns[i].lundata[j+1];
6131
6132				fprintf(stdout, "%d", scsi_2btoul(tmplun));
6133				no_more = 1;
6134				break;
6135			}
6136			case RPL_LUNDATA_ATYP_LUN:
6137				fprintf(stdout, "%d:%d:%d",
6138					(lundata->luns[i].lundata[j+1] &
6139					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
6140					lundata->luns[i].lundata[j] &
6141					RPL_LUNDATA_LUN_TARG_MASK,
6142					lundata->luns[i].lundata[j+1] &
6143					RPL_LUNDATA_LUN_LUN_MASK);
6144				break;
6145			case RPL_LUNDATA_ATYP_EXTLUN: {
6146				int field_len_code, eam_code;
6147
6148				eam_code = lundata->luns[i].lundata[j] &
6149					RPL_LUNDATA_EXT_EAM_MASK;
6150				field_len_code = (lundata->luns[i].lundata[j] &
6151					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
6152
6153				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
6154				 && (field_len_code == 0x00)) {
6155					fprintf(stdout, "%d",
6156						lundata->luns[i].lundata[j+1]);
6157				} else if ((eam_code ==
6158					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
6159					&& (field_len_code == 0x03)) {
6160					uint8_t tmp_lun[8];
6161
6162					/*
6163					 * This format takes up all 8 bytes.
6164					 * If we aren't starting at offset 0,
6165					 * that's a bug.
6166					 */
6167					if (j != 0) {
6168						fprintf(stdout, "Invalid "
6169							"offset %d for "
6170							"Extended LUN not "
6171							"specified format", j);
6172						no_more = 1;
6173						break;
6174					}
6175					bzero(tmp_lun, sizeof(tmp_lun));
6176					bcopy(&lundata->luns[i].lundata[j+1],
6177					      &tmp_lun[1], sizeof(tmp_lun) - 1);
6178					fprintf(stdout, "%#jx",
6179					       (intmax_t)scsi_8btou64(tmp_lun));
6180					no_more = 1;
6181				} else {
6182					fprintf(stderr, "Unknown Extended LUN"
6183						"Address method %#x, length "
6184						"code %#x", eam_code,
6185						field_len_code);
6186					no_more = 1;
6187				}
6188				break;
6189			}
6190			default:
6191				fprintf(stderr, "Unknown LUN address method "
6192					"%#x\n", lundata->luns[i].lundata[0] &
6193					RPL_LUNDATA_ATYP_MASK);
6194				break;
6195			}
6196			/*
6197			 * For the flat addressing method, there are no
6198			 * other levels after it.
6199			 */
6200			if (no_more != 0)
6201				break;
6202		}
6203		fprintf(stdout, "\n");
6204	}
6205
6206bailout:
6207
6208	cam_freeccb(ccb);
6209
6210	free(lundata);
6211
6212	return (retval);
6213}
6214
6215static int
6216scsireadcapacity(struct cam_device *device, int argc, char **argv,
6217		 char *combinedopt, int retry_count, int timeout)
6218{
6219	union ccb *ccb;
6220	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
6221	struct scsi_read_capacity_data rcap;
6222	struct scsi_read_capacity_data_long rcaplong;
6223	uint64_t maxsector;
6224	uint32_t block_len;
6225	int retval;
6226	int c;
6227
6228	blocksizeonly = 0;
6229	humanize = 0;
6230	numblocks = 0;
6231	quiet = 0;
6232	sizeonly = 0;
6233	baseten = 0;
6234	retval = 0;
6235
6236	ccb = cam_getccb(device);
6237
6238	if (ccb == NULL) {
6239		warnx("%s: error allocating ccb", __func__);
6240		return (1);
6241	}
6242
6243	bzero(&(&ccb->ccb_h)[1],
6244	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
6245
6246	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6247		switch (c) {
6248		case 'b':
6249			blocksizeonly++;
6250			break;
6251		case 'h':
6252			humanize++;
6253			baseten = 0;
6254			break;
6255		case 'H':
6256			humanize++;
6257			baseten++;
6258			break;
6259		case 'N':
6260			numblocks++;
6261			break;
6262		case 'q':
6263			quiet++;
6264			break;
6265		case 's':
6266			sizeonly++;
6267			break;
6268		default:
6269			break;
6270		}
6271	}
6272
6273	if ((blocksizeonly != 0)
6274	 && (numblocks != 0)) {
6275		warnx("%s: you can only specify one of -b or -N", __func__);
6276		retval = 1;
6277		goto bailout;
6278	}
6279
6280	if ((blocksizeonly != 0)
6281	 && (sizeonly != 0)) {
6282		warnx("%s: you can only specify one of -b or -s", __func__);
6283		retval = 1;
6284		goto bailout;
6285	}
6286
6287	if ((humanize != 0)
6288	 && (quiet != 0)) {
6289		warnx("%s: you can only specify one of -h/-H or -q", __func__);
6290		retval = 1;
6291		goto bailout;
6292	}
6293
6294	if ((humanize != 0)
6295	 && (blocksizeonly != 0)) {
6296		warnx("%s: you can only specify one of -h/-H or -b", __func__);
6297		retval = 1;
6298		goto bailout;
6299	}
6300
6301	scsi_read_capacity(&ccb->csio,
6302			   /*retries*/ retry_count,
6303			   /*cbfcnp*/ NULL,
6304			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
6305			   &rcap,
6306			   SSD_FULL_SIZE,
6307			   /*timeout*/ timeout ? timeout : 5000);
6308
6309	/* Disable freezing the device queue */
6310	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6311
6312	if (arglist & CAM_ARG_ERR_RECOVER)
6313		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6314
6315	if (cam_send_ccb(device, ccb) < 0) {
6316		warn("error sending READ CAPACITY command");
6317
6318		if (arglist & CAM_ARG_VERBOSE)
6319			cam_error_print(device, ccb, CAM_ESF_ALL,
6320					CAM_EPF_ALL, stderr);
6321
6322		retval = 1;
6323		goto bailout;
6324	}
6325
6326	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6327		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6328		retval = 1;
6329		goto bailout;
6330	}
6331
6332	maxsector = scsi_4btoul(rcap.addr);
6333	block_len = scsi_4btoul(rcap.length);
6334
6335	/*
6336	 * A last block of 2^32-1 means that the true capacity is over 2TB,
6337	 * and we need to issue the long READ CAPACITY to get the real
6338	 * capacity.  Otherwise, we're all set.
6339	 */
6340	if (maxsector != 0xffffffff)
6341		goto do_print;
6342
6343	scsi_read_capacity_16(&ccb->csio,
6344			      /*retries*/ retry_count,
6345			      /*cbfcnp*/ NULL,
6346			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
6347			      /*lba*/ 0,
6348			      /*reladdr*/ 0,
6349			      /*pmi*/ 0,
6350			      &rcaplong,
6351			      /*sense_len*/ SSD_FULL_SIZE,
6352			      /*timeout*/ timeout ? timeout : 5000);
6353
6354	/* Disable freezing the device queue */
6355	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
6356
6357	if (arglist & CAM_ARG_ERR_RECOVER)
6358		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
6359
6360	if (cam_send_ccb(device, ccb) < 0) {
6361		warn("error sending READ CAPACITY (16) command");
6362
6363		if (arglist & CAM_ARG_VERBOSE)
6364			cam_error_print(device, ccb, CAM_ESF_ALL,
6365					CAM_EPF_ALL, stderr);
6366
6367		retval = 1;
6368		goto bailout;
6369	}
6370
6371	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
6372		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
6373		retval = 1;
6374		goto bailout;
6375	}
6376
6377	maxsector = scsi_8btou64(rcaplong.addr);
6378	block_len = scsi_4btoul(rcaplong.length);
6379
6380do_print:
6381	if (blocksizeonly == 0) {
6382		/*
6383		 * Humanize implies !quiet, and also implies numblocks.
6384		 */
6385		if (humanize != 0) {
6386			char tmpstr[6];
6387			int64_t tmpbytes;
6388			int ret;
6389
6390			tmpbytes = (maxsector + 1) * block_len;
6391			ret = humanize_number(tmpstr, sizeof(tmpstr),
6392					      tmpbytes, "", HN_AUTOSCALE,
6393					      HN_B | HN_DECIMAL |
6394					      ((baseten != 0) ?
6395					      HN_DIVISOR_1000 : 0));
6396			if (ret == -1) {
6397				warnx("%s: humanize_number failed!", __func__);
6398				retval = 1;
6399				goto bailout;
6400			}
6401			fprintf(stdout, "Device Size: %s%s", tmpstr,
6402				(sizeonly == 0) ?  ", " : "\n");
6403		} else if (numblocks != 0) {
6404			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6405				"Blocks: " : "", (uintmax_t)maxsector + 1,
6406				(sizeonly == 0) ? ", " : "\n");
6407		} else {
6408			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
6409				"Last Block: " : "", (uintmax_t)maxsector,
6410				(sizeonly == 0) ? ", " : "\n");
6411		}
6412	}
6413	if (sizeonly == 0)
6414		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
6415			"Block Length: " : "", block_len, (quiet == 0) ?
6416			" bytes" : "");
6417bailout:
6418	cam_freeccb(ccb);
6419
6420	return (retval);
6421}
6422
6423static int
6424smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
6425       int retry_count, int timeout)
6426{
6427	int c, error = 0;
6428	union ccb *ccb;
6429	uint8_t *smp_request = NULL, *smp_response = NULL;
6430	int request_size = 0, response_size = 0;
6431	int fd_request = 0, fd_response = 0;
6432	char *datastr = NULL;
6433	struct get_hook hook;
6434	int retval;
6435	int flags = 0;
6436
6437	/*
6438	 * Note that at the moment we don't support sending SMP CCBs to
6439	 * devices that aren't probed by CAM.
6440	 */
6441	ccb = cam_getccb(device);
6442	if (ccb == NULL) {
6443		warnx("%s: error allocating CCB", __func__);
6444		return (1);
6445	}
6446
6447	bzero(&(&ccb->ccb_h)[1],
6448	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6449
6450	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6451		switch (c) {
6452		case 'R':
6453			arglist |= CAM_ARG_CMD_IN;
6454			response_size = strtol(optarg, NULL, 0);
6455			if (response_size <= 0) {
6456				warnx("invalid number of response bytes %d",
6457				      response_size);
6458				error = 1;
6459				goto smpcmd_bailout;
6460			}
6461			hook.argc = argc - optind;
6462			hook.argv = argv + optind;
6463			hook.got = 0;
6464			optind++;
6465			datastr = cget(&hook, NULL);
6466			/*
6467			 * If the user supplied "-" instead of a format, he
6468			 * wants the data to be written to stdout.
6469			 */
6470			if ((datastr != NULL)
6471			 && (datastr[0] == '-'))
6472				fd_response = 1;
6473
6474			smp_response = (u_int8_t *)malloc(response_size);
6475			if (smp_response == NULL) {
6476				warn("can't malloc memory for SMP response");
6477				error = 1;
6478				goto smpcmd_bailout;
6479			}
6480			break;
6481		case 'r':
6482			arglist |= CAM_ARG_CMD_OUT;
6483			request_size = strtol(optarg, NULL, 0);
6484			if (request_size <= 0) {
6485				warnx("invalid number of request bytes %d",
6486				      request_size);
6487				error = 1;
6488				goto smpcmd_bailout;
6489			}
6490			hook.argc = argc - optind;
6491			hook.argv = argv + optind;
6492			hook.got = 0;
6493			datastr = cget(&hook, NULL);
6494			smp_request = (u_int8_t *)malloc(request_size);
6495			if (smp_request == NULL) {
6496				warn("can't malloc memory for SMP request");
6497				error = 1;
6498				goto smpcmd_bailout;
6499			}
6500			bzero(smp_request, request_size);
6501			/*
6502			 * If the user supplied "-" instead of a format, he
6503			 * wants the data to be read from stdin.
6504			 */
6505			if ((datastr != NULL)
6506			 && (datastr[0] == '-'))
6507				fd_request = 1;
6508			else
6509				buff_encode_visit(smp_request, request_size,
6510						  datastr,
6511						  iget, &hook);
6512			optind += hook.got;
6513			break;
6514		default:
6515			break;
6516		}
6517	}
6518
6519	/*
6520	 * If fd_data is set, and we're writing to the device, we need to
6521	 * read the data the user wants written from stdin.
6522	 */
6523	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
6524		ssize_t amt_read;
6525		int amt_to_read = request_size;
6526		u_int8_t *buf_ptr = smp_request;
6527
6528		for (amt_read = 0; amt_to_read > 0;
6529		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
6530			if (amt_read == -1) {
6531				warn("error reading data from stdin");
6532				error = 1;
6533				goto smpcmd_bailout;
6534			}
6535			amt_to_read -= amt_read;
6536			buf_ptr += amt_read;
6537		}
6538	}
6539
6540	if (((arglist & CAM_ARG_CMD_IN) == 0)
6541	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
6542		warnx("%s: need both the request (-r) and response (-R) "
6543		      "arguments", __func__);
6544		error = 1;
6545		goto smpcmd_bailout;
6546	}
6547
6548	flags |= CAM_DEV_QFRZDIS;
6549
6550	cam_fill_smpio(&ccb->smpio,
6551		       /*retries*/ retry_count,
6552		       /*cbfcnp*/ NULL,
6553		       /*flags*/ flags,
6554		       /*smp_request*/ smp_request,
6555		       /*smp_request_len*/ request_size,
6556		       /*smp_response*/ smp_response,
6557		       /*smp_response_len*/ response_size,
6558		       /*timeout*/ timeout ? timeout : 5000);
6559
6560	ccb->smpio.flags = SMP_FLAG_NONE;
6561
6562	if (((retval = cam_send_ccb(device, ccb)) < 0)
6563	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6564		const char warnstr[] = "error sending command";
6565
6566		if (retval < 0)
6567			warn(warnstr);
6568		else
6569			warnx(warnstr);
6570
6571		if (arglist & CAM_ARG_VERBOSE) {
6572			cam_error_print(device, ccb, CAM_ESF_ALL,
6573					CAM_EPF_ALL, stderr);
6574		}
6575	}
6576
6577	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
6578	 && (response_size > 0)) {
6579		if (fd_response == 0) {
6580			buff_decode_visit(smp_response, response_size,
6581					  datastr, arg_put, NULL);
6582			fprintf(stdout, "\n");
6583		} else {
6584			ssize_t amt_written;
6585			int amt_to_write = response_size;
6586			u_int8_t *buf_ptr = smp_response;
6587
6588			for (amt_written = 0; (amt_to_write > 0) &&
6589			     (amt_written = write(STDOUT_FILENO, buf_ptr,
6590						  amt_to_write)) > 0;){
6591				amt_to_write -= amt_written;
6592				buf_ptr += amt_written;
6593			}
6594			if (amt_written == -1) {
6595				warn("error writing data to stdout");
6596				error = 1;
6597				goto smpcmd_bailout;
6598			} else if ((amt_written == 0)
6599				&& (amt_to_write > 0)) {
6600				warnx("only wrote %u bytes out of %u",
6601				      response_size - amt_to_write,
6602				      response_size);
6603			}
6604		}
6605	}
6606smpcmd_bailout:
6607	if (ccb != NULL)
6608		cam_freeccb(ccb);
6609
6610	if (smp_request != NULL)
6611		free(smp_request);
6612
6613	if (smp_response != NULL)
6614		free(smp_response);
6615
6616	return (error);
6617}
6618
6619static int
6620smpreportgeneral(struct cam_device *device, int argc, char **argv,
6621		 char *combinedopt, int retry_count, int timeout)
6622{
6623	union ccb *ccb;
6624	struct smp_report_general_request *request = NULL;
6625	struct smp_report_general_response *response = NULL;
6626	struct sbuf *sb = NULL;
6627	int error = 0;
6628	int c, long_response = 0;
6629	int retval;
6630
6631	/*
6632	 * Note that at the moment we don't support sending SMP CCBs to
6633	 * devices that aren't probed by CAM.
6634	 */
6635	ccb = cam_getccb(device);
6636	if (ccb == NULL) {
6637		warnx("%s: error allocating CCB", __func__);
6638		return (1);
6639	}
6640
6641	bzero(&(&ccb->ccb_h)[1],
6642	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6643
6644	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6645		switch (c) {
6646		case 'l':
6647			long_response = 1;
6648			break;
6649		default:
6650			break;
6651		}
6652	}
6653	request = malloc(sizeof(*request));
6654	if (request == NULL) {
6655		warn("%s: unable to allocate %zd bytes", __func__,
6656		     sizeof(*request));
6657		error = 1;
6658		goto bailout;
6659	}
6660
6661	response = malloc(sizeof(*response));
6662	if (response == NULL) {
6663		warn("%s: unable to allocate %zd bytes", __func__,
6664		     sizeof(*response));
6665		error = 1;
6666		goto bailout;
6667	}
6668
6669try_long:
6670	smp_report_general(&ccb->smpio,
6671			   retry_count,
6672			   /*cbfcnp*/ NULL,
6673			   request,
6674			   /*request_len*/ sizeof(*request),
6675			   (uint8_t *)response,
6676			   /*response_len*/ sizeof(*response),
6677			   /*long_response*/ long_response,
6678			   timeout);
6679
6680	if (((retval = cam_send_ccb(device, ccb)) < 0)
6681	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6682		const char warnstr[] = "error sending command";
6683
6684		if (retval < 0)
6685			warn(warnstr);
6686		else
6687			warnx(warnstr);
6688
6689		if (arglist & CAM_ARG_VERBOSE) {
6690			cam_error_print(device, ccb, CAM_ESF_ALL,
6691					CAM_EPF_ALL, stderr);
6692		}
6693		error = 1;
6694		goto bailout;
6695	}
6696
6697	/*
6698	 * If the device supports the long response bit, try again and see
6699	 * if we can get all of the data.
6700	 */
6701	if ((response->long_response & SMP_RG_LONG_RESPONSE)
6702	 && (long_response == 0)) {
6703		ccb->ccb_h.status = CAM_REQ_INPROG;
6704		bzero(&(&ccb->ccb_h)[1],
6705		      sizeof(union ccb) - sizeof(struct ccb_hdr));
6706		long_response = 1;
6707		goto try_long;
6708	}
6709
6710	/*
6711	 * XXX KDM detect and decode SMP errors here.
6712	 */
6713	sb = sbuf_new_auto();
6714	if (sb == NULL) {
6715		warnx("%s: error allocating sbuf", __func__);
6716		goto bailout;
6717	}
6718
6719	smp_report_general_sbuf(response, sizeof(*response), sb);
6720
6721	if (sbuf_finish(sb) != 0) {
6722		warnx("%s: sbuf_finish", __func__);
6723		goto bailout;
6724	}
6725
6726	printf("%s", sbuf_data(sb));
6727
6728bailout:
6729	if (ccb != NULL)
6730		cam_freeccb(ccb);
6731
6732	if (request != NULL)
6733		free(request);
6734
6735	if (response != NULL)
6736		free(response);
6737
6738	if (sb != NULL)
6739		sbuf_delete(sb);
6740
6741	return (error);
6742}
6743
6744static struct camcontrol_opts phy_ops[] = {
6745	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
6746	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
6747	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
6748	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
6749	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
6750	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
6751	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
6752	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
6753	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
6754	{NULL, 0, 0, NULL}
6755};
6756
6757static int
6758smpphycontrol(struct cam_device *device, int argc, char **argv,
6759	      char *combinedopt, int retry_count, int timeout)
6760{
6761	union ccb *ccb;
6762	struct smp_phy_control_request *request = NULL;
6763	struct smp_phy_control_response *response = NULL;
6764	int long_response = 0;
6765	int retval = 0;
6766	int phy = -1;
6767	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
6768	int phy_op_set = 0;
6769	uint64_t attached_dev_name = 0;
6770	int dev_name_set = 0;
6771	uint32_t min_plr = 0, max_plr = 0;
6772	uint32_t pp_timeout_val = 0;
6773	int slumber_partial = 0;
6774	int set_pp_timeout_val = 0;
6775	int c;
6776
6777	/*
6778	 * Note that at the moment we don't support sending SMP CCBs to
6779	 * devices that aren't probed by CAM.
6780	 */
6781	ccb = cam_getccb(device);
6782	if (ccb == NULL) {
6783		warnx("%s: error allocating CCB", __func__);
6784		return (1);
6785	}
6786
6787	bzero(&(&ccb->ccb_h)[1],
6788	      sizeof(union ccb) - sizeof(struct ccb_hdr));
6789
6790	while ((c = getopt(argc, argv, combinedopt)) != -1) {
6791		switch (c) {
6792		case 'a':
6793		case 'A':
6794		case 's':
6795		case 'S': {
6796			int enable = -1;
6797
6798			if (strcasecmp(optarg, "enable") == 0)
6799				enable = 1;
6800			else if (strcasecmp(optarg, "disable") == 0)
6801				enable = 2;
6802			else {
6803				warnx("%s: Invalid argument %s", __func__,
6804				      optarg);
6805				retval = 1;
6806				goto bailout;
6807			}
6808			switch (c) {
6809			case 's':
6810				slumber_partial |= enable <<
6811						   SMP_PC_SAS_SLUMBER_SHIFT;
6812				break;
6813			case 'S':
6814				slumber_partial |= enable <<
6815						   SMP_PC_SAS_PARTIAL_SHIFT;
6816				break;
6817			case 'a':
6818				slumber_partial |= enable <<
6819						   SMP_PC_SATA_SLUMBER_SHIFT;
6820				break;
6821			case 'A':
6822				slumber_partial |= enable <<
6823						   SMP_PC_SATA_PARTIAL_SHIFT;
6824				break;
6825			default:
6826				warnx("%s: programmer error", __func__);
6827				retval = 1;
6828				goto bailout;
6829				break; /*NOTREACHED*/
6830			}
6831			break;
6832		}
6833		case 'd':
6834			attached_dev_name = (uintmax_t)strtoumax(optarg,
6835								 NULL,0);
6836			dev_name_set = 1;
6837			break;
6838		case 'l':
6839			long_response = 1;
6840			break;
6841		case 'm':
6842			/*
6843			 * We don't do extensive checking here, so this
6844			 * will continue to work when new speeds come out.
6845			 */
6846			min_plr = strtoul(optarg, NULL, 0);
6847			if ((min_plr == 0)
6848			 || (min_plr > 0xf)) {
6849				warnx("%s: invalid link rate %x",
6850				      __func__, min_plr);
6851				retval = 1;
6852				goto bailout;
6853			}
6854			break;
6855		case 'M':
6856			/*
6857			 * We don't do extensive checking here, so this
6858			 * will continue to work when new speeds come out.
6859			 */
6860			max_plr = strtoul(optarg, NULL, 0);
6861			if ((max_plr == 0)
6862			 || (max_plr > 0xf)) {
6863				warnx("%s: invalid link rate %x",
6864				      __func__, max_plr);
6865				retval = 1;
6866				goto bailout;
6867			}
6868			break;
6869		case 'o': {
6870			camcontrol_optret optreturn;
6871			cam_argmask argnums;
6872			const char *subopt;
6873
6874			if (phy_op_set != 0) {
6875				warnx("%s: only one phy operation argument "
6876				      "(-o) allowed", __func__);
6877				retval = 1;
6878				goto bailout;
6879			}
6880
6881			phy_op_set = 1;
6882
6883			/*
6884			 * Allow the user to specify the phy operation
6885			 * numerically, as well as with a name.  This will
6886			 * future-proof it a bit, so options that are added
6887			 * in future specs can be used.
6888			 */
6889			if (isdigit(optarg[0])) {
6890				phy_operation = strtoul(optarg, NULL, 0);
6891				if ((phy_operation == 0)
6892				 || (phy_operation > 0xff)) {
6893					warnx("%s: invalid phy operation %#x",
6894					      __func__, phy_operation);
6895					retval = 1;
6896					goto bailout;
6897				}
6898				break;
6899			}
6900			optreturn = getoption(phy_ops, optarg, &phy_operation,
6901					      &argnums, &subopt);
6902
6903			if (optreturn == CC_OR_AMBIGUOUS) {
6904				warnx("%s: ambiguous option %s", __func__,
6905				      optarg);
6906				usage(0);
6907				retval = 1;
6908				goto bailout;
6909			} else if (optreturn == CC_OR_NOT_FOUND) {
6910				warnx("%s: option %s not found", __func__,
6911				      optarg);
6912				usage(0);
6913				retval = 1;
6914				goto bailout;
6915			}
6916			break;
6917		}
6918		case 'p':
6919			phy = atoi(optarg);
6920			break;
6921		case 'T':
6922			pp_timeout_val = strtoul(optarg, NULL, 0);
6923			if (pp_timeout_val > 15) {
6924				warnx("%s: invalid partial pathway timeout "
6925				      "value %u, need a value less than 16",
6926				      __func__, pp_timeout_val);
6927				retval = 1;
6928				goto bailout;
6929			}
6930			set_pp_timeout_val = 1;
6931			break;
6932		default:
6933			break;
6934		}
6935	}
6936
6937	if (phy == -1) {
6938		warnx("%s: a PHY (-p phy) argument is required",__func__);
6939		retval = 1;
6940		goto bailout;
6941	}
6942
6943	if (((dev_name_set != 0)
6944	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
6945	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
6946	  && (dev_name_set == 0))) {
6947		warnx("%s: -d name and -o setdevname arguments both "
6948		      "required to set device name", __func__);
6949		retval = 1;
6950		goto bailout;
6951	}
6952
6953	request = malloc(sizeof(*request));
6954	if (request == NULL) {
6955		warn("%s: unable to allocate %zd bytes", __func__,
6956		     sizeof(*request));
6957		retval = 1;
6958		goto bailout;
6959	}
6960
6961	response = malloc(sizeof(*response));
6962	if (response == NULL) {
6963		warn("%s: unable to allocate %zd bytes", __func__,
6964		     sizeof(*request));
6965		retval = 1;
6966		goto bailout;
6967	}
6968
6969	smp_phy_control(&ccb->smpio,
6970			retry_count,
6971			/*cbfcnp*/ NULL,
6972			request,
6973			sizeof(*request),
6974			(uint8_t *)response,
6975			sizeof(*response),
6976			long_response,
6977			/*expected_exp_change_count*/ 0,
6978			phy,
6979			phy_operation,
6980			(set_pp_timeout_val != 0) ? 1 : 0,
6981			attached_dev_name,
6982			min_plr,
6983			max_plr,
6984			slumber_partial,
6985			pp_timeout_val,
6986			timeout);
6987
6988	if (((retval = cam_send_ccb(device, ccb)) < 0)
6989	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
6990		const char warnstr[] = "error sending command";
6991
6992		if (retval < 0)
6993			warn(warnstr);
6994		else
6995			warnx(warnstr);
6996
6997		if (arglist & CAM_ARG_VERBOSE) {
6998			/*
6999			 * Use CAM_EPF_NORMAL so we only get one line of
7000			 * SMP command decoding.
7001			 */
7002			cam_error_print(device, ccb, CAM_ESF_ALL,
7003					CAM_EPF_NORMAL, stderr);
7004		}
7005		retval = 1;
7006		goto bailout;
7007	}
7008
7009	/* XXX KDM print out something here for success? */
7010bailout:
7011	if (ccb != NULL)
7012		cam_freeccb(ccb);
7013
7014	if (request != NULL)
7015		free(request);
7016
7017	if (response != NULL)
7018		free(response);
7019
7020	return (retval);
7021}
7022
7023static int
7024smpmaninfo(struct cam_device *device, int argc, char **argv,
7025	   char *combinedopt, int retry_count, int timeout)
7026{
7027	union ccb *ccb;
7028	struct smp_report_manuf_info_request request;
7029	struct smp_report_manuf_info_response response;
7030	struct sbuf *sb = NULL;
7031	int long_response = 0;
7032	int retval = 0;
7033	int c;
7034
7035	/*
7036	 * Note that at the moment we don't support sending SMP CCBs to
7037	 * devices that aren't probed by CAM.
7038	 */
7039	ccb = cam_getccb(device);
7040	if (ccb == NULL) {
7041		warnx("%s: error allocating CCB", __func__);
7042		return (1);
7043	}
7044
7045	bzero(&(&ccb->ccb_h)[1],
7046	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7047
7048	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7049		switch (c) {
7050		case 'l':
7051			long_response = 1;
7052			break;
7053		default:
7054			break;
7055		}
7056	}
7057	bzero(&request, sizeof(request));
7058	bzero(&response, sizeof(response));
7059
7060	smp_report_manuf_info(&ccb->smpio,
7061			      retry_count,
7062			      /*cbfcnp*/ NULL,
7063			      &request,
7064			      sizeof(request),
7065			      (uint8_t *)&response,
7066			      sizeof(response),
7067			      long_response,
7068			      timeout);
7069
7070	if (((retval = cam_send_ccb(device, ccb)) < 0)
7071	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7072		const char warnstr[] = "error sending command";
7073
7074		if (retval < 0)
7075			warn(warnstr);
7076		else
7077			warnx(warnstr);
7078
7079		if (arglist & CAM_ARG_VERBOSE) {
7080			cam_error_print(device, ccb, CAM_ESF_ALL,
7081					CAM_EPF_ALL, stderr);
7082		}
7083		retval = 1;
7084		goto bailout;
7085	}
7086
7087	sb = sbuf_new_auto();
7088	if (sb == NULL) {
7089		warnx("%s: error allocating sbuf", __func__);
7090		goto bailout;
7091	}
7092
7093	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
7094
7095	if (sbuf_finish(sb) != 0) {
7096		warnx("%s: sbuf_finish", __func__);
7097		goto bailout;
7098	}
7099
7100	printf("%s", sbuf_data(sb));
7101
7102bailout:
7103
7104	if (ccb != NULL)
7105		cam_freeccb(ccb);
7106
7107	if (sb != NULL)
7108		sbuf_delete(sb);
7109
7110	return (retval);
7111}
7112
7113static int
7114getdevid(struct cam_devitem *item)
7115{
7116	int retval = 0;
7117	union ccb *ccb = NULL;
7118
7119	struct cam_device *dev;
7120
7121	dev = cam_open_btl(item->dev_match.path_id,
7122			   item->dev_match.target_id,
7123			   item->dev_match.target_lun, O_RDWR, NULL);
7124
7125	if (dev == NULL) {
7126		warnx("%s", cam_errbuf);
7127		retval = 1;
7128		goto bailout;
7129	}
7130
7131	item->device_id_len = 0;
7132
7133	ccb = cam_getccb(dev);
7134	if (ccb == NULL) {
7135		warnx("%s: error allocating CCB", __func__);
7136		retval = 1;
7137		goto bailout;
7138	}
7139
7140	bzero(&(&ccb->ccb_h)[1],
7141	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7142
7143	/*
7144	 * On the first try, we just probe for the size of the data, and
7145	 * then allocate that much memory and try again.
7146	 */
7147retry:
7148	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
7149	ccb->ccb_h.flags = CAM_DIR_IN;
7150	ccb->cdai.flags = 0;
7151	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
7152	ccb->cdai.bufsiz = item->device_id_len;
7153	if (item->device_id_len != 0)
7154		ccb->cdai.buf = (uint8_t *)item->device_id;
7155
7156	if (cam_send_ccb(dev, ccb) < 0) {
7157		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
7158		retval = 1;
7159		goto bailout;
7160	}
7161
7162	if (ccb->ccb_h.status != CAM_REQ_CMP) {
7163		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
7164		retval = 1;
7165		goto bailout;
7166	}
7167
7168	if (item->device_id_len == 0) {
7169		/*
7170		 * This is our first time through.  Allocate the buffer,
7171		 * and then go back to get the data.
7172		 */
7173		if (ccb->cdai.provsiz == 0) {
7174			warnx("%s: invalid .provsiz field returned with "
7175			     "XPT_GDEV_ADVINFO CCB", __func__);
7176			retval = 1;
7177			goto bailout;
7178		}
7179		item->device_id_len = ccb->cdai.provsiz;
7180		item->device_id = malloc(item->device_id_len);
7181		if (item->device_id == NULL) {
7182			warn("%s: unable to allocate %d bytes", __func__,
7183			     item->device_id_len);
7184			retval = 1;
7185			goto bailout;
7186		}
7187		ccb->ccb_h.status = CAM_REQ_INPROG;
7188		goto retry;
7189	}
7190
7191bailout:
7192	if (dev != NULL)
7193		cam_close_device(dev);
7194
7195	if (ccb != NULL)
7196		cam_freeccb(ccb);
7197
7198	return (retval);
7199}
7200
7201/*
7202 * XXX KDM merge this code with getdevtree()?
7203 */
7204static int
7205buildbusdevlist(struct cam_devlist *devlist)
7206{
7207	union ccb ccb;
7208	int bufsize, fd = -1;
7209	struct dev_match_pattern *patterns;
7210	struct cam_devitem *item = NULL;
7211	int skip_device = 0;
7212	int retval = 0;
7213
7214	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
7215		warn("couldn't open %s", XPT_DEVICE);
7216		return(1);
7217	}
7218
7219	bzero(&ccb, sizeof(union ccb));
7220
7221	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
7222	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
7223	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
7224
7225	ccb.ccb_h.func_code = XPT_DEV_MATCH;
7226	bufsize = sizeof(struct dev_match_result) * 100;
7227	ccb.cdm.match_buf_len = bufsize;
7228	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
7229	if (ccb.cdm.matches == NULL) {
7230		warnx("can't malloc memory for matches");
7231		close(fd);
7232		return(1);
7233	}
7234	ccb.cdm.num_matches = 0;
7235	ccb.cdm.num_patterns = 2;
7236	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
7237		ccb.cdm.num_patterns;
7238
7239	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
7240	if (patterns == NULL) {
7241		warnx("can't malloc memory for patterns");
7242		retval = 1;
7243		goto bailout;
7244	}
7245
7246	ccb.cdm.patterns = patterns;
7247	bzero(patterns, ccb.cdm.pattern_buf_len);
7248
7249	patterns[0].type = DEV_MATCH_DEVICE;
7250	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
7251	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
7252	patterns[1].type = DEV_MATCH_PERIPH;
7253	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
7254	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
7255
7256	/*
7257	 * We do the ioctl multiple times if necessary, in case there are
7258	 * more than 100 nodes in the EDT.
7259	 */
7260	do {
7261		unsigned int i;
7262
7263		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
7264			warn("error sending CAMIOCOMMAND ioctl");
7265			retval = 1;
7266			goto bailout;
7267		}
7268
7269		if ((ccb.ccb_h.status != CAM_REQ_CMP)
7270		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
7271		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
7272			warnx("got CAM error %#x, CDM error %d\n",
7273			      ccb.ccb_h.status, ccb.cdm.status);
7274			retval = 1;
7275			goto bailout;
7276		}
7277
7278		for (i = 0; i < ccb.cdm.num_matches; i++) {
7279			switch (ccb.cdm.matches[i].type) {
7280			case DEV_MATCH_DEVICE: {
7281				struct device_match_result *dev_result;
7282
7283				dev_result =
7284				     &ccb.cdm.matches[i].result.device_result;
7285
7286				if (dev_result->flags &
7287				    DEV_RESULT_UNCONFIGURED) {
7288					skip_device = 1;
7289					break;
7290				} else
7291					skip_device = 0;
7292
7293				item = malloc(sizeof(*item));
7294				if (item == NULL) {
7295					warn("%s: unable to allocate %zd bytes",
7296					     __func__, sizeof(*item));
7297					retval = 1;
7298					goto bailout;
7299				}
7300				bzero(item, sizeof(*item));
7301				bcopy(dev_result, &item->dev_match,
7302				      sizeof(*dev_result));
7303				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
7304						   links);
7305
7306				if (getdevid(item) != 0) {
7307					retval = 1;
7308					goto bailout;
7309				}
7310				break;
7311			}
7312			case DEV_MATCH_PERIPH: {
7313				struct periph_match_result *periph_result;
7314
7315				periph_result =
7316				      &ccb.cdm.matches[i].result.periph_result;
7317
7318				if (skip_device != 0)
7319					break;
7320				item->num_periphs++;
7321				item->periph_matches = realloc(
7322					item->periph_matches,
7323					item->num_periphs *
7324					sizeof(struct periph_match_result));
7325				if (item->periph_matches == NULL) {
7326					warn("%s: error allocating periph "
7327					     "list", __func__);
7328					retval = 1;
7329					goto bailout;
7330				}
7331				bcopy(periph_result, &item->periph_matches[
7332				      item->num_periphs - 1],
7333				      sizeof(*periph_result));
7334				break;
7335			}
7336			default:
7337				fprintf(stderr, "%s: unexpected match "
7338					"type %d\n", __func__,
7339					ccb.cdm.matches[i].type);
7340				retval = 1;
7341				goto bailout;
7342				break; /*NOTREACHED*/
7343			}
7344		}
7345	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
7346		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
7347bailout:
7348
7349	if (fd != -1)
7350		close(fd);
7351
7352	free(patterns);
7353
7354	free(ccb.cdm.matches);
7355
7356	if (retval != 0)
7357		freebusdevlist(devlist);
7358
7359	return (retval);
7360}
7361
7362static void
7363freebusdevlist(struct cam_devlist *devlist)
7364{
7365	struct cam_devitem *item, *item2;
7366
7367	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
7368		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
7369			      links);
7370		free(item->device_id);
7371		free(item->periph_matches);
7372		free(item);
7373	}
7374}
7375
7376static struct cam_devitem *
7377findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
7378{
7379	struct cam_devitem *item;
7380
7381	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
7382		struct scsi_vpd_id_descriptor *idd;
7383
7384		/*
7385		 * XXX KDM look for LUN IDs as well?
7386		 */
7387		idd = scsi_get_devid(item->device_id,
7388					   item->device_id_len,
7389					   scsi_devid_is_sas_target);
7390		if (idd == NULL)
7391			continue;
7392
7393		if (scsi_8btou64(idd->identifier) == sasaddr)
7394			return (item);
7395	}
7396
7397	return (NULL);
7398}
7399
7400static int
7401smpphylist(struct cam_device *device, int argc, char **argv,
7402	   char *combinedopt, int retry_count, int timeout)
7403{
7404	struct smp_report_general_request *rgrequest = NULL;
7405	struct smp_report_general_response *rgresponse = NULL;
7406	struct smp_discover_request *disrequest = NULL;
7407	struct smp_discover_response *disresponse = NULL;
7408	struct cam_devlist devlist;
7409	union ccb *ccb;
7410	int long_response = 0;
7411	int num_phys = 0;
7412	int quiet = 0;
7413	int retval;
7414	int i, c;
7415
7416	/*
7417	 * Note that at the moment we don't support sending SMP CCBs to
7418	 * devices that aren't probed by CAM.
7419	 */
7420	ccb = cam_getccb(device);
7421	if (ccb == NULL) {
7422		warnx("%s: error allocating CCB", __func__);
7423		return (1);
7424	}
7425
7426	bzero(&(&ccb->ccb_h)[1],
7427	      sizeof(union ccb) - sizeof(struct ccb_hdr));
7428	STAILQ_INIT(&devlist.dev_queue);
7429
7430	rgrequest = malloc(sizeof(*rgrequest));
7431	if (rgrequest == NULL) {
7432		warn("%s: unable to allocate %zd bytes", __func__,
7433		     sizeof(*rgrequest));
7434		retval = 1;
7435		goto bailout;
7436	}
7437
7438	rgresponse = malloc(sizeof(*rgresponse));
7439	if (rgresponse == NULL) {
7440		warn("%s: unable to allocate %zd bytes", __func__,
7441		     sizeof(*rgresponse));
7442		retval = 1;
7443		goto bailout;
7444	}
7445
7446	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7447		switch (c) {
7448		case 'l':
7449			long_response = 1;
7450			break;
7451		case 'q':
7452			quiet = 1;
7453			break;
7454		default:
7455			break;
7456		}
7457	}
7458
7459	smp_report_general(&ccb->smpio,
7460			   retry_count,
7461			   /*cbfcnp*/ NULL,
7462			   rgrequest,
7463			   /*request_len*/ sizeof(*rgrequest),
7464			   (uint8_t *)rgresponse,
7465			   /*response_len*/ sizeof(*rgresponse),
7466			   /*long_response*/ long_response,
7467			   timeout);
7468
7469	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7470
7471	if (((retval = cam_send_ccb(device, ccb)) < 0)
7472	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
7473		const char warnstr[] = "error sending command";
7474
7475		if (retval < 0)
7476			warn(warnstr);
7477		else
7478			warnx(warnstr);
7479
7480		if (arglist & CAM_ARG_VERBOSE) {
7481			cam_error_print(device, ccb, CAM_ESF_ALL,
7482					CAM_EPF_ALL, stderr);
7483		}
7484		retval = 1;
7485		goto bailout;
7486	}
7487
7488	num_phys = rgresponse->num_phys;
7489
7490	if (num_phys == 0) {
7491		if (quiet == 0)
7492			fprintf(stdout, "%s: No Phys reported\n", __func__);
7493		retval = 1;
7494		goto bailout;
7495	}
7496
7497	devlist.path_id = device->path_id;
7498
7499	retval = buildbusdevlist(&devlist);
7500	if (retval != 0)
7501		goto bailout;
7502
7503	if (quiet == 0) {
7504		fprintf(stdout, "%d PHYs:\n", num_phys);
7505		fprintf(stdout, "PHY  Attached SAS Address\n");
7506	}
7507
7508	disrequest = malloc(sizeof(*disrequest));
7509	if (disrequest == NULL) {
7510		warn("%s: unable to allocate %zd bytes", __func__,
7511		     sizeof(*disrequest));
7512		retval = 1;
7513		goto bailout;
7514	}
7515
7516	disresponse = malloc(sizeof(*disresponse));
7517	if (disresponse == NULL) {
7518		warn("%s: unable to allocate %zd bytes", __func__,
7519		     sizeof(*disresponse));
7520		retval = 1;
7521		goto bailout;
7522	}
7523
7524	for (i = 0; i < num_phys; i++) {
7525		struct cam_devitem *item;
7526		struct device_match_result *dev_match;
7527		char vendor[16], product[48], revision[16];
7528		char tmpstr[256];
7529		int j;
7530
7531		bzero(&(&ccb->ccb_h)[1],
7532		      sizeof(union ccb) - sizeof(struct ccb_hdr));
7533
7534		ccb->ccb_h.status = CAM_REQ_INPROG;
7535		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7536
7537		smp_discover(&ccb->smpio,
7538			     retry_count,
7539			     /*cbfcnp*/ NULL,
7540			     disrequest,
7541			     sizeof(*disrequest),
7542			     (uint8_t *)disresponse,
7543			     sizeof(*disresponse),
7544			     long_response,
7545			     /*ignore_zone_group*/ 0,
7546			     /*phy*/ i,
7547			     timeout);
7548
7549		if (((retval = cam_send_ccb(device, ccb)) < 0)
7550		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
7551		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
7552			const char warnstr[] = "error sending command";
7553
7554			if (retval < 0)
7555				warn(warnstr);
7556			else
7557				warnx(warnstr);
7558
7559			if (arglist & CAM_ARG_VERBOSE) {
7560				cam_error_print(device, ccb, CAM_ESF_ALL,
7561						CAM_EPF_ALL, stderr);
7562			}
7563			retval = 1;
7564			goto bailout;
7565		}
7566
7567		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
7568			if (quiet == 0)
7569				fprintf(stdout, "%3d  <vacant>\n", i);
7570			continue;
7571		}
7572
7573		if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) {
7574			item = NULL;
7575		} else {
7576			item = findsasdevice(&devlist,
7577			    scsi_8btou64(disresponse->attached_sas_address));
7578		}
7579
7580		if ((quiet == 0)
7581		 || (item != NULL)) {
7582			fprintf(stdout, "%3d  0x%016jx", i,
7583				(uintmax_t)scsi_8btou64(
7584				disresponse->attached_sas_address));
7585			if (item == NULL) {
7586				fprintf(stdout, "\n");
7587				continue;
7588			}
7589		} else if (quiet != 0)
7590			continue;
7591
7592		dev_match = &item->dev_match;
7593
7594		if (dev_match->protocol == PROTO_SCSI) {
7595			cam_strvis(vendor, dev_match->inq_data.vendor,
7596				   sizeof(dev_match->inq_data.vendor),
7597				   sizeof(vendor));
7598			cam_strvis(product, dev_match->inq_data.product,
7599				   sizeof(dev_match->inq_data.product),
7600				   sizeof(product));
7601			cam_strvis(revision, dev_match->inq_data.revision,
7602				   sizeof(dev_match->inq_data.revision),
7603				   sizeof(revision));
7604			sprintf(tmpstr, "<%s %s %s>", vendor, product,
7605				revision);
7606		} else if ((dev_match->protocol == PROTO_ATA)
7607			|| (dev_match->protocol == PROTO_SATAPM)) {
7608			cam_strvis(product, dev_match->ident_data.model,
7609				   sizeof(dev_match->ident_data.model),
7610				   sizeof(product));
7611			cam_strvis(revision, dev_match->ident_data.revision,
7612				   sizeof(dev_match->ident_data.revision),
7613				   sizeof(revision));
7614			sprintf(tmpstr, "<%s %s>", product, revision);
7615		} else {
7616			sprintf(tmpstr, "<>");
7617		}
7618		fprintf(stdout, "   %-33s ", tmpstr);
7619
7620		/*
7621		 * If we have 0 periphs, that's a bug...
7622		 */
7623		if (item->num_periphs == 0) {
7624			fprintf(stdout, "\n");
7625			continue;
7626		}
7627
7628		fprintf(stdout, "(");
7629		for (j = 0; j < item->num_periphs; j++) {
7630			if (j > 0)
7631				fprintf(stdout, ",");
7632
7633			fprintf(stdout, "%s%d",
7634				item->periph_matches[j].periph_name,
7635				item->periph_matches[j].unit_number);
7636
7637		}
7638		fprintf(stdout, ")\n");
7639	}
7640bailout:
7641	if (ccb != NULL)
7642		cam_freeccb(ccb);
7643
7644	free(rgrequest);
7645
7646	free(rgresponse);
7647
7648	free(disrequest);
7649
7650	free(disresponse);
7651
7652	freebusdevlist(&devlist);
7653
7654	return (retval);
7655}
7656
7657static int
7658atapm(struct cam_device *device, int argc, char **argv,
7659		 char *combinedopt, int retry_count, int timeout)
7660{
7661	union ccb *ccb;
7662	int retval = 0;
7663	int t = -1;
7664	int c;
7665	u_char cmd, sc;
7666
7667	ccb = cam_getccb(device);
7668
7669	if (ccb == NULL) {
7670		warnx("%s: error allocating ccb", __func__);
7671		return (1);
7672	}
7673
7674	while ((c = getopt(argc, argv, combinedopt)) != -1) {
7675		switch (c) {
7676		case 't':
7677			t = atoi(optarg);
7678			break;
7679		default:
7680			break;
7681		}
7682	}
7683	if (strcmp(argv[1], "idle") == 0) {
7684		if (t == -1)
7685			cmd = ATA_IDLE_IMMEDIATE;
7686		else
7687			cmd = ATA_IDLE_CMD;
7688	} else if (strcmp(argv[1], "standby") == 0) {
7689		if (t == -1)
7690			cmd = ATA_STANDBY_IMMEDIATE;
7691		else
7692			cmd = ATA_STANDBY_CMD;
7693	} else {
7694		cmd = ATA_SLEEP;
7695		t = -1;
7696	}
7697
7698	if (t < 0)
7699		sc = 0;
7700	else if (t <= (240 * 5))
7701		sc = (t + 4) / 5;
7702	else if (t <= (252 * 5))
7703		/* special encoding for 21 minutes */
7704		sc = 252;
7705	else if (t <= (11 * 30 * 60))
7706		sc = (t - 1) / (30 * 60) + 241;
7707	else
7708		sc = 253;
7709
7710	cam_fill_ataio(&ccb->ataio,
7711		      retry_count,
7712		      NULL,
7713		      /*flags*/CAM_DIR_NONE,
7714		      MSG_SIMPLE_Q_TAG,
7715		      /*data_ptr*/NULL,
7716		      /*dxfer_len*/0,
7717		      timeout ? timeout : 30 * 1000);
7718	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
7719
7720	/* Disable freezing the device queue */
7721	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
7722
7723	if (arglist & CAM_ARG_ERR_RECOVER)
7724		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
7725
7726	if (cam_send_ccb(device, ccb) < 0) {
7727		warn("error sending command");
7728
7729		if (arglist & CAM_ARG_VERBOSE)
7730			cam_error_print(device, ccb, CAM_ESF_ALL,
7731					CAM_EPF_ALL, stderr);
7732
7733		retval = 1;
7734		goto bailout;
7735	}
7736
7737	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
7738		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
7739		retval = 1;
7740		goto bailout;
7741	}
7742bailout:
7743	cam_freeccb(ccb);
7744	return (retval);
7745}
7746
7747#endif /* MINIMALISTIC */
7748
7749void
7750usage(int printlong)
7751{
7752
7753	fprintf(printlong ? stdout : stderr,
7754"usage:  camcontrol <command>  [device id][generic args][command args]\n"
7755"        camcontrol devlist    [-v]\n"
7756#ifndef MINIMALISTIC
7757"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
7758"        camcontrol tur        [dev_id][generic args]\n"
7759"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
7760"        camcontrol identify   [dev_id][generic args] [-v]\n"
7761"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
7762"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
7763"                              [-q] [-s]\n"
7764"        camcontrol start      [dev_id][generic args]\n"
7765"        camcontrol stop       [dev_id][generic args]\n"
7766"        camcontrol load       [dev_id][generic args]\n"
7767"        camcontrol eject      [dev_id][generic args]\n"
7768#endif /* MINIMALISTIC */
7769"        camcontrol rescan     <all | bus[:target:lun]>\n"
7770"        camcontrol reset      <all | bus[:target:lun]>\n"
7771#ifndef MINIMALISTIC
7772"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
7773"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
7774"                              [-P pagectl][-e | -b][-d]\n"
7775"        camcontrol cmd        [dev_id][generic args]\n"
7776"                              <-a cmd [args] | -c cmd [args]>\n"
7777"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
7778"        camcontrol smpcmd     [dev_id][generic args]\n"
7779"                              <-r len fmt [args]> <-R len fmt [args]>\n"
7780"        camcontrol smprg      [dev_id][generic args][-l]\n"
7781"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
7782"                              [-o operation][-d name][-m rate][-M rate]\n"
7783"                              [-T pp_timeout][-a enable|disable]\n"
7784"                              [-A enable|disable][-s enable|disable]\n"
7785"                              [-S enable|disable]\n"
7786"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
7787"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
7788"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
7789"                              <all|bus[:target[:lun]]|off>\n"
7790"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
7791"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
7792"                              [-D <enable|disable>][-M mode][-O offset]\n"
7793"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
7794"                              [-U][-W bus_width]\n"
7795"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
7796"        camcontrol sanitize   [dev_id][generic args]\n"
7797"                              [-a overwrite|block|crypto|exitfailure]\n"
7798"                              [-c passes][-I][-P pattern][-q][-U][-r][-w]\n"
7799"                              [-y]\n"
7800"        camcontrol idle       [dev_id][generic args][-t time]\n"
7801"        camcontrol standby    [dev_id][generic args][-t time]\n"
7802"        camcontrol sleep      [dev_id][generic args]\n"
7803"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
7804"        camcontrol security   [dev_id][generic args]\n"
7805"                              <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n"
7806"                              [-l <high|maximum>] [-q] [-s pwd] [-T timeout]\n"
7807"                              [-U <user|master>] [-y]\n"
7808"        camcontrol hpa        [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n"
7809"                              [-q] [-s max_sectors] [-U pwd] [-y]\n"
7810#endif /* MINIMALISTIC */
7811"        camcontrol help\n");
7812	if (!printlong)
7813		return;
7814#ifndef MINIMALISTIC
7815	fprintf(stdout,
7816"Specify one of the following options:\n"
7817"devlist     list all CAM devices\n"
7818"periphlist  list all CAM peripheral drivers attached to a device\n"
7819"tur         send a test unit ready to the named device\n"
7820"inquiry     send a SCSI inquiry command to the named device\n"
7821"identify    send a ATA identify command to the named device\n"
7822"reportluns  send a SCSI report luns command to the device\n"
7823"readcap     send a SCSI read capacity command to the device\n"
7824"start       send a Start Unit command to the device\n"
7825"stop        send a Stop Unit command to the device\n"
7826"load        send a Start Unit command to the device with the load bit set\n"
7827"eject       send a Stop Unit command to the device with the eject bit set\n"
7828"rescan      rescan all busses, the given bus, or bus:target:lun\n"
7829"reset       reset all busses, the given bus, or bus:target:lun\n"
7830"defects     read the defect list of the specified device\n"
7831"modepage    display or edit (-e) the given mode page\n"
7832"cmd         send the given SCSI command, may need -i or -o as well\n"
7833"smpcmd      send the given SMP command, requires -o and -i\n"
7834"smprg       send the SMP Report General command\n"
7835"smppc       send the SMP PHY Control command, requires -p\n"
7836"smpphylist  display phys attached to a SAS expander\n"
7837"smpmaninfo  send the SMP Report Manufacturer Info command\n"
7838"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
7839"tags        report or set the number of transaction slots for a device\n"
7840"negotiate   report or set device negotiation parameters\n"
7841"format      send the SCSI FORMAT UNIT command to the named device\n"
7842"sanitize    send the SCSI SANITIZE command to the named device\n"
7843"idle        send the ATA IDLE command to the named device\n"
7844"standby     send the ATA STANDBY command to the named device\n"
7845"sleep       send the ATA SLEEP command to the named device\n"
7846"fwdownload  program firmware of the named device with the given image"
7847"security    report or send ATA security commands to the named device\n"
7848"help        this message\n"
7849"Device Identifiers:\n"
7850"bus:target        specify the bus and target, lun defaults to 0\n"
7851"bus:target:lun    specify the bus, target and lun\n"
7852"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
7853"Generic arguments:\n"
7854"-v                be verbose, print out sense information\n"
7855"-t timeout        command timeout in seconds, overrides default timeout\n"
7856"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
7857"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
7858"-E                have the kernel attempt to perform SCSI error recovery\n"
7859"-C count          specify the SCSI command retry count (needs -E to work)\n"
7860"modepage arguments:\n"
7861"-l                list all available mode pages\n"
7862"-m page           specify the mode page to view or edit\n"
7863"-e                edit the specified mode page\n"
7864"-b                force view to binary mode\n"
7865"-d                disable block descriptors for mode sense\n"
7866"-P pgctl          page control field 0-3\n"
7867"defects arguments:\n"
7868"-f format         specify defect list format (block, bfi or phys)\n"
7869"-G                get the grown defect list\n"
7870"-P                get the permanent defect list\n"
7871"inquiry arguments:\n"
7872"-D                get the standard inquiry data\n"
7873"-S                get the serial number\n"
7874"-R                get the transfer rate, etc.\n"
7875"reportluns arguments:\n"
7876"-c                only report a count of available LUNs\n"
7877"-l                only print out luns, and not a count\n"
7878"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
7879"readcap arguments\n"
7880"-b                only report the blocksize\n"
7881"-h                human readable device size, base 2\n"
7882"-H                human readable device size, base 10\n"
7883"-N                print the number of blocks instead of last block\n"
7884"-q                quiet, print numbers only\n"
7885"-s                only report the last block/device size\n"
7886"cmd arguments:\n"
7887"-c cdb [args]     specify the SCSI CDB\n"
7888"-i len fmt        specify input data and input data format\n"
7889"-o len fmt [args] specify output data and output data fmt\n"
7890"smpcmd arguments:\n"
7891"-r len fmt [args] specify the SMP command to be sent\n"
7892"-R len fmt [args] specify SMP response format\n"
7893"smprg arguments:\n"
7894"-l                specify the long response format\n"
7895"smppc arguments:\n"
7896"-p phy            specify the PHY to operate on\n"
7897"-l                specify the long request/response format\n"
7898"-o operation      specify the phy control operation\n"
7899"-d name           set the attached device name\n"
7900"-m rate           set the minimum physical link rate\n"
7901"-M rate           set the maximum physical link rate\n"
7902"-T pp_timeout     set the partial pathway timeout value\n"
7903"-a enable|disable enable or disable SATA slumber\n"
7904"-A enable|disable enable or disable SATA partial phy power\n"
7905"-s enable|disable enable or disable SAS slumber\n"
7906"-S enable|disable enable or disable SAS partial phy power\n"
7907"smpphylist arguments:\n"
7908"-l                specify the long response format\n"
7909"-q                only print phys with attached devices\n"
7910"smpmaninfo arguments:\n"
7911"-l                specify the long response format\n"
7912"debug arguments:\n"
7913"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
7914"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
7915"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
7916"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
7917"tags arguments:\n"
7918"-N tags           specify the number of tags to use for this device\n"
7919"-q                be quiet, don't report the number of tags\n"
7920"-v                report a number of tag-related parameters\n"
7921"negotiate arguments:\n"
7922"-a                send a test unit ready after negotiation\n"
7923"-c                report/set current negotiation settings\n"
7924"-D <arg>          \"enable\" or \"disable\" disconnection\n"
7925"-M mode           set ATA mode\n"
7926"-O offset         set command delay offset\n"
7927"-q                be quiet, don't report anything\n"
7928"-R syncrate       synchronization rate in MHz\n"
7929"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
7930"-U                report/set user negotiation settings\n"
7931"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
7932"-v                also print a Path Inquiry CCB for the controller\n"
7933"format arguments:\n"
7934"-q                be quiet, don't print status messages\n"
7935"-r                run in report only mode\n"
7936"-w                don't send immediate format command\n"
7937"-y                don't ask any questions\n"
7938"sanitize arguments:\n"
7939"-a operation      operation mode: overwrite, block, crypto or exitfailure\n"
7940"-c passes         overwrite passes to perform (1 to 31)\n"
7941"-I                invert overwrite pattern after each pass\n"
7942"-P pattern        path to overwrite pattern file\n"
7943"-q                be quiet, don't print status messages\n"
7944"-r                run in report only mode\n"
7945"-U                run operation in unrestricted completion exit mode\n"
7946"-w                don't send immediate sanitize command\n"
7947"-y                don't ask any questions\n"
7948"idle/standby arguments:\n"
7949"-t <arg>          number of seconds before respective state.\n"
7950"fwdownload arguments:\n"
7951"-f fw_image       path to firmware image file\n"
7952"-y                don't ask any questions\n"
7953"-s                run in simulation mode\n"
7954"-v                print info for every firmware segment sent to device\n"
7955"security arguments:\n"
7956"-d pwd            disable security using the given password for the selected\n"
7957"                  user\n"
7958"-e pwd            erase the device using the given pwd for the selected user\n"
7959"-f                freeze the security configuration of the specified device\n"
7960"-h pwd            enhanced erase the device using the given pwd for the\n"
7961"                  selected user\n"
7962"-k pwd            unlock the device using the given pwd for the selected\n"
7963"                  user\n"
7964"-l <high|maximum> specifies which security level to set: high or maximum\n"
7965"-q                be quiet, do not print any status messages\n"
7966"-s pwd            password the device (enable security) using the given\n"
7967"                  pwd for the selected user\n"
7968"-T timeout        overrides the timeout (seconds) used for erase operation\n"
7969"-U <user|master>  specifies which user to set: user or master\n"
7970"-y                don't ask any questions\n"
7971"hpa arguments:\n"
7972"-f                freeze the HPA configuration of the device\n"
7973"-l                lock the HPA configuration of the device\n"
7974"-P                make the HPA max sectors persist\n"
7975"-p pwd            Set the HPA configuration password required for unlock\n"
7976"                  calls\n"
7977"-q                be quiet, do not print any status messages\n"
7978"-s sectors        configures the maximum user accessible sectors of the\n"
7979"                  device\n"
7980"-U pwd            unlock the HPA configuration of the device\n"
7981"-y                don't ask any questions\n"
7982);
7983#endif /* MINIMALISTIC */
7984}
7985
7986int
7987main(int argc, char **argv)
7988{
7989	int c;
7990	char *device = NULL;
7991	int unit = 0;
7992	struct cam_device *cam_dev = NULL;
7993	int timeout = 0, retry_count = 1;
7994	camcontrol_optret optreturn;
7995	char *tstr;
7996	const char *mainopt = "C:En:t:u:v";
7997	const char *subopt = NULL;
7998	char combinedopt[256];
7999	int error = 0, optstart = 2;
8000	int devopen = 1;
8001#ifndef MINIMALISTIC
8002	path_id_t bus;
8003	target_id_t target;
8004	lun_id_t lun;
8005#endif /* MINIMALISTIC */
8006
8007	cmdlist = CAM_CMD_NONE;
8008	arglist = CAM_ARG_NONE;
8009
8010	if (argc < 2) {
8011		usage(0);
8012		exit(1);
8013	}
8014
8015	/*
8016	 * Get the base option.
8017	 */
8018	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
8019
8020	if (optreturn == CC_OR_AMBIGUOUS) {
8021		warnx("ambiguous option %s", argv[1]);
8022		usage(0);
8023		exit(1);
8024	} else if (optreturn == CC_OR_NOT_FOUND) {
8025		warnx("option %s not found", argv[1]);
8026		usage(0);
8027		exit(1);
8028	}
8029
8030	/*
8031	 * Ahh, getopt(3) is a pain.
8032	 *
8033	 * This is a gross hack.  There really aren't many other good
8034	 * options (excuse the pun) for parsing options in a situation like
8035	 * this.  getopt is kinda braindead, so you end up having to run
8036	 * through the options twice, and give each invocation of getopt
8037	 * the option string for the other invocation.
8038	 *
8039	 * You would think that you could just have two groups of options.
8040	 * The first group would get parsed by the first invocation of
8041	 * getopt, and the second group would get parsed by the second
8042	 * invocation of getopt.  It doesn't quite work out that way.  When
8043	 * the first invocation of getopt finishes, it leaves optind pointing
8044	 * to the argument _after_ the first argument in the second group.
8045	 * So when the second invocation of getopt comes around, it doesn't
8046	 * recognize the first argument it gets and then bails out.
8047	 *
8048	 * A nice alternative would be to have a flag for getopt that says
8049	 * "just keep parsing arguments even when you encounter an unknown
8050	 * argument", but there isn't one.  So there's no real clean way to
8051	 * easily parse two sets of arguments without having one invocation
8052	 * of getopt know about the other.
8053	 *
8054	 * Without this hack, the first invocation of getopt would work as
8055	 * long as the generic arguments are first, but the second invocation
8056	 * (in the subfunction) would fail in one of two ways.  In the case
8057	 * where you don't set optreset, it would fail because optind may be
8058	 * pointing to the argument after the one it should be pointing at.
8059	 * In the case where you do set optreset, and reset optind, it would
8060	 * fail because getopt would run into the first set of options, which
8061	 * it doesn't understand.
8062	 *
8063	 * All of this would "sort of" work if you could somehow figure out
8064	 * whether optind had been incremented one option too far.  The
8065	 * mechanics of that, however, are more daunting than just giving
8066	 * both invocations all of the expect options for either invocation.
8067	 *
8068	 * Needless to say, I wouldn't mind if someone invented a better
8069	 * (non-GPL!) command line parsing interface than getopt.  I
8070	 * wouldn't mind if someone added more knobs to getopt to make it
8071	 * work better.  Who knows, I may talk myself into doing it someday,
8072	 * if the standards weenies let me.  As it is, it just leads to
8073	 * hackery like this and causes people to avoid it in some cases.
8074	 *
8075	 * KDM, September 8th, 1998
8076	 */
8077	if (subopt != NULL)
8078		sprintf(combinedopt, "%s%s", mainopt, subopt);
8079	else
8080		sprintf(combinedopt, "%s", mainopt);
8081
8082	/*
8083	 * For these options we do not parse optional device arguments and
8084	 * we do not open a passthrough device.
8085	 */
8086	if ((cmdlist == CAM_CMD_RESCAN)
8087	 || (cmdlist == CAM_CMD_RESET)
8088	 || (cmdlist == CAM_CMD_DEVTREE)
8089	 || (cmdlist == CAM_CMD_USAGE)
8090	 || (cmdlist == CAM_CMD_DEBUG))
8091		devopen = 0;
8092
8093#ifndef MINIMALISTIC
8094	if ((devopen == 1)
8095	 && (argc > 2 && argv[2][0] != '-')) {
8096		char name[30];
8097		int rv;
8098
8099		if (isdigit(argv[2][0])) {
8100			/* device specified as bus:target[:lun] */
8101			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
8102			if (rv < 2)
8103				errx(1, "numeric device specification must "
8104				     "be either bus:target, or "
8105				     "bus:target:lun");
8106			/* default to 0 if lun was not specified */
8107			if ((arglist & CAM_ARG_LUN) == 0) {
8108				lun = 0;
8109				arglist |= CAM_ARG_LUN;
8110			}
8111			optstart++;
8112		} else {
8113			if (cam_get_device(argv[2], name, sizeof name, &unit)
8114			    == -1)
8115				errx(1, "%s", cam_errbuf);
8116			device = strdup(name);
8117			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
8118			optstart++;
8119		}
8120	}
8121#endif /* MINIMALISTIC */
8122	/*
8123	 * Start getopt processing at argv[2/3], since we've already
8124	 * accepted argv[1..2] as the command name, and as a possible
8125	 * device name.
8126	 */
8127	optind = optstart;
8128
8129	/*
8130	 * Now we run through the argument list looking for generic
8131	 * options, and ignoring options that possibly belong to
8132	 * subfunctions.
8133	 */
8134	while ((c = getopt(argc, argv, combinedopt))!= -1){
8135		switch(c) {
8136			case 'C':
8137				retry_count = strtol(optarg, NULL, 0);
8138				if (retry_count < 0)
8139					errx(1, "retry count %d is < 0",
8140					     retry_count);
8141				arglist |= CAM_ARG_RETRIES;
8142				break;
8143			case 'E':
8144				arglist |= CAM_ARG_ERR_RECOVER;
8145				break;
8146			case 'n':
8147				arglist |= CAM_ARG_DEVICE;
8148				tstr = optarg;
8149				while (isspace(*tstr) && (*tstr != '\0'))
8150					tstr++;
8151				device = (char *)strdup(tstr);
8152				break;
8153			case 't':
8154				timeout = strtol(optarg, NULL, 0);
8155				if (timeout < 0)
8156					errx(1, "invalid timeout %d", timeout);
8157				/* Convert the timeout from seconds to ms */
8158				timeout *= 1000;
8159				arglist |= CAM_ARG_TIMEOUT;
8160				break;
8161			case 'u':
8162				arglist |= CAM_ARG_UNIT;
8163				unit = strtol(optarg, NULL, 0);
8164				break;
8165			case 'v':
8166				arglist |= CAM_ARG_VERBOSE;
8167				break;
8168			default:
8169				break;
8170		}
8171	}
8172
8173#ifndef MINIMALISTIC
8174	/*
8175	 * For most commands we'll want to open the passthrough device
8176	 * associated with the specified device.  In the case of the rescan
8177	 * commands, we don't use a passthrough device at all, just the
8178	 * transport layer device.
8179	 */
8180	if (devopen == 1) {
8181		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
8182		 && (((arglist & CAM_ARG_DEVICE) == 0)
8183		  || ((arglist & CAM_ARG_UNIT) == 0))) {
8184			errx(1, "subcommand \"%s\" requires a valid device "
8185			     "identifier", argv[1]);
8186		}
8187
8188		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
8189				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
8190				cam_open_spec_device(device,unit,O_RDWR,NULL)))
8191		     == NULL)
8192			errx(1,"%s", cam_errbuf);
8193	}
8194#endif /* MINIMALISTIC */
8195
8196	/*
8197	 * Reset optind to 2, and reset getopt, so these routines can parse
8198	 * the arguments again.
8199	 */
8200	optind = optstart;
8201	optreset = 1;
8202
8203	switch(cmdlist) {
8204#ifndef MINIMALISTIC
8205		case CAM_CMD_DEVLIST:
8206			error = getdevlist(cam_dev);
8207			break;
8208		case CAM_CMD_HPA:
8209			error = atahpa(cam_dev, retry_count, timeout,
8210				       argc, argv, combinedopt);
8211			break;
8212#endif /* MINIMALISTIC */
8213		case CAM_CMD_DEVTREE:
8214			error = getdevtree();
8215			break;
8216#ifndef MINIMALISTIC
8217		case CAM_CMD_TUR:
8218			error = testunitready(cam_dev, retry_count, timeout, 0);
8219			break;
8220		case CAM_CMD_INQUIRY:
8221			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
8222					      retry_count, timeout);
8223			break;
8224		case CAM_CMD_IDENTIFY:
8225			error = ataidentify(cam_dev, retry_count, timeout);
8226			break;
8227		case CAM_CMD_STARTSTOP:
8228			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
8229					  arglist & CAM_ARG_EJECT, retry_count,
8230					  timeout);
8231			break;
8232#endif /* MINIMALISTIC */
8233		case CAM_CMD_RESCAN:
8234			error = dorescan_or_reset(argc, argv, 1);
8235			break;
8236		case CAM_CMD_RESET:
8237			error = dorescan_or_reset(argc, argv, 0);
8238			break;
8239#ifndef MINIMALISTIC
8240		case CAM_CMD_READ_DEFECTS:
8241			error = readdefects(cam_dev, argc, argv, combinedopt,
8242					    retry_count, timeout);
8243			break;
8244		case CAM_CMD_MODE_PAGE:
8245			modepage(cam_dev, argc, argv, combinedopt,
8246				 retry_count, timeout);
8247			break;
8248		case CAM_CMD_SCSI_CMD:
8249			error = scsicmd(cam_dev, argc, argv, combinedopt,
8250					retry_count, timeout);
8251			break;
8252		case CAM_CMD_SMP_CMD:
8253			error = smpcmd(cam_dev, argc, argv, combinedopt,
8254				       retry_count, timeout);
8255			break;
8256		case CAM_CMD_SMP_RG:
8257			error = smpreportgeneral(cam_dev, argc, argv,
8258						 combinedopt, retry_count,
8259						 timeout);
8260			break;
8261		case CAM_CMD_SMP_PC:
8262			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
8263					      retry_count, timeout);
8264			break;
8265		case CAM_CMD_SMP_PHYLIST:
8266			error = smpphylist(cam_dev, argc, argv, combinedopt,
8267					   retry_count, timeout);
8268			break;
8269		case CAM_CMD_SMP_MANINFO:
8270			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
8271					   retry_count, timeout);
8272			break;
8273		case CAM_CMD_DEBUG:
8274			error = camdebug(argc, argv, combinedopt);
8275			break;
8276		case CAM_CMD_TAG:
8277			error = tagcontrol(cam_dev, argc, argv, combinedopt);
8278			break;
8279		case CAM_CMD_RATE:
8280			error = ratecontrol(cam_dev, retry_count, timeout,
8281					    argc, argv, combinedopt);
8282			break;
8283		case CAM_CMD_FORMAT:
8284			error = scsiformat(cam_dev, argc, argv,
8285					   combinedopt, retry_count, timeout);
8286			break;
8287		case CAM_CMD_REPORTLUNS:
8288			error = scsireportluns(cam_dev, argc, argv,
8289					       combinedopt, retry_count,
8290					       timeout);
8291			break;
8292		case CAM_CMD_READCAP:
8293			error = scsireadcapacity(cam_dev, argc, argv,
8294						 combinedopt, retry_count,
8295						 timeout);
8296			break;
8297		case CAM_CMD_IDLE:
8298		case CAM_CMD_STANDBY:
8299		case CAM_CMD_SLEEP:
8300			error = atapm(cam_dev, argc, argv,
8301				      combinedopt, retry_count, timeout);
8302			break;
8303		case CAM_CMD_SECURITY:
8304			error = atasecurity(cam_dev, retry_count, timeout,
8305					    argc, argv, combinedopt);
8306			break;
8307		case CAM_CMD_DOWNLOAD_FW:
8308			error = fwdownload(cam_dev, argc, argv, combinedopt,
8309			    arglist & CAM_ARG_VERBOSE, retry_count, timeout,
8310			    get_disk_type(cam_dev));
8311			break;
8312		case CAM_CMD_SANITIZE:
8313			error = scsisanitize(cam_dev, argc, argv,
8314					     combinedopt, retry_count, timeout);
8315			break;
8316#endif /* MINIMALISTIC */
8317		case CAM_CMD_USAGE:
8318			usage(1);
8319			break;
8320		default:
8321			usage(0);
8322			error = 1;
8323			break;
8324	}
8325
8326	if (cam_dev != NULL)
8327		cam_close_device(cam_dev);
8328
8329	exit(error);
8330}
8331