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