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