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