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