camcontrol.c revision 204195
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: head/sbin/camcontrol/camcontrol.c 204195 2010-02-22 10:45:40Z mav $");
31
32#include <sys/ioctl.h>
33#include <sys/stdint.h>
34#include <sys/types.h>
35#include <sys/endian.h>
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41#include <fcntl.h>
42#include <ctype.h>
43#include <err.h>
44#include <libutil.h>
45
46#include <cam/cam.h>
47#include <cam/cam_debug.h>
48#include <cam/cam_ccb.h>
49#include <cam/scsi/scsi_all.h>
50#include <cam/scsi/scsi_da.h>
51#include <cam/scsi/scsi_pass.h>
52#include <cam/scsi/scsi_message.h>
53#include <cam/ata/ata_all.h>
54#include <camlib.h>
55#include "camcontrol.h"
56
57typedef enum {
58	CAM_CMD_NONE		= 0x00000000,
59	CAM_CMD_DEVLIST		= 0x00000001,
60	CAM_CMD_TUR		= 0x00000002,
61	CAM_CMD_INQUIRY		= 0x00000003,
62	CAM_CMD_STARTSTOP	= 0x00000004,
63	CAM_CMD_RESCAN		= 0x00000005,
64	CAM_CMD_READ_DEFECTS	= 0x00000006,
65	CAM_CMD_MODE_PAGE	= 0x00000007,
66	CAM_CMD_SCSI_CMD	= 0x00000008,
67	CAM_CMD_DEVTREE		= 0x00000009,
68	CAM_CMD_USAGE		= 0x0000000a,
69	CAM_CMD_DEBUG		= 0x0000000b,
70	CAM_CMD_RESET		= 0x0000000c,
71	CAM_CMD_FORMAT		= 0x0000000d,
72	CAM_CMD_TAG		= 0x0000000e,
73	CAM_CMD_RATE		= 0x0000000f,
74	CAM_CMD_DETACH		= 0x00000010,
75	CAM_CMD_REPORTLUNS	= 0x00000011,
76	CAM_CMD_READCAP		= 0x00000012,
77	CAM_CMD_IDENTIFY	= 0x00000013,
78	CAM_CMD_IDLE		= 0x00000014,
79	CAM_CMD_STANDBY		= 0x00000015,
80	CAM_CMD_SLEEP		= 0x00000016
81} cam_cmdmask;
82
83typedef enum {
84	CAM_ARG_NONE		= 0x00000000,
85	CAM_ARG_VERBOSE		= 0x00000001,
86	CAM_ARG_DEVICE		= 0x00000002,
87	CAM_ARG_BUS		= 0x00000004,
88	CAM_ARG_TARGET		= 0x00000008,
89	CAM_ARG_LUN		= 0x00000010,
90	CAM_ARG_EJECT		= 0x00000020,
91	CAM_ARG_UNIT		= 0x00000040,
92	CAM_ARG_FORMAT_BLOCK	= 0x00000080,
93	CAM_ARG_FORMAT_BFI	= 0x00000100,
94	CAM_ARG_FORMAT_PHYS	= 0x00000200,
95	CAM_ARG_PLIST		= 0x00000400,
96	CAM_ARG_GLIST		= 0x00000800,
97	CAM_ARG_GET_SERIAL	= 0x00001000,
98	CAM_ARG_GET_STDINQ	= 0x00002000,
99	CAM_ARG_GET_XFERRATE	= 0x00004000,
100	CAM_ARG_INQ_MASK	= 0x00007000,
101	CAM_ARG_MODE_EDIT	= 0x00008000,
102	CAM_ARG_PAGE_CNTL	= 0x00010000,
103	CAM_ARG_TIMEOUT		= 0x00020000,
104	CAM_ARG_CMD_IN		= 0x00040000,
105	CAM_ARG_CMD_OUT		= 0x00080000,
106	CAM_ARG_DBD		= 0x00100000,
107	CAM_ARG_ERR_RECOVER	= 0x00200000,
108	CAM_ARG_RETRIES		= 0x00400000,
109	CAM_ARG_START_UNIT	= 0x00800000,
110	CAM_ARG_DEBUG_INFO	= 0x01000000,
111	CAM_ARG_DEBUG_TRACE	= 0x02000000,
112	CAM_ARG_DEBUG_SUBTRACE	= 0x04000000,
113	CAM_ARG_DEBUG_CDB	= 0x08000000,
114	CAM_ARG_DEBUG_XPT	= 0x10000000,
115	CAM_ARG_DEBUG_PERIPH	= 0x20000000,
116} cam_argmask;
117
118struct camcontrol_opts {
119	const char	*optname;
120	cam_cmdmask	cmdnum;
121	cam_argmask	argnum;
122	const char	*subopt;
123};
124
125#ifndef MINIMALISTIC
126static const char scsicmd_opts[] = "a:c:i:o:r";
127static const char readdefect_opts[] = "f:GP";
128static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
129#endif
130
131struct camcontrol_opts option_table[] = {
132#ifndef MINIMALISTIC
133	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
134	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
135	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
136	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
137	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
138	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
139	{"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL},
140	{"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"},
141	{"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"},
142#endif /* MINIMALISTIC */
143	{"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL},
144	{"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL},
145#ifndef MINIMALISTIC
146	{"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
147	{"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts},
148	{"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
149	{"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts},
150#endif /* MINIMALISTIC */
151	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
152#ifndef MINIMALISTIC
153	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
154	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
155	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
156	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
157	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
158	{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
159	{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
160	{"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
161	{"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
162	{"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
163#endif /* MINIMALISTIC */
164	{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
165	{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
166	{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
167	{NULL, 0, 0, NULL}
168};
169
170typedef enum {
171	CC_OR_NOT_FOUND,
172	CC_OR_AMBIGUOUS,
173	CC_OR_FOUND
174} camcontrol_optret;
175
176cam_cmdmask cmdlist;
177cam_argmask arglist;
178
179
180camcontrol_optret getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
181			    const char **subopt);
182#ifndef MINIMALISTIC
183static int getdevlist(struct cam_device *device);
184#endif /* MINIMALISTIC */
185static int getdevtree(void);
186#ifndef MINIMALISTIC
187static int testunitready(struct cam_device *device, int retry_count,
188			 int timeout, int quiet);
189static int scsistart(struct cam_device *device, int startstop, int loadeject,
190		     int retry_count, int timeout);
191static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
192			 char *combinedopt, int retry_count, int timeout);
193static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
194static int scsiserial(struct cam_device *device, int retry_count, int timeout);
195static int camxferrate(struct cam_device *device);
196#endif /* MINIMALISTIC */
197static int parse_btl(char *tstr, int *bus, int *target, int *lun,
198		     cam_argmask *arglst);
199static int dorescan_or_reset(int argc, char **argv, int rescan);
200static int rescan_or_reset_bus(int bus, int rescan);
201static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
202#ifndef MINIMALISTIC
203static int readdefects(struct cam_device *device, int argc, char **argv,
204		       char *combinedopt, int retry_count, int timeout);
205static void modepage(struct cam_device *device, int argc, char **argv,
206		     char *combinedopt, int retry_count, int timeout);
207static int scsicmd(struct cam_device *device, int argc, char **argv,
208		   char *combinedopt, int retry_count, int timeout);
209static int tagcontrol(struct cam_device *device, int argc, char **argv,
210		      char *combinedopt);
211static void cts_print(struct cam_device *device,
212		      struct ccb_trans_settings *cts);
213static void cpi_print(struct ccb_pathinq *cpi);
214static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
215static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd);
216static int get_print_cts(struct cam_device *device, int user_settings,
217			 int quiet, struct ccb_trans_settings *cts);
218static int ratecontrol(struct cam_device *device, int retry_count,
219		       int timeout, int argc, char **argv, char *combinedopt);
220static int scsiformat(struct cam_device *device, int argc, char **argv,
221		      char *combinedopt, int retry_count, int timeout);
222static int scsireportluns(struct cam_device *device, int argc, char **argv,
223			  char *combinedopt, int retry_count, int timeout);
224static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
225			    char *combinedopt, int retry_count, int timeout);
226static int atapm(struct cam_device *device, int argc, char **argv,
227			    char *combinedopt, int retry_count, int timeout);
228#endif /* MINIMALISTIC */
229#ifndef min
230#define min(a,b) (((a)<(b))?(a):(b))
231#endif
232#ifndef max
233#define max(a,b) (((a)>(b))?(a):(b))
234#endif
235
236camcontrol_optret
237getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum,
238	  const char **subopt)
239{
240	struct camcontrol_opts *opts;
241	int num_matches = 0;
242
243	for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
244	     opts++) {
245		if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
246			*cmdnum = opts->cmdnum;
247			*argnum = opts->argnum;
248			*subopt = opts->subopt;
249			if (++num_matches > 1)
250				return(CC_OR_AMBIGUOUS);
251		}
252	}
253
254	if (num_matches > 0)
255		return(CC_OR_FOUND);
256	else
257		return(CC_OR_NOT_FOUND);
258}
259
260#ifndef MINIMALISTIC
261static int
262getdevlist(struct cam_device *device)
263{
264	union ccb *ccb;
265	char status[32];
266	int error = 0;
267
268	ccb = cam_getccb(device);
269
270	ccb->ccb_h.func_code = XPT_GDEVLIST;
271	ccb->ccb_h.flags = CAM_DIR_NONE;
272	ccb->ccb_h.retry_count = 1;
273	ccb->cgdl.index = 0;
274	ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
275	while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
276		if (cam_send_ccb(device, ccb) < 0) {
277			perror("error getting device list");
278			cam_freeccb(ccb);
279			return(1);
280		}
281
282		status[0] = '\0';
283
284		switch (ccb->cgdl.status) {
285			case CAM_GDEVLIST_MORE_DEVS:
286				strcpy(status, "MORE");
287				break;
288			case CAM_GDEVLIST_LAST_DEVICE:
289				strcpy(status, "LAST");
290				break;
291			case CAM_GDEVLIST_LIST_CHANGED:
292				strcpy(status, "CHANGED");
293				break;
294			case CAM_GDEVLIST_ERROR:
295				strcpy(status, "ERROR");
296				error = 1;
297				break;
298		}
299
300		fprintf(stdout, "%s%d:  generation: %d index: %d status: %s\n",
301			ccb->cgdl.periph_name,
302			ccb->cgdl.unit_number,
303			ccb->cgdl.generation,
304			ccb->cgdl.index,
305			status);
306
307		/*
308		 * If the list has changed, we need to start over from the
309		 * beginning.
310		 */
311		if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
312			ccb->cgdl.index = 0;
313	}
314
315	cam_freeccb(ccb);
316
317	return(error);
318}
319#endif /* MINIMALISTIC */
320
321static int
322getdevtree(void)
323{
324	union ccb ccb;
325	int bufsize, fd;
326	unsigned int i;
327	int need_close = 0;
328	int error = 0;
329	int skip_device = 0;
330
331	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
332		warn("couldn't open %s", XPT_DEVICE);
333		return(1);
334	}
335
336	bzero(&ccb, sizeof(union ccb));
337
338	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
339	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
340	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
341
342	ccb.ccb_h.func_code = XPT_DEV_MATCH;
343	bufsize = sizeof(struct dev_match_result) * 100;
344	ccb.cdm.match_buf_len = bufsize;
345	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
346	if (ccb.cdm.matches == NULL) {
347		warnx("can't malloc memory for matches");
348		close(fd);
349		return(1);
350	}
351	ccb.cdm.num_matches = 0;
352
353	/*
354	 * We fetch all nodes, since we display most of them in the default
355	 * case, and all in the verbose case.
356	 */
357	ccb.cdm.num_patterns = 0;
358	ccb.cdm.pattern_buf_len = 0;
359
360	/*
361	 * We do the ioctl multiple times if necessary, in case there are
362	 * more than 100 nodes in the EDT.
363	 */
364	do {
365		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
366			warn("error sending CAMIOCOMMAND ioctl");
367			error = 1;
368			break;
369		}
370
371		if ((ccb.ccb_h.status != CAM_REQ_CMP)
372		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
373		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
374			warnx("got CAM error %#x, CDM error %d\n",
375			      ccb.ccb_h.status, ccb.cdm.status);
376			error = 1;
377			break;
378		}
379
380		for (i = 0; i < ccb.cdm.num_matches; i++) {
381			switch (ccb.cdm.matches[i].type) {
382			case DEV_MATCH_BUS: {
383				struct bus_match_result *bus_result;
384
385				/*
386				 * Only print the bus information if the
387				 * user turns on the verbose flag.
388				 */
389				if ((arglist & CAM_ARG_VERBOSE) == 0)
390					break;
391
392				bus_result =
393					&ccb.cdm.matches[i].result.bus_result;
394
395				if (need_close) {
396					fprintf(stdout, ")\n");
397					need_close = 0;
398				}
399
400				fprintf(stdout, "scbus%d on %s%d bus %d:\n",
401					bus_result->path_id,
402					bus_result->dev_name,
403					bus_result->unit_number,
404					bus_result->bus_id);
405				break;
406			}
407			case DEV_MATCH_DEVICE: {
408				struct device_match_result *dev_result;
409				char vendor[16], product[48], revision[16];
410				char tmpstr[256];
411
412				dev_result =
413				     &ccb.cdm.matches[i].result.device_result;
414
415				if ((dev_result->flags
416				     & DEV_RESULT_UNCONFIGURED)
417				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
418					skip_device = 1;
419					break;
420				} else
421					skip_device = 0;
422
423				if (dev_result->protocol == PROTO_SCSI) {
424				    cam_strvis(vendor, dev_result->inq_data.vendor,
425					   sizeof(dev_result->inq_data.vendor),
426					   sizeof(vendor));
427				    cam_strvis(product,
428					   dev_result->inq_data.product,
429					   sizeof(dev_result->inq_data.product),
430					   sizeof(product));
431				    cam_strvis(revision,
432					   dev_result->inq_data.revision,
433					  sizeof(dev_result->inq_data.revision),
434					   sizeof(revision));
435				    sprintf(tmpstr, "<%s %s %s>", vendor, product,
436					revision);
437				} else if (dev_result->protocol == PROTO_ATA ||
438				    dev_result->protocol == PROTO_SATAPM) {
439				    cam_strvis(product,
440					   dev_result->ident_data.model,
441					   sizeof(dev_result->ident_data.model),
442					   sizeof(product));
443				    cam_strvis(revision,
444					   dev_result->ident_data.revision,
445					  sizeof(dev_result->ident_data.revision),
446					   sizeof(revision));
447				    sprintf(tmpstr, "<%s %s>", product,
448					revision);
449				} else {
450				    sprintf(tmpstr, "<>");
451				}
452				if (need_close) {
453					fprintf(stdout, ")\n");
454					need_close = 0;
455				}
456
457				fprintf(stdout, "%-33s  at scbus%d "
458					"target %d lun %d (",
459					tmpstr,
460					dev_result->path_id,
461					dev_result->target_id,
462					dev_result->target_lun);
463
464				need_close = 1;
465
466				break;
467			}
468			case DEV_MATCH_PERIPH: {
469				struct periph_match_result *periph_result;
470
471				periph_result =
472				      &ccb.cdm.matches[i].result.periph_result;
473
474				if (skip_device != 0)
475					break;
476
477				if (need_close > 1)
478					fprintf(stdout, ",");
479
480				fprintf(stdout, "%s%d",
481					periph_result->periph_name,
482					periph_result->unit_number);
483
484				need_close++;
485				break;
486			}
487			default:
488				fprintf(stdout, "unknown match type\n");
489				break;
490			}
491		}
492
493	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
494		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
495
496	if (need_close)
497		fprintf(stdout, ")\n");
498
499	close(fd);
500
501	return(error);
502}
503
504#ifndef MINIMALISTIC
505static int
506testunitready(struct cam_device *device, int retry_count, int timeout,
507	      int quiet)
508{
509	int error = 0;
510	union ccb *ccb;
511
512	ccb = cam_getccb(device);
513
514	scsi_test_unit_ready(&ccb->csio,
515			     /* retries */ retry_count,
516			     /* cbfcnp */ NULL,
517			     /* tag_action */ MSG_SIMPLE_Q_TAG,
518			     /* sense_len */ SSD_FULL_SIZE,
519			     /* timeout */ timeout ? timeout : 5000);
520
521	/* Disable freezing the device queue */
522	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
523
524	if (arglist & CAM_ARG_ERR_RECOVER)
525		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
526
527	if (cam_send_ccb(device, ccb) < 0) {
528		if (quiet == 0)
529			perror("error sending test unit ready");
530
531		if (arglist & CAM_ARG_VERBOSE) {
532			cam_error_print(device, ccb, CAM_ESF_ALL,
533					CAM_EPF_ALL, stderr);
534		}
535
536		cam_freeccb(ccb);
537		return(1);
538	}
539
540	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
541		if (quiet == 0)
542			fprintf(stdout, "Unit is ready\n");
543	} else {
544		if (quiet == 0)
545			fprintf(stdout, "Unit is not ready\n");
546		error = 1;
547
548		if (arglist & CAM_ARG_VERBOSE) {
549			cam_error_print(device, ccb, CAM_ESF_ALL,
550					CAM_EPF_ALL, stderr);
551		}
552	}
553
554	cam_freeccb(ccb);
555
556	return(error);
557}
558
559static int
560scsistart(struct cam_device *device, int startstop, int loadeject,
561	  int retry_count, int timeout)
562{
563	union ccb *ccb;
564	int error = 0;
565
566	ccb = cam_getccb(device);
567
568	/*
569	 * If we're stopping, send an ordered tag so the drive in question
570	 * will finish any previously queued writes before stopping.  If
571	 * the device isn't capable of tagged queueing, or if tagged
572	 * queueing is turned off, the tag action is a no-op.
573	 */
574	scsi_start_stop(&ccb->csio,
575			/* retries */ retry_count,
576			/* cbfcnp */ NULL,
577			/* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
578						     MSG_ORDERED_Q_TAG,
579			/* start/stop */ startstop,
580			/* load_eject */ loadeject,
581			/* immediate */ 0,
582			/* sense_len */ SSD_FULL_SIZE,
583			/* timeout */ timeout ? timeout : 120000);
584
585	/* Disable freezing the device queue */
586	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
587
588	if (arglist & CAM_ARG_ERR_RECOVER)
589		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
590
591	if (cam_send_ccb(device, ccb) < 0) {
592		perror("error sending start unit");
593
594		if (arglist & CAM_ARG_VERBOSE) {
595			cam_error_print(device, ccb, CAM_ESF_ALL,
596					CAM_EPF_ALL, stderr);
597		}
598
599		cam_freeccb(ccb);
600		return(1);
601	}
602
603	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
604		if (startstop) {
605			fprintf(stdout, "Unit started successfully");
606			if (loadeject)
607				fprintf(stdout,", Media loaded\n");
608			else
609				fprintf(stdout,"\n");
610		} else {
611			fprintf(stdout, "Unit stopped successfully");
612			if (loadeject)
613				fprintf(stdout, ", Media ejected\n");
614			else
615				fprintf(stdout, "\n");
616		}
617	else {
618		error = 1;
619		if (startstop)
620			fprintf(stdout,
621				"Error received from start unit command\n");
622		else
623			fprintf(stdout,
624				"Error received from stop unit command\n");
625
626		if (arglist & CAM_ARG_VERBOSE) {
627			cam_error_print(device, ccb, CAM_ESF_ALL,
628					CAM_EPF_ALL, stderr);
629		}
630	}
631
632	cam_freeccb(ccb);
633
634	return(error);
635}
636
637static int
638scsidoinquiry(struct cam_device *device, int argc, char **argv,
639	      char *combinedopt, int retry_count, int timeout)
640{
641	int c;
642	int error = 0;
643
644	while ((c = getopt(argc, argv, combinedopt)) != -1) {
645		switch(c) {
646		case 'D':
647			arglist |= CAM_ARG_GET_STDINQ;
648			break;
649		case 'R':
650			arglist |= CAM_ARG_GET_XFERRATE;
651			break;
652		case 'S':
653			arglist |= CAM_ARG_GET_SERIAL;
654			break;
655		default:
656			break;
657		}
658	}
659
660	/*
661	 * If the user didn't specify any inquiry options, he wants all of
662	 * them.
663	 */
664	if ((arglist & CAM_ARG_INQ_MASK) == 0)
665		arglist |= CAM_ARG_INQ_MASK;
666
667	if (arglist & CAM_ARG_GET_STDINQ)
668		error = scsiinquiry(device, retry_count, timeout);
669
670	if (error != 0)
671		return(error);
672
673	if (arglist & CAM_ARG_GET_SERIAL)
674		scsiserial(device, retry_count, timeout);
675
676	if (error != 0)
677		return(error);
678
679	if (arglist & CAM_ARG_GET_XFERRATE)
680		error = camxferrate(device);
681
682	return(error);
683}
684
685static int
686scsiinquiry(struct cam_device *device, int retry_count, int timeout)
687{
688	union ccb *ccb;
689	struct scsi_inquiry_data *inq_buf;
690	int error = 0;
691
692	ccb = cam_getccb(device);
693
694	if (ccb == NULL) {
695		warnx("couldn't allocate CCB");
696		return(1);
697	}
698
699	/* cam_getccb cleans up the header, caller has to zero the payload */
700	bzero(&(&ccb->ccb_h)[1],
701	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
702
703	inq_buf = (struct scsi_inquiry_data *)malloc(
704		sizeof(struct scsi_inquiry_data));
705
706	if (inq_buf == NULL) {
707		cam_freeccb(ccb);
708		warnx("can't malloc memory for inquiry\n");
709		return(1);
710	}
711	bzero(inq_buf, sizeof(*inq_buf));
712
713	/*
714	 * Note that although the size of the inquiry buffer is the full
715	 * 256 bytes specified in the SCSI spec, we only tell the device
716	 * that we have allocated SHORT_INQUIRY_LENGTH bytes.  There are
717	 * two reasons for this:
718	 *
719	 *  - The SCSI spec says that when a length field is only 1 byte,
720	 *    a value of 0 will be interpreted as 256.  Therefore
721	 *    scsi_inquiry() will convert an inq_len (which is passed in as
722	 *    a u_int32_t, but the field in the CDB is only 1 byte) of 256
723	 *    to 0.  Evidently, very few devices meet the spec in that
724	 *    regard.  Some devices, like many Seagate disks, take the 0 as
725	 *    0, and don't return any data.  One Pioneer DVD-R drive
726	 *    returns more data than the command asked for.
727	 *
728	 *    So, since there are numerous devices that just don't work
729	 *    right with the full inquiry size, we don't send the full size.
730	 *
731	 *  - The second reason not to use the full inquiry data length is
732	 *    that we don't need it here.  The only reason we issue a
733	 *    standard inquiry is to get the vendor name, device name,
734	 *    and revision so scsi_print_inquiry() can print them.
735	 *
736	 * If, at some point in the future, more inquiry data is needed for
737	 * some reason, this code should use a procedure similar to the
738	 * probe code.  i.e., issue a short inquiry, and determine from
739	 * the additional length passed back from the device how much
740	 * inquiry data the device supports.  Once the amount the device
741	 * supports is determined, issue an inquiry for that amount and no
742	 * more.
743	 *
744	 * KDM, 2/18/2000
745	 */
746	scsi_inquiry(&ccb->csio,
747		     /* retries */ retry_count,
748		     /* cbfcnp */ NULL,
749		     /* tag_action */ MSG_SIMPLE_Q_TAG,
750		     /* inq_buf */ (u_int8_t *)inq_buf,
751		     /* inq_len */ SHORT_INQUIRY_LENGTH,
752		     /* evpd */ 0,
753		     /* page_code */ 0,
754		     /* sense_len */ SSD_FULL_SIZE,
755		     /* timeout */ timeout ? timeout : 5000);
756
757	/* Disable freezing the device queue */
758	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
759
760	if (arglist & CAM_ARG_ERR_RECOVER)
761		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
762
763	if (cam_send_ccb(device, ccb) < 0) {
764		perror("error sending SCSI inquiry");
765
766		if (arglist & CAM_ARG_VERBOSE) {
767			cam_error_print(device, ccb, CAM_ESF_ALL,
768					CAM_EPF_ALL, stderr);
769		}
770
771		cam_freeccb(ccb);
772		return(1);
773	}
774
775	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
776		error = 1;
777
778		if (arglist & CAM_ARG_VERBOSE) {
779			cam_error_print(device, ccb, CAM_ESF_ALL,
780					CAM_EPF_ALL, stderr);
781		}
782	}
783
784	cam_freeccb(ccb);
785
786	if (error != 0) {
787		free(inq_buf);
788		return(error);
789	}
790
791	fprintf(stdout, "%s%d: ", device->device_name,
792		device->dev_unit_num);
793	scsi_print_inquiry(inq_buf);
794
795	free(inq_buf);
796
797	return(0);
798}
799
800static int
801scsiserial(struct cam_device *device, int retry_count, int timeout)
802{
803	union ccb *ccb;
804	struct scsi_vpd_unit_serial_number *serial_buf;
805	char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
806	int error = 0;
807
808	ccb = cam_getccb(device);
809
810	if (ccb == NULL) {
811		warnx("couldn't allocate CCB");
812		return(1);
813	}
814
815	/* cam_getccb cleans up the header, caller has to zero the payload */
816	bzero(&(&ccb->ccb_h)[1],
817	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
818
819	serial_buf = (struct scsi_vpd_unit_serial_number *)
820		malloc(sizeof(*serial_buf));
821
822	if (serial_buf == NULL) {
823		cam_freeccb(ccb);
824		warnx("can't malloc memory for serial number");
825		return(1);
826	}
827
828	scsi_inquiry(&ccb->csio,
829		     /*retries*/ retry_count,
830		     /*cbfcnp*/ NULL,
831		     /* tag_action */ MSG_SIMPLE_Q_TAG,
832		     /* inq_buf */ (u_int8_t *)serial_buf,
833		     /* inq_len */ sizeof(*serial_buf),
834		     /* evpd */ 1,
835		     /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
836		     /* sense_len */ SSD_FULL_SIZE,
837		     /* timeout */ timeout ? timeout : 5000);
838
839	/* Disable freezing the device queue */
840	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
841
842	if (arglist & CAM_ARG_ERR_RECOVER)
843		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
844
845	if (cam_send_ccb(device, ccb) < 0) {
846		warn("error getting serial number");
847
848		if (arglist & CAM_ARG_VERBOSE) {
849			cam_error_print(device, ccb, CAM_ESF_ALL,
850					CAM_EPF_ALL, stderr);
851		}
852
853		cam_freeccb(ccb);
854		free(serial_buf);
855		return(1);
856	}
857
858	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
859		error = 1;
860
861		if (arglist & CAM_ARG_VERBOSE) {
862			cam_error_print(device, ccb, CAM_ESF_ALL,
863					CAM_EPF_ALL, stderr);
864		}
865	}
866
867	cam_freeccb(ccb);
868
869	if (error != 0) {
870		free(serial_buf);
871		return(error);
872	}
873
874	bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
875	serial_num[serial_buf->length] = '\0';
876
877	if ((arglist & CAM_ARG_GET_STDINQ)
878	 || (arglist & CAM_ARG_GET_XFERRATE))
879		fprintf(stdout, "%s%d: Serial Number ",
880			device->device_name, device->dev_unit_num);
881
882	fprintf(stdout, "%.60s\n", serial_num);
883
884	free(serial_buf);
885
886	return(0);
887}
888
889static int
890camxferrate(struct cam_device *device)
891{
892	struct ccb_pathinq cpi;
893	u_int32_t freq = 0;
894	u_int32_t speed = 0;
895	union ccb *ccb;
896	u_int mb;
897	int retval = 0;
898
899	if ((retval = get_cpi(device, &cpi)) != 0)
900		return (1);
901
902	ccb = cam_getccb(device);
903
904	if (ccb == NULL) {
905		warnx("couldn't allocate CCB");
906		return(1);
907	}
908
909	bzero(&(&ccb->ccb_h)[1],
910	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
911
912	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
913	ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
914
915	if (((retval = cam_send_ccb(device, ccb)) < 0)
916	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
917		const char error_string[] = "error getting transfer settings";
918
919		if (retval < 0)
920			warn(error_string);
921		else
922			warnx(error_string);
923
924		if (arglist & CAM_ARG_VERBOSE)
925			cam_error_print(device, ccb, CAM_ESF_ALL,
926					CAM_EPF_ALL, stderr);
927
928		retval = 1;
929
930		goto xferrate_bailout;
931
932	}
933
934	speed = cpi.base_transfer_speed;
935	freq = 0;
936	if (ccb->cts.transport == XPORT_SPI) {
937		struct ccb_trans_settings_spi *spi =
938		    &ccb->cts.xport_specific.spi;
939
940		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
941			freq = scsi_calc_syncsrate(spi->sync_period);
942			speed = freq;
943		}
944		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
945			speed *= (0x01 << spi->bus_width);
946		}
947	} else if (ccb->cts.transport == XPORT_FC) {
948		struct ccb_trans_settings_fc *fc =
949		    &ccb->cts.xport_specific.fc;
950
951		if (fc->valid & CTS_FC_VALID_SPEED)
952			speed = fc->bitrate;
953	} else if (ccb->cts.transport == XPORT_SAS) {
954		struct ccb_trans_settings_sas *sas =
955		    &ccb->cts.xport_specific.sas;
956
957		if (sas->valid & CTS_SAS_VALID_SPEED)
958			speed = sas->bitrate;
959	} else if (ccb->cts.transport == XPORT_ATA) {
960		struct ccb_trans_settings_ata *ata =
961		    &ccb->cts.xport_specific.ata;
962
963		if (ata->valid & CTS_ATA_VALID_MODE)
964			speed = ata_mode2speed(ata->mode);
965	} else if (ccb->cts.transport == XPORT_SATA) {
966		struct	ccb_trans_settings_sata *sata =
967		    &ccb->cts.xport_specific.sata;
968
969		if (sata->valid & CTS_SATA_VALID_REVISION)
970			speed = ata_revision2speed(sata->revision);
971	}
972
973	mb = speed / 1000;
974	if (mb > 0) {
975		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
976			device->device_name, device->dev_unit_num,
977			mb, speed % 1000);
978	} else {
979		fprintf(stdout, "%s%d: %dKB/s transfers",
980			device->device_name, device->dev_unit_num,
981			speed);
982	}
983
984	if (ccb->cts.transport == XPORT_SPI) {
985		struct ccb_trans_settings_spi *spi =
986		    &ccb->cts.xport_specific.spi;
987
988		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
989		 && (spi->sync_offset != 0))
990			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
991				freq % 1000, spi->sync_offset);
992
993		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
994		 && (spi->bus_width > 0)) {
995			if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
996			 && (spi->sync_offset != 0)) {
997				fprintf(stdout, ", ");
998			} else {
999				fprintf(stdout, " (");
1000			}
1001			fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width));
1002		} else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
1003		 && (spi->sync_offset != 0)) {
1004			fprintf(stdout, ")");
1005		}
1006	} else if (ccb->cts.transport == XPORT_ATA) {
1007		struct ccb_trans_settings_ata *ata =
1008		    &ccb->cts.xport_specific.ata;
1009
1010		printf(" (");
1011		if (ata->valid & CTS_ATA_VALID_MODE)
1012			printf("%s, ", ata_mode2string(ata->mode));
1013		if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
1014			printf("ATAPI %dbytes, ", ata->atapi);
1015		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
1016			printf("PIO %dbytes", ata->bytecount);
1017		printf(")");
1018	} else if (ccb->cts.transport == XPORT_SATA) {
1019		struct ccb_trans_settings_sata *sata =
1020		    &ccb->cts.xport_specific.sata;
1021
1022		printf(" (");
1023		if (sata->valid & CTS_SATA_VALID_REVISION)
1024			printf("SATA %d.x, ", sata->revision);
1025		else
1026			printf("SATA, ");
1027		if (sata->valid & CTS_SATA_VALID_MODE)
1028			printf("%s, ", ata_mode2string(sata->mode));
1029		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
1030			printf("ATAPI %dbytes, ", sata->atapi);
1031		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
1032			printf("PIO %dbytes", sata->bytecount);
1033		printf(")");
1034	}
1035
1036	if (ccb->cts.protocol == PROTO_SCSI) {
1037		struct ccb_trans_settings_scsi *scsi =
1038		    &ccb->cts.proto_specific.scsi;
1039		if (scsi->valid & CTS_SCSI_VALID_TQ) {
1040			if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1041				fprintf(stdout, ", Command Queueing Enabled");
1042			}
1043		}
1044	}
1045
1046        fprintf(stdout, "\n");
1047
1048xferrate_bailout:
1049
1050	cam_freeccb(ccb);
1051
1052	return(retval);
1053}
1054
1055static void
1056atacapprint(struct ata_params *parm)
1057{
1058	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
1059				((u_int32_t)parm->lba_size_2 << 16);
1060
1061	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
1062				((u_int64_t)parm->lba_size48_2 << 16) |
1063				((u_int64_t)parm->lba_size48_3 << 32) |
1064				((u_int64_t)parm->lba_size48_4 << 48);
1065
1066	printf("\n");
1067	printf("protocol              ");
1068	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
1069	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1070		if (parm->satacapabilities & ATA_SATA_GEN3)
1071			printf(" SATA 3.x\n");
1072		else if (parm->satacapabilities & ATA_SATA_GEN2)
1073			printf(" SATA 2.x\n");
1074		else if (parm->satacapabilities & ATA_SATA_GEN1)
1075			printf(" SATA 1.x\n");
1076		else
1077			printf(" SATA\n");
1078	}
1079	else
1080		printf("\n");
1081	printf("device model          %.40s\n", parm->model);
1082	printf("firmware revision     %.8s\n", parm->revision);
1083	printf("serial number         %.20s\n", parm->serial);
1084	if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
1085		printf("WWN                   %02x%02x%02x%02x\n",
1086		    parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
1087	}
1088	if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
1089		printf("media serial number   %.30s\n",
1090		    parm->media_serial);
1091	}
1092
1093	printf("cylinders             %d\n", parm->cylinders);
1094	printf("heads                 %d\n", parm->heads);
1095	printf("sectors/track         %d\n", parm->sectors);
1096	printf("sector size           logical %u, physical %lu, offset %lu\n",
1097	    ata_logical_sector_size(parm),
1098	    (unsigned long)ata_physical_sector_size(parm),
1099	    (unsigned long)ata_logical_sector_offset(parm));
1100
1101	if (parm->config == ATA_PROTO_CFA ||
1102	    (parm->support.command2 & ATA_SUPPORT_CFA))
1103		printf("CFA supported\n");
1104
1105	printf("LBA%ssupported         ",
1106		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
1107	if (lbasize)
1108		printf("%d sectors\n", lbasize);
1109	else
1110		printf("\n");
1111
1112	printf("LBA48%ssupported       ",
1113		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
1114	if (lbasize48)
1115		printf("%ju sectors\n", (uintmax_t)lbasize48);
1116	else
1117		printf("\n");
1118
1119	printf("PIO supported         PIO");
1120	switch (ata_max_pmode(parm)) {
1121	case ATA_PIO4:
1122		printf("4");
1123		break;
1124	case ATA_PIO3:
1125		printf("3");
1126		break;
1127	case ATA_PIO2:
1128		printf("2");
1129		break;
1130	case ATA_PIO1:
1131		printf("1");
1132		break;
1133	default:
1134		printf("0");
1135	}
1136	if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0)
1137		printf(" w/o IORDY");
1138	printf("\n");
1139
1140	printf("DMA%ssupported         ",
1141		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
1142	if (parm->capabilities1 & ATA_SUPPORT_DMA) {
1143		if (parm->mwdmamodes & 0xff) {
1144			printf("WDMA");
1145			if (parm->mwdmamodes & 0x04)
1146				printf("2");
1147			else if (parm->mwdmamodes & 0x02)
1148				printf("1");
1149			else if (parm->mwdmamodes & 0x01)
1150				printf("0");
1151			printf(" ");
1152		}
1153		if ((parm->atavalid & ATA_FLAG_88) &&
1154		    (parm->udmamodes & 0xff)) {
1155			printf("UDMA");
1156			if (parm->udmamodes & 0x40)
1157				printf("6");
1158			else if (parm->udmamodes & 0x20)
1159				printf("5");
1160			else if (parm->udmamodes & 0x10)
1161				printf("4");
1162			else if (parm->udmamodes & 0x08)
1163				printf("3");
1164			else if (parm->udmamodes & 0x04)
1165				printf("2");
1166			else if (parm->udmamodes & 0x02)
1167				printf("1");
1168			else if (parm->udmamodes & 0x01)
1169				printf("0");
1170			printf(" ");
1171		}
1172	}
1173	printf("\n");
1174
1175	if (parm->media_rotation_rate == 1) {
1176		printf("media RPM             non-rotating\n");
1177	} else if (parm->media_rotation_rate >= 0x0401 &&
1178	    parm->media_rotation_rate <= 0xFFFE) {
1179		printf("media RPM             %d\n",
1180			parm->media_rotation_rate);
1181	}
1182
1183	printf("\nFeature                      "
1184		"Support  Enable    Value           Vendor\n");
1185	printf("read ahead                     %s	%s\n",
1186		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
1187		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
1188	printf("write cache                    %s	%s\n",
1189		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
1190		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
1191	printf("flush cache                    %s	%s\n",
1192		parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no",
1193		parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no");
1194	printf("overlap                        %s\n",
1195		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no");
1196	printf("Tagged Command Queuing (TCQ)   %s	%s",
1197		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
1198		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no");
1199		if (parm->support.command2 & ATA_SUPPORT_QUEUED) {
1200			printf("	%d tags\n",
1201			    ATA_QUEUE_LEN(parm->queue) + 1);
1202		} else
1203			printf("\n");
1204	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
1205		printf("Native Command Queuing (NCQ)   %s	",
1206			parm->satacapabilities & ATA_SUPPORT_NCQ ?
1207				"yes" : "no");
1208		if (parm->satacapabilities & ATA_SUPPORT_NCQ) {
1209			printf("	%d tags\n",
1210			    ATA_QUEUE_LEN(parm->queue) + 1);
1211		} else
1212			printf("\n");
1213	}
1214	printf("SMART                          %s	%s\n",
1215		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
1216		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
1217	printf("microcode download             %s	%s\n",
1218		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
1219		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
1220	printf("security                       %s	%s\n",
1221		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
1222		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
1223	printf("power management               %s	%s\n",
1224		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
1225		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
1226	printf("advanced power management      %s	%s	%d/0x%02X\n",
1227		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1228		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
1229		parm->apm_value, parm->apm_value);
1230	printf("automatic acoustic management  %s	%s	"
1231		"%d/0x%02X	%d/0x%02X\n",
1232		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1233		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
1234		ATA_ACOUSTIC_CURRENT(parm->acoustic),
1235		ATA_ACOUSTIC_CURRENT(parm->acoustic),
1236		ATA_ACOUSTIC_VENDOR(parm->acoustic),
1237		ATA_ACOUSTIC_VENDOR(parm->acoustic));
1238	printf("media status notification      %s	%s\n",
1239		parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no",
1240		parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no");
1241	printf("power-up in Standby            %s	%s\n",
1242		parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no",
1243		parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no");
1244	printf("write-read-verify              %s	%s	%d/0x%x\n",
1245		parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1246		parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no",
1247		parm->wrv_mode, parm->wrv_mode);
1248	printf("unload                         %s	%s\n",
1249		parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no",
1250		parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no");
1251	printf("free-fall                      %s	%s\n",
1252		parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no",
1253		parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no");
1254	printf("data set management (TRIM)     %s\n",
1255		parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no");
1256}
1257
1258
1259static int
1260ataidentify(struct cam_device *device, int retry_count, int timeout)
1261{
1262	union ccb *ccb;
1263	struct ata_params *ident_buf;
1264	struct ccb_getdev cgd;
1265	u_int i, error = 0;
1266	int16_t *ptr;
1267
1268	if (get_cgd(device, &cgd) != 0) {
1269		warnx("couldn't get CGD");
1270		return(1);
1271	}
1272	ccb = cam_getccb(device);
1273
1274	if (ccb == NULL) {
1275		warnx("couldn't allocate CCB");
1276		return(1);
1277	}
1278
1279	/* cam_getccb cleans up the header, caller has to zero the payload */
1280	bzero(&(&ccb->ccb_h)[1],
1281	      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
1282
1283	ptr = (uint16_t *)malloc(sizeof(struct ata_params));
1284
1285	if (ptr == NULL) {
1286		cam_freeccb(ccb);
1287		warnx("can't malloc memory for identify\n");
1288		return(1);
1289	}
1290	bzero(ptr, sizeof(struct ata_params));
1291
1292	cam_fill_ataio(&ccb->ataio,
1293		      retry_count,
1294		      NULL,
1295		      /*flags*/CAM_DIR_IN,
1296		      MSG_SIMPLE_Q_TAG,
1297		      /*data_ptr*/(u_int8_t *)ptr,
1298		      /*dxfer_len*/sizeof(struct ata_params),
1299		      timeout ? timeout : 30 * 1000);
1300	if (cgd.protocol == PROTO_ATA)
1301		ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
1302	else
1303		ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
1304
1305	/* Disable freezing the device queue */
1306	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1307
1308	if (arglist & CAM_ARG_ERR_RECOVER)
1309		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1310
1311	if (cam_send_ccb(device, ccb) < 0) {
1312		perror("error sending ATA identify");
1313
1314		if (arglist & CAM_ARG_VERBOSE) {
1315			cam_error_print(device, ccb, CAM_ESF_ALL,
1316					CAM_EPF_ALL, stderr);
1317		}
1318
1319		free(ptr);
1320		cam_freeccb(ccb);
1321		return(1);
1322	}
1323
1324	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1325		error = 1;
1326
1327		if (arglist & CAM_ARG_VERBOSE) {
1328			cam_error_print(device, ccb, CAM_ESF_ALL,
1329					CAM_EPF_ALL, stderr);
1330		}
1331	}
1332
1333	cam_freeccb(ccb);
1334
1335	if (error != 0) {
1336		free(ptr);
1337		return(error);
1338	}
1339
1340	for (i = 0; i < sizeof(struct ata_params) / 2; i++)
1341		ptr[i] = le16toh(ptr[i]);
1342	if (arglist & CAM_ARG_VERBOSE) {
1343		fprintf(stdout, "%s%d: Raw identify data:\n",
1344		    device->device_name, device->dev_unit_num);
1345		for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
1346			if ((i % 8) == 0)
1347			    fprintf(stdout, " %3d: ", i);
1348			fprintf(stdout, "%04x ", (uint16_t)ptr[i]);
1349			if ((i % 8) == 7)
1350			    fprintf(stdout, "\n");
1351		}
1352	}
1353	ident_buf = (struct ata_params *)ptr;
1354	if (strncmp(ident_buf->model, "FX", 2) &&
1355	    strncmp(ident_buf->model, "NEC", 3) &&
1356	    strncmp(ident_buf->model, "Pioneer", 7) &&
1357	    strncmp(ident_buf->model, "SHARP", 5)) {
1358		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1359		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1360		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1361		ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1362	}
1363	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1364	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1365	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1366	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1367	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1368	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1369	ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
1370	ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
1371	    sizeof(ident_buf->media_serial));
1372
1373	fprintf(stdout, "%s%d: ", device->device_name,
1374		device->dev_unit_num);
1375	ata_print_ident(ident_buf);
1376	camxferrate(device);
1377	atacapprint(ident_buf);
1378
1379	free(ident_buf);
1380
1381	return(0);
1382}
1383#endif /* MINIMALISTIC */
1384
1385/*
1386 * Parse out a bus, or a bus, target and lun in the following
1387 * format:
1388 * bus
1389 * bus:target
1390 * bus:target:lun
1391 *
1392 * Returns the number of parsed components, or 0.
1393 */
1394static int
1395parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst)
1396{
1397	char *tmpstr;
1398	int convs = 0;
1399
1400	while (isspace(*tstr) && (*tstr != '\0'))
1401		tstr++;
1402
1403	tmpstr = (char *)strtok(tstr, ":");
1404	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1405		*bus = strtol(tmpstr, NULL, 0);
1406		*arglst |= CAM_ARG_BUS;
1407		convs++;
1408		tmpstr = (char *)strtok(NULL, ":");
1409		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1410			*target = strtol(tmpstr, NULL, 0);
1411			*arglst |= CAM_ARG_TARGET;
1412			convs++;
1413			tmpstr = (char *)strtok(NULL, ":");
1414			if ((tmpstr != NULL) && (*tmpstr != '\0')) {
1415				*lun = strtol(tmpstr, NULL, 0);
1416				*arglst |= CAM_ARG_LUN;
1417				convs++;
1418			}
1419		}
1420	}
1421
1422	return convs;
1423}
1424
1425static int
1426dorescan_or_reset(int argc, char **argv, int rescan)
1427{
1428	static const char must[] =
1429		"you must specify \"all\", a bus, or a bus:target:lun to %s";
1430	int rv, error = 0;
1431	int bus = -1, target = -1, lun = -1;
1432	char *tstr;
1433
1434	if (argc < 3) {
1435		warnx(must, rescan? "rescan" : "reset");
1436		return(1);
1437	}
1438
1439	tstr = argv[optind];
1440	while (isspace(*tstr) && (*tstr != '\0'))
1441		tstr++;
1442	if (strncasecmp(tstr, "all", strlen("all")) == 0)
1443		arglist |= CAM_ARG_BUS;
1444	else {
1445		rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1446		if (rv != 1 && rv != 3) {
1447			warnx(must, rescan? "rescan" : "reset");
1448			return(1);
1449		}
1450	}
1451
1452	if ((arglist & CAM_ARG_BUS)
1453	    && (arglist & CAM_ARG_TARGET)
1454	    && (arglist & CAM_ARG_LUN))
1455		error = scanlun_or_reset_dev(bus, target, lun, rescan);
1456	else
1457		error = rescan_or_reset_bus(bus, rescan);
1458
1459	return(error);
1460}
1461
1462static int
1463rescan_or_reset_bus(int bus, int rescan)
1464{
1465	union ccb ccb, matchccb;
1466	int fd, retval;
1467	int bufsize;
1468
1469	retval = 0;
1470
1471	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1472		warnx("error opening transport layer device %s", XPT_DEVICE);
1473		warn("%s", XPT_DEVICE);
1474		return(1);
1475	}
1476
1477	if (bus != -1) {
1478		ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS;
1479		ccb.ccb_h.path_id = bus;
1480		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1481		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1482		ccb.crcn.flags = CAM_FLAG_NONE;
1483
1484		/* run this at a low priority */
1485		ccb.ccb_h.pinfo.priority = 5;
1486
1487		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1488			warn("CAMIOCOMMAND ioctl failed");
1489			close(fd);
1490			return(1);
1491		}
1492
1493		if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1494			fprintf(stdout, "%s of bus %d was successful\n",
1495			    rescan ? "Re-scan" : "Reset", bus);
1496		} else {
1497			fprintf(stdout, "%s of bus %d returned error %#x\n",
1498				rescan ? "Re-scan" : "Reset", bus,
1499				ccb.ccb_h.status & CAM_STATUS_MASK);
1500			retval = 1;
1501		}
1502
1503		close(fd);
1504		return(retval);
1505
1506	}
1507
1508
1509	/*
1510	 * The right way to handle this is to modify the xpt so that it can
1511	 * handle a wildcarded bus in a rescan or reset CCB.  At the moment
1512	 * that isn't implemented, so instead we enumerate the busses and
1513	 * send the rescan or reset to those busses in the case where the
1514	 * given bus is -1 (wildcard).  We don't send a rescan or reset
1515	 * to the xpt bus; sending a rescan to the xpt bus is effectively a
1516	 * no-op, sending a rescan to the xpt bus would result in a status of
1517	 * CAM_REQ_INVALID.
1518	 */
1519	bzero(&(&matchccb.ccb_h)[1],
1520	      sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
1521	matchccb.ccb_h.func_code = XPT_DEV_MATCH;
1522	bufsize = sizeof(struct dev_match_result) * 20;
1523	matchccb.cdm.match_buf_len = bufsize;
1524	matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize);
1525	if (matchccb.cdm.matches == NULL) {
1526		warnx("can't malloc memory for matches");
1527		retval = 1;
1528		goto bailout;
1529	}
1530	matchccb.cdm.num_matches = 0;
1531
1532	matchccb.cdm.num_patterns = 1;
1533	matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
1534
1535	matchccb.cdm.patterns = (struct dev_match_pattern *)malloc(
1536		matchccb.cdm.pattern_buf_len);
1537	if (matchccb.cdm.patterns == NULL) {
1538		warnx("can't malloc memory for patterns");
1539		retval = 1;
1540		goto bailout;
1541	}
1542	matchccb.cdm.patterns[0].type = DEV_MATCH_BUS;
1543	matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY;
1544
1545	do {
1546		unsigned int i;
1547
1548		if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) {
1549			warn("CAMIOCOMMAND ioctl failed");
1550			retval = 1;
1551			goto bailout;
1552		}
1553
1554		if ((matchccb.ccb_h.status != CAM_REQ_CMP)
1555		 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST)
1556		   && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1557			warnx("got CAM error %#x, CDM error %d\n",
1558			      matchccb.ccb_h.status, matchccb.cdm.status);
1559			retval = 1;
1560			goto bailout;
1561		}
1562
1563		for (i = 0; i < matchccb.cdm.num_matches; i++) {
1564			struct bus_match_result *bus_result;
1565
1566			/* This shouldn't happen. */
1567			if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS)
1568				continue;
1569
1570			bus_result = &matchccb.cdm.matches[i].result.bus_result;
1571
1572			/*
1573			 * We don't want to rescan or reset the xpt bus.
1574			 * See above.
1575			 */
1576			if ((int)bus_result->path_id == -1)
1577				continue;
1578
1579			ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS :
1580						       XPT_RESET_BUS;
1581			ccb.ccb_h.path_id = bus_result->path_id;
1582			ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1583			ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1584			ccb.crcn.flags = CAM_FLAG_NONE;
1585
1586			/* run this at a low priority */
1587			ccb.ccb_h.pinfo.priority = 5;
1588
1589			if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1590				warn("CAMIOCOMMAND ioctl failed");
1591				retval = 1;
1592				goto bailout;
1593			}
1594
1595			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){
1596				fprintf(stdout, "%s of bus %d was successful\n",
1597					rescan? "Re-scan" : "Reset",
1598					bus_result->path_id);
1599			} else {
1600				/*
1601				 * Don't bail out just yet, maybe the other
1602				 * rescan or reset commands will complete
1603				 * successfully.
1604				 */
1605				fprintf(stderr, "%s of bus %d returned error "
1606					"%#x\n", rescan? "Re-scan" : "Reset",
1607					bus_result->path_id,
1608					ccb.ccb_h.status & CAM_STATUS_MASK);
1609				retval = 1;
1610			}
1611		}
1612	} while ((matchccb.ccb_h.status == CAM_REQ_CMP)
1613		 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE));
1614
1615bailout:
1616
1617	if (fd != -1)
1618		close(fd);
1619
1620	if (matchccb.cdm.patterns != NULL)
1621		free(matchccb.cdm.patterns);
1622	if (matchccb.cdm.matches != NULL)
1623		free(matchccb.cdm.matches);
1624
1625	return(retval);
1626}
1627
1628static int
1629scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1630{
1631	union ccb ccb;
1632	struct cam_device *device;
1633	int fd;
1634
1635	device = NULL;
1636
1637	if (bus < 0) {
1638		warnx("invalid bus number %d", bus);
1639		return(1);
1640	}
1641
1642	if (target < 0) {
1643		warnx("invalid target number %d", target);
1644		return(1);
1645	}
1646
1647	if (lun < 0) {
1648		warnx("invalid lun number %d", lun);
1649		return(1);
1650	}
1651
1652	fd = -1;
1653
1654	bzero(&ccb, sizeof(union ccb));
1655
1656	if (scan) {
1657		if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1658			warnx("error opening transport layer device %s\n",
1659			    XPT_DEVICE);
1660			warn("%s", XPT_DEVICE);
1661			return(1);
1662		}
1663	} else {
1664		device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1665		if (device == NULL) {
1666			warnx("%s", cam_errbuf);
1667			return(1);
1668		}
1669	}
1670
1671	ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1672	ccb.ccb_h.path_id = bus;
1673	ccb.ccb_h.target_id = target;
1674	ccb.ccb_h.target_lun = lun;
1675	ccb.ccb_h.timeout = 5000;
1676	ccb.crcn.flags = CAM_FLAG_NONE;
1677
1678	/* run this at a low priority */
1679	ccb.ccb_h.pinfo.priority = 5;
1680
1681	if (scan) {
1682		if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1683			warn("CAMIOCOMMAND ioctl failed");
1684			close(fd);
1685			return(1);
1686		}
1687	} else {
1688		if (cam_send_ccb(device, &ccb) < 0) {
1689			warn("error sending XPT_RESET_DEV CCB");
1690			cam_close_device(device);
1691			return(1);
1692		}
1693	}
1694
1695	if (scan)
1696		close(fd);
1697	else
1698		cam_close_device(device);
1699
1700	/*
1701	 * An error code of CAM_BDR_SENT is normal for a BDR request.
1702	 */
1703	if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1704	 || ((!scan)
1705	  && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1706		fprintf(stdout, "%s of %d:%d:%d was successful\n",
1707		    scan? "Re-scan" : "Reset", bus, target, lun);
1708		return(0);
1709	} else {
1710		fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1711		    scan? "Re-scan" : "Reset", bus, target, lun,
1712		    ccb.ccb_h.status & CAM_STATUS_MASK);
1713		return(1);
1714	}
1715}
1716
1717#ifndef MINIMALISTIC
1718static int
1719readdefects(struct cam_device *device, int argc, char **argv,
1720	    char *combinedopt, int retry_count, int timeout)
1721{
1722	union ccb *ccb = NULL;
1723	struct scsi_read_defect_data_10 *rdd_cdb;
1724	u_int8_t *defect_list = NULL;
1725	u_int32_t dlist_length = 65000;
1726	u_int32_t returned_length = 0;
1727	u_int32_t num_returned = 0;
1728	u_int8_t returned_format;
1729	unsigned int i;
1730	int c, error = 0;
1731	int lists_specified = 0;
1732
1733	while ((c = getopt(argc, argv, combinedopt)) != -1) {
1734		switch(c){
1735		case 'f':
1736		{
1737			char *tstr;
1738			tstr = optarg;
1739			while (isspace(*tstr) && (*tstr != '\0'))
1740				tstr++;
1741			if (strcmp(tstr, "block") == 0)
1742				arglist |= CAM_ARG_FORMAT_BLOCK;
1743			else if (strcmp(tstr, "bfi") == 0)
1744				arglist |= CAM_ARG_FORMAT_BFI;
1745			else if (strcmp(tstr, "phys") == 0)
1746				arglist |= CAM_ARG_FORMAT_PHYS;
1747			else {
1748				error = 1;
1749				warnx("invalid defect format %s", tstr);
1750				goto defect_bailout;
1751			}
1752			break;
1753		}
1754		case 'G':
1755			arglist |= CAM_ARG_GLIST;
1756			break;
1757		case 'P':
1758			arglist |= CAM_ARG_PLIST;
1759			break;
1760		default:
1761			break;
1762		}
1763	}
1764
1765	ccb = cam_getccb(device);
1766
1767	/*
1768	 * Hopefully 65000 bytes is enough to hold the defect list.  If it
1769	 * isn't, the disk is probably dead already.  We'd have to go with
1770	 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1771	 * to hold them all.
1772	 */
1773	defect_list = malloc(dlist_length);
1774	if (defect_list == NULL) {
1775		warnx("can't malloc memory for defect list");
1776		error = 1;
1777		goto defect_bailout;
1778	}
1779
1780	rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1781
1782	/*
1783	 * cam_getccb() zeros the CCB header only.  So we need to zero the
1784	 * payload portion of the ccb.
1785	 */
1786	bzero(&(&ccb->ccb_h)[1],
1787	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1788
1789	cam_fill_csio(&ccb->csio,
1790		      /*retries*/ retry_count,
1791		      /*cbfcnp*/ NULL,
1792		      /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1793					      CAM_PASS_ERR_RECOVER : 0),
1794		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
1795		      /*data_ptr*/ defect_list,
1796		      /*dxfer_len*/ dlist_length,
1797		      /*sense_len*/ SSD_FULL_SIZE,
1798		      /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1799		      /*timeout*/ timeout ? timeout : 5000);
1800
1801	rdd_cdb->opcode = READ_DEFECT_DATA_10;
1802	if (arglist & CAM_ARG_FORMAT_BLOCK)
1803		rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1804	else if (arglist & CAM_ARG_FORMAT_BFI)
1805		rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1806	else if (arglist & CAM_ARG_FORMAT_PHYS)
1807		rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1808	else {
1809		error = 1;
1810		warnx("no defect list format specified");
1811		goto defect_bailout;
1812	}
1813	if (arglist & CAM_ARG_PLIST) {
1814		rdd_cdb->format |= SRDD10_PLIST;
1815		lists_specified++;
1816	}
1817
1818	if (arglist & CAM_ARG_GLIST) {
1819		rdd_cdb->format |= SRDD10_GLIST;
1820		lists_specified++;
1821	}
1822
1823	scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1824
1825	/* Disable freezing the device queue */
1826	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1827
1828	if (cam_send_ccb(device, ccb) < 0) {
1829		perror("error reading defect list");
1830
1831		if (arglist & CAM_ARG_VERBOSE) {
1832			cam_error_print(device, ccb, CAM_ESF_ALL,
1833					CAM_EPF_ALL, stderr);
1834		}
1835
1836		error = 1;
1837		goto defect_bailout;
1838	}
1839
1840	returned_length = scsi_2btoul(((struct
1841		scsi_read_defect_data_hdr_10 *)defect_list)->length);
1842
1843	returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1844			defect_list)->format;
1845
1846	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
1847	 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1848	 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
1849		struct scsi_sense_data *sense;
1850		int error_code, sense_key, asc, ascq;
1851
1852		sense = &ccb->csio.sense_data;
1853		scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1854
1855		/*
1856		 * According to the SCSI spec, if the disk doesn't support
1857		 * the requested format, it will generally return a sense
1858		 * key of RECOVERED ERROR, and an additional sense code
1859		 * of "DEFECT LIST NOT FOUND".  So, we check for that, and
1860		 * also check to make sure that the returned length is
1861		 * greater than 0, and then print out whatever format the
1862		 * disk gave us.
1863		 */
1864		if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1865		 && (asc == 0x1c) && (ascq == 0x00)
1866		 && (returned_length > 0)) {
1867			warnx("requested defect format not available");
1868			switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1869			case SRDD10_BLOCK_FORMAT:
1870				warnx("Device returned block format");
1871				break;
1872			case SRDD10_BYTES_FROM_INDEX_FORMAT:
1873				warnx("Device returned bytes from index"
1874				      " format");
1875				break;
1876			case SRDD10_PHYSICAL_SECTOR_FORMAT:
1877				warnx("Device returned physical sector format");
1878				break;
1879			default:
1880				error = 1;
1881				warnx("Device returned unknown defect"
1882				     " data format %#x", returned_format);
1883				goto defect_bailout;
1884				break; /* NOTREACHED */
1885			}
1886		} else {
1887			error = 1;
1888			warnx("Error returned from read defect data command");
1889			if (arglist & CAM_ARG_VERBOSE)
1890				cam_error_print(device, ccb, CAM_ESF_ALL,
1891						CAM_EPF_ALL, stderr);
1892			goto defect_bailout;
1893		}
1894	} else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1895		error = 1;
1896		warnx("Error returned from read defect data command");
1897		if (arglist & CAM_ARG_VERBOSE)
1898			cam_error_print(device, ccb, CAM_ESF_ALL,
1899					CAM_EPF_ALL, stderr);
1900		goto defect_bailout;
1901	}
1902
1903	/*
1904	 * XXX KDM  I should probably clean up the printout format for the
1905	 * disk defects.
1906	 */
1907	switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1908		case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1909		{
1910			struct scsi_defect_desc_phys_sector *dlist;
1911
1912			dlist = (struct scsi_defect_desc_phys_sector *)
1913				(defect_list +
1914				sizeof(struct scsi_read_defect_data_hdr_10));
1915
1916			num_returned = returned_length /
1917				sizeof(struct scsi_defect_desc_phys_sector);
1918
1919			fprintf(stderr, "Got %d defect", num_returned);
1920
1921			if ((lists_specified == 0) || (num_returned == 0)) {
1922				fprintf(stderr, "s.\n");
1923				break;
1924			} else if (num_returned == 1)
1925				fprintf(stderr, ":\n");
1926			else
1927				fprintf(stderr, "s:\n");
1928
1929			for (i = 0; i < num_returned; i++) {
1930				fprintf(stdout, "%d:%d:%d\n",
1931					scsi_3btoul(dlist[i].cylinder),
1932					dlist[i].head,
1933					scsi_4btoul(dlist[i].sector));
1934			}
1935			break;
1936		}
1937		case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1938		{
1939			struct scsi_defect_desc_bytes_from_index *dlist;
1940
1941			dlist = (struct scsi_defect_desc_bytes_from_index *)
1942				(defect_list +
1943				sizeof(struct scsi_read_defect_data_hdr_10));
1944
1945			num_returned = returned_length /
1946			      sizeof(struct scsi_defect_desc_bytes_from_index);
1947
1948			fprintf(stderr, "Got %d defect", num_returned);
1949
1950			if ((lists_specified == 0) || (num_returned == 0)) {
1951				fprintf(stderr, "s.\n");
1952				break;
1953			} else if (num_returned == 1)
1954				fprintf(stderr, ":\n");
1955			else
1956				fprintf(stderr, "s:\n");
1957
1958			for (i = 0; i < num_returned; i++) {
1959				fprintf(stdout, "%d:%d:%d\n",
1960					scsi_3btoul(dlist[i].cylinder),
1961					dlist[i].head,
1962					scsi_4btoul(dlist[i].bytes_from_index));
1963			}
1964			break;
1965		}
1966		case SRDDH10_BLOCK_FORMAT:
1967		{
1968			struct scsi_defect_desc_block *dlist;
1969
1970			dlist = (struct scsi_defect_desc_block *)(defect_list +
1971				sizeof(struct scsi_read_defect_data_hdr_10));
1972
1973			num_returned = returned_length /
1974			      sizeof(struct scsi_defect_desc_block);
1975
1976			fprintf(stderr, "Got %d defect", num_returned);
1977
1978			if ((lists_specified == 0) || (num_returned == 0)) {
1979				fprintf(stderr, "s.\n");
1980				break;
1981			} else if (num_returned == 1)
1982				fprintf(stderr, ":\n");
1983			else
1984				fprintf(stderr, "s:\n");
1985
1986			for (i = 0; i < num_returned; i++)
1987				fprintf(stdout, "%u\n",
1988					scsi_4btoul(dlist[i].address));
1989			break;
1990		}
1991		default:
1992			fprintf(stderr, "Unknown defect format %d\n",
1993				returned_format & SRDDH10_DLIST_FORMAT_MASK);
1994			error = 1;
1995			break;
1996	}
1997defect_bailout:
1998
1999	if (defect_list != NULL)
2000		free(defect_list);
2001
2002	if (ccb != NULL)
2003		cam_freeccb(ccb);
2004
2005	return(error);
2006}
2007#endif /* MINIMALISTIC */
2008
2009#if 0
2010void
2011reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
2012{
2013	union ccb *ccb;
2014
2015	ccb = cam_getccb(device);
2016
2017	cam_freeccb(ccb);
2018}
2019#endif
2020
2021#ifndef MINIMALISTIC
2022void
2023mode_sense(struct cam_device *device, int mode_page, int page_control,
2024	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
2025{
2026	union ccb *ccb;
2027	int retval;
2028
2029	ccb = cam_getccb(device);
2030
2031	if (ccb == NULL)
2032		errx(1, "mode_sense: couldn't allocate CCB");
2033
2034	bzero(&(&ccb->ccb_h)[1],
2035	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2036
2037	scsi_mode_sense(&ccb->csio,
2038			/* retries */ retry_count,
2039			/* cbfcnp */ NULL,
2040			/* tag_action */ MSG_SIMPLE_Q_TAG,
2041			/* dbd */ dbd,
2042			/* page_code */ page_control << 6,
2043			/* page */ mode_page,
2044			/* param_buf */ data,
2045			/* param_len */ datalen,
2046			/* sense_len */ SSD_FULL_SIZE,
2047			/* timeout */ timeout ? timeout : 5000);
2048
2049	if (arglist & CAM_ARG_ERR_RECOVER)
2050		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2051
2052	/* Disable freezing the device queue */
2053	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2054
2055	if (((retval = cam_send_ccb(device, ccb)) < 0)
2056	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2057		if (arglist & CAM_ARG_VERBOSE) {
2058			cam_error_print(device, ccb, CAM_ESF_ALL,
2059					CAM_EPF_ALL, stderr);
2060		}
2061		cam_freeccb(ccb);
2062		cam_close_device(device);
2063		if (retval < 0)
2064			err(1, "error sending mode sense command");
2065		else
2066			errx(1, "error sending mode sense command");
2067	}
2068
2069	cam_freeccb(ccb);
2070}
2071
2072void
2073mode_select(struct cam_device *device, int save_pages, int retry_count,
2074	   int timeout, u_int8_t *data, int datalen)
2075{
2076	union ccb *ccb;
2077	int retval;
2078
2079	ccb = cam_getccb(device);
2080
2081	if (ccb == NULL)
2082		errx(1, "mode_select: couldn't allocate CCB");
2083
2084	bzero(&(&ccb->ccb_h)[1],
2085	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2086
2087	scsi_mode_select(&ccb->csio,
2088			 /* retries */ retry_count,
2089			 /* cbfcnp */ NULL,
2090			 /* tag_action */ MSG_SIMPLE_Q_TAG,
2091			 /* scsi_page_fmt */ 1,
2092			 /* save_pages */ save_pages,
2093			 /* param_buf */ data,
2094			 /* param_len */ datalen,
2095			 /* sense_len */ SSD_FULL_SIZE,
2096			 /* timeout */ timeout ? timeout : 5000);
2097
2098	if (arglist & CAM_ARG_ERR_RECOVER)
2099		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2100
2101	/* Disable freezing the device queue */
2102	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2103
2104	if (((retval = cam_send_ccb(device, ccb)) < 0)
2105	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2106		if (arglist & CAM_ARG_VERBOSE) {
2107			cam_error_print(device, ccb, CAM_ESF_ALL,
2108					CAM_EPF_ALL, stderr);
2109		}
2110		cam_freeccb(ccb);
2111		cam_close_device(device);
2112
2113		if (retval < 0)
2114			err(1, "error sending mode select command");
2115		else
2116			errx(1, "error sending mode select command");
2117
2118	}
2119
2120	cam_freeccb(ccb);
2121}
2122
2123void
2124modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
2125	 int retry_count, int timeout)
2126{
2127	int c, mode_page = -1, page_control = 0;
2128	int binary = 0, list = 0;
2129
2130	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2131		switch(c) {
2132		case 'b':
2133			binary = 1;
2134			break;
2135		case 'd':
2136			arglist |= CAM_ARG_DBD;
2137			break;
2138		case 'e':
2139			arglist |= CAM_ARG_MODE_EDIT;
2140			break;
2141		case 'l':
2142			list = 1;
2143			break;
2144		case 'm':
2145			mode_page = strtol(optarg, NULL, 0);
2146			if (mode_page < 0)
2147				errx(1, "invalid mode page %d", mode_page);
2148			break;
2149		case 'P':
2150			page_control = strtol(optarg, NULL, 0);
2151			if ((page_control < 0) || (page_control > 3))
2152				errx(1, "invalid page control field %d",
2153				     page_control);
2154			arglist |= CAM_ARG_PAGE_CNTL;
2155			break;
2156		default:
2157			break;
2158		}
2159	}
2160
2161	if (mode_page == -1 && list == 0)
2162		errx(1, "you must specify a mode page!");
2163
2164	if (list) {
2165		mode_list(device, page_control, arglist & CAM_ARG_DBD,
2166		    retry_count, timeout);
2167	} else {
2168		mode_edit(device, mode_page, page_control,
2169		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
2170		    retry_count, timeout);
2171	}
2172}
2173
2174static int
2175scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
2176	int retry_count, int timeout)
2177{
2178	union ccb *ccb;
2179	u_int32_t flags = CAM_DIR_NONE;
2180	u_int8_t *data_ptr = NULL;
2181	u_int8_t cdb[20];
2182	u_int8_t atacmd[12];
2183	struct get_hook hook;
2184	int c, data_bytes = 0;
2185	int cdb_len = 0;
2186	int atacmd_len = 0;
2187	int need_res = 0;
2188	char *datastr = NULL, *tstr, *resstr = NULL;
2189	int error = 0;
2190	int fd_data = 0, fd_res = 0;
2191	int retval;
2192
2193	ccb = cam_getccb(device);
2194
2195	if (ccb == NULL) {
2196		warnx("scsicmd: error allocating ccb");
2197		return(1);
2198	}
2199
2200	bzero(&(&ccb->ccb_h)[1],
2201	      sizeof(union ccb) - sizeof(struct ccb_hdr));
2202
2203	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2204		switch(c) {
2205		case 'a':
2206			tstr = optarg;
2207			while (isspace(*tstr) && (*tstr != '\0'))
2208				tstr++;
2209			hook.argc = argc - optind;
2210			hook.argv = argv + optind;
2211			hook.got = 0;
2212			atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr,
2213						    iget, &hook);
2214			/*
2215			 * Increment optind by the number of arguments the
2216			 * encoding routine processed.  After each call to
2217			 * getopt(3), optind points to the argument that
2218			 * getopt should process _next_.  In this case,
2219			 * that means it points to the first command string
2220			 * argument, if there is one.  Once we increment
2221			 * this, it should point to either the next command
2222			 * line argument, or it should be past the end of
2223			 * the list.
2224			 */
2225			optind += hook.got;
2226			break;
2227		case 'c':
2228			tstr = optarg;
2229			while (isspace(*tstr) && (*tstr != '\0'))
2230				tstr++;
2231			hook.argc = argc - optind;
2232			hook.argv = argv + optind;
2233			hook.got = 0;
2234			cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
2235						    iget, &hook);
2236			/*
2237			 * Increment optind by the number of arguments the
2238			 * encoding routine processed.  After each call to
2239			 * getopt(3), optind points to the argument that
2240			 * getopt should process _next_.  In this case,
2241			 * that means it points to the first command string
2242			 * argument, if there is one.  Once we increment
2243			 * this, it should point to either the next command
2244			 * line argument, or it should be past the end of
2245			 * the list.
2246			 */
2247			optind += hook.got;
2248			break;
2249		case 'i':
2250			if (arglist & CAM_ARG_CMD_OUT) {
2251				warnx("command must either be "
2252				      "read or write, not both");
2253				error = 1;
2254				goto scsicmd_bailout;
2255			}
2256			arglist |= CAM_ARG_CMD_IN;
2257			flags = CAM_DIR_IN;
2258			data_bytes = strtol(optarg, NULL, 0);
2259			if (data_bytes <= 0) {
2260				warnx("invalid number of input bytes %d",
2261				      data_bytes);
2262				error = 1;
2263				goto scsicmd_bailout;
2264			}
2265			hook.argc = argc - optind;
2266			hook.argv = argv + optind;
2267			hook.got = 0;
2268			optind++;
2269			datastr = cget(&hook, NULL);
2270			/*
2271			 * If the user supplied "-" instead of a format, he
2272			 * wants the data to be written to stdout.
2273			 */
2274			if ((datastr != NULL)
2275			 && (datastr[0] == '-'))
2276				fd_data = 1;
2277
2278			data_ptr = (u_int8_t *)malloc(data_bytes);
2279			if (data_ptr == NULL) {
2280				warnx("can't malloc memory for data_ptr");
2281				error = 1;
2282				goto scsicmd_bailout;
2283			}
2284			break;
2285		case 'o':
2286			if (arglist & CAM_ARG_CMD_IN) {
2287				warnx("command must either be "
2288				      "read or write, not both");
2289				error = 1;
2290				goto scsicmd_bailout;
2291			}
2292			arglist |= CAM_ARG_CMD_OUT;
2293			flags = CAM_DIR_OUT;
2294			data_bytes = strtol(optarg, NULL, 0);
2295			if (data_bytes <= 0) {
2296				warnx("invalid number of output bytes %d",
2297				      data_bytes);
2298				error = 1;
2299				goto scsicmd_bailout;
2300			}
2301			hook.argc = argc - optind;
2302			hook.argv = argv + optind;
2303			hook.got = 0;
2304			datastr = cget(&hook, NULL);
2305			data_ptr = (u_int8_t *)malloc(data_bytes);
2306			if (data_ptr == NULL) {
2307				warnx("can't malloc memory for data_ptr");
2308				error = 1;
2309				goto scsicmd_bailout;
2310			}
2311			bzero(data_ptr, data_bytes);
2312			/*
2313			 * If the user supplied "-" instead of a format, he
2314			 * wants the data to be read from stdin.
2315			 */
2316			if ((datastr != NULL)
2317			 && (datastr[0] == '-'))
2318				fd_data = 1;
2319			else
2320				buff_encode_visit(data_ptr, data_bytes, datastr,
2321						  iget, &hook);
2322			optind += hook.got;
2323			break;
2324		case 'r':
2325			need_res = 1;
2326			hook.argc = argc - optind;
2327			hook.argv = argv + optind;
2328			hook.got = 0;
2329			resstr = cget(&hook, NULL);
2330			if ((resstr != NULL) && (resstr[0] == '-'))
2331				fd_res = 1;
2332			optind += hook.got;
2333			break;
2334		default:
2335			break;
2336		}
2337	}
2338
2339	/*
2340	 * If fd_data is set, and we're writing to the device, we need to
2341	 * read the data the user wants written from stdin.
2342	 */
2343	if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
2344		ssize_t amt_read;
2345		int amt_to_read = data_bytes;
2346		u_int8_t *buf_ptr = data_ptr;
2347
2348		for (amt_read = 0; amt_to_read > 0;
2349		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
2350			if (amt_read == -1) {
2351				warn("error reading data from stdin");
2352				error = 1;
2353				goto scsicmd_bailout;
2354			}
2355			amt_to_read -= amt_read;
2356			buf_ptr += amt_read;
2357		}
2358	}
2359
2360	if (arglist & CAM_ARG_ERR_RECOVER)
2361		flags |= CAM_PASS_ERR_RECOVER;
2362
2363	/* Disable freezing the device queue */
2364	flags |= CAM_DEV_QFRZDIS;
2365
2366	if (cdb_len) {
2367		/*
2368		 * This is taken from the SCSI-3 draft spec.
2369		 * (T10/1157D revision 0.3)
2370		 * The top 3 bits of an opcode are the group code.
2371		 * The next 5 bits are the command code.
2372		 * Group 0:  six byte commands
2373		 * Group 1:  ten byte commands
2374		 * Group 2:  ten byte commands
2375		 * Group 3:  reserved
2376		 * Group 4:  sixteen byte commands
2377		 * Group 5:  twelve byte commands
2378		 * Group 6:  vendor specific
2379		 * Group 7:  vendor specific
2380		 */
2381		switch((cdb[0] >> 5) & 0x7) {
2382			case 0:
2383				cdb_len = 6;
2384				break;
2385			case 1:
2386			case 2:
2387				cdb_len = 10;
2388				break;
2389			case 3:
2390			case 6:
2391			case 7:
2392			        /* computed by buff_encode_visit */
2393				break;
2394			case 4:
2395				cdb_len = 16;
2396				break;
2397			case 5:
2398				cdb_len = 12;
2399				break;
2400		}
2401
2402		/*
2403		 * We should probably use csio_build_visit or something like that
2404		 * here, but it's easier to encode arguments as you go.  The
2405		 * alternative would be skipping the CDB argument and then encoding
2406		 * it here, since we've got the data buffer argument by now.
2407		 */
2408		bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
2409
2410		cam_fill_csio(&ccb->csio,
2411		      /*retries*/ retry_count,
2412		      /*cbfcnp*/ NULL,
2413		      /*flags*/ flags,
2414		      /*tag_action*/ MSG_SIMPLE_Q_TAG,
2415		      /*data_ptr*/ data_ptr,
2416		      /*dxfer_len*/ data_bytes,
2417		      /*sense_len*/ SSD_FULL_SIZE,
2418		      /*cdb_len*/ cdb_len,
2419		      /*timeout*/ timeout ? timeout : 5000);
2420	} else {
2421		atacmd_len = 12;
2422		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
2423		if (need_res)
2424			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
2425
2426		cam_fill_ataio(&ccb->ataio,
2427		      /*retries*/ retry_count,
2428		      /*cbfcnp*/ NULL,
2429		      /*flags*/ flags,
2430		      /*tag_action*/ 0,
2431		      /*data_ptr*/ data_ptr,
2432		      /*dxfer_len*/ data_bytes,
2433		      /*timeout*/ timeout ? timeout : 5000);
2434	}
2435
2436	if (((retval = cam_send_ccb(device, ccb)) < 0)
2437	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
2438		if (retval < 0)
2439			warn("error sending command");
2440		else
2441			warnx("error sending command");
2442
2443		if (arglist & CAM_ARG_VERBOSE) {
2444			cam_error_print(device, ccb, CAM_ESF_ALL,
2445					CAM_EPF_ALL, stderr);
2446		}
2447
2448		error = 1;
2449		goto scsicmd_bailout;
2450	}
2451
2452	if (atacmd_len && need_res) {
2453		if (fd_res == 0) {
2454			buff_decode_visit(&ccb->ataio.res.status, 11, resstr,
2455					  arg_put, NULL);
2456			fprintf(stdout, "\n");
2457		} else {
2458			fprintf(stdout,
2459			    "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
2460			    ccb->ataio.res.status,
2461			    ccb->ataio.res.error,
2462			    ccb->ataio.res.lba_low,
2463			    ccb->ataio.res.lba_mid,
2464			    ccb->ataio.res.lba_high,
2465			    ccb->ataio.res.device,
2466			    ccb->ataio.res.lba_low_exp,
2467			    ccb->ataio.res.lba_mid_exp,
2468			    ccb->ataio.res.lba_high_exp,
2469			    ccb->ataio.res.sector_count,
2470			    ccb->ataio.res.sector_count_exp);
2471			fflush(stdout);
2472		}
2473	}
2474
2475	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
2476	 && (arglist & CAM_ARG_CMD_IN)
2477	 && (data_bytes > 0)) {
2478		if (fd_data == 0) {
2479			buff_decode_visit(data_ptr, data_bytes, datastr,
2480					  arg_put, NULL);
2481			fprintf(stdout, "\n");
2482		} else {
2483			ssize_t amt_written;
2484			int amt_to_write = data_bytes;
2485			u_int8_t *buf_ptr = data_ptr;
2486
2487			for (amt_written = 0; (amt_to_write > 0) &&
2488			     (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
2489				amt_to_write -= amt_written;
2490				buf_ptr += amt_written;
2491			}
2492			if (amt_written == -1) {
2493				warn("error writing data to stdout");
2494				error = 1;
2495				goto scsicmd_bailout;
2496			} else if ((amt_written == 0)
2497				&& (amt_to_write > 0)) {
2498				warnx("only wrote %u bytes out of %u",
2499				      data_bytes - amt_to_write, data_bytes);
2500			}
2501		}
2502	}
2503
2504scsicmd_bailout:
2505
2506	if ((data_bytes > 0) && (data_ptr != NULL))
2507		free(data_ptr);
2508
2509	cam_freeccb(ccb);
2510
2511	return(error);
2512}
2513
2514static int
2515camdebug(int argc, char **argv, char *combinedopt)
2516{
2517	int c, fd;
2518	int bus = -1, target = -1, lun = -1;
2519	char *tstr, *tmpstr = NULL;
2520	union ccb ccb;
2521	int error = 0;
2522
2523	bzero(&ccb, sizeof(union ccb));
2524
2525	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2526		switch(c) {
2527		case 'I':
2528			arglist |= CAM_ARG_DEBUG_INFO;
2529			ccb.cdbg.flags |= CAM_DEBUG_INFO;
2530			break;
2531		case 'P':
2532			arglist |= CAM_ARG_DEBUG_PERIPH;
2533			ccb.cdbg.flags |= CAM_DEBUG_PERIPH;
2534			break;
2535		case 'S':
2536			arglist |= CAM_ARG_DEBUG_SUBTRACE;
2537			ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
2538			break;
2539		case 'T':
2540			arglist |= CAM_ARG_DEBUG_TRACE;
2541			ccb.cdbg.flags |= CAM_DEBUG_TRACE;
2542			break;
2543		case 'X':
2544			arglist |= CAM_ARG_DEBUG_XPT;
2545			ccb.cdbg.flags |= CAM_DEBUG_XPT;
2546			break;
2547		case 'c':
2548			arglist |= CAM_ARG_DEBUG_CDB;
2549			ccb.cdbg.flags |= CAM_DEBUG_CDB;
2550			break;
2551		default:
2552			break;
2553		}
2554	}
2555
2556	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
2557		warnx("error opening transport layer device %s", XPT_DEVICE);
2558		warn("%s", XPT_DEVICE);
2559		return(1);
2560	}
2561	argc -= optind;
2562	argv += optind;
2563
2564	if (argc <= 0) {
2565		warnx("you must specify \"off\", \"all\" or a bus,");
2566		warnx("bus:target, or bus:target:lun");
2567		close(fd);
2568		return(1);
2569	}
2570
2571	tstr = *argv;
2572
2573	while (isspace(*tstr) && (*tstr != '\0'))
2574		tstr++;
2575
2576	if (strncmp(tstr, "off", 3) == 0) {
2577		ccb.cdbg.flags = CAM_DEBUG_NONE;
2578		arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH|
2579			     CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE|
2580			     CAM_ARG_DEBUG_XPT);
2581	} else if (strncmp(tstr, "all", 3) != 0) {
2582		tmpstr = (char *)strtok(tstr, ":");
2583		if ((tmpstr != NULL) && (*tmpstr != '\0')){
2584			bus = strtol(tmpstr, NULL, 0);
2585			arglist |= CAM_ARG_BUS;
2586			tmpstr = (char *)strtok(NULL, ":");
2587			if ((tmpstr != NULL) && (*tmpstr != '\0')){
2588				target = strtol(tmpstr, NULL, 0);
2589				arglist |= CAM_ARG_TARGET;
2590				tmpstr = (char *)strtok(NULL, ":");
2591				if ((tmpstr != NULL) && (*tmpstr != '\0')){
2592					lun = strtol(tmpstr, NULL, 0);
2593					arglist |= CAM_ARG_LUN;
2594				}
2595			}
2596		} else {
2597			error = 1;
2598			warnx("you must specify \"all\", \"off\", or a bus,");
2599			warnx("bus:target, or bus:target:lun to debug");
2600		}
2601	}
2602
2603	if (error == 0) {
2604
2605		ccb.ccb_h.func_code = XPT_DEBUG;
2606		ccb.ccb_h.path_id = bus;
2607		ccb.ccb_h.target_id = target;
2608		ccb.ccb_h.target_lun = lun;
2609
2610		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
2611			warn("CAMIOCOMMAND ioctl failed");
2612			error = 1;
2613		}
2614
2615		if (error == 0) {
2616			if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
2617			     CAM_FUNC_NOTAVAIL) {
2618				warnx("CAM debugging not available");
2619				warnx("you need to put options CAMDEBUG in"
2620				      " your kernel config file!");
2621				error = 1;
2622			} else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
2623				    CAM_REQ_CMP) {
2624				warnx("XPT_DEBUG CCB failed with status %#x",
2625				      ccb.ccb_h.status);
2626				error = 1;
2627			} else {
2628				if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
2629					fprintf(stderr,
2630						"Debugging turned off\n");
2631				} else {
2632					fprintf(stderr,
2633						"Debugging enabled for "
2634						"%d:%d:%d\n",
2635						bus, target, lun);
2636				}
2637			}
2638		}
2639		close(fd);
2640	}
2641
2642	return(error);
2643}
2644
2645static int
2646tagcontrol(struct cam_device *device, int argc, char **argv,
2647	   char *combinedopt)
2648{
2649	int c;
2650	union ccb *ccb;
2651	int numtags = -1;
2652	int retval = 0;
2653	int quiet = 0;
2654	char pathstr[1024];
2655
2656	ccb = cam_getccb(device);
2657
2658	if (ccb == NULL) {
2659		warnx("tagcontrol: error allocating ccb");
2660		return(1);
2661	}
2662
2663	while ((c = getopt(argc, argv, combinedopt)) != -1) {
2664		switch(c) {
2665		case 'N':
2666			numtags = strtol(optarg, NULL, 0);
2667			if (numtags < 0) {
2668				warnx("tag count %d is < 0", numtags);
2669				retval = 1;
2670				goto tagcontrol_bailout;
2671			}
2672			break;
2673		case 'q':
2674			quiet++;
2675			break;
2676		default:
2677			break;
2678		}
2679	}
2680
2681	cam_path_string(device, pathstr, sizeof(pathstr));
2682
2683	if (numtags >= 0) {
2684		bzero(&(&ccb->ccb_h)[1],
2685		      sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2686		ccb->ccb_h.func_code = XPT_REL_SIMQ;
2687		ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2688		ccb->crs.openings = numtags;
2689
2690
2691		if (cam_send_ccb(device, ccb) < 0) {
2692			perror("error sending XPT_REL_SIMQ CCB");
2693			retval = 1;
2694			goto tagcontrol_bailout;
2695		}
2696
2697		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2698			warnx("XPT_REL_SIMQ CCB failed");
2699			cam_error_print(device, ccb, CAM_ESF_ALL,
2700					CAM_EPF_ALL, stderr);
2701			retval = 1;
2702			goto tagcontrol_bailout;
2703		}
2704
2705
2706		if (quiet == 0)
2707			fprintf(stdout, "%stagged openings now %d\n",
2708				pathstr, ccb->crs.openings);
2709	}
2710
2711	bzero(&(&ccb->ccb_h)[1],
2712	      sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr));
2713
2714	ccb->ccb_h.func_code = XPT_GDEV_STATS;
2715
2716	if (cam_send_ccb(device, ccb) < 0) {
2717		perror("error sending XPT_GDEV_STATS CCB");
2718		retval = 1;
2719		goto tagcontrol_bailout;
2720	}
2721
2722	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2723		warnx("XPT_GDEV_STATS CCB failed");
2724		cam_error_print(device, ccb, CAM_ESF_ALL,
2725				CAM_EPF_ALL, stderr);
2726		retval = 1;
2727		goto tagcontrol_bailout;
2728	}
2729
2730	if (arglist & CAM_ARG_VERBOSE) {
2731		fprintf(stdout, "%s", pathstr);
2732		fprintf(stdout, "dev_openings  %d\n", ccb->cgds.dev_openings);
2733		fprintf(stdout, "%s", pathstr);
2734		fprintf(stdout, "dev_active    %d\n", ccb->cgds.dev_active);
2735		fprintf(stdout, "%s", pathstr);
2736		fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2737		fprintf(stdout, "%s", pathstr);
2738		fprintf(stdout, "devq_queued   %d\n", ccb->cgds.devq_queued);
2739		fprintf(stdout, "%s", pathstr);
2740		fprintf(stdout, "held          %d\n", ccb->cgds.held);
2741		fprintf(stdout, "%s", pathstr);
2742		fprintf(stdout, "mintags       %d\n", ccb->cgds.mintags);
2743		fprintf(stdout, "%s", pathstr);
2744		fprintf(stdout, "maxtags       %d\n", ccb->cgds.maxtags);
2745	} else {
2746		if (quiet == 0) {
2747			fprintf(stdout, "%s", pathstr);
2748			fprintf(stdout, "device openings: ");
2749		}
2750		fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2751			ccb->cgds.dev_active);
2752	}
2753
2754tagcontrol_bailout:
2755
2756	cam_freeccb(ccb);
2757	return(retval);
2758}
2759
2760static void
2761cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2762{
2763	char pathstr[1024];
2764
2765	cam_path_string(device, pathstr, sizeof(pathstr));
2766
2767	if (cts->transport == XPORT_SPI) {
2768		struct ccb_trans_settings_spi *spi =
2769		    &cts->xport_specific.spi;
2770
2771		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) {
2772
2773			fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2774				spi->sync_period);
2775
2776			if (spi->sync_offset != 0) {
2777				u_int freq;
2778
2779				freq = scsi_calc_syncsrate(spi->sync_period);
2780				fprintf(stdout, "%sfrequency: %d.%03dMHz\n",
2781					pathstr, freq / 1000, freq % 1000);
2782			}
2783		}
2784
2785		if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
2786			fprintf(stdout, "%soffset: %d\n", pathstr,
2787			    spi->sync_offset);
2788		}
2789
2790		if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
2791			fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2792				(0x01 << spi->bus_width) * 8);
2793		}
2794
2795		if (spi->valid & CTS_SPI_VALID_DISC) {
2796			fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2797				(spi->flags & CTS_SPI_FLAGS_DISC_ENB) ?
2798				"enabled" : "disabled");
2799		}
2800	}
2801	if (cts->transport == XPORT_ATA) {
2802		struct ccb_trans_settings_ata *ata =
2803		    &cts->xport_specific.ata;
2804
2805		if ((ata->valid & CTS_ATA_VALID_MODE) != 0) {
2806			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2807				ata_mode2string(ata->mode));
2808		}
2809		if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
2810			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2811				ata->atapi);
2812		}
2813		if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
2814			fprintf(stdout, "%sPIO transaction length: %d\n",
2815				pathstr, ata->bytecount);
2816		}
2817	}
2818	if (cts->transport == XPORT_SATA) {
2819		struct ccb_trans_settings_sata *sata =
2820		    &cts->xport_specific.sata;
2821
2822		if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) {
2823			fprintf(stdout, "%sSATA revision: %d.x\n", pathstr,
2824				sata->revision);
2825		}
2826		if ((sata->valid & CTS_SATA_VALID_MODE) != 0) {
2827			fprintf(stdout, "%sATA mode: %s\n", pathstr,
2828				ata_mode2string(sata->mode));
2829		}
2830		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
2831			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
2832				sata->atapi);
2833		}
2834		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
2835			fprintf(stdout, "%sPIO transaction length: %d\n",
2836				pathstr, sata->bytecount);
2837		}
2838		if ((sata->valid & CTS_SATA_VALID_PM) != 0) {
2839			fprintf(stdout, "%sPMP presence: %d\n", pathstr,
2840				sata->pm_present);
2841		}
2842		if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) {
2843			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
2844				sata->tags);
2845		}
2846	}
2847	if (cts->protocol == PROTO_SCSI) {
2848		struct ccb_trans_settings_scsi *scsi=
2849		    &cts->proto_specific.scsi;
2850
2851		if (scsi->valid & CTS_SCSI_VALID_TQ) {
2852			fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2853				(scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ?
2854				"enabled" : "disabled");
2855		}
2856	}
2857
2858}
2859
2860/*
2861 * Get a path inquiry CCB for the specified device.
2862 */
2863static int
2864get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2865{
2866	union ccb *ccb;
2867	int retval = 0;
2868
2869	ccb = cam_getccb(device);
2870	if (ccb == NULL) {
2871		warnx("get_cpi: couldn't allocate CCB");
2872		return(1);
2873	}
2874	bzero(&(&ccb->ccb_h)[1],
2875	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2876	ccb->ccb_h.func_code = XPT_PATH_INQ;
2877	if (cam_send_ccb(device, ccb) < 0) {
2878		warn("get_cpi: error sending Path Inquiry CCB");
2879		if (arglist & CAM_ARG_VERBOSE)
2880			cam_error_print(device, ccb, CAM_ESF_ALL,
2881					CAM_EPF_ALL, stderr);
2882		retval = 1;
2883		goto get_cpi_bailout;
2884	}
2885	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2886		if (arglist & CAM_ARG_VERBOSE)
2887			cam_error_print(device, ccb, CAM_ESF_ALL,
2888					CAM_EPF_ALL, stderr);
2889		retval = 1;
2890		goto get_cpi_bailout;
2891	}
2892	bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2893
2894get_cpi_bailout:
2895	cam_freeccb(ccb);
2896	return(retval);
2897}
2898
2899/*
2900 * Get a get device CCB for the specified device.
2901 */
2902static int
2903get_cgd(struct cam_device *device, struct ccb_getdev *cgd)
2904{
2905	union ccb *ccb;
2906	int retval = 0;
2907
2908	ccb = cam_getccb(device);
2909	if (ccb == NULL) {
2910		warnx("get_cgd: couldn't allocate CCB");
2911		return(1);
2912	}
2913	bzero(&(&ccb->ccb_h)[1],
2914	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2915	ccb->ccb_h.func_code = XPT_GDEV_TYPE;
2916	if (cam_send_ccb(device, ccb) < 0) {
2917		warn("get_cgd: error sending Path Inquiry CCB");
2918		if (arglist & CAM_ARG_VERBOSE)
2919			cam_error_print(device, ccb, CAM_ESF_ALL,
2920					CAM_EPF_ALL, stderr);
2921		retval = 1;
2922		goto get_cgd_bailout;
2923	}
2924	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2925		if (arglist & CAM_ARG_VERBOSE)
2926			cam_error_print(device, ccb, CAM_ESF_ALL,
2927					CAM_EPF_ALL, stderr);
2928		retval = 1;
2929		goto get_cgd_bailout;
2930	}
2931	bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev));
2932
2933get_cgd_bailout:
2934	cam_freeccb(ccb);
2935	return(retval);
2936}
2937
2938static void
2939cpi_print(struct ccb_pathinq *cpi)
2940{
2941	char adapter_str[1024];
2942	int i;
2943
2944	snprintf(adapter_str, sizeof(adapter_str),
2945		 "%s%d:", cpi->dev_name, cpi->unit_number);
2946
2947	fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2948		cpi->version_num);
2949
2950	for (i = 1; i < 0xff; i = i << 1) {
2951		const char *str;
2952
2953		if ((i & cpi->hba_inquiry) == 0)
2954			continue;
2955
2956		fprintf(stdout, "%s supports ", adapter_str);
2957
2958		switch(i) {
2959		case PI_MDP_ABLE:
2960			str = "MDP message";
2961			break;
2962		case PI_WIDE_32:
2963			str = "32 bit wide SCSI";
2964			break;
2965		case PI_WIDE_16:
2966			str = "16 bit wide SCSI";
2967			break;
2968		case PI_SDTR_ABLE:
2969			str = "SDTR message";
2970			break;
2971		case PI_LINKED_CDB:
2972			str = "linked CDBs";
2973			break;
2974		case PI_TAG_ABLE:
2975			str = "tag queue messages";
2976			break;
2977		case PI_SOFT_RST:
2978			str = "soft reset alternative";
2979			break;
2980		case PI_SATAPM:
2981			str = "SATA Port Multiplier";
2982			break;
2983		default:
2984			str = "unknown PI bit set";
2985			break;
2986		}
2987		fprintf(stdout, "%s\n", str);
2988	}
2989
2990	for (i = 1; i < 0xff; i = i << 1) {
2991		const char *str;
2992
2993		if ((i & cpi->hba_misc) == 0)
2994			continue;
2995
2996		fprintf(stdout, "%s ", adapter_str);
2997
2998		switch(i) {
2999		case PIM_SCANHILO:
3000			str = "bus scans from high ID to low ID";
3001			break;
3002		case PIM_NOREMOVE:
3003			str = "removable devices not included in scan";
3004			break;
3005		case PIM_NOINITIATOR:
3006			str = "initiator role not supported";
3007			break;
3008		case PIM_NOBUSRESET:
3009			str = "user has disabled initial BUS RESET or"
3010			      " controller is in target/mixed mode";
3011			break;
3012		case PIM_NO_6_BYTE:
3013			str = "do not send 6-byte commands";
3014			break;
3015		case PIM_SEQSCAN:
3016			str = "scan bus sequentially";
3017			break;
3018		default:
3019			str = "unknown PIM bit set";
3020			break;
3021		}
3022		fprintf(stdout, "%s\n", str);
3023	}
3024
3025	for (i = 1; i < 0xff; i = i << 1) {
3026		const char *str;
3027
3028		if ((i & cpi->target_sprt) == 0)
3029			continue;
3030
3031		fprintf(stdout, "%s supports ", adapter_str);
3032		switch(i) {
3033		case PIT_PROCESSOR:
3034			str = "target mode processor mode";
3035			break;
3036		case PIT_PHASE:
3037			str = "target mode phase cog. mode";
3038			break;
3039		case PIT_DISCONNECT:
3040			str = "disconnects in target mode";
3041			break;
3042		case PIT_TERM_IO:
3043			str = "terminate I/O message in target mode";
3044			break;
3045		case PIT_GRP_6:
3046			str = "group 6 commands in target mode";
3047			break;
3048		case PIT_GRP_7:
3049			str = "group 7 commands in target mode";
3050			break;
3051		default:
3052			str = "unknown PIT bit set";
3053			break;
3054		}
3055
3056		fprintf(stdout, "%s\n", str);
3057	}
3058	fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
3059		cpi->hba_eng_cnt);
3060	fprintf(stdout, "%s maximum target: %d\n", adapter_str,
3061		cpi->max_target);
3062	fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
3063		cpi->max_lun);
3064	fprintf(stdout, "%s highest path ID in subsystem: %d\n",
3065		adapter_str, cpi->hpath_id);
3066	fprintf(stdout, "%s initiator ID: %d\n", adapter_str,
3067		cpi->initiator_id);
3068	fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
3069	fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
3070	fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
3071	fprintf(stdout, "%s base transfer speed: ", adapter_str);
3072	if (cpi->base_transfer_speed > 1000)
3073		fprintf(stdout, "%d.%03dMB/sec\n",
3074			cpi->base_transfer_speed / 1000,
3075			cpi->base_transfer_speed % 1000);
3076	else
3077		fprintf(stdout, "%dKB/sec\n",
3078			(cpi->base_transfer_speed % 1000) * 1000);
3079}
3080
3081static int
3082get_print_cts(struct cam_device *device, int user_settings, int quiet,
3083	      struct ccb_trans_settings *cts)
3084{
3085	int retval;
3086	union ccb *ccb;
3087
3088	retval = 0;
3089	ccb = cam_getccb(device);
3090
3091	if (ccb == NULL) {
3092		warnx("get_print_cts: error allocating ccb");
3093		return(1);
3094	}
3095
3096	bzero(&(&ccb->ccb_h)[1],
3097	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3098
3099	ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
3100
3101	if (user_settings == 0)
3102		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
3103	else
3104		ccb->cts.type = CTS_TYPE_USER_SETTINGS;
3105
3106	if (cam_send_ccb(device, ccb) < 0) {
3107		perror("error sending XPT_GET_TRAN_SETTINGS CCB");
3108		if (arglist & CAM_ARG_VERBOSE)
3109			cam_error_print(device, ccb, CAM_ESF_ALL,
3110					CAM_EPF_ALL, stderr);
3111		retval = 1;
3112		goto get_print_cts_bailout;
3113	}
3114
3115	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3116		warnx("XPT_GET_TRANS_SETTINGS CCB failed");
3117		if (arglist & CAM_ARG_VERBOSE)
3118			cam_error_print(device, ccb, CAM_ESF_ALL,
3119					CAM_EPF_ALL, stderr);
3120		retval = 1;
3121		goto get_print_cts_bailout;
3122	}
3123
3124	if (quiet == 0)
3125		cts_print(device, &ccb->cts);
3126
3127	if (cts != NULL)
3128		bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
3129
3130get_print_cts_bailout:
3131
3132	cam_freeccb(ccb);
3133
3134	return(retval);
3135}
3136
3137static int
3138ratecontrol(struct cam_device *device, int retry_count, int timeout,
3139	    int argc, char **argv, char *combinedopt)
3140{
3141	int c;
3142	union ccb *ccb;
3143	int user_settings = 0;
3144	int retval = 0;
3145	int disc_enable = -1, tag_enable = -1;
3146	int mode = -1;
3147	int offset = -1;
3148	double syncrate = -1;
3149	int bus_width = -1;
3150	int quiet = 0;
3151	int change_settings = 0, send_tur = 0;
3152	struct ccb_pathinq cpi;
3153
3154	ccb = cam_getccb(device);
3155	if (ccb == NULL) {
3156		warnx("ratecontrol: error allocating ccb");
3157		return(1);
3158	}
3159	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3160		switch(c){
3161		case 'a':
3162			send_tur = 1;
3163			break;
3164		case 'c':
3165			user_settings = 0;
3166			break;
3167		case 'D':
3168			if (strncasecmp(optarg, "enable", 6) == 0)
3169				disc_enable = 1;
3170			else if (strncasecmp(optarg, "disable", 7) == 0)
3171				disc_enable = 0;
3172			else {
3173				warnx("-D argument \"%s\" is unknown", optarg);
3174				retval = 1;
3175				goto ratecontrol_bailout;
3176			}
3177			change_settings = 1;
3178			break;
3179		case 'M':
3180			mode = ata_string2mode(optarg);
3181			if (mode < 0) {
3182				warnx("unknown mode '%s'", optarg);
3183				retval = 1;
3184				goto ratecontrol_bailout;
3185			}
3186			change_settings = 1;
3187			break;
3188		case 'O':
3189			offset = strtol(optarg, NULL, 0);
3190			if (offset < 0) {
3191				warnx("offset value %d is < 0", offset);
3192				retval = 1;
3193				goto ratecontrol_bailout;
3194			}
3195			change_settings = 1;
3196			break;
3197		case 'q':
3198			quiet++;
3199			break;
3200		case 'R':
3201			syncrate = atof(optarg);
3202			if (syncrate < 0) {
3203				warnx("sync rate %f is < 0", syncrate);
3204				retval = 1;
3205				goto ratecontrol_bailout;
3206			}
3207			change_settings = 1;
3208			break;
3209		case 'T':
3210			if (strncasecmp(optarg, "enable", 6) == 0)
3211				tag_enable = 1;
3212			else if (strncasecmp(optarg, "disable", 7) == 0)
3213				tag_enable = 0;
3214			else {
3215				warnx("-T argument \"%s\" is unknown", optarg);
3216				retval = 1;
3217				goto ratecontrol_bailout;
3218			}
3219			change_settings = 1;
3220			break;
3221		case 'U':
3222			user_settings = 1;
3223			break;
3224		case 'W':
3225			bus_width = strtol(optarg, NULL, 0);
3226			if (bus_width < 0) {
3227				warnx("bus width %d is < 0", bus_width);
3228				retval = 1;
3229				goto ratecontrol_bailout;
3230			}
3231			change_settings = 1;
3232			break;
3233		default:
3234			break;
3235		}
3236	}
3237	bzero(&(&ccb->ccb_h)[1],
3238	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
3239	/*
3240	 * Grab path inquiry information, so we can determine whether
3241	 * or not the initiator is capable of the things that the user
3242	 * requests.
3243	 */
3244	ccb->ccb_h.func_code = XPT_PATH_INQ;
3245	if (cam_send_ccb(device, ccb) < 0) {
3246		perror("error sending XPT_PATH_INQ CCB");
3247		if (arglist & CAM_ARG_VERBOSE) {
3248			cam_error_print(device, ccb, CAM_ESF_ALL,
3249					CAM_EPF_ALL, stderr);
3250		}
3251		retval = 1;
3252		goto ratecontrol_bailout;
3253	}
3254	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3255		warnx("XPT_PATH_INQ CCB failed");
3256		if (arglist & CAM_ARG_VERBOSE) {
3257			cam_error_print(device, ccb, CAM_ESF_ALL,
3258					CAM_EPF_ALL, stderr);
3259		}
3260		retval = 1;
3261		goto ratecontrol_bailout;
3262	}
3263	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
3264	bzero(&(&ccb->ccb_h)[1],
3265	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
3266	if (quiet == 0) {
3267		fprintf(stdout, "%s parameters:\n",
3268		    user_settings ? "User" : "Current");
3269	}
3270	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
3271	if (retval != 0)
3272		goto ratecontrol_bailout;
3273
3274	if (arglist & CAM_ARG_VERBOSE)
3275		cpi_print(&cpi);
3276
3277	if (change_settings) {
3278		int didsettings = 0;
3279		struct ccb_trans_settings_spi *spi = NULL;
3280		struct ccb_trans_settings_ata *ata = NULL;
3281		struct ccb_trans_settings_sata *sata = NULL;
3282		struct ccb_trans_settings_scsi *scsi = NULL;
3283
3284		if (ccb->cts.transport == XPORT_SPI)
3285			spi = &ccb->cts.xport_specific.spi;
3286		if (ccb->cts.transport == XPORT_ATA)
3287			ata = &ccb->cts.xport_specific.ata;
3288		if (ccb->cts.transport == XPORT_SATA)
3289			sata = &ccb->cts.xport_specific.sata;
3290		if (ccb->cts.protocol == PROTO_SCSI)
3291			scsi = &ccb->cts.proto_specific.scsi;
3292		ccb->cts.xport_specific.valid = 0;
3293		ccb->cts.proto_specific.valid = 0;
3294		if (spi && disc_enable != -1) {
3295			spi->valid |= CTS_SPI_VALID_DISC;
3296			if (disc_enable == 0)
3297				spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
3298			else
3299				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3300		}
3301		if (scsi && tag_enable != -1) {
3302			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
3303				warnx("HBA does not support tagged queueing, "
3304				      "so you cannot modify tag settings");
3305				retval = 1;
3306				goto ratecontrol_bailout;
3307			}
3308			scsi->valid |= CTS_SCSI_VALID_TQ;
3309			if (tag_enable == 0)
3310				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
3311			else
3312				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3313			didsettings++;
3314		}
3315		if (spi && offset != -1) {
3316			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3317				warnx("HBA is not capable of changing offset");
3318				retval = 1;
3319				goto ratecontrol_bailout;
3320			}
3321			spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3322			spi->sync_offset = offset;
3323			didsettings++;
3324		}
3325		if (spi && syncrate != -1) {
3326			int prelim_sync_period;
3327			u_int freq;
3328
3329			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3330				warnx("HBA is not capable of changing "
3331				      "transfer rates");
3332				retval = 1;
3333				goto ratecontrol_bailout;
3334			}
3335			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3336			/*
3337			 * The sync rate the user gives us is in MHz.
3338			 * We need to translate it into KHz for this
3339			 * calculation.
3340			 */
3341			syncrate *= 1000;
3342			/*
3343			 * Next, we calculate a "preliminary" sync period
3344			 * in tenths of a nanosecond.
3345			 */
3346			if (syncrate == 0)
3347				prelim_sync_period = 0;
3348			else
3349				prelim_sync_period = 10000000 / syncrate;
3350			spi->sync_period =
3351				scsi_calc_syncparam(prelim_sync_period);
3352			freq = scsi_calc_syncsrate(spi->sync_period);
3353			didsettings++;
3354		}
3355		if (sata && syncrate != -1) {
3356			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3357				warnx("HBA is not capable of changing "
3358				      "transfer rates");
3359				retval = 1;
3360				goto ratecontrol_bailout;
3361			}
3362			sata->revision = ata_speed2revision(syncrate * 100);
3363			if (sata->revision < 0) {
3364				warnx("Invalid rate %f", syncrate);
3365				retval = 1;
3366				goto ratecontrol_bailout;
3367			}
3368			sata->valid |= CTS_SATA_VALID_REVISION;
3369			didsettings++;
3370		}
3371		if ((ata || sata) && mode != -1) {
3372			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3373				warnx("HBA is not capable of changing "
3374				      "transfer rates");
3375				retval = 1;
3376				goto ratecontrol_bailout;
3377			}
3378			if (ata) {
3379				ata->mode = mode;
3380				ata->valid |= CTS_ATA_VALID_MODE;
3381			} else {
3382				sata->mode = mode;
3383				sata->valid |= CTS_SATA_VALID_MODE;
3384			}
3385			didsettings++;
3386		}
3387		/*
3388		 * The bus_width argument goes like this:
3389		 * 0 == 8 bit
3390		 * 1 == 16 bit
3391		 * 2 == 32 bit
3392		 * Therefore, if you shift the number of bits given on the
3393		 * command line right by 4, you should get the correct
3394		 * number.
3395		 */
3396		if (spi && bus_width != -1) {
3397			/*
3398			 * We might as well validate things here with a
3399			 * decipherable error message, rather than what
3400			 * will probably be an indecipherable error message
3401			 * by the time it gets back to us.
3402			 */
3403			if ((bus_width == 16)
3404			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3405				warnx("HBA does not support 16 bit bus width");
3406				retval = 1;
3407				goto ratecontrol_bailout;
3408			} else if ((bus_width == 32)
3409				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3410				warnx("HBA does not support 32 bit bus width");
3411				retval = 1;
3412				goto ratecontrol_bailout;
3413			} else if ((bus_width != 8)
3414				&& (bus_width != 16)
3415				&& (bus_width != 32)) {
3416				warnx("Invalid bus width %d", bus_width);
3417				retval = 1;
3418				goto ratecontrol_bailout;
3419			}
3420			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3421			spi->bus_width = bus_width >> 4;
3422			didsettings++;
3423		}
3424		if  (didsettings == 0) {
3425			goto ratecontrol_bailout;
3426		}
3427		if  (!user_settings && (ata || sata)) {
3428			warnx("You can modify only user settings for ATA/SATA");
3429			retval = 1;
3430			goto ratecontrol_bailout;
3431		}
3432		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3433		if (cam_send_ccb(device, ccb) < 0) {
3434			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3435			if (arglist & CAM_ARG_VERBOSE) {
3436				cam_error_print(device, ccb, CAM_ESF_ALL,
3437						CAM_EPF_ALL, stderr);
3438			}
3439			retval = 1;
3440			goto ratecontrol_bailout;
3441		}
3442		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3443			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3444			if (arglist & CAM_ARG_VERBOSE) {
3445				cam_error_print(device, ccb, CAM_ESF_ALL,
3446						CAM_EPF_ALL, stderr);
3447			}
3448			retval = 1;
3449			goto ratecontrol_bailout;
3450		}
3451	}
3452	if (send_tur) {
3453		retval = testunitready(device, retry_count, timeout,
3454				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3455		/*
3456		 * If the TUR didn't succeed, just bail.
3457		 */
3458		if (retval != 0) {
3459			if (quiet == 0)
3460				fprintf(stderr, "Test Unit Ready failed\n");
3461			goto ratecontrol_bailout;
3462		}
3463		/*
3464		 * If the user wants things quiet, there's no sense in
3465		 * getting the transfer settings, if we're not going
3466		 * to print them.
3467		 */
3468		if (quiet != 0)
3469			goto ratecontrol_bailout;
3470		fprintf(stdout, "New parameters:\n");
3471		retval = get_print_cts(device, user_settings, 0, NULL);
3472	}
3473
3474ratecontrol_bailout:
3475	cam_freeccb(ccb);
3476	return(retval);
3477}
3478
3479static int
3480scsiformat(struct cam_device *device, int argc, char **argv,
3481	   char *combinedopt, int retry_count, int timeout)
3482{
3483	union ccb *ccb;
3484	int c;
3485	int ycount = 0, quiet = 0;
3486	int error = 0, response = 0, retval = 0;
3487	int use_timeout = 10800 * 1000;
3488	int immediate = 1;
3489	struct format_defect_list_header fh;
3490	u_int8_t *data_ptr = NULL;
3491	u_int32_t dxfer_len = 0;
3492	u_int8_t byte2 = 0;
3493	int num_warnings = 0;
3494	int reportonly = 0;
3495
3496	ccb = cam_getccb(device);
3497
3498	if (ccb == NULL) {
3499		warnx("scsiformat: error allocating ccb");
3500		return(1);
3501	}
3502
3503	bzero(&(&ccb->ccb_h)[1],
3504	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3505
3506	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3507		switch(c) {
3508		case 'q':
3509			quiet++;
3510			break;
3511		case 'r':
3512			reportonly = 1;
3513			break;
3514		case 'w':
3515			immediate = 0;
3516			break;
3517		case 'y':
3518			ycount++;
3519			break;
3520		}
3521	}
3522
3523	if (reportonly)
3524		goto doreport;
3525
3526	if (quiet == 0) {
3527		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3528			"following device:\n");
3529
3530		error = scsidoinquiry(device, argc, argv, combinedopt,
3531				      retry_count, timeout);
3532
3533		if (error != 0) {
3534			warnx("scsiformat: error sending inquiry");
3535			goto scsiformat_bailout;
3536		}
3537	}
3538
3539	if (ycount == 0) {
3540
3541		do {
3542			char str[1024];
3543
3544			fprintf(stdout, "Are you SURE you want to do "
3545				"this? (yes/no) ");
3546
3547			if (fgets(str, sizeof(str), stdin) != NULL) {
3548
3549				if (strncasecmp(str, "yes", 3) == 0)
3550					response = 1;
3551				else if (strncasecmp(str, "no", 2) == 0)
3552					response = -1;
3553				else {
3554					fprintf(stdout, "Please answer"
3555						" \"yes\" or \"no\"\n");
3556				}
3557			}
3558		} while (response == 0);
3559
3560		if (response == -1) {
3561			error = 1;
3562			goto scsiformat_bailout;
3563		}
3564	}
3565
3566	if (timeout != 0)
3567		use_timeout = timeout;
3568
3569	if (quiet == 0) {
3570		fprintf(stdout, "Current format timeout is %d seconds\n",
3571			use_timeout / 1000);
3572	}
3573
3574	/*
3575	 * If the user hasn't disabled questions and didn't specify a
3576	 * timeout on the command line, ask them if they want the current
3577	 * timeout.
3578	 */
3579	if ((ycount == 0)
3580	 && (timeout == 0)) {
3581		char str[1024];
3582		int new_timeout = 0;
3583
3584		fprintf(stdout, "Enter new timeout in seconds or press\n"
3585			"return to keep the current timeout [%d] ",
3586			use_timeout / 1000);
3587
3588		if (fgets(str, sizeof(str), stdin) != NULL) {
3589			if (str[0] != '\0')
3590				new_timeout = atoi(str);
3591		}
3592
3593		if (new_timeout != 0) {
3594			use_timeout = new_timeout * 1000;
3595			fprintf(stdout, "Using new timeout value %d\n",
3596				use_timeout / 1000);
3597		}
3598	}
3599
3600	/*
3601	 * Keep this outside the if block below to silence any unused
3602	 * variable warnings.
3603	 */
3604	bzero(&fh, sizeof(fh));
3605
3606	/*
3607	 * If we're in immediate mode, we've got to include the format
3608	 * header
3609	 */
3610	if (immediate != 0) {
3611		fh.byte2 = FU_DLH_IMMED;
3612		data_ptr = (u_int8_t *)&fh;
3613		dxfer_len = sizeof(fh);
3614		byte2 = FU_FMT_DATA;
3615	} else if (quiet == 0) {
3616		fprintf(stdout, "Formatting...");
3617		fflush(stdout);
3618	}
3619
3620	scsi_format_unit(&ccb->csio,
3621			 /* retries */ retry_count,
3622			 /* cbfcnp */ NULL,
3623			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3624			 /* byte2 */ byte2,
3625			 /* ileave */ 0,
3626			 /* data_ptr */ data_ptr,
3627			 /* dxfer_len */ dxfer_len,
3628			 /* sense_len */ SSD_FULL_SIZE,
3629			 /* timeout */ use_timeout);
3630
3631	/* Disable freezing the device queue */
3632	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3633
3634	if (arglist & CAM_ARG_ERR_RECOVER)
3635		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3636
3637	if (((retval = cam_send_ccb(device, ccb)) < 0)
3638	 || ((immediate == 0)
3639	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3640		const char errstr[] = "error sending format command";
3641
3642		if (retval < 0)
3643			warn(errstr);
3644		else
3645			warnx(errstr);
3646
3647		if (arglist & CAM_ARG_VERBOSE) {
3648			cam_error_print(device, ccb, CAM_ESF_ALL,
3649					CAM_EPF_ALL, stderr);
3650		}
3651		error = 1;
3652		goto scsiformat_bailout;
3653	}
3654
3655	/*
3656	 * If we ran in non-immediate mode, we already checked for errors
3657	 * above and printed out any necessary information.  If we're in
3658	 * immediate mode, we need to loop through and get status
3659	 * information periodically.
3660	 */
3661	if (immediate == 0) {
3662		if (quiet == 0) {
3663			fprintf(stdout, "Format Complete\n");
3664		}
3665		goto scsiformat_bailout;
3666	}
3667
3668doreport:
3669	do {
3670		cam_status status;
3671
3672		bzero(&(&ccb->ccb_h)[1],
3673		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3674
3675		/*
3676		 * There's really no need to do error recovery or
3677		 * retries here, since we're just going to sit in a
3678		 * loop and wait for the device to finish formatting.
3679		 */
3680		scsi_test_unit_ready(&ccb->csio,
3681				     /* retries */ 0,
3682				     /* cbfcnp */ NULL,
3683				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3684				     /* sense_len */ SSD_FULL_SIZE,
3685				     /* timeout */ 5000);
3686
3687		/* Disable freezing the device queue */
3688		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3689
3690		retval = cam_send_ccb(device, ccb);
3691
3692		/*
3693		 * If we get an error from the ioctl, bail out.  SCSI
3694		 * errors are expected.
3695		 */
3696		if (retval < 0) {
3697			warn("error sending CAMIOCOMMAND ioctl");
3698			if (arglist & CAM_ARG_VERBOSE) {
3699				cam_error_print(device, ccb, CAM_ESF_ALL,
3700						CAM_EPF_ALL, stderr);
3701			}
3702			error = 1;
3703			goto scsiformat_bailout;
3704		}
3705
3706		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3707
3708		if ((status != CAM_REQ_CMP)
3709		 && (status == CAM_SCSI_STATUS_ERROR)
3710		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3711			struct scsi_sense_data *sense;
3712			int error_code, sense_key, asc, ascq;
3713
3714			sense = &ccb->csio.sense_data;
3715			scsi_extract_sense(sense, &error_code, &sense_key,
3716					   &asc, &ascq);
3717
3718			/*
3719			 * According to the SCSI-2 and SCSI-3 specs, a
3720			 * drive that is in the middle of a format should
3721			 * return NOT READY with an ASC of "logical unit
3722			 * not ready, format in progress".  The sense key
3723			 * specific bytes will then be a progress indicator.
3724			 */
3725			if ((sense_key == SSD_KEY_NOT_READY)
3726			 && (asc == 0x04) && (ascq == 0x04)) {
3727				if ((sense->extra_len >= 10)
3728				 && ((sense->sense_key_spec[0] &
3729				      SSD_SCS_VALID) != 0)
3730				 && (quiet == 0)) {
3731					int val;
3732					u_int64_t percentage;
3733
3734					val = scsi_2btoul(
3735						&sense->sense_key_spec[1]);
3736					percentage = 10000 * val;
3737
3738					fprintf(stdout,
3739						"\rFormatting:  %ju.%02u %% "
3740						"(%d/%d) done",
3741						(uintmax_t)(percentage /
3742						(0x10000 * 100)),
3743						(unsigned)((percentage /
3744						0x10000) % 100),
3745						val, 0x10000);
3746					fflush(stdout);
3747				} else if ((quiet == 0)
3748					&& (++num_warnings <= 1)) {
3749					warnx("Unexpected SCSI Sense Key "
3750					      "Specific value returned "
3751					      "during format:");
3752					scsi_sense_print(device, &ccb->csio,
3753							 stderr);
3754					warnx("Unable to print status "
3755					      "information, but format will "
3756					      "proceed.");
3757					warnx("will exit when format is "
3758					      "complete");
3759				}
3760				sleep(1);
3761			} else {
3762				warnx("Unexpected SCSI error during format");
3763				cam_error_print(device, ccb, CAM_ESF_ALL,
3764						CAM_EPF_ALL, stderr);
3765				error = 1;
3766				goto scsiformat_bailout;
3767			}
3768
3769		} else if (status != CAM_REQ_CMP) {
3770			warnx("Unexpected CAM status %#x", status);
3771			if (arglist & CAM_ARG_VERBOSE)
3772				cam_error_print(device, ccb, CAM_ESF_ALL,
3773						CAM_EPF_ALL, stderr);
3774			error = 1;
3775			goto scsiformat_bailout;
3776		}
3777
3778	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3779
3780	if (quiet == 0)
3781		fprintf(stdout, "\nFormat Complete\n");
3782
3783scsiformat_bailout:
3784
3785	cam_freeccb(ccb);
3786
3787	return(error);
3788}
3789
3790static int
3791scsireportluns(struct cam_device *device, int argc, char **argv,
3792	       char *combinedopt, int retry_count, int timeout)
3793{
3794	union ccb *ccb;
3795	int c, countonly, lunsonly;
3796	struct scsi_report_luns_data *lundata;
3797	int alloc_len;
3798	uint8_t report_type;
3799	uint32_t list_len, i, j;
3800	int retval;
3801
3802	retval = 0;
3803	lundata = NULL;
3804	report_type = RPL_REPORT_DEFAULT;
3805	ccb = cam_getccb(device);
3806
3807	if (ccb == NULL) {
3808		warnx("%s: error allocating ccb", __func__);
3809		return (1);
3810	}
3811
3812	bzero(&(&ccb->ccb_h)[1],
3813	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3814
3815	countonly = 0;
3816	lunsonly = 0;
3817
3818	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3819		switch (c) {
3820		case 'c':
3821			countonly++;
3822			break;
3823		case 'l':
3824			lunsonly++;
3825			break;
3826		case 'r':
3827			if (strcasecmp(optarg, "default") == 0)
3828				report_type = RPL_REPORT_DEFAULT;
3829			else if (strcasecmp(optarg, "wellknown") == 0)
3830				report_type = RPL_REPORT_WELLKNOWN;
3831			else if (strcasecmp(optarg, "all") == 0)
3832				report_type = RPL_REPORT_ALL;
3833			else {
3834				warnx("%s: invalid report type \"%s\"",
3835				      __func__, optarg);
3836				retval = 1;
3837				goto bailout;
3838			}
3839			break;
3840		default:
3841			break;
3842		}
3843	}
3844
3845	if ((countonly != 0)
3846	 && (lunsonly != 0)) {
3847		warnx("%s: you can only specify one of -c or -l", __func__);
3848		retval = 1;
3849		goto bailout;
3850	}
3851	/*
3852	 * According to SPC-4, the allocation length must be at least 16
3853	 * bytes -- enough for the header and one LUN.
3854	 */
3855	alloc_len = sizeof(*lundata) + 8;
3856
3857retry:
3858
3859	lundata = malloc(alloc_len);
3860
3861	if (lundata == NULL) {
3862		warn("%s: error mallocing %d bytes", __func__, alloc_len);
3863		retval = 1;
3864		goto bailout;
3865	}
3866
3867	scsi_report_luns(&ccb->csio,
3868			 /*retries*/ retry_count,
3869			 /*cbfcnp*/ NULL,
3870			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3871			 /*select_report*/ report_type,
3872			 /*rpl_buf*/ lundata,
3873			 /*alloc_len*/ alloc_len,
3874			 /*sense_len*/ SSD_FULL_SIZE,
3875			 /*timeout*/ timeout ? timeout : 5000);
3876
3877	/* Disable freezing the device queue */
3878	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3879
3880	if (arglist & CAM_ARG_ERR_RECOVER)
3881		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3882
3883	if (cam_send_ccb(device, ccb) < 0) {
3884		warn("error sending REPORT LUNS command");
3885
3886		if (arglist & CAM_ARG_VERBOSE)
3887			cam_error_print(device, ccb, CAM_ESF_ALL,
3888					CAM_EPF_ALL, stderr);
3889
3890		retval = 1;
3891		goto bailout;
3892	}
3893
3894	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3895		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3896		retval = 1;
3897		goto bailout;
3898	}
3899
3900
3901	list_len = scsi_4btoul(lundata->length);
3902
3903	/*
3904	 * If we need to list the LUNs, and our allocation
3905	 * length was too short, reallocate and retry.
3906	 */
3907	if ((countonly == 0)
3908	 && (list_len > (alloc_len - sizeof(*lundata)))) {
3909		alloc_len = list_len + sizeof(*lundata);
3910		free(lundata);
3911		goto retry;
3912	}
3913
3914	if (lunsonly == 0)
3915		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3916			((list_len / 8) > 1) ? "s" : "");
3917
3918	if (countonly != 0)
3919		goto bailout;
3920
3921	for (i = 0; i < (list_len / 8); i++) {
3922		int no_more;
3923
3924		no_more = 0;
3925		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3926			if (j != 0)
3927				fprintf(stdout, ",");
3928			switch (lundata->luns[i].lundata[j] &
3929				RPL_LUNDATA_ATYP_MASK) {
3930			case RPL_LUNDATA_ATYP_PERIPH:
3931				if ((lundata->luns[i].lundata[j] &
3932				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
3933					fprintf(stdout, "%d:",
3934						lundata->luns[i].lundata[j] &
3935						RPL_LUNDATA_PERIPH_BUS_MASK);
3936				else if ((j == 0)
3937				      && ((lundata->luns[i].lundata[j+2] &
3938					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
3939					no_more = 1;
3940
3941				fprintf(stdout, "%d",
3942					lundata->luns[i].lundata[j+1]);
3943				break;
3944			case RPL_LUNDATA_ATYP_FLAT: {
3945				uint8_t tmplun[2];
3946				tmplun[0] = lundata->luns[i].lundata[j] &
3947					RPL_LUNDATA_FLAT_LUN_MASK;
3948				tmplun[1] = lundata->luns[i].lundata[j+1];
3949
3950				fprintf(stdout, "%d", scsi_2btoul(tmplun));
3951				no_more = 1;
3952				break;
3953			}
3954			case RPL_LUNDATA_ATYP_LUN:
3955				fprintf(stdout, "%d:%d:%d",
3956					(lundata->luns[i].lundata[j+1] &
3957					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
3958					lundata->luns[i].lundata[j] &
3959					RPL_LUNDATA_LUN_TARG_MASK,
3960					lundata->luns[i].lundata[j+1] &
3961					RPL_LUNDATA_LUN_LUN_MASK);
3962				break;
3963			case RPL_LUNDATA_ATYP_EXTLUN: {
3964				int field_len, field_len_code, eam_code;
3965
3966				eam_code = lundata->luns[i].lundata[j] &
3967					RPL_LUNDATA_EXT_EAM_MASK;
3968				field_len_code = (lundata->luns[i].lundata[j] &
3969					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
3970				field_len = field_len_code * 2;
3971
3972				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
3973				 && (field_len_code == 0x00)) {
3974					fprintf(stdout, "%d",
3975						lundata->luns[i].lundata[j+1]);
3976				} else if ((eam_code ==
3977					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
3978					&& (field_len_code == 0x03)) {
3979					uint8_t tmp_lun[8];
3980
3981					/*
3982					 * This format takes up all 8 bytes.
3983					 * If we aren't starting at offset 0,
3984					 * that's a bug.
3985					 */
3986					if (j != 0) {
3987						fprintf(stdout, "Invalid "
3988							"offset %d for "
3989							"Extended LUN not "
3990							"specified format", j);
3991						no_more = 1;
3992						break;
3993					}
3994					bzero(tmp_lun, sizeof(tmp_lun));
3995					bcopy(&lundata->luns[i].lundata[j+1],
3996					      &tmp_lun[1], sizeof(tmp_lun) - 1);
3997					fprintf(stdout, "%#jx",
3998					       (intmax_t)scsi_8btou64(tmp_lun));
3999					no_more = 1;
4000				} else {
4001					fprintf(stderr, "Unknown Extended LUN"
4002						"Address method %#x, length "
4003						"code %#x", eam_code,
4004						field_len_code);
4005					no_more = 1;
4006				}
4007				break;
4008			}
4009			default:
4010				fprintf(stderr, "Unknown LUN address method "
4011					"%#x\n", lundata->luns[i].lundata[0] &
4012					RPL_LUNDATA_ATYP_MASK);
4013				break;
4014			}
4015			/*
4016			 * For the flat addressing method, there are no
4017			 * other levels after it.
4018			 */
4019			if (no_more != 0)
4020				break;
4021		}
4022		fprintf(stdout, "\n");
4023	}
4024
4025bailout:
4026
4027	cam_freeccb(ccb);
4028
4029	free(lundata);
4030
4031	return (retval);
4032}
4033
4034static int
4035scsireadcapacity(struct cam_device *device, int argc, char **argv,
4036		 char *combinedopt, int retry_count, int timeout)
4037{
4038	union ccb *ccb;
4039	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4040	struct scsi_read_capacity_data rcap;
4041	struct scsi_read_capacity_data_long rcaplong;
4042	uint64_t maxsector;
4043	uint32_t block_len;
4044	int retval;
4045	int c;
4046
4047	blocksizeonly = 0;
4048	humanize = 0;
4049	numblocks = 0;
4050	quiet = 0;
4051	sizeonly = 0;
4052	baseten = 0;
4053	retval = 0;
4054
4055	ccb = cam_getccb(device);
4056
4057	if (ccb == NULL) {
4058		warnx("%s: error allocating ccb", __func__);
4059		return (1);
4060	}
4061
4062	bzero(&(&ccb->ccb_h)[1],
4063	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4064
4065	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4066		switch (c) {
4067		case 'b':
4068			blocksizeonly++;
4069			break;
4070		case 'h':
4071			humanize++;
4072			baseten = 0;
4073			break;
4074		case 'H':
4075			humanize++;
4076			baseten++;
4077			break;
4078		case 'N':
4079			numblocks++;
4080			break;
4081		case 'q':
4082			quiet++;
4083			break;
4084		case 's':
4085			sizeonly++;
4086			break;
4087		default:
4088			break;
4089		}
4090	}
4091
4092	if ((blocksizeonly != 0)
4093	 && (numblocks != 0)) {
4094		warnx("%s: you can only specify one of -b or -N", __func__);
4095		retval = 1;
4096		goto bailout;
4097	}
4098
4099	if ((blocksizeonly != 0)
4100	 && (sizeonly != 0)) {
4101		warnx("%s: you can only specify one of -b or -s", __func__);
4102		retval = 1;
4103		goto bailout;
4104	}
4105
4106	if ((humanize != 0)
4107	 && (quiet != 0)) {
4108		warnx("%s: you can only specify one of -h/-H or -q", __func__);
4109		retval = 1;
4110		goto bailout;
4111	}
4112
4113	if ((humanize != 0)
4114	 && (blocksizeonly != 0)) {
4115		warnx("%s: you can only specify one of -h/-H or -b", __func__);
4116		retval = 1;
4117		goto bailout;
4118	}
4119
4120	scsi_read_capacity(&ccb->csio,
4121			   /*retries*/ retry_count,
4122			   /*cbfcnp*/ NULL,
4123			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
4124			   &rcap,
4125			   SSD_FULL_SIZE,
4126			   /*timeout*/ timeout ? timeout : 5000);
4127
4128	/* Disable freezing the device queue */
4129	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4130
4131	if (arglist & CAM_ARG_ERR_RECOVER)
4132		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4133
4134	if (cam_send_ccb(device, ccb) < 0) {
4135		warn("error sending READ CAPACITY command");
4136
4137		if (arglist & CAM_ARG_VERBOSE)
4138			cam_error_print(device, ccb, CAM_ESF_ALL,
4139					CAM_EPF_ALL, stderr);
4140
4141		retval = 1;
4142		goto bailout;
4143	}
4144
4145	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4146		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4147		retval = 1;
4148		goto bailout;
4149	}
4150
4151	maxsector = scsi_4btoul(rcap.addr);
4152	block_len = scsi_4btoul(rcap.length);
4153
4154	/*
4155	 * A last block of 2^32-1 means that the true capacity is over 2TB,
4156	 * and we need to issue the long READ CAPACITY to get the real
4157	 * capacity.  Otherwise, we're all set.
4158	 */
4159	if (maxsector != 0xffffffff)
4160		goto do_print;
4161
4162	scsi_read_capacity_16(&ccb->csio,
4163			      /*retries*/ retry_count,
4164			      /*cbfcnp*/ NULL,
4165			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4166			      /*lba*/ 0,
4167			      /*reladdr*/ 0,
4168			      /*pmi*/ 0,
4169			      &rcaplong,
4170			      /*sense_len*/ SSD_FULL_SIZE,
4171			      /*timeout*/ timeout ? timeout : 5000);
4172
4173	/* Disable freezing the device queue */
4174	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4175
4176	if (arglist & CAM_ARG_ERR_RECOVER)
4177		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4178
4179	if (cam_send_ccb(device, ccb) < 0) {
4180		warn("error sending READ CAPACITY (16) command");
4181
4182		if (arglist & CAM_ARG_VERBOSE)
4183			cam_error_print(device, ccb, CAM_ESF_ALL,
4184					CAM_EPF_ALL, stderr);
4185
4186		retval = 1;
4187		goto bailout;
4188	}
4189
4190	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4191		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4192		retval = 1;
4193		goto bailout;
4194	}
4195
4196	maxsector = scsi_8btou64(rcaplong.addr);
4197	block_len = scsi_4btoul(rcaplong.length);
4198
4199do_print:
4200	if (blocksizeonly == 0) {
4201		/*
4202		 * Humanize implies !quiet, and also implies numblocks.
4203		 */
4204		if (humanize != 0) {
4205			char tmpstr[6];
4206			int64_t tmpbytes;
4207			int ret;
4208
4209			tmpbytes = (maxsector + 1) * block_len;
4210			ret = humanize_number(tmpstr, sizeof(tmpstr),
4211					      tmpbytes, "", HN_AUTOSCALE,
4212					      HN_B | HN_DECIMAL |
4213					      ((baseten != 0) ?
4214					      HN_DIVISOR_1000 : 0));
4215			if (ret == -1) {
4216				warnx("%s: humanize_number failed!", __func__);
4217				retval = 1;
4218				goto bailout;
4219			}
4220			fprintf(stdout, "Device Size: %s%s", tmpstr,
4221				(sizeonly == 0) ?  ", " : "\n");
4222		} else if (numblocks != 0) {
4223			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4224				"Blocks: " : "", (uintmax_t)maxsector + 1,
4225				(sizeonly == 0) ? ", " : "\n");
4226		} else {
4227			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4228				"Last Block: " : "", (uintmax_t)maxsector,
4229				(sizeonly == 0) ? ", " : "\n");
4230		}
4231	}
4232	if (sizeonly == 0)
4233		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4234			"Block Length: " : "", block_len, (quiet == 0) ?
4235			" bytes" : "");
4236bailout:
4237	cam_freeccb(ccb);
4238
4239	return (retval);
4240}
4241
4242static int
4243atapm(struct cam_device *device, int argc, char **argv,
4244		 char *combinedopt, int retry_count, int timeout)
4245{
4246	union ccb *ccb;
4247	int retval = 0;
4248	int t = -1;
4249	int c;
4250	u_char cmd, sc;
4251
4252	ccb = cam_getccb(device);
4253
4254	if (ccb == NULL) {
4255		warnx("%s: error allocating ccb", __func__);
4256		return (1);
4257	}
4258
4259	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4260		switch (c) {
4261		case 't':
4262			t = atoi(optarg);
4263			break;
4264		default:
4265			break;
4266		}
4267	}
4268	if (strcmp(argv[1], "idle") == 0) {
4269		if (t == -1)
4270			cmd = ATA_IDLE_IMMEDIATE;
4271		else
4272			cmd = ATA_IDLE_CMD;
4273	} else if (strcmp(argv[1], "standby") == 0) {
4274		if (t == -1)
4275			cmd = ATA_STANDBY_IMMEDIATE;
4276		else
4277			cmd = ATA_STANDBY_CMD;
4278	} else {
4279		cmd = ATA_SLEEP;
4280		t = -1;
4281	}
4282	if (t < 0)
4283		sc = 0;
4284	else if (t <= (240 * 5))
4285		sc = t / 5;
4286	else if (t <= (11 * 30 * 60))
4287		sc = t / (30 * 60) + 241;
4288	else
4289		sc = 253;
4290	cam_fill_ataio(&ccb->ataio,
4291		      retry_count,
4292		      NULL,
4293		      /*flags*/CAM_DIR_NONE,
4294		      MSG_SIMPLE_Q_TAG,
4295		      /*data_ptr*/NULL,
4296		      /*dxfer_len*/0,
4297		      timeout ? timeout : 30 * 1000);
4298	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
4299
4300	/* Disable freezing the device queue */
4301	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4302
4303	if (arglist & CAM_ARG_ERR_RECOVER)
4304		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4305
4306	if (cam_send_ccb(device, ccb) < 0) {
4307		warn("error sending command");
4308
4309		if (arglist & CAM_ARG_VERBOSE)
4310			cam_error_print(device, ccb, CAM_ESF_ALL,
4311					CAM_EPF_ALL, stderr);
4312
4313		retval = 1;
4314		goto bailout;
4315	}
4316
4317	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4318		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4319		retval = 1;
4320		goto bailout;
4321	}
4322bailout:
4323	cam_freeccb(ccb);
4324	return (retval);
4325}
4326
4327#endif /* MINIMALISTIC */
4328
4329void
4330usage(int verbose)
4331{
4332	fprintf(verbose ? stdout : stderr,
4333"usage:  camcontrol <command>  [device id][generic args][command args]\n"
4334"        camcontrol devlist    [-v]\n"
4335#ifndef MINIMALISTIC
4336"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
4337"        camcontrol tur        [dev_id][generic args]\n"
4338"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
4339"        camcontrol identify   [dev_id][generic args] [-v]\n"
4340"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
4341"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
4342"                              [-q] [-s]\n"
4343"        camcontrol start      [dev_id][generic args]\n"
4344"        camcontrol stop       [dev_id][generic args]\n"
4345"        camcontrol load       [dev_id][generic args]\n"
4346"        camcontrol eject      [dev_id][generic args]\n"
4347#endif /* MINIMALISTIC */
4348"        camcontrol rescan     <all | bus[:target:lun]>\n"
4349"        camcontrol reset      <all | bus[:target:lun]>\n"
4350#ifndef MINIMALISTIC
4351"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
4352"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
4353"                              [-P pagectl][-e | -b][-d]\n"
4354"        camcontrol cmd        [dev_id][generic args]\n"
4355"                              <-a cmd [args] | -c cmd [args]>\n"
4356"                              [-i len fmt|-o len fmt [args]] [-r fmt]\n"
4357"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
4358"                              <all|bus[:target[:lun]]|off>\n"
4359"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
4360"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
4361"                              [-D <enable|disable>][-M mode][-O offset]\n"
4362"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
4363"                              [-U][-W bus_width]\n"
4364"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
4365"        camcontrol idle       [dev_id][generic args][-t time]\n"
4366"        camcontrol standby    [dev_id][generic args][-t time]\n"
4367"        camcontrol sleep      [dev_id][generic args]\n"
4368#endif /* MINIMALISTIC */
4369"        camcontrol help\n");
4370	if (!verbose)
4371		return;
4372#ifndef MINIMALISTIC
4373	fprintf(stdout,
4374"Specify one of the following options:\n"
4375"devlist     list all CAM devices\n"
4376"periphlist  list all CAM peripheral drivers attached to a device\n"
4377"tur         send a test unit ready to the named device\n"
4378"inquiry     send a SCSI inquiry command to the named device\n"
4379"identify    send a ATA identify command to the named device\n"
4380"reportluns  send a SCSI report luns command to the device\n"
4381"readcap     send a SCSI read capacity command to the device\n"
4382"start       send a Start Unit command to the device\n"
4383"stop        send a Stop Unit command to the device\n"
4384"load        send a Start Unit command to the device with the load bit set\n"
4385"eject       send a Stop Unit command to the device with the eject bit set\n"
4386"rescan      rescan all busses, the given bus, or bus:target:lun\n"
4387"reset       reset all busses, the given bus, or bus:target:lun\n"
4388"defects     read the defect list of the specified device\n"
4389"modepage    display or edit (-e) the given mode page\n"
4390"cmd         send the given scsi command, may need -i or -o as well\n"
4391"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
4392"tags        report or set the number of transaction slots for a device\n"
4393"negotiate   report or set device negotiation parameters\n"
4394"format      send the SCSI FORMAT UNIT command to the named device\n"
4395"idle        send the ATA IDLE command to the named device\n"
4396"standby     send the ATA STANDBY command to the named device\n"
4397"sleep       send the ATA SLEEP command to the named device\n"
4398"help        this message\n"
4399"Device Identifiers:\n"
4400"bus:target        specify the bus and target, lun defaults to 0\n"
4401"bus:target:lun    specify the bus, target and lun\n"
4402"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
4403"Generic arguments:\n"
4404"-v                be verbose, print out sense information\n"
4405"-t timeout        command timeout in seconds, overrides default timeout\n"
4406"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
4407"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
4408"-E                have the kernel attempt to perform SCSI error recovery\n"
4409"-C count          specify the SCSI command retry count (needs -E to work)\n"
4410"modepage arguments:\n"
4411"-l                list all available mode pages\n"
4412"-m page           specify the mode page to view or edit\n"
4413"-e                edit the specified mode page\n"
4414"-b                force view to binary mode\n"
4415"-d                disable block descriptors for mode sense\n"
4416"-P pgctl          page control field 0-3\n"
4417"defects arguments:\n"
4418"-f format         specify defect list format (block, bfi or phys)\n"
4419"-G                get the grown defect list\n"
4420"-P                get the permanant defect list\n"
4421"inquiry arguments:\n"
4422"-D                get the standard inquiry data\n"
4423"-S                get the serial number\n"
4424"-R                get the transfer rate, etc.\n"
4425"reportluns arguments:\n"
4426"-c                only report a count of available LUNs\n"
4427"-l                only print out luns, and not a count\n"
4428"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
4429"readcap arguments\n"
4430"-b                only report the blocksize\n"
4431"-h                human readable device size, base 2\n"
4432"-H                human readable device size, base 10\n"
4433"-N                print the number of blocks instead of last block\n"
4434"-q                quiet, print numbers only\n"
4435"-s                only report the last block/device size\n"
4436"cmd arguments:\n"
4437"-c cdb [args]     specify the SCSI CDB\n"
4438"-i len fmt        specify input data and input data format\n"
4439"-o len fmt [args] specify output data and output data fmt\n"
4440"debug arguments:\n"
4441"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
4442"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
4443"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
4444"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
4445"tags arguments:\n"
4446"-N tags           specify the number of tags to use for this device\n"
4447"-q                be quiet, don't report the number of tags\n"
4448"-v                report a number of tag-related parameters\n"
4449"negotiate arguments:\n"
4450"-a                send a test unit ready after negotiation\n"
4451"-c                report/set current negotiation settings\n"
4452"-D <arg>          \"enable\" or \"disable\" disconnection\n"
4453"-M mode           set ATA mode\n"
4454"-O offset         set command delay offset\n"
4455"-q                be quiet, don't report anything\n"
4456"-R syncrate       synchronization rate in MHz\n"
4457"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
4458"-U                report/set user negotiation settings\n"
4459"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
4460"-v                also print a Path Inquiry CCB for the controller\n"
4461"format arguments:\n"
4462"-q                be quiet, don't print status messages\n"
4463"-r                run in report only mode\n"
4464"-w                don't send immediate format command\n"
4465"-y                don't ask any questions\n"
4466"idle/standby arguments:\n"
4467"-t <arg>          number of seconds before respective state.\n");
4468#endif /* MINIMALISTIC */
4469}
4470
4471int
4472main(int argc, char **argv)
4473{
4474	int c;
4475	char *device = NULL;
4476	int unit = 0;
4477	struct cam_device *cam_dev = NULL;
4478	int timeout = 0, retry_count = 1;
4479	camcontrol_optret optreturn;
4480	char *tstr;
4481	const char *mainopt = "C:En:t:u:v";
4482	const char *subopt = NULL;
4483	char combinedopt[256];
4484	int error = 0, optstart = 2;
4485	int devopen = 1;
4486#ifndef MINIMALISTIC
4487	int bus, target, lun;
4488#endif /* MINIMALISTIC */
4489
4490	cmdlist = CAM_CMD_NONE;
4491	arglist = CAM_ARG_NONE;
4492
4493	if (argc < 2) {
4494		usage(0);
4495		exit(1);
4496	}
4497
4498	/*
4499	 * Get the base option.
4500	 */
4501	optreturn = getoption(argv[1], &cmdlist, &arglist, &subopt);
4502
4503	if (optreturn == CC_OR_AMBIGUOUS) {
4504		warnx("ambiguous option %s", argv[1]);
4505		usage(0);
4506		exit(1);
4507	} else if (optreturn == CC_OR_NOT_FOUND) {
4508		warnx("option %s not found", argv[1]);
4509		usage(0);
4510		exit(1);
4511	}
4512
4513	/*
4514	 * Ahh, getopt(3) is a pain.
4515	 *
4516	 * This is a gross hack.  There really aren't many other good
4517	 * options (excuse the pun) for parsing options in a situation like
4518	 * this.  getopt is kinda braindead, so you end up having to run
4519	 * through the options twice, and give each invocation of getopt
4520	 * the option string for the other invocation.
4521	 *
4522	 * You would think that you could just have two groups of options.
4523	 * The first group would get parsed by the first invocation of
4524	 * getopt, and the second group would get parsed by the second
4525	 * invocation of getopt.  It doesn't quite work out that way.  When
4526	 * the first invocation of getopt finishes, it leaves optind pointing
4527	 * to the argument _after_ the first argument in the second group.
4528	 * So when the second invocation of getopt comes around, it doesn't
4529	 * recognize the first argument it gets and then bails out.
4530	 *
4531	 * A nice alternative would be to have a flag for getopt that says
4532	 * "just keep parsing arguments even when you encounter an unknown
4533	 * argument", but there isn't one.  So there's no real clean way to
4534	 * easily parse two sets of arguments without having one invocation
4535	 * of getopt know about the other.
4536	 *
4537	 * Without this hack, the first invocation of getopt would work as
4538	 * long as the generic arguments are first, but the second invocation
4539	 * (in the subfunction) would fail in one of two ways.  In the case
4540	 * where you don't set optreset, it would fail because optind may be
4541	 * pointing to the argument after the one it should be pointing at.
4542	 * In the case where you do set optreset, and reset optind, it would
4543	 * fail because getopt would run into the first set of options, which
4544	 * it doesn't understand.
4545	 *
4546	 * All of this would "sort of" work if you could somehow figure out
4547	 * whether optind had been incremented one option too far.  The
4548	 * mechanics of that, however, are more daunting than just giving
4549	 * both invocations all of the expect options for either invocation.
4550	 *
4551	 * Needless to say, I wouldn't mind if someone invented a better
4552	 * (non-GPL!) command line parsing interface than getopt.  I
4553	 * wouldn't mind if someone added more knobs to getopt to make it
4554	 * work better.  Who knows, I may talk myself into doing it someday,
4555	 * if the standards weenies let me.  As it is, it just leads to
4556	 * hackery like this and causes people to avoid it in some cases.
4557	 *
4558	 * KDM, September 8th, 1998
4559	 */
4560	if (subopt != NULL)
4561		sprintf(combinedopt, "%s%s", mainopt, subopt);
4562	else
4563		sprintf(combinedopt, "%s", mainopt);
4564
4565	/*
4566	 * For these options we do not parse optional device arguments and
4567	 * we do not open a passthrough device.
4568	 */
4569	if ((cmdlist == CAM_CMD_RESCAN)
4570	 || (cmdlist == CAM_CMD_RESET)
4571	 || (cmdlist == CAM_CMD_DEVTREE)
4572	 || (cmdlist == CAM_CMD_USAGE)
4573	 || (cmdlist == CAM_CMD_DEBUG))
4574		devopen = 0;
4575
4576#ifndef MINIMALISTIC
4577	if ((devopen == 1)
4578	 && (argc > 2 && argv[2][0] != '-')) {
4579		char name[30];
4580		int rv;
4581
4582		/*
4583		 * First catch people who try to do things like:
4584		 * camcontrol tur /dev/da0
4585		 * camcontrol doesn't take device nodes as arguments.
4586		 */
4587		if (argv[2][0] == '/') {
4588			warnx("%s is not a valid device identifier", argv[2]);
4589			errx(1, "please read the camcontrol(8) man page");
4590		} else if (isdigit(argv[2][0])) {
4591			/* device specified as bus:target[:lun] */
4592			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
4593			if (rv < 2)
4594				errx(1, "numeric device specification must "
4595				     "be either bus:target, or "
4596				     "bus:target:lun");
4597			/* default to 0 if lun was not specified */
4598			if ((arglist & CAM_ARG_LUN) == 0) {
4599				lun = 0;
4600				arglist |= CAM_ARG_LUN;
4601			}
4602			optstart++;
4603		} else {
4604			if (cam_get_device(argv[2], name, sizeof name, &unit)
4605			    == -1)
4606				errx(1, "%s", cam_errbuf);
4607			device = strdup(name);
4608			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
4609			optstart++;
4610		}
4611	}
4612#endif /* MINIMALISTIC */
4613	/*
4614	 * Start getopt processing at argv[2/3], since we've already
4615	 * accepted argv[1..2] as the command name, and as a possible
4616	 * device name.
4617	 */
4618	optind = optstart;
4619
4620	/*
4621	 * Now we run through the argument list looking for generic
4622	 * options, and ignoring options that possibly belong to
4623	 * subfunctions.
4624	 */
4625	while ((c = getopt(argc, argv, combinedopt))!= -1){
4626		switch(c) {
4627			case 'C':
4628				retry_count = strtol(optarg, NULL, 0);
4629				if (retry_count < 0)
4630					errx(1, "retry count %d is < 0",
4631					     retry_count);
4632				arglist |= CAM_ARG_RETRIES;
4633				break;
4634			case 'E':
4635				arglist |= CAM_ARG_ERR_RECOVER;
4636				break;
4637			case 'n':
4638				arglist |= CAM_ARG_DEVICE;
4639				tstr = optarg;
4640				while (isspace(*tstr) && (*tstr != '\0'))
4641					tstr++;
4642				device = (char *)strdup(tstr);
4643				break;
4644			case 't':
4645				timeout = strtol(optarg, NULL, 0);
4646				if (timeout < 0)
4647					errx(1, "invalid timeout %d", timeout);
4648				/* Convert the timeout from seconds to ms */
4649				timeout *= 1000;
4650				arglist |= CAM_ARG_TIMEOUT;
4651				break;
4652			case 'u':
4653				arglist |= CAM_ARG_UNIT;
4654				unit = strtol(optarg, NULL, 0);
4655				break;
4656			case 'v':
4657				arglist |= CAM_ARG_VERBOSE;
4658				break;
4659			default:
4660				break;
4661		}
4662	}
4663
4664#ifndef MINIMALISTIC
4665	/*
4666	 * For most commands we'll want to open the passthrough device
4667	 * associated with the specified device.  In the case of the rescan
4668	 * commands, we don't use a passthrough device at all, just the
4669	 * transport layer device.
4670	 */
4671	if (devopen == 1) {
4672		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
4673		 && (((arglist & CAM_ARG_DEVICE) == 0)
4674		  || ((arglist & CAM_ARG_UNIT) == 0))) {
4675			errx(1, "subcommand \"%s\" requires a valid device "
4676			     "identifier", argv[1]);
4677		}
4678
4679		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
4680				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
4681				cam_open_spec_device(device,unit,O_RDWR,NULL)))
4682		     == NULL)
4683			errx(1,"%s", cam_errbuf);
4684	}
4685#endif /* MINIMALISTIC */
4686
4687	/*
4688	 * Reset optind to 2, and reset getopt, so these routines can parse
4689	 * the arguments again.
4690	 */
4691	optind = optstart;
4692	optreset = 1;
4693
4694	switch(cmdlist) {
4695#ifndef MINIMALISTIC
4696		case CAM_CMD_DEVLIST:
4697			error = getdevlist(cam_dev);
4698			break;
4699#endif /* MINIMALISTIC */
4700		case CAM_CMD_DEVTREE:
4701			error = getdevtree();
4702			break;
4703#ifndef MINIMALISTIC
4704		case CAM_CMD_TUR:
4705			error = testunitready(cam_dev, retry_count, timeout, 0);
4706			break;
4707		case CAM_CMD_INQUIRY:
4708			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
4709					      retry_count, timeout);
4710			break;
4711		case CAM_CMD_IDENTIFY:
4712			error = ataidentify(cam_dev, retry_count, timeout);
4713			break;
4714		case CAM_CMD_STARTSTOP:
4715			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
4716					  arglist & CAM_ARG_EJECT, retry_count,
4717					  timeout);
4718			break;
4719#endif /* MINIMALISTIC */
4720		case CAM_CMD_RESCAN:
4721			error = dorescan_or_reset(argc, argv, 1);
4722			break;
4723		case CAM_CMD_RESET:
4724			error = dorescan_or_reset(argc, argv, 0);
4725			break;
4726#ifndef MINIMALISTIC
4727		case CAM_CMD_READ_DEFECTS:
4728			error = readdefects(cam_dev, argc, argv, combinedopt,
4729					    retry_count, timeout);
4730			break;
4731		case CAM_CMD_MODE_PAGE:
4732			modepage(cam_dev, argc, argv, combinedopt,
4733				 retry_count, timeout);
4734			break;
4735		case CAM_CMD_SCSI_CMD:
4736			error = scsicmd(cam_dev, argc, argv, combinedopt,
4737					retry_count, timeout);
4738			break;
4739		case CAM_CMD_DEBUG:
4740			error = camdebug(argc, argv, combinedopt);
4741			break;
4742		case CAM_CMD_TAG:
4743			error = tagcontrol(cam_dev, argc, argv, combinedopt);
4744			break;
4745		case CAM_CMD_RATE:
4746			error = ratecontrol(cam_dev, retry_count, timeout,
4747					    argc, argv, combinedopt);
4748			break;
4749		case CAM_CMD_FORMAT:
4750			error = scsiformat(cam_dev, argc, argv,
4751					   combinedopt, retry_count, timeout);
4752			break;
4753		case CAM_CMD_REPORTLUNS:
4754			error = scsireportluns(cam_dev, argc, argv,
4755					       combinedopt, retry_count,
4756					       timeout);
4757			break;
4758		case CAM_CMD_READCAP:
4759			error = scsireadcapacity(cam_dev, argc, argv,
4760						 combinedopt, retry_count,
4761						 timeout);
4762			break;
4763		case CAM_CMD_IDLE:
4764		case CAM_CMD_STANDBY:
4765		case CAM_CMD_SLEEP:
4766			error = atapm(cam_dev, argc, argv,
4767						 combinedopt, retry_count,
4768						 timeout);
4769			break;
4770#endif /* MINIMALISTIC */
4771		case CAM_CMD_USAGE:
4772			usage(1);
4773			break;
4774		default:
4775			usage(0);
4776			error = 1;
4777			break;
4778	}
4779
4780	if (cam_dev != NULL)
4781		cam_close_device(cam_dev);
4782
4783	exit(error);
4784}
4785