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