camcontrol.c revision 229778
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 229778 2012-01-07 16:09:33Z uqs $");
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			u_int freq;
3416
3417			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3418				warnx("HBA is not capable of changing "
3419				      "transfer rates");
3420				retval = 1;
3421				goto ratecontrol_bailout;
3422			}
3423			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3424			/*
3425			 * The sync rate the user gives us is in MHz.
3426			 * We need to translate it into KHz for this
3427			 * calculation.
3428			 */
3429			syncrate *= 1000;
3430			/*
3431			 * Next, we calculate a "preliminary" sync period
3432			 * in tenths of a nanosecond.
3433			 */
3434			if (syncrate == 0)
3435				prelim_sync_period = 0;
3436			else
3437				prelim_sync_period = 10000000 / syncrate;
3438			spi->sync_period =
3439				scsi_calc_syncparam(prelim_sync_period);
3440			freq = scsi_calc_syncsrate(spi->sync_period);
3441			didsettings++;
3442		}
3443		if (sata && syncrate != -1) {
3444			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3445				warnx("HBA is not capable of changing "
3446				      "transfer rates");
3447				retval = 1;
3448				goto ratecontrol_bailout;
3449			}
3450			sata->revision = ata_speed2revision(syncrate * 100);
3451			if (sata->revision < 0) {
3452				warnx("Invalid rate %f", syncrate);
3453				retval = 1;
3454				goto ratecontrol_bailout;
3455			}
3456			sata->valid |= CTS_SATA_VALID_REVISION;
3457			didsettings++;
3458		}
3459		if ((ata || sata) && mode != -1) {
3460			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
3461				warnx("HBA is not capable of changing "
3462				      "transfer rates");
3463				retval = 1;
3464				goto ratecontrol_bailout;
3465			}
3466			if (ata) {
3467				ata->mode = mode;
3468				ata->valid |= CTS_ATA_VALID_MODE;
3469			} else {
3470				sata->mode = mode;
3471				sata->valid |= CTS_SATA_VALID_MODE;
3472			}
3473			didsettings++;
3474		}
3475		/*
3476		 * The bus_width argument goes like this:
3477		 * 0 == 8 bit
3478		 * 1 == 16 bit
3479		 * 2 == 32 bit
3480		 * Therefore, if you shift the number of bits given on the
3481		 * command line right by 4, you should get the correct
3482		 * number.
3483		 */
3484		if (spi && bus_width != -1) {
3485			/*
3486			 * We might as well validate things here with a
3487			 * decipherable error message, rather than what
3488			 * will probably be an indecipherable error message
3489			 * by the time it gets back to us.
3490			 */
3491			if ((bus_width == 16)
3492			 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
3493				warnx("HBA does not support 16 bit bus width");
3494				retval = 1;
3495				goto ratecontrol_bailout;
3496			} else if ((bus_width == 32)
3497				&& ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
3498				warnx("HBA does not support 32 bit bus width");
3499				retval = 1;
3500				goto ratecontrol_bailout;
3501			} else if ((bus_width != 8)
3502				&& (bus_width != 16)
3503				&& (bus_width != 32)) {
3504				warnx("Invalid bus width %d", bus_width);
3505				retval = 1;
3506				goto ratecontrol_bailout;
3507			}
3508			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
3509			spi->bus_width = bus_width >> 4;
3510			didsettings++;
3511		}
3512		if  (didsettings == 0) {
3513			goto ratecontrol_bailout;
3514		}
3515		if  (!user_settings && (ata || sata)) {
3516			warnx("You can modify only user settings for ATA/SATA");
3517			retval = 1;
3518			goto ratecontrol_bailout;
3519		}
3520		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
3521		if (cam_send_ccb(device, ccb) < 0) {
3522			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
3523			if (arglist & CAM_ARG_VERBOSE) {
3524				cam_error_print(device, ccb, CAM_ESF_ALL,
3525						CAM_EPF_ALL, stderr);
3526			}
3527			retval = 1;
3528			goto ratecontrol_bailout;
3529		}
3530		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3531			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
3532			if (arglist & CAM_ARG_VERBOSE) {
3533				cam_error_print(device, ccb, CAM_ESF_ALL,
3534						CAM_EPF_ALL, stderr);
3535			}
3536			retval = 1;
3537			goto ratecontrol_bailout;
3538		}
3539	}
3540	if (send_tur) {
3541		retval = testunitready(device, retry_count, timeout,
3542				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
3543		/*
3544		 * If the TUR didn't succeed, just bail.
3545		 */
3546		if (retval != 0) {
3547			if (quiet == 0)
3548				fprintf(stderr, "Test Unit Ready failed\n");
3549			goto ratecontrol_bailout;
3550		}
3551		/*
3552		 * If the user wants things quiet, there's no sense in
3553		 * getting the transfer settings, if we're not going
3554		 * to print them.
3555		 */
3556		if (quiet != 0)
3557			goto ratecontrol_bailout;
3558		fprintf(stdout, "New parameters:\n");
3559		retval = get_print_cts(device, user_settings, 0, NULL);
3560	}
3561
3562ratecontrol_bailout:
3563	cam_freeccb(ccb);
3564	return(retval);
3565}
3566
3567static int
3568scsiformat(struct cam_device *device, int argc, char **argv,
3569	   char *combinedopt, int retry_count, int timeout)
3570{
3571	union ccb *ccb;
3572	int c;
3573	int ycount = 0, quiet = 0;
3574	int error = 0, retval = 0;
3575	int use_timeout = 10800 * 1000;
3576	int immediate = 1;
3577	struct format_defect_list_header fh;
3578	u_int8_t *data_ptr = NULL;
3579	u_int32_t dxfer_len = 0;
3580	u_int8_t byte2 = 0;
3581	int num_warnings = 0;
3582	int reportonly = 0;
3583
3584	ccb = cam_getccb(device);
3585
3586	if (ccb == NULL) {
3587		warnx("scsiformat: error allocating ccb");
3588		return(1);
3589	}
3590
3591	bzero(&(&ccb->ccb_h)[1],
3592	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3593
3594	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3595		switch(c) {
3596		case 'q':
3597			quiet++;
3598			break;
3599		case 'r':
3600			reportonly = 1;
3601			break;
3602		case 'w':
3603			immediate = 0;
3604			break;
3605		case 'y':
3606			ycount++;
3607			break;
3608		}
3609	}
3610
3611	if (reportonly)
3612		goto doreport;
3613
3614	if (quiet == 0) {
3615		fprintf(stdout, "You are about to REMOVE ALL DATA from the "
3616			"following device:\n");
3617
3618		error = scsidoinquiry(device, argc, argv, combinedopt,
3619				      retry_count, timeout);
3620
3621		if (error != 0) {
3622			warnx("scsiformat: error sending inquiry");
3623			goto scsiformat_bailout;
3624		}
3625	}
3626
3627	if (ycount == 0) {
3628		if (!get_confirmation()) {
3629			error = 1;
3630			goto scsiformat_bailout;
3631		}
3632	}
3633
3634	if (timeout != 0)
3635		use_timeout = timeout;
3636
3637	if (quiet == 0) {
3638		fprintf(stdout, "Current format timeout is %d seconds\n",
3639			use_timeout / 1000);
3640	}
3641
3642	/*
3643	 * If the user hasn't disabled questions and didn't specify a
3644	 * timeout on the command line, ask them if they want the current
3645	 * timeout.
3646	 */
3647	if ((ycount == 0)
3648	 && (timeout == 0)) {
3649		char str[1024];
3650		int new_timeout = 0;
3651
3652		fprintf(stdout, "Enter new timeout in seconds or press\n"
3653			"return to keep the current timeout [%d] ",
3654			use_timeout / 1000);
3655
3656		if (fgets(str, sizeof(str), stdin) != NULL) {
3657			if (str[0] != '\0')
3658				new_timeout = atoi(str);
3659		}
3660
3661		if (new_timeout != 0) {
3662			use_timeout = new_timeout * 1000;
3663			fprintf(stdout, "Using new timeout value %d\n",
3664				use_timeout / 1000);
3665		}
3666	}
3667
3668	/*
3669	 * Keep this outside the if block below to silence any unused
3670	 * variable warnings.
3671	 */
3672	bzero(&fh, sizeof(fh));
3673
3674	/*
3675	 * If we're in immediate mode, we've got to include the format
3676	 * header
3677	 */
3678	if (immediate != 0) {
3679		fh.byte2 = FU_DLH_IMMED;
3680		data_ptr = (u_int8_t *)&fh;
3681		dxfer_len = sizeof(fh);
3682		byte2 = FU_FMT_DATA;
3683	} else if (quiet == 0) {
3684		fprintf(stdout, "Formatting...");
3685		fflush(stdout);
3686	}
3687
3688	scsi_format_unit(&ccb->csio,
3689			 /* retries */ retry_count,
3690			 /* cbfcnp */ NULL,
3691			 /* tag_action */ MSG_SIMPLE_Q_TAG,
3692			 /* byte2 */ byte2,
3693			 /* ileave */ 0,
3694			 /* data_ptr */ data_ptr,
3695			 /* dxfer_len */ dxfer_len,
3696			 /* sense_len */ SSD_FULL_SIZE,
3697			 /* timeout */ use_timeout);
3698
3699	/* Disable freezing the device queue */
3700	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3701
3702	if (arglist & CAM_ARG_ERR_RECOVER)
3703		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3704
3705	if (((retval = cam_send_ccb(device, ccb)) < 0)
3706	 || ((immediate == 0)
3707	   && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
3708		const char errstr[] = "error sending format command";
3709
3710		if (retval < 0)
3711			warn(errstr);
3712		else
3713			warnx(errstr);
3714
3715		if (arglist & CAM_ARG_VERBOSE) {
3716			cam_error_print(device, ccb, CAM_ESF_ALL,
3717					CAM_EPF_ALL, stderr);
3718		}
3719		error = 1;
3720		goto scsiformat_bailout;
3721	}
3722
3723	/*
3724	 * If we ran in non-immediate mode, we already checked for errors
3725	 * above and printed out any necessary information.  If we're in
3726	 * immediate mode, we need to loop through and get status
3727	 * information periodically.
3728	 */
3729	if (immediate == 0) {
3730		if (quiet == 0) {
3731			fprintf(stdout, "Format Complete\n");
3732		}
3733		goto scsiformat_bailout;
3734	}
3735
3736doreport:
3737	do {
3738		cam_status status;
3739
3740		bzero(&(&ccb->ccb_h)[1],
3741		      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3742
3743		/*
3744		 * There's really no need to do error recovery or
3745		 * retries here, since we're just going to sit in a
3746		 * loop and wait for the device to finish formatting.
3747		 */
3748		scsi_test_unit_ready(&ccb->csio,
3749				     /* retries */ 0,
3750				     /* cbfcnp */ NULL,
3751				     /* tag_action */ MSG_SIMPLE_Q_TAG,
3752				     /* sense_len */ SSD_FULL_SIZE,
3753				     /* timeout */ 5000);
3754
3755		/* Disable freezing the device queue */
3756		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3757
3758		retval = cam_send_ccb(device, ccb);
3759
3760		/*
3761		 * If we get an error from the ioctl, bail out.  SCSI
3762		 * errors are expected.
3763		 */
3764		if (retval < 0) {
3765			warn("error sending CAMIOCOMMAND ioctl");
3766			if (arglist & CAM_ARG_VERBOSE) {
3767				cam_error_print(device, ccb, CAM_ESF_ALL,
3768						CAM_EPF_ALL, stderr);
3769			}
3770			error = 1;
3771			goto scsiformat_bailout;
3772		}
3773
3774		status = ccb->ccb_h.status & CAM_STATUS_MASK;
3775
3776		if ((status != CAM_REQ_CMP)
3777		 && (status == CAM_SCSI_STATUS_ERROR)
3778		 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
3779			struct scsi_sense_data *sense;
3780			int error_code, sense_key, asc, ascq;
3781
3782			sense = &ccb->csio.sense_data;
3783			scsi_extract_sense_len(sense, ccb->csio.sense_len -
3784			    ccb->csio.sense_resid, &error_code, &sense_key,
3785			    &asc, &ascq, /*show_errors*/ 1);
3786
3787			/*
3788			 * According to the SCSI-2 and SCSI-3 specs, a
3789			 * drive that is in the middle of a format should
3790			 * return NOT READY with an ASC of "logical unit
3791			 * not ready, format in progress".  The sense key
3792			 * specific bytes will then be a progress indicator.
3793			 */
3794			if ((sense_key == SSD_KEY_NOT_READY)
3795			 && (asc == 0x04) && (ascq == 0x04)) {
3796				uint8_t sks[3];
3797
3798				if ((scsi_get_sks(sense, ccb->csio.sense_len -
3799				     ccb->csio.sense_resid, sks) == 0)
3800				 && (quiet == 0)) {
3801					int val;
3802					u_int64_t percentage;
3803
3804					val = scsi_2btoul(&sks[1]);
3805					percentage = 10000 * val;
3806
3807					fprintf(stdout,
3808						"\rFormatting:  %ju.%02u %% "
3809						"(%d/%d) done",
3810						(uintmax_t)(percentage /
3811						(0x10000 * 100)),
3812						(unsigned)((percentage /
3813						0x10000) % 100),
3814						val, 0x10000);
3815					fflush(stdout);
3816				} else if ((quiet == 0)
3817					&& (++num_warnings <= 1)) {
3818					warnx("Unexpected SCSI Sense Key "
3819					      "Specific value returned "
3820					      "during format:");
3821					scsi_sense_print(device, &ccb->csio,
3822							 stderr);
3823					warnx("Unable to print status "
3824					      "information, but format will "
3825					      "proceed.");
3826					warnx("will exit when format is "
3827					      "complete");
3828				}
3829				sleep(1);
3830			} else {
3831				warnx("Unexpected SCSI error during format");
3832				cam_error_print(device, ccb, CAM_ESF_ALL,
3833						CAM_EPF_ALL, stderr);
3834				error = 1;
3835				goto scsiformat_bailout;
3836			}
3837
3838		} else if (status != CAM_REQ_CMP) {
3839			warnx("Unexpected CAM status %#x", status);
3840			if (arglist & CAM_ARG_VERBOSE)
3841				cam_error_print(device, ccb, CAM_ESF_ALL,
3842						CAM_EPF_ALL, stderr);
3843			error = 1;
3844			goto scsiformat_bailout;
3845		}
3846
3847	} while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
3848
3849	if (quiet == 0)
3850		fprintf(stdout, "\nFormat Complete\n");
3851
3852scsiformat_bailout:
3853
3854	cam_freeccb(ccb);
3855
3856	return(error);
3857}
3858
3859static int
3860scsireportluns(struct cam_device *device, int argc, char **argv,
3861	       char *combinedopt, int retry_count, int timeout)
3862{
3863	union ccb *ccb;
3864	int c, countonly, lunsonly;
3865	struct scsi_report_luns_data *lundata;
3866	int alloc_len;
3867	uint8_t report_type;
3868	uint32_t list_len, i, j;
3869	int retval;
3870
3871	retval = 0;
3872	lundata = NULL;
3873	report_type = RPL_REPORT_DEFAULT;
3874	ccb = cam_getccb(device);
3875
3876	if (ccb == NULL) {
3877		warnx("%s: error allocating ccb", __func__);
3878		return (1);
3879	}
3880
3881	bzero(&(&ccb->ccb_h)[1],
3882	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
3883
3884	countonly = 0;
3885	lunsonly = 0;
3886
3887	while ((c = getopt(argc, argv, combinedopt)) != -1) {
3888		switch (c) {
3889		case 'c':
3890			countonly++;
3891			break;
3892		case 'l':
3893			lunsonly++;
3894			break;
3895		case 'r':
3896			if (strcasecmp(optarg, "default") == 0)
3897				report_type = RPL_REPORT_DEFAULT;
3898			else if (strcasecmp(optarg, "wellknown") == 0)
3899				report_type = RPL_REPORT_WELLKNOWN;
3900			else if (strcasecmp(optarg, "all") == 0)
3901				report_type = RPL_REPORT_ALL;
3902			else {
3903				warnx("%s: invalid report type \"%s\"",
3904				      __func__, optarg);
3905				retval = 1;
3906				goto bailout;
3907			}
3908			break;
3909		default:
3910			break;
3911		}
3912	}
3913
3914	if ((countonly != 0)
3915	 && (lunsonly != 0)) {
3916		warnx("%s: you can only specify one of -c or -l", __func__);
3917		retval = 1;
3918		goto bailout;
3919	}
3920	/*
3921	 * According to SPC-4, the allocation length must be at least 16
3922	 * bytes -- enough for the header and one LUN.
3923	 */
3924	alloc_len = sizeof(*lundata) + 8;
3925
3926retry:
3927
3928	lundata = malloc(alloc_len);
3929
3930	if (lundata == NULL) {
3931		warn("%s: error mallocing %d bytes", __func__, alloc_len);
3932		retval = 1;
3933		goto bailout;
3934	}
3935
3936	scsi_report_luns(&ccb->csio,
3937			 /*retries*/ retry_count,
3938			 /*cbfcnp*/ NULL,
3939			 /*tag_action*/ MSG_SIMPLE_Q_TAG,
3940			 /*select_report*/ report_type,
3941			 /*rpl_buf*/ lundata,
3942			 /*alloc_len*/ alloc_len,
3943			 /*sense_len*/ SSD_FULL_SIZE,
3944			 /*timeout*/ timeout ? timeout : 5000);
3945
3946	/* Disable freezing the device queue */
3947	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
3948
3949	if (arglist & CAM_ARG_ERR_RECOVER)
3950		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
3951
3952	if (cam_send_ccb(device, ccb) < 0) {
3953		warn("error sending REPORT LUNS command");
3954
3955		if (arglist & CAM_ARG_VERBOSE)
3956			cam_error_print(device, ccb, CAM_ESF_ALL,
3957					CAM_EPF_ALL, stderr);
3958
3959		retval = 1;
3960		goto bailout;
3961	}
3962
3963	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3964		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
3965		retval = 1;
3966		goto bailout;
3967	}
3968
3969
3970	list_len = scsi_4btoul(lundata->length);
3971
3972	/*
3973	 * If we need to list the LUNs, and our allocation
3974	 * length was too short, reallocate and retry.
3975	 */
3976	if ((countonly == 0)
3977	 && (list_len > (alloc_len - sizeof(*lundata)))) {
3978		alloc_len = list_len + sizeof(*lundata);
3979		free(lundata);
3980		goto retry;
3981	}
3982
3983	if (lunsonly == 0)
3984		fprintf(stdout, "%u LUN%s found\n", list_len / 8,
3985			((list_len / 8) > 1) ? "s" : "");
3986
3987	if (countonly != 0)
3988		goto bailout;
3989
3990	for (i = 0; i < (list_len / 8); i++) {
3991		int no_more;
3992
3993		no_more = 0;
3994		for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) {
3995			if (j != 0)
3996				fprintf(stdout, ",");
3997			switch (lundata->luns[i].lundata[j] &
3998				RPL_LUNDATA_ATYP_MASK) {
3999			case RPL_LUNDATA_ATYP_PERIPH:
4000				if ((lundata->luns[i].lundata[j] &
4001				    RPL_LUNDATA_PERIPH_BUS_MASK) != 0)
4002					fprintf(stdout, "%d:",
4003						lundata->luns[i].lundata[j] &
4004						RPL_LUNDATA_PERIPH_BUS_MASK);
4005				else if ((j == 0)
4006				      && ((lundata->luns[i].lundata[j+2] &
4007					  RPL_LUNDATA_PERIPH_BUS_MASK) == 0))
4008					no_more = 1;
4009
4010				fprintf(stdout, "%d",
4011					lundata->luns[i].lundata[j+1]);
4012				break;
4013			case RPL_LUNDATA_ATYP_FLAT: {
4014				uint8_t tmplun[2];
4015				tmplun[0] = lundata->luns[i].lundata[j] &
4016					RPL_LUNDATA_FLAT_LUN_MASK;
4017				tmplun[1] = lundata->luns[i].lundata[j+1];
4018
4019				fprintf(stdout, "%d", scsi_2btoul(tmplun));
4020				no_more = 1;
4021				break;
4022			}
4023			case RPL_LUNDATA_ATYP_LUN:
4024				fprintf(stdout, "%d:%d:%d",
4025					(lundata->luns[i].lundata[j+1] &
4026					RPL_LUNDATA_LUN_BUS_MASK) >> 5,
4027					lundata->luns[i].lundata[j] &
4028					RPL_LUNDATA_LUN_TARG_MASK,
4029					lundata->luns[i].lundata[j+1] &
4030					RPL_LUNDATA_LUN_LUN_MASK);
4031				break;
4032			case RPL_LUNDATA_ATYP_EXTLUN: {
4033				int field_len, field_len_code, eam_code;
4034
4035				eam_code = lundata->luns[i].lundata[j] &
4036					RPL_LUNDATA_EXT_EAM_MASK;
4037				field_len_code = (lundata->luns[i].lundata[j] &
4038					RPL_LUNDATA_EXT_LEN_MASK) >> 4;
4039				field_len = field_len_code * 2;
4040
4041				if ((eam_code == RPL_LUNDATA_EXT_EAM_WK)
4042				 && (field_len_code == 0x00)) {
4043					fprintf(stdout, "%d",
4044						lundata->luns[i].lundata[j+1]);
4045				} else if ((eam_code ==
4046					    RPL_LUNDATA_EXT_EAM_NOT_SPEC)
4047					&& (field_len_code == 0x03)) {
4048					uint8_t tmp_lun[8];
4049
4050					/*
4051					 * This format takes up all 8 bytes.
4052					 * If we aren't starting at offset 0,
4053					 * that's a bug.
4054					 */
4055					if (j != 0) {
4056						fprintf(stdout, "Invalid "
4057							"offset %d for "
4058							"Extended LUN not "
4059							"specified format", j);
4060						no_more = 1;
4061						break;
4062					}
4063					bzero(tmp_lun, sizeof(tmp_lun));
4064					bcopy(&lundata->luns[i].lundata[j+1],
4065					      &tmp_lun[1], sizeof(tmp_lun) - 1);
4066					fprintf(stdout, "%#jx",
4067					       (intmax_t)scsi_8btou64(tmp_lun));
4068					no_more = 1;
4069				} else {
4070					fprintf(stderr, "Unknown Extended LUN"
4071						"Address method %#x, length "
4072						"code %#x", eam_code,
4073						field_len_code);
4074					no_more = 1;
4075				}
4076				break;
4077			}
4078			default:
4079				fprintf(stderr, "Unknown LUN address method "
4080					"%#x\n", lundata->luns[i].lundata[0] &
4081					RPL_LUNDATA_ATYP_MASK);
4082				break;
4083			}
4084			/*
4085			 * For the flat addressing method, there are no
4086			 * other levels after it.
4087			 */
4088			if (no_more != 0)
4089				break;
4090		}
4091		fprintf(stdout, "\n");
4092	}
4093
4094bailout:
4095
4096	cam_freeccb(ccb);
4097
4098	free(lundata);
4099
4100	return (retval);
4101}
4102
4103static int
4104scsireadcapacity(struct cam_device *device, int argc, char **argv,
4105		 char *combinedopt, int retry_count, int timeout)
4106{
4107	union ccb *ccb;
4108	int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten;
4109	struct scsi_read_capacity_data rcap;
4110	struct scsi_read_capacity_data_long rcaplong;
4111	uint64_t maxsector;
4112	uint32_t block_len;
4113	int retval;
4114	int c;
4115
4116	blocksizeonly = 0;
4117	humanize = 0;
4118	numblocks = 0;
4119	quiet = 0;
4120	sizeonly = 0;
4121	baseten = 0;
4122	retval = 0;
4123
4124	ccb = cam_getccb(device);
4125
4126	if (ccb == NULL) {
4127		warnx("%s: error allocating ccb", __func__);
4128		return (1);
4129	}
4130
4131	bzero(&(&ccb->ccb_h)[1],
4132	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
4133
4134	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4135		switch (c) {
4136		case 'b':
4137			blocksizeonly++;
4138			break;
4139		case 'h':
4140			humanize++;
4141			baseten = 0;
4142			break;
4143		case 'H':
4144			humanize++;
4145			baseten++;
4146			break;
4147		case 'N':
4148			numblocks++;
4149			break;
4150		case 'q':
4151			quiet++;
4152			break;
4153		case 's':
4154			sizeonly++;
4155			break;
4156		default:
4157			break;
4158		}
4159	}
4160
4161	if ((blocksizeonly != 0)
4162	 && (numblocks != 0)) {
4163		warnx("%s: you can only specify one of -b or -N", __func__);
4164		retval = 1;
4165		goto bailout;
4166	}
4167
4168	if ((blocksizeonly != 0)
4169	 && (sizeonly != 0)) {
4170		warnx("%s: you can only specify one of -b or -s", __func__);
4171		retval = 1;
4172		goto bailout;
4173	}
4174
4175	if ((humanize != 0)
4176	 && (quiet != 0)) {
4177		warnx("%s: you can only specify one of -h/-H or -q", __func__);
4178		retval = 1;
4179		goto bailout;
4180	}
4181
4182	if ((humanize != 0)
4183	 && (blocksizeonly != 0)) {
4184		warnx("%s: you can only specify one of -h/-H or -b", __func__);
4185		retval = 1;
4186		goto bailout;
4187	}
4188
4189	scsi_read_capacity(&ccb->csio,
4190			   /*retries*/ retry_count,
4191			   /*cbfcnp*/ NULL,
4192			   /*tag_action*/ MSG_SIMPLE_Q_TAG,
4193			   &rcap,
4194			   SSD_FULL_SIZE,
4195			   /*timeout*/ timeout ? timeout : 5000);
4196
4197	/* Disable freezing the device queue */
4198	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4199
4200	if (arglist & CAM_ARG_ERR_RECOVER)
4201		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4202
4203	if (cam_send_ccb(device, ccb) < 0) {
4204		warn("error sending READ CAPACITY command");
4205
4206		if (arglist & CAM_ARG_VERBOSE)
4207			cam_error_print(device, ccb, CAM_ESF_ALL,
4208					CAM_EPF_ALL, stderr);
4209
4210		retval = 1;
4211		goto bailout;
4212	}
4213
4214	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4215		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4216		retval = 1;
4217		goto bailout;
4218	}
4219
4220	maxsector = scsi_4btoul(rcap.addr);
4221	block_len = scsi_4btoul(rcap.length);
4222
4223	/*
4224	 * A last block of 2^32-1 means that the true capacity is over 2TB,
4225	 * and we need to issue the long READ CAPACITY to get the real
4226	 * capacity.  Otherwise, we're all set.
4227	 */
4228	if (maxsector != 0xffffffff)
4229		goto do_print;
4230
4231	scsi_read_capacity_16(&ccb->csio,
4232			      /*retries*/ retry_count,
4233			      /*cbfcnp*/ NULL,
4234			      /*tag_action*/ MSG_SIMPLE_Q_TAG,
4235			      /*lba*/ 0,
4236			      /*reladdr*/ 0,
4237			      /*pmi*/ 0,
4238			      &rcaplong,
4239			      /*sense_len*/ SSD_FULL_SIZE,
4240			      /*timeout*/ timeout ? timeout : 5000);
4241
4242	/* Disable freezing the device queue */
4243	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
4244
4245	if (arglist & CAM_ARG_ERR_RECOVER)
4246		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
4247
4248	if (cam_send_ccb(device, ccb) < 0) {
4249		warn("error sending READ CAPACITY (16) command");
4250
4251		if (arglist & CAM_ARG_VERBOSE)
4252			cam_error_print(device, ccb, CAM_ESF_ALL,
4253					CAM_EPF_ALL, stderr);
4254
4255		retval = 1;
4256		goto bailout;
4257	}
4258
4259	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4260		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
4261		retval = 1;
4262		goto bailout;
4263	}
4264
4265	maxsector = scsi_8btou64(rcaplong.addr);
4266	block_len = scsi_4btoul(rcaplong.length);
4267
4268do_print:
4269	if (blocksizeonly == 0) {
4270		/*
4271		 * Humanize implies !quiet, and also implies numblocks.
4272		 */
4273		if (humanize != 0) {
4274			char tmpstr[6];
4275			int64_t tmpbytes;
4276			int ret;
4277
4278			tmpbytes = (maxsector + 1) * block_len;
4279			ret = humanize_number(tmpstr, sizeof(tmpstr),
4280					      tmpbytes, "", HN_AUTOSCALE,
4281					      HN_B | HN_DECIMAL |
4282					      ((baseten != 0) ?
4283					      HN_DIVISOR_1000 : 0));
4284			if (ret == -1) {
4285				warnx("%s: humanize_number failed!", __func__);
4286				retval = 1;
4287				goto bailout;
4288			}
4289			fprintf(stdout, "Device Size: %s%s", tmpstr,
4290				(sizeonly == 0) ?  ", " : "\n");
4291		} else if (numblocks != 0) {
4292			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4293				"Blocks: " : "", (uintmax_t)maxsector + 1,
4294				(sizeonly == 0) ? ", " : "\n");
4295		} else {
4296			fprintf(stdout, "%s%ju%s", (quiet == 0) ?
4297				"Last Block: " : "", (uintmax_t)maxsector,
4298				(sizeonly == 0) ? ", " : "\n");
4299		}
4300	}
4301	if (sizeonly == 0)
4302		fprintf(stdout, "%s%u%s\n", (quiet == 0) ?
4303			"Block Length: " : "", block_len, (quiet == 0) ?
4304			" bytes" : "");
4305bailout:
4306	cam_freeccb(ccb);
4307
4308	return (retval);
4309}
4310
4311static int
4312smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
4313       int retry_count, int timeout)
4314{
4315	int c, error;
4316	union ccb *ccb;
4317	uint8_t *smp_request = NULL, *smp_response = NULL;
4318	int request_size = 0, response_size = 0;
4319	int fd_request = 0, fd_response = 0;
4320	char *datastr = NULL;
4321	struct get_hook hook;
4322	int retval;
4323	int flags = 0;
4324
4325	/*
4326	 * Note that at the moment we don't support sending SMP CCBs to
4327	 * devices that aren't probed by CAM.
4328	 */
4329	ccb = cam_getccb(device);
4330	if (ccb == NULL) {
4331		warnx("%s: error allocating CCB", __func__);
4332		return (1);
4333	}
4334
4335	bzero(&(&ccb->ccb_h)[1],
4336	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4337
4338	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4339		switch (c) {
4340		case 'R':
4341			arglist |= CAM_ARG_CMD_IN;
4342			response_size = strtol(optarg, NULL, 0);
4343			if (response_size <= 0) {
4344				warnx("invalid number of response bytes %d",
4345				      response_size);
4346				error = 1;
4347				goto smpcmd_bailout;
4348			}
4349			hook.argc = argc - optind;
4350			hook.argv = argv + optind;
4351			hook.got = 0;
4352			optind++;
4353			datastr = cget(&hook, NULL);
4354			/*
4355			 * If the user supplied "-" instead of a format, he
4356			 * wants the data to be written to stdout.
4357			 */
4358			if ((datastr != NULL)
4359			 && (datastr[0] == '-'))
4360				fd_response = 1;
4361
4362			smp_response = (u_int8_t *)malloc(response_size);
4363			if (smp_response == NULL) {
4364				warn("can't malloc memory for SMP response");
4365				error = 1;
4366				goto smpcmd_bailout;
4367			}
4368			break;
4369		case 'r':
4370			arglist |= CAM_ARG_CMD_OUT;
4371			request_size = strtol(optarg, NULL, 0);
4372			if (request_size <= 0) {
4373				warnx("invalid number of request bytes %d",
4374				      request_size);
4375				error = 1;
4376				goto smpcmd_bailout;
4377			}
4378			hook.argc = argc - optind;
4379			hook.argv = argv + optind;
4380			hook.got = 0;
4381			datastr = cget(&hook, NULL);
4382			smp_request = (u_int8_t *)malloc(request_size);
4383			if (smp_request == NULL) {
4384				warn("can't malloc memory for SMP request");
4385				error = 1;
4386				goto smpcmd_bailout;
4387			}
4388			bzero(smp_request, request_size);
4389			/*
4390			 * If the user supplied "-" instead of a format, he
4391			 * wants the data to be read from stdin.
4392			 */
4393			if ((datastr != NULL)
4394			 && (datastr[0] == '-'))
4395				fd_request = 1;
4396			else
4397				buff_encode_visit(smp_request, request_size,
4398						  datastr,
4399						  iget, &hook);
4400			optind += hook.got;
4401			break;
4402		default:
4403			break;
4404		}
4405	}
4406
4407	/*
4408	 * If fd_data is set, and we're writing to the device, we need to
4409	 * read the data the user wants written from stdin.
4410	 */
4411	if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
4412		ssize_t amt_read;
4413		int amt_to_read = request_size;
4414		u_int8_t *buf_ptr = smp_request;
4415
4416		for (amt_read = 0; amt_to_read > 0;
4417		     amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
4418			if (amt_read == -1) {
4419				warn("error reading data from stdin");
4420				error = 1;
4421				goto smpcmd_bailout;
4422			}
4423			amt_to_read -= amt_read;
4424			buf_ptr += amt_read;
4425		}
4426	}
4427
4428	if (((arglist & CAM_ARG_CMD_IN) == 0)
4429	 || ((arglist & CAM_ARG_CMD_OUT) == 0)) {
4430		warnx("%s: need both the request (-r) and response (-R) "
4431		      "arguments", __func__);
4432		error = 1;
4433		goto smpcmd_bailout;
4434	}
4435
4436	flags |= CAM_DEV_QFRZDIS;
4437
4438	cam_fill_smpio(&ccb->smpio,
4439		       /*retries*/ retry_count,
4440		       /*cbfcnp*/ NULL,
4441		       /*flags*/ flags,
4442		       /*smp_request*/ smp_request,
4443		       /*smp_request_len*/ request_size,
4444		       /*smp_response*/ smp_response,
4445		       /*smp_response_len*/ response_size,
4446		       /*timeout*/ timeout ? timeout : 5000);
4447
4448	ccb->smpio.flags = SMP_FLAG_NONE;
4449
4450	if (((retval = cam_send_ccb(device, ccb)) < 0)
4451	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4452		const char warnstr[] = "error sending command";
4453
4454		if (retval < 0)
4455			warn(warnstr);
4456		else
4457			warnx(warnstr);
4458
4459		if (arglist & CAM_ARG_VERBOSE) {
4460			cam_error_print(device, ccb, CAM_ESF_ALL,
4461					CAM_EPF_ALL, stderr);
4462		}
4463	}
4464
4465	if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
4466	 && (response_size > 0)) {
4467		if (fd_response == 0) {
4468			buff_decode_visit(smp_response, response_size,
4469					  datastr, arg_put, NULL);
4470			fprintf(stdout, "\n");
4471		} else {
4472			ssize_t amt_written;
4473			int amt_to_write = response_size;
4474			u_int8_t *buf_ptr = smp_response;
4475
4476			for (amt_written = 0; (amt_to_write > 0) &&
4477			     (amt_written = write(STDOUT_FILENO, buf_ptr,
4478						  amt_to_write)) > 0;){
4479				amt_to_write -= amt_written;
4480				buf_ptr += amt_written;
4481			}
4482			if (amt_written == -1) {
4483				warn("error writing data to stdout");
4484				error = 1;
4485				goto smpcmd_bailout;
4486			} else if ((amt_written == 0)
4487				&& (amt_to_write > 0)) {
4488				warnx("only wrote %u bytes out of %u",
4489				      response_size - amt_to_write,
4490				      response_size);
4491			}
4492		}
4493	}
4494smpcmd_bailout:
4495	if (ccb != NULL)
4496		cam_freeccb(ccb);
4497
4498	if (smp_request != NULL)
4499		free(smp_request);
4500
4501	if (smp_response != NULL)
4502		free(smp_response);
4503
4504	return (error);
4505}
4506
4507static int
4508smpreportgeneral(struct cam_device *device, int argc, char **argv,
4509		 char *combinedopt, int retry_count, int timeout)
4510{
4511	union ccb *ccb;
4512	struct smp_report_general_request *request = NULL;
4513	struct smp_report_general_response *response = NULL;
4514	struct sbuf *sb = NULL;
4515	int error = 0;
4516	int c, long_response = 0;
4517	int retval;
4518
4519	/*
4520	 * Note that at the moment we don't support sending SMP CCBs to
4521	 * devices that aren't probed by CAM.
4522	 */
4523	ccb = cam_getccb(device);
4524	if (ccb == NULL) {
4525		warnx("%s: error allocating CCB", __func__);
4526		return (1);
4527	}
4528
4529	bzero(&(&ccb->ccb_h)[1],
4530	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4531
4532	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4533		switch (c) {
4534		case 'l':
4535			long_response = 1;
4536			break;
4537		default:
4538			break;
4539		}
4540	}
4541	request = malloc(sizeof(*request));
4542	if (request == NULL) {
4543		warn("%s: unable to allocate %zd bytes", __func__,
4544		     sizeof(*request));
4545		error = 1;
4546		goto bailout;
4547	}
4548
4549	response = malloc(sizeof(*response));
4550	if (response == NULL) {
4551		warn("%s: unable to allocate %zd bytes", __func__,
4552		     sizeof(*response));
4553		error = 1;
4554		goto bailout;
4555	}
4556
4557try_long:
4558	smp_report_general(&ccb->smpio,
4559			   retry_count,
4560			   /*cbfcnp*/ NULL,
4561			   request,
4562			   /*request_len*/ sizeof(*request),
4563			   (uint8_t *)response,
4564			   /*response_len*/ sizeof(*response),
4565			   /*long_response*/ long_response,
4566			   timeout);
4567
4568	if (((retval = cam_send_ccb(device, ccb)) < 0)
4569	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4570		const char warnstr[] = "error sending command";
4571
4572		if (retval < 0)
4573			warn(warnstr);
4574		else
4575			warnx(warnstr);
4576
4577		if (arglist & CAM_ARG_VERBOSE) {
4578			cam_error_print(device, ccb, CAM_ESF_ALL,
4579					CAM_EPF_ALL, stderr);
4580		}
4581		error = 1;
4582		goto bailout;
4583	}
4584
4585	/*
4586	 * If the device supports the long response bit, try again and see
4587	 * if we can get all of the data.
4588	 */
4589	if ((response->long_response & SMP_RG_LONG_RESPONSE)
4590	 && (long_response == 0)) {
4591		ccb->ccb_h.status = CAM_REQ_INPROG;
4592		bzero(&(&ccb->ccb_h)[1],
4593		      sizeof(union ccb) - sizeof(struct ccb_hdr));
4594		long_response = 1;
4595		goto try_long;
4596	}
4597
4598	/*
4599	 * XXX KDM detect and decode SMP errors here.
4600	 */
4601	sb = sbuf_new_auto();
4602	if (sb == NULL) {
4603		warnx("%s: error allocating sbuf", __func__);
4604		goto bailout;
4605	}
4606
4607	smp_report_general_sbuf(response, sizeof(*response), sb);
4608
4609	sbuf_finish(sb);
4610
4611	printf("%s", sbuf_data(sb));
4612
4613bailout:
4614	if (ccb != NULL)
4615		cam_freeccb(ccb);
4616
4617	if (request != NULL)
4618		free(request);
4619
4620	if (response != NULL)
4621		free(response);
4622
4623	if (sb != NULL)
4624		sbuf_delete(sb);
4625
4626	return (error);
4627}
4628
4629static struct camcontrol_opts phy_ops[] = {
4630	{"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL},
4631	{"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL},
4632	{"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL},
4633	{"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL},
4634	{"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL},
4635	{"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL},
4636	{"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL},
4637	{"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL},
4638	{"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL},
4639	{NULL, 0, 0, NULL}
4640};
4641
4642static int
4643smpphycontrol(struct cam_device *device, int argc, char **argv,
4644	      char *combinedopt, int retry_count, int timeout)
4645{
4646	union ccb *ccb;
4647	struct smp_phy_control_request *request = NULL;
4648	struct smp_phy_control_response *response = NULL;
4649	int long_response = 0;
4650	int retval = 0;
4651	int phy = -1;
4652	uint32_t phy_operation = SMP_PC_PHY_OP_NOP;
4653	int phy_op_set = 0;
4654	uint64_t attached_dev_name = 0;
4655	int dev_name_set = 0;
4656	uint32_t min_plr = 0, max_plr = 0;
4657	uint32_t pp_timeout_val = 0;
4658	int slumber_partial = 0;
4659	int set_pp_timeout_val = 0;
4660	int c;
4661
4662	/*
4663	 * Note that at the moment we don't support sending SMP CCBs to
4664	 * devices that aren't probed by CAM.
4665	 */
4666	ccb = cam_getccb(device);
4667	if (ccb == NULL) {
4668		warnx("%s: error allocating CCB", __func__);
4669		return (1);
4670	}
4671
4672	bzero(&(&ccb->ccb_h)[1],
4673	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4674
4675	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4676		switch (c) {
4677		case 'a':
4678		case 'A':
4679		case 's':
4680		case 'S': {
4681			int enable = -1;
4682
4683			if (strcasecmp(optarg, "enable") == 0)
4684				enable = 1;
4685			else if (strcasecmp(optarg, "disable") == 0)
4686				enable = 2;
4687			else {
4688				warnx("%s: Invalid argument %s", __func__,
4689				      optarg);
4690				retval = 1;
4691				goto bailout;
4692			}
4693			switch (c) {
4694			case 's':
4695				slumber_partial |= enable <<
4696						   SMP_PC_SAS_SLUMBER_SHIFT;
4697				break;
4698			case 'S':
4699				slumber_partial |= enable <<
4700						   SMP_PC_SAS_PARTIAL_SHIFT;
4701				break;
4702			case 'a':
4703				slumber_partial |= enable <<
4704						   SMP_PC_SATA_SLUMBER_SHIFT;
4705				break;
4706			case 'A':
4707				slumber_partial |= enable <<
4708						   SMP_PC_SATA_PARTIAL_SHIFT;
4709				break;
4710			default:
4711				warnx("%s: programmer error", __func__);
4712				retval = 1;
4713				goto bailout;
4714				break; /*NOTREACHED*/
4715			}
4716			break;
4717		}
4718		case 'd':
4719			attached_dev_name = (uintmax_t)strtoumax(optarg,
4720								 NULL,0);
4721			dev_name_set = 1;
4722			break;
4723		case 'l':
4724			long_response = 1;
4725			break;
4726		case 'm':
4727			/*
4728			 * We don't do extensive checking here, so this
4729			 * will continue to work when new speeds come out.
4730			 */
4731			min_plr = strtoul(optarg, NULL, 0);
4732			if ((min_plr == 0)
4733			 || (min_plr > 0xf)) {
4734				warnx("%s: invalid link rate %x",
4735				      __func__, min_plr);
4736				retval = 1;
4737				goto bailout;
4738			}
4739			break;
4740		case 'M':
4741			/*
4742			 * We don't do extensive checking here, so this
4743			 * will continue to work when new speeds come out.
4744			 */
4745			max_plr = strtoul(optarg, NULL, 0);
4746			if ((max_plr == 0)
4747			 || (max_plr > 0xf)) {
4748				warnx("%s: invalid link rate %x",
4749				      __func__, max_plr);
4750				retval = 1;
4751				goto bailout;
4752			}
4753			break;
4754		case 'o': {
4755			camcontrol_optret optreturn;
4756			cam_argmask argnums;
4757			const char *subopt;
4758
4759			if (phy_op_set != 0) {
4760				warnx("%s: only one phy operation argument "
4761				      "(-o) allowed", __func__);
4762				retval = 1;
4763				goto bailout;
4764			}
4765
4766			phy_op_set = 1;
4767
4768			/*
4769			 * Allow the user to specify the phy operation
4770			 * numerically, as well as with a name.  This will
4771			 * future-proof it a bit, so options that are added
4772			 * in future specs can be used.
4773			 */
4774			if (isdigit(optarg[0])) {
4775				phy_operation = strtoul(optarg, NULL, 0);
4776				if ((phy_operation == 0)
4777				 || (phy_operation > 0xff)) {
4778					warnx("%s: invalid phy operation %#x",
4779					      __func__, phy_operation);
4780					retval = 1;
4781					goto bailout;
4782				}
4783				break;
4784			}
4785			optreturn = getoption(phy_ops, optarg, &phy_operation,
4786					      &argnums, &subopt);
4787
4788			if (optreturn == CC_OR_AMBIGUOUS) {
4789				warnx("%s: ambiguous option %s", __func__,
4790				      optarg);
4791				usage(0);
4792				retval = 1;
4793				goto bailout;
4794			} else if (optreturn == CC_OR_NOT_FOUND) {
4795				warnx("%s: option %s not found", __func__,
4796				      optarg);
4797				usage(0);
4798				retval = 1;
4799				goto bailout;
4800			}
4801			break;
4802		}
4803		case 'p':
4804			phy = atoi(optarg);
4805			break;
4806		case 'T':
4807			pp_timeout_val = strtoul(optarg, NULL, 0);
4808			if (pp_timeout_val > 15) {
4809				warnx("%s: invalid partial pathway timeout "
4810				      "value %u, need a value less than 16",
4811				      __func__, pp_timeout_val);
4812				retval = 1;
4813				goto bailout;
4814			}
4815			set_pp_timeout_val = 1;
4816			break;
4817		default:
4818			break;
4819		}
4820	}
4821
4822	if (phy == -1) {
4823		warnx("%s: a PHY (-p phy) argument is required",__func__);
4824		retval = 1;
4825		goto bailout;
4826	}
4827
4828	if (((dev_name_set != 0)
4829	  && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME))
4830	 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME)
4831	  && (dev_name_set == 0))) {
4832		warnx("%s: -d name and -o setdevname arguments both "
4833		      "required to set device name", __func__);
4834		retval = 1;
4835		goto bailout;
4836	}
4837
4838	request = malloc(sizeof(*request));
4839	if (request == NULL) {
4840		warn("%s: unable to allocate %zd bytes", __func__,
4841		     sizeof(*request));
4842		retval = 1;
4843		goto bailout;
4844	}
4845
4846	response = malloc(sizeof(*response));
4847	if (response == NULL) {
4848		warn("%s: unable to allocate %zd bytes", __func__,
4849		     sizeof(*request));
4850		retval = 1;
4851		goto bailout;
4852	}
4853
4854	smp_phy_control(&ccb->smpio,
4855			retry_count,
4856			/*cbfcnp*/ NULL,
4857			request,
4858			sizeof(*request),
4859			(uint8_t *)response,
4860			sizeof(*response),
4861			long_response,
4862			/*expected_exp_change_count*/ 0,
4863			phy,
4864			phy_operation,
4865			(set_pp_timeout_val != 0) ? 1 : 0,
4866			attached_dev_name,
4867			min_plr,
4868			max_plr,
4869			slumber_partial,
4870			pp_timeout_val,
4871			timeout);
4872
4873	if (((retval = cam_send_ccb(device, ccb)) < 0)
4874	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4875		const char warnstr[] = "error sending command";
4876
4877		if (retval < 0)
4878			warn(warnstr);
4879		else
4880			warnx(warnstr);
4881
4882		if (arglist & CAM_ARG_VERBOSE) {
4883			/*
4884			 * Use CAM_EPF_NORMAL so we only get one line of
4885			 * SMP command decoding.
4886			 */
4887			cam_error_print(device, ccb, CAM_ESF_ALL,
4888					CAM_EPF_NORMAL, stderr);
4889		}
4890		retval = 1;
4891		goto bailout;
4892	}
4893
4894	/* XXX KDM print out something here for success? */
4895bailout:
4896	if (ccb != NULL)
4897		cam_freeccb(ccb);
4898
4899	if (request != NULL)
4900		free(request);
4901
4902	if (response != NULL)
4903		free(response);
4904
4905	return (retval);
4906}
4907
4908static int
4909smpmaninfo(struct cam_device *device, int argc, char **argv,
4910	   char *combinedopt, int retry_count, int timeout)
4911{
4912	union ccb *ccb;
4913	struct smp_report_manuf_info_request request;
4914	struct smp_report_manuf_info_response response;
4915	struct sbuf *sb = NULL;
4916	int long_response = 0;
4917	int retval = 0;
4918	int c;
4919
4920	/*
4921	 * Note that at the moment we don't support sending SMP CCBs to
4922	 * devices that aren't probed by CAM.
4923	 */
4924	ccb = cam_getccb(device);
4925	if (ccb == NULL) {
4926		warnx("%s: error allocating CCB", __func__);
4927		return (1);
4928	}
4929
4930	bzero(&(&ccb->ccb_h)[1],
4931	      sizeof(union ccb) - sizeof(struct ccb_hdr));
4932
4933	while ((c = getopt(argc, argv, combinedopt)) != -1) {
4934		switch (c) {
4935		case 'l':
4936			long_response = 1;
4937			break;
4938		default:
4939			break;
4940		}
4941	}
4942	bzero(&request, sizeof(request));
4943	bzero(&response, sizeof(response));
4944
4945	smp_report_manuf_info(&ccb->smpio,
4946			      retry_count,
4947			      /*cbfcnp*/ NULL,
4948			      &request,
4949			      sizeof(request),
4950			      (uint8_t *)&response,
4951			      sizeof(response),
4952			      long_response,
4953			      timeout);
4954
4955	if (((retval = cam_send_ccb(device, ccb)) < 0)
4956	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
4957		const char warnstr[] = "error sending command";
4958
4959		if (retval < 0)
4960			warn(warnstr);
4961		else
4962			warnx(warnstr);
4963
4964		if (arglist & CAM_ARG_VERBOSE) {
4965			cam_error_print(device, ccb, CAM_ESF_ALL,
4966					CAM_EPF_ALL, stderr);
4967		}
4968		retval = 1;
4969		goto bailout;
4970	}
4971
4972	sb = sbuf_new_auto();
4973	if (sb == NULL) {
4974		warnx("%s: error allocating sbuf", __func__);
4975		goto bailout;
4976	}
4977
4978	smp_report_manuf_info_sbuf(&response, sizeof(response), sb);
4979
4980	sbuf_finish(sb);
4981
4982	printf("%s", sbuf_data(sb));
4983
4984bailout:
4985
4986	if (ccb != NULL)
4987		cam_freeccb(ccb);
4988
4989	if (sb != NULL)
4990		sbuf_delete(sb);
4991
4992	return (retval);
4993}
4994
4995static int
4996getdevid(struct cam_devitem *item)
4997{
4998	int retval = 0;
4999	union ccb *ccb = NULL;
5000
5001	struct cam_device *dev;
5002
5003	dev = cam_open_btl(item->dev_match.path_id,
5004			   item->dev_match.target_id,
5005			   item->dev_match.target_lun, O_RDWR, NULL);
5006
5007	if (dev == NULL) {
5008		warnx("%s", cam_errbuf);
5009		retval = 1;
5010		goto bailout;
5011	}
5012
5013	item->device_id_len = 0;
5014
5015	ccb = cam_getccb(dev);
5016	if (ccb == NULL) {
5017		warnx("%s: error allocating CCB", __func__);
5018		retval = 1;
5019		goto bailout;
5020	}
5021
5022	bzero(&(&ccb->ccb_h)[1],
5023	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5024
5025	/*
5026	 * On the first try, we just probe for the size of the data, and
5027	 * then allocate that much memory and try again.
5028	 */
5029retry:
5030	ccb->ccb_h.func_code = XPT_DEV_ADVINFO;
5031	ccb->ccb_h.flags = CAM_DIR_IN;
5032	ccb->cdai.flags = 0;
5033	ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID;
5034	ccb->cdai.bufsiz = item->device_id_len;
5035	if (item->device_id_len != 0)
5036		ccb->cdai.buf = (uint8_t *)item->device_id;
5037
5038	if (cam_send_ccb(dev, ccb) < 0) {
5039		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
5040		retval = 1;
5041		goto bailout;
5042	}
5043
5044	if (ccb->ccb_h.status != CAM_REQ_CMP) {
5045		warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status);
5046		retval = 1;
5047		goto bailout;
5048	}
5049
5050	if (item->device_id_len == 0) {
5051		/*
5052		 * This is our first time through.  Allocate the buffer,
5053		 * and then go back to get the data.
5054		 */
5055		if (ccb->cdai.provsiz == 0) {
5056			warnx("%s: invalid .provsiz field returned with "
5057			     "XPT_GDEV_ADVINFO CCB", __func__);
5058			retval = 1;
5059			goto bailout;
5060		}
5061		item->device_id_len = ccb->cdai.provsiz;
5062		item->device_id = malloc(item->device_id_len);
5063		if (item->device_id == NULL) {
5064			warn("%s: unable to allocate %d bytes", __func__,
5065			     item->device_id_len);
5066			retval = 1;
5067			goto bailout;
5068		}
5069		ccb->ccb_h.status = CAM_REQ_INPROG;
5070		goto retry;
5071	}
5072
5073bailout:
5074	if (dev != NULL)
5075		cam_close_device(dev);
5076
5077	if (ccb != NULL)
5078		cam_freeccb(ccb);
5079
5080	return (retval);
5081}
5082
5083/*
5084 * XXX KDM merge this code with getdevtree()?
5085 */
5086static int
5087buildbusdevlist(struct cam_devlist *devlist)
5088{
5089	union ccb ccb;
5090	int bufsize, fd = -1;
5091	struct dev_match_pattern *patterns;
5092	struct cam_devitem *item = NULL;
5093	int skip_device = 0;
5094	int retval = 0;
5095
5096	if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
5097		warn("couldn't open %s", XPT_DEVICE);
5098		return(1);
5099	}
5100
5101	bzero(&ccb, sizeof(union ccb));
5102
5103	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
5104	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
5105	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
5106
5107	ccb.ccb_h.func_code = XPT_DEV_MATCH;
5108	bufsize = sizeof(struct dev_match_result) * 100;
5109	ccb.cdm.match_buf_len = bufsize;
5110	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
5111	if (ccb.cdm.matches == NULL) {
5112		warnx("can't malloc memory for matches");
5113		close(fd);
5114		return(1);
5115	}
5116	ccb.cdm.num_matches = 0;
5117	ccb.cdm.num_patterns = 2;
5118	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) *
5119		ccb.cdm.num_patterns;
5120
5121	patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len);
5122	if (patterns == NULL) {
5123		warnx("can't malloc memory for patterns");
5124		retval = 1;
5125		goto bailout;
5126	}
5127
5128	ccb.cdm.patterns = patterns;
5129	bzero(patterns, ccb.cdm.pattern_buf_len);
5130
5131	patterns[0].type = DEV_MATCH_DEVICE;
5132	patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH;
5133	patterns[0].pattern.device_pattern.path_id = devlist->path_id;
5134	patterns[1].type = DEV_MATCH_PERIPH;
5135	patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH;
5136	patterns[1].pattern.periph_pattern.path_id = devlist->path_id;
5137
5138	/*
5139	 * We do the ioctl multiple times if necessary, in case there are
5140	 * more than 100 nodes in the EDT.
5141	 */
5142	do {
5143		unsigned int i;
5144
5145		if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
5146			warn("error sending CAMIOCOMMAND ioctl");
5147			retval = 1;
5148			goto bailout;
5149		}
5150
5151		if ((ccb.ccb_h.status != CAM_REQ_CMP)
5152		 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
5153		    && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
5154			warnx("got CAM error %#x, CDM error %d\n",
5155			      ccb.ccb_h.status, ccb.cdm.status);
5156			retval = 1;
5157			goto bailout;
5158		}
5159
5160		for (i = 0; i < ccb.cdm.num_matches; i++) {
5161			switch (ccb.cdm.matches[i].type) {
5162			case DEV_MATCH_DEVICE: {
5163				struct device_match_result *dev_result;
5164
5165				dev_result =
5166				     &ccb.cdm.matches[i].result.device_result;
5167
5168				if (dev_result->flags &
5169				    DEV_RESULT_UNCONFIGURED) {
5170					skip_device = 1;
5171					break;
5172				} else
5173					skip_device = 0;
5174
5175				item = malloc(sizeof(*item));
5176				if (item == NULL) {
5177					warn("%s: unable to allocate %zd bytes",
5178					     __func__, sizeof(*item));
5179					retval = 1;
5180					goto bailout;
5181				}
5182				bzero(item, sizeof(*item));
5183				bcopy(dev_result, &item->dev_match,
5184				      sizeof(*dev_result));
5185				STAILQ_INSERT_TAIL(&devlist->dev_queue, item,
5186						   links);
5187
5188				if (getdevid(item) != 0) {
5189					retval = 1;
5190					goto bailout;
5191				}
5192				break;
5193			}
5194			case DEV_MATCH_PERIPH: {
5195				struct periph_match_result *periph_result;
5196
5197				periph_result =
5198				      &ccb.cdm.matches[i].result.periph_result;
5199
5200				if (skip_device != 0)
5201					break;
5202				item->num_periphs++;
5203				item->periph_matches = realloc(
5204					item->periph_matches,
5205					item->num_periphs *
5206					sizeof(struct periph_match_result));
5207				if (item->periph_matches == NULL) {
5208					warn("%s: error allocating periph "
5209					     "list", __func__);
5210					retval = 1;
5211					goto bailout;
5212				}
5213				bcopy(periph_result, &item->periph_matches[
5214				      item->num_periphs - 1],
5215				      sizeof(*periph_result));
5216				break;
5217			}
5218			default:
5219				fprintf(stderr, "%s: unexpected match "
5220					"type %d\n", __func__,
5221					ccb.cdm.matches[i].type);
5222				retval = 1;
5223				goto bailout;
5224				break; /*NOTREACHED*/
5225			}
5226		}
5227	} while ((ccb.ccb_h.status == CAM_REQ_CMP)
5228		&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
5229bailout:
5230
5231	if (fd != -1)
5232		close(fd);
5233
5234	free(patterns);
5235
5236	free(ccb.cdm.matches);
5237
5238	if (retval != 0)
5239		freebusdevlist(devlist);
5240
5241	return (retval);
5242}
5243
5244static void
5245freebusdevlist(struct cam_devlist *devlist)
5246{
5247	struct cam_devitem *item, *item2;
5248
5249	STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) {
5250		STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem,
5251			      links);
5252		free(item->device_id);
5253		free(item->periph_matches);
5254		free(item);
5255	}
5256}
5257
5258static struct cam_devitem *
5259findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr)
5260{
5261	struct cam_devitem *item;
5262
5263	STAILQ_FOREACH(item, &devlist->dev_queue, links) {
5264		uint8_t *item_addr;
5265
5266		/*
5267		 * XXX KDM look for LUN IDs as well?
5268		 */
5269		item_addr = scsi_get_devid(item->device_id,
5270					   item->device_id_len,
5271					   scsi_devid_is_sas_target);
5272		if (item_addr == NULL)
5273			continue;
5274
5275		if (scsi_8btou64(item_addr) == sasaddr)
5276			return (item);
5277	}
5278
5279	return (NULL);
5280}
5281
5282static int
5283smpphylist(struct cam_device *device, int argc, char **argv,
5284	   char *combinedopt, int retry_count, int timeout)
5285{
5286	struct smp_report_general_request *rgrequest = NULL;
5287	struct smp_report_general_response *rgresponse = NULL;
5288	struct smp_discover_request *disrequest = NULL;
5289	struct smp_discover_response *disresponse = NULL;
5290	struct cam_devlist devlist;
5291	union ccb *ccb;
5292	int long_response = 0;
5293	int num_phys = 0;
5294	int quiet = 0;
5295	int retval;
5296	int i, c;
5297
5298	/*
5299	 * Note that at the moment we don't support sending SMP CCBs to
5300	 * devices that aren't probed by CAM.
5301	 */
5302	ccb = cam_getccb(device);
5303	if (ccb == NULL) {
5304		warnx("%s: error allocating CCB", __func__);
5305		return (1);
5306	}
5307
5308	bzero(&(&ccb->ccb_h)[1],
5309	      sizeof(union ccb) - sizeof(struct ccb_hdr));
5310
5311	rgrequest = malloc(sizeof(*rgrequest));
5312	if (rgrequest == NULL) {
5313		warn("%s: unable to allocate %zd bytes", __func__,
5314		     sizeof(*rgrequest));
5315		retval = 1;
5316		goto bailout;
5317	}
5318
5319	rgresponse = malloc(sizeof(*rgresponse));
5320	if (rgresponse == NULL) {
5321		warn("%s: unable to allocate %zd bytes", __func__,
5322		     sizeof(*rgresponse));
5323		retval = 1;
5324		goto bailout;
5325	}
5326
5327	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5328		switch (c) {
5329		case 'l':
5330			long_response = 1;
5331			break;
5332		case 'q':
5333			quiet = 1;
5334			break;
5335		default:
5336			break;
5337		}
5338	}
5339
5340	smp_report_general(&ccb->smpio,
5341			   retry_count,
5342			   /*cbfcnp*/ NULL,
5343			   rgrequest,
5344			   /*request_len*/ sizeof(*rgrequest),
5345			   (uint8_t *)rgresponse,
5346			   /*response_len*/ sizeof(*rgresponse),
5347			   /*long_response*/ long_response,
5348			   timeout);
5349
5350	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5351
5352	if (((retval = cam_send_ccb(device, ccb)) < 0)
5353	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
5354		const char warnstr[] = "error sending command";
5355
5356		if (retval < 0)
5357			warn(warnstr);
5358		else
5359			warnx(warnstr);
5360
5361		if (arglist & CAM_ARG_VERBOSE) {
5362			cam_error_print(device, ccb, CAM_ESF_ALL,
5363					CAM_EPF_ALL, stderr);
5364		}
5365		retval = 1;
5366		goto bailout;
5367	}
5368
5369	num_phys = rgresponse->num_phys;
5370
5371	if (num_phys == 0) {
5372		if (quiet == 0)
5373			fprintf(stdout, "%s: No Phys reported\n", __func__);
5374		retval = 1;
5375		goto bailout;
5376	}
5377
5378	STAILQ_INIT(&devlist.dev_queue);
5379	devlist.path_id = device->path_id;
5380
5381	retval = buildbusdevlist(&devlist);
5382	if (retval != 0)
5383		goto bailout;
5384
5385	if (quiet == 0) {
5386		fprintf(stdout, "%d PHYs:\n", num_phys);
5387		fprintf(stdout, "PHY  Attached SAS Address\n");
5388	}
5389
5390	disrequest = malloc(sizeof(*disrequest));
5391	if (disrequest == NULL) {
5392		warn("%s: unable to allocate %zd bytes", __func__,
5393		     sizeof(*disrequest));
5394		retval = 1;
5395		goto bailout;
5396	}
5397
5398	disresponse = malloc(sizeof(*disresponse));
5399	if (disresponse == NULL) {
5400		warn("%s: unable to allocate %zd bytes", __func__,
5401		     sizeof(*disresponse));
5402		retval = 1;
5403		goto bailout;
5404	}
5405
5406	for (i = 0; i < num_phys; i++) {
5407		struct cam_devitem *item;
5408		struct device_match_result *dev_match;
5409		char vendor[16], product[48], revision[16];
5410		char tmpstr[256];
5411		int j;
5412
5413		bzero(&(&ccb->ccb_h)[1],
5414		      sizeof(union ccb) - sizeof(struct ccb_hdr));
5415
5416		ccb->ccb_h.status = CAM_REQ_INPROG;
5417		ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5418
5419		smp_discover(&ccb->smpio,
5420			     retry_count,
5421			     /*cbfcnp*/ NULL,
5422			     disrequest,
5423			     sizeof(*disrequest),
5424			     (uint8_t *)disresponse,
5425			     sizeof(*disresponse),
5426			     long_response,
5427			     /*ignore_zone_group*/ 0,
5428			     /*phy*/ i,
5429			     timeout);
5430
5431		if (((retval = cam_send_ccb(device, ccb)) < 0)
5432		 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
5433		  && (disresponse->function_result != SMP_FR_PHY_VACANT))) {
5434			const char warnstr[] = "error sending command";
5435
5436			if (retval < 0)
5437				warn(warnstr);
5438			else
5439				warnx(warnstr);
5440
5441			if (arglist & CAM_ARG_VERBOSE) {
5442				cam_error_print(device, ccb, CAM_ESF_ALL,
5443						CAM_EPF_ALL, stderr);
5444			}
5445			retval = 1;
5446			goto bailout;
5447		}
5448
5449		if (disresponse->function_result == SMP_FR_PHY_VACANT) {
5450			if (quiet == 0)
5451				fprintf(stdout, "%3d  <vacant>\n", i);
5452			continue;
5453		}
5454
5455		item = findsasdevice(&devlist,
5456			scsi_8btou64(disresponse->attached_sas_address));
5457
5458		if ((quiet == 0)
5459		 || (item != NULL)) {
5460			fprintf(stdout, "%3d  0x%016jx", i,
5461				(uintmax_t)scsi_8btou64(
5462				disresponse->attached_sas_address));
5463			if (item == NULL) {
5464				fprintf(stdout, "\n");
5465				continue;
5466			}
5467		} else if (quiet != 0)
5468			continue;
5469
5470		dev_match = &item->dev_match;
5471
5472		if (dev_match->protocol == PROTO_SCSI) {
5473			cam_strvis(vendor, dev_match->inq_data.vendor,
5474				   sizeof(dev_match->inq_data.vendor),
5475				   sizeof(vendor));
5476			cam_strvis(product, dev_match->inq_data.product,
5477				   sizeof(dev_match->inq_data.product),
5478				   sizeof(product));
5479			cam_strvis(revision, dev_match->inq_data.revision,
5480				   sizeof(dev_match->inq_data.revision),
5481				   sizeof(revision));
5482			sprintf(tmpstr, "<%s %s %s>", vendor, product,
5483				revision);
5484		} else if ((dev_match->protocol == PROTO_ATA)
5485			|| (dev_match->protocol == PROTO_SATAPM)) {
5486			cam_strvis(product, dev_match->ident_data.model,
5487				   sizeof(dev_match->ident_data.model),
5488				   sizeof(product));
5489			cam_strvis(revision, dev_match->ident_data.revision,
5490				   sizeof(dev_match->ident_data.revision),
5491				   sizeof(revision));
5492			sprintf(tmpstr, "<%s %s>", product, revision);
5493		} else {
5494			sprintf(tmpstr, "<>");
5495		}
5496		fprintf(stdout, "   %-33s ", tmpstr);
5497
5498		/*
5499		 * If we have 0 periphs, that's a bug...
5500		 */
5501		if (item->num_periphs == 0) {
5502			fprintf(stdout, "\n");
5503			continue;
5504		}
5505
5506		fprintf(stdout, "(");
5507		for (j = 0; j < item->num_periphs; j++) {
5508			if (j > 0)
5509				fprintf(stdout, ",");
5510
5511			fprintf(stdout, "%s%d",
5512				item->periph_matches[j].periph_name,
5513				item->periph_matches[j].unit_number);
5514
5515		}
5516		fprintf(stdout, ")\n");
5517	}
5518bailout:
5519	if (ccb != NULL)
5520		cam_freeccb(ccb);
5521
5522	free(rgrequest);
5523
5524	free(rgresponse);
5525
5526	free(disrequest);
5527
5528	free(disresponse);
5529
5530	freebusdevlist(&devlist);
5531
5532	return (retval);
5533}
5534
5535static int
5536atapm(struct cam_device *device, int argc, char **argv,
5537		 char *combinedopt, int retry_count, int timeout)
5538{
5539	union ccb *ccb;
5540	int retval = 0;
5541	int t = -1;
5542	int c;
5543	u_char cmd, sc;
5544
5545	ccb = cam_getccb(device);
5546
5547	if (ccb == NULL) {
5548		warnx("%s: error allocating ccb", __func__);
5549		return (1);
5550	}
5551
5552	while ((c = getopt(argc, argv, combinedopt)) != -1) {
5553		switch (c) {
5554		case 't':
5555			t = atoi(optarg);
5556			break;
5557		default:
5558			break;
5559		}
5560	}
5561	if (strcmp(argv[1], "idle") == 0) {
5562		if (t == -1)
5563			cmd = ATA_IDLE_IMMEDIATE;
5564		else
5565			cmd = ATA_IDLE_CMD;
5566	} else if (strcmp(argv[1], "standby") == 0) {
5567		if (t == -1)
5568			cmd = ATA_STANDBY_IMMEDIATE;
5569		else
5570			cmd = ATA_STANDBY_CMD;
5571	} else {
5572		cmd = ATA_SLEEP;
5573		t = -1;
5574	}
5575
5576	if (t < 0)
5577		sc = 0;
5578	else if (t <= (240 * 5))
5579		sc = (t + 4) / 5;
5580	else if (t <= (252 * 5))
5581		/* special encoding for 21 minutes */
5582		sc = 252;
5583	else if (t <= (11 * 30 * 60))
5584		sc = (t - 1) / (30 * 60) + 241;
5585	else
5586		sc = 253;
5587
5588	cam_fill_ataio(&ccb->ataio,
5589		      retry_count,
5590		      NULL,
5591		      /*flags*/CAM_DIR_NONE,
5592		      MSG_SIMPLE_Q_TAG,
5593		      /*data_ptr*/NULL,
5594		      /*dxfer_len*/0,
5595		      timeout ? timeout : 30 * 1000);
5596	ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
5597
5598	/* Disable freezing the device queue */
5599	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
5600
5601	if (arglist & CAM_ARG_ERR_RECOVER)
5602		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
5603
5604	if (cam_send_ccb(device, ccb) < 0) {
5605		warn("error sending command");
5606
5607		if (arglist & CAM_ARG_VERBOSE)
5608			cam_error_print(device, ccb, CAM_ESF_ALL,
5609					CAM_EPF_ALL, stderr);
5610
5611		retval = 1;
5612		goto bailout;
5613	}
5614
5615	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
5616		cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
5617		retval = 1;
5618		goto bailout;
5619	}
5620bailout:
5621	cam_freeccb(ccb);
5622	return (retval);
5623}
5624
5625#endif /* MINIMALISTIC */
5626
5627void
5628usage(int verbose)
5629{
5630	fprintf(verbose ? stdout : stderr,
5631"usage:  camcontrol <command>  [device id][generic args][command args]\n"
5632"        camcontrol devlist    [-v]\n"
5633#ifndef MINIMALISTIC
5634"        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
5635"        camcontrol tur        [dev_id][generic args]\n"
5636"        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
5637"        camcontrol identify   [dev_id][generic args] [-v]\n"
5638"        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
5639"        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
5640"                              [-q] [-s]\n"
5641"        camcontrol start      [dev_id][generic args]\n"
5642"        camcontrol stop       [dev_id][generic args]\n"
5643"        camcontrol load       [dev_id][generic args]\n"
5644"        camcontrol eject      [dev_id][generic args]\n"
5645#endif /* MINIMALISTIC */
5646"        camcontrol rescan     <all | bus[:target:lun]>\n"
5647"        camcontrol reset      <all | bus[:target:lun]>\n"
5648#ifndef MINIMALISTIC
5649"        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]\n"
5650"        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
5651"                              [-P pagectl][-e | -b][-d]\n"
5652"        camcontrol cmd        [dev_id][generic args]\n"
5653"                              <-a cmd [args] | -c cmd [args]>\n"
5654"                              [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
5655"        camcontrol smpcmd     [dev_id][generic args]\n"
5656"                              <-r len fmt [args]> <-R len fmt [args]>\n"
5657"        camcontrol smprg      [dev_id][generic args][-l]\n"
5658"        camcontrol smppc      [dev_id][generic args] <-p phy> [-l]\n"
5659"                              [-o operation][-d name][-m rate][-M rate]\n"
5660"                              [-T pp_timeout][-a enable|disable]\n"
5661"                              [-A enable|disable][-s enable|disable]\n"
5662"                              [-S enable|disable]\n"
5663"        camcontrol smpphylist [dev_id][generic args][-l][-q]\n"
5664"        camcontrol smpmaninfo [dev_id][generic args][-l]\n"
5665"        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
5666"                              <all|bus[:target[:lun]]|off>\n"
5667"        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
5668"        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
5669"                              [-D <enable|disable>][-M mode][-O offset]\n"
5670"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
5671"                              [-U][-W bus_width]\n"
5672"        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
5673"        camcontrol idle       [dev_id][generic args][-t time]\n"
5674"        camcontrol standby    [dev_id][generic args][-t time]\n"
5675"        camcontrol sleep      [dev_id][generic args]\n"
5676"        camcontrol fwdownload [dev_id][generic args] <-f fw_image> [-y][-s]\n"
5677#endif /* MINIMALISTIC */
5678"        camcontrol help\n");
5679	if (!verbose)
5680		return;
5681#ifndef MINIMALISTIC
5682	fprintf(stdout,
5683"Specify one of the following options:\n"
5684"devlist     list all CAM devices\n"
5685"periphlist  list all CAM peripheral drivers attached to a device\n"
5686"tur         send a test unit ready to the named device\n"
5687"inquiry     send a SCSI inquiry command to the named device\n"
5688"identify    send a ATA identify command to the named device\n"
5689"reportluns  send a SCSI report luns command to the device\n"
5690"readcap     send a SCSI read capacity command to the device\n"
5691"start       send a Start Unit command to the device\n"
5692"stop        send a Stop Unit command to the device\n"
5693"load        send a Start Unit command to the device with the load bit set\n"
5694"eject       send a Stop Unit command to the device with the eject bit set\n"
5695"rescan      rescan all busses, the given bus, or bus:target:lun\n"
5696"reset       reset all busses, the given bus, or bus:target:lun\n"
5697"defects     read the defect list of the specified device\n"
5698"modepage    display or edit (-e) the given mode page\n"
5699"cmd         send the given SCSI command, may need -i or -o as well\n"
5700"smpcmd      send the given SMP command, requires -o and -i\n"
5701"smprg       send the SMP Report General command\n"
5702"smppc       send the SMP PHY Control command, requires -p\n"
5703"smpphylist  display phys attached to a SAS expander\n"
5704"smpmaninfo  send the SMP Report Manufacturer Info command\n"
5705"debug       turn debugging on/off for a bus, target, or lun, or all devices\n"
5706"tags        report or set the number of transaction slots for a device\n"
5707"negotiate   report or set device negotiation parameters\n"
5708"format      send the SCSI FORMAT UNIT command to the named device\n"
5709"idle        send the ATA IDLE command to the named device\n"
5710"standby     send the ATA STANDBY command to the named device\n"
5711"sleep       send the ATA SLEEP command to the named device\n"
5712"fwdownload  program firmware of the named device with the given image"
5713"help        this message\n"
5714"Device Identifiers:\n"
5715"bus:target        specify the bus and target, lun defaults to 0\n"
5716"bus:target:lun    specify the bus, target and lun\n"
5717"deviceUNIT        specify the device name, like \"da4\" or \"cd2\"\n"
5718"Generic arguments:\n"
5719"-v                be verbose, print out sense information\n"
5720"-t timeout        command timeout in seconds, overrides default timeout\n"
5721"-n dev_name       specify device name, e.g. \"da\", \"cd\"\n"
5722"-u unit           specify unit number, e.g. \"0\", \"5\"\n"
5723"-E                have the kernel attempt to perform SCSI error recovery\n"
5724"-C count          specify the SCSI command retry count (needs -E to work)\n"
5725"modepage arguments:\n"
5726"-l                list all available mode pages\n"
5727"-m page           specify the mode page to view or edit\n"
5728"-e                edit the specified mode page\n"
5729"-b                force view to binary mode\n"
5730"-d                disable block descriptors for mode sense\n"
5731"-P pgctl          page control field 0-3\n"
5732"defects arguments:\n"
5733"-f format         specify defect list format (block, bfi or phys)\n"
5734"-G                get the grown defect list\n"
5735"-P                get the permanent defect list\n"
5736"inquiry arguments:\n"
5737"-D                get the standard inquiry data\n"
5738"-S                get the serial number\n"
5739"-R                get the transfer rate, etc.\n"
5740"reportluns arguments:\n"
5741"-c                only report a count of available LUNs\n"
5742"-l                only print out luns, and not a count\n"
5743"-r <reporttype>   specify \"default\", \"wellknown\" or \"all\"\n"
5744"readcap arguments\n"
5745"-b                only report the blocksize\n"
5746"-h                human readable device size, base 2\n"
5747"-H                human readable device size, base 10\n"
5748"-N                print the number of blocks instead of last block\n"
5749"-q                quiet, print numbers only\n"
5750"-s                only report the last block/device size\n"
5751"cmd arguments:\n"
5752"-c cdb [args]     specify the SCSI CDB\n"
5753"-i len fmt        specify input data and input data format\n"
5754"-o len fmt [args] specify output data and output data fmt\n"
5755"smpcmd arguments:\n"
5756"-r len fmt [args] specify the SMP command to be sent\n"
5757"-R len fmt [args] specify SMP response format\n"
5758"smprg arguments:\n"
5759"-l                specify the long response format\n"
5760"smppc arguments:\n"
5761"-p phy            specify the PHY to operate on\n"
5762"-l                specify the long request/response format\n"
5763"-o operation      specify the phy control operation\n"
5764"-d name           set the attached device name\n"
5765"-m rate           set the minimum physical link rate\n"
5766"-M rate           set the maximum physical link rate\n"
5767"-T pp_timeout     set the partial pathway timeout value\n"
5768"-a enable|disable enable or disable SATA slumber\n"
5769"-A enable|disable enable or disable SATA partial phy power\n"
5770"-s enable|disable enable or disable SAS slumber\n"
5771"-S enable|disable enable or disable SAS partial phy power\n"
5772"smpphylist arguments:\n"
5773"-l                specify the long response format\n"
5774"-q                only print phys with attached devices\n"
5775"smpmaninfo arguments:\n"
5776"-l                specify the long response format\n"
5777"debug arguments:\n"
5778"-I                CAM_DEBUG_INFO -- scsi commands, errors, data\n"
5779"-T                CAM_DEBUG_TRACE -- routine flow tracking\n"
5780"-S                CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
5781"-c                CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
5782"tags arguments:\n"
5783"-N tags           specify the number of tags to use for this device\n"
5784"-q                be quiet, don't report the number of tags\n"
5785"-v                report a number of tag-related parameters\n"
5786"negotiate arguments:\n"
5787"-a                send a test unit ready after negotiation\n"
5788"-c                report/set current negotiation settings\n"
5789"-D <arg>          \"enable\" or \"disable\" disconnection\n"
5790"-M mode           set ATA mode\n"
5791"-O offset         set command delay offset\n"
5792"-q                be quiet, don't report anything\n"
5793"-R syncrate       synchronization rate in MHz\n"
5794"-T <arg>          \"enable\" or \"disable\" tagged queueing\n"
5795"-U                report/set user negotiation settings\n"
5796"-W bus_width      set the bus width in bits (8, 16 or 32)\n"
5797"-v                also print a Path Inquiry CCB for the controller\n"
5798"format arguments:\n"
5799"-q                be quiet, don't print status messages\n"
5800"-r                run in report only mode\n"
5801"-w                don't send immediate format command\n"
5802"-y                don't ask any questions\n"
5803"idle/standby arguments:\n"
5804"-t <arg>          number of seconds before respective state.\n"
5805"fwdownload arguments:\n"
5806"-f fw_image       path to firmware image file\n"
5807"-y                don't ask any questions\n"
5808"-s                run in simulation mode\n"
5809"-v                print info for every firmware segment sent to device\n");
5810#endif /* MINIMALISTIC */
5811}
5812
5813int
5814main(int argc, char **argv)
5815{
5816	int c;
5817	char *device = NULL;
5818	int unit = 0;
5819	struct cam_device *cam_dev = NULL;
5820	int timeout = 0, retry_count = 1;
5821	camcontrol_optret optreturn;
5822	char *tstr;
5823	const char *mainopt = "C:En:t:u:v";
5824	const char *subopt = NULL;
5825	char combinedopt[256];
5826	int error = 0, optstart = 2;
5827	int devopen = 1;
5828#ifndef MINIMALISTIC
5829	int bus, target, lun;
5830#endif /* MINIMALISTIC */
5831
5832	cmdlist = CAM_CMD_NONE;
5833	arglist = CAM_ARG_NONE;
5834
5835	if (argc < 2) {
5836		usage(0);
5837		exit(1);
5838	}
5839
5840	/*
5841	 * Get the base option.
5842	 */
5843	optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt);
5844
5845	if (optreturn == CC_OR_AMBIGUOUS) {
5846		warnx("ambiguous option %s", argv[1]);
5847		usage(0);
5848		exit(1);
5849	} else if (optreturn == CC_OR_NOT_FOUND) {
5850		warnx("option %s not found", argv[1]);
5851		usage(0);
5852		exit(1);
5853	}
5854
5855	/*
5856	 * Ahh, getopt(3) is a pain.
5857	 *
5858	 * This is a gross hack.  There really aren't many other good
5859	 * options (excuse the pun) for parsing options in a situation like
5860	 * this.  getopt is kinda braindead, so you end up having to run
5861	 * through the options twice, and give each invocation of getopt
5862	 * the option string for the other invocation.
5863	 *
5864	 * You would think that you could just have two groups of options.
5865	 * The first group would get parsed by the first invocation of
5866	 * getopt, and the second group would get parsed by the second
5867	 * invocation of getopt.  It doesn't quite work out that way.  When
5868	 * the first invocation of getopt finishes, it leaves optind pointing
5869	 * to the argument _after_ the first argument in the second group.
5870	 * So when the second invocation of getopt comes around, it doesn't
5871	 * recognize the first argument it gets and then bails out.
5872	 *
5873	 * A nice alternative would be to have a flag for getopt that says
5874	 * "just keep parsing arguments even when you encounter an unknown
5875	 * argument", but there isn't one.  So there's no real clean way to
5876	 * easily parse two sets of arguments without having one invocation
5877	 * of getopt know about the other.
5878	 *
5879	 * Without this hack, the first invocation of getopt would work as
5880	 * long as the generic arguments are first, but the second invocation
5881	 * (in the subfunction) would fail in one of two ways.  In the case
5882	 * where you don't set optreset, it would fail because optind may be
5883	 * pointing to the argument after the one it should be pointing at.
5884	 * In the case where you do set optreset, and reset optind, it would
5885	 * fail because getopt would run into the first set of options, which
5886	 * it doesn't understand.
5887	 *
5888	 * All of this would "sort of" work if you could somehow figure out
5889	 * whether optind had been incremented one option too far.  The
5890	 * mechanics of that, however, are more daunting than just giving
5891	 * both invocations all of the expect options for either invocation.
5892	 *
5893	 * Needless to say, I wouldn't mind if someone invented a better
5894	 * (non-GPL!) command line parsing interface than getopt.  I
5895	 * wouldn't mind if someone added more knobs to getopt to make it
5896	 * work better.  Who knows, I may talk myself into doing it someday,
5897	 * if the standards weenies let me.  As it is, it just leads to
5898	 * hackery like this and causes people to avoid it in some cases.
5899	 *
5900	 * KDM, September 8th, 1998
5901	 */
5902	if (subopt != NULL)
5903		sprintf(combinedopt, "%s%s", mainopt, subopt);
5904	else
5905		sprintf(combinedopt, "%s", mainopt);
5906
5907	/*
5908	 * For these options we do not parse optional device arguments and
5909	 * we do not open a passthrough device.
5910	 */
5911	if ((cmdlist == CAM_CMD_RESCAN)
5912	 || (cmdlist == CAM_CMD_RESET)
5913	 || (cmdlist == CAM_CMD_DEVTREE)
5914	 || (cmdlist == CAM_CMD_USAGE)
5915	 || (cmdlist == CAM_CMD_DEBUG))
5916		devopen = 0;
5917
5918#ifndef MINIMALISTIC
5919	if ((devopen == 1)
5920	 && (argc > 2 && argv[2][0] != '-')) {
5921		char name[30];
5922		int rv;
5923
5924		if (isdigit(argv[2][0])) {
5925			/* device specified as bus:target[:lun] */
5926			rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
5927			if (rv < 2)
5928				errx(1, "numeric device specification must "
5929				     "be either bus:target, or "
5930				     "bus:target:lun");
5931			/* default to 0 if lun was not specified */
5932			if ((arglist & CAM_ARG_LUN) == 0) {
5933				lun = 0;
5934				arglist |= CAM_ARG_LUN;
5935			}
5936			optstart++;
5937		} else {
5938			if (cam_get_device(argv[2], name, sizeof name, &unit)
5939			    == -1)
5940				errx(1, "%s", cam_errbuf);
5941			device = strdup(name);
5942			arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
5943			optstart++;
5944		}
5945	}
5946#endif /* MINIMALISTIC */
5947	/*
5948	 * Start getopt processing at argv[2/3], since we've already
5949	 * accepted argv[1..2] as the command name, and as a possible
5950	 * device name.
5951	 */
5952	optind = optstart;
5953
5954	/*
5955	 * Now we run through the argument list looking for generic
5956	 * options, and ignoring options that possibly belong to
5957	 * subfunctions.
5958	 */
5959	while ((c = getopt(argc, argv, combinedopt))!= -1){
5960		switch(c) {
5961			case 'C':
5962				retry_count = strtol(optarg, NULL, 0);
5963				if (retry_count < 0)
5964					errx(1, "retry count %d is < 0",
5965					     retry_count);
5966				arglist |= CAM_ARG_RETRIES;
5967				break;
5968			case 'E':
5969				arglist |= CAM_ARG_ERR_RECOVER;
5970				break;
5971			case 'n':
5972				arglist |= CAM_ARG_DEVICE;
5973				tstr = optarg;
5974				while (isspace(*tstr) && (*tstr != '\0'))
5975					tstr++;
5976				device = (char *)strdup(tstr);
5977				break;
5978			case 't':
5979				timeout = strtol(optarg, NULL, 0);
5980				if (timeout < 0)
5981					errx(1, "invalid timeout %d", timeout);
5982				/* Convert the timeout from seconds to ms */
5983				timeout *= 1000;
5984				arglist |= CAM_ARG_TIMEOUT;
5985				break;
5986			case 'u':
5987				arglist |= CAM_ARG_UNIT;
5988				unit = strtol(optarg, NULL, 0);
5989				break;
5990			case 'v':
5991				arglist |= CAM_ARG_VERBOSE;
5992				break;
5993			default:
5994				break;
5995		}
5996	}
5997
5998#ifndef MINIMALISTIC
5999	/*
6000	 * For most commands we'll want to open the passthrough device
6001	 * associated with the specified device.  In the case of the rescan
6002	 * commands, we don't use a passthrough device at all, just the
6003	 * transport layer device.
6004	 */
6005	if (devopen == 1) {
6006		if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
6007		 && (((arglist & CAM_ARG_DEVICE) == 0)
6008		  || ((arglist & CAM_ARG_UNIT) == 0))) {
6009			errx(1, "subcommand \"%s\" requires a valid device "
6010			     "identifier", argv[1]);
6011		}
6012
6013		if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
6014				cam_open_btl(bus, target, lun, O_RDWR, NULL) :
6015				cam_open_spec_device(device,unit,O_RDWR,NULL)))
6016		     == NULL)
6017			errx(1,"%s", cam_errbuf);
6018	}
6019#endif /* MINIMALISTIC */
6020
6021	/*
6022	 * Reset optind to 2, and reset getopt, so these routines can parse
6023	 * the arguments again.
6024	 */
6025	optind = optstart;
6026	optreset = 1;
6027
6028	switch(cmdlist) {
6029#ifndef MINIMALISTIC
6030		case CAM_CMD_DEVLIST:
6031			error = getdevlist(cam_dev);
6032			break;
6033#endif /* MINIMALISTIC */
6034		case CAM_CMD_DEVTREE:
6035			error = getdevtree();
6036			break;
6037#ifndef MINIMALISTIC
6038		case CAM_CMD_TUR:
6039			error = testunitready(cam_dev, retry_count, timeout, 0);
6040			break;
6041		case CAM_CMD_INQUIRY:
6042			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
6043					      retry_count, timeout);
6044			break;
6045		case CAM_CMD_IDENTIFY:
6046			error = ataidentify(cam_dev, retry_count, timeout);
6047			break;
6048		case CAM_CMD_STARTSTOP:
6049			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
6050					  arglist & CAM_ARG_EJECT, retry_count,
6051					  timeout);
6052			break;
6053#endif /* MINIMALISTIC */
6054		case CAM_CMD_RESCAN:
6055			error = dorescan_or_reset(argc, argv, 1);
6056			break;
6057		case CAM_CMD_RESET:
6058			error = dorescan_or_reset(argc, argv, 0);
6059			break;
6060#ifndef MINIMALISTIC
6061		case CAM_CMD_READ_DEFECTS:
6062			error = readdefects(cam_dev, argc, argv, combinedopt,
6063					    retry_count, timeout);
6064			break;
6065		case CAM_CMD_MODE_PAGE:
6066			modepage(cam_dev, argc, argv, combinedopt,
6067				 retry_count, timeout);
6068			break;
6069		case CAM_CMD_SCSI_CMD:
6070			error = scsicmd(cam_dev, argc, argv, combinedopt,
6071					retry_count, timeout);
6072			break;
6073		case CAM_CMD_SMP_CMD:
6074			error = smpcmd(cam_dev, argc, argv, combinedopt,
6075				       retry_count, timeout);
6076			break;
6077		case CAM_CMD_SMP_RG:
6078			error = smpreportgeneral(cam_dev, argc, argv,
6079						 combinedopt, retry_count,
6080						 timeout);
6081			break;
6082		case CAM_CMD_SMP_PC:
6083			error = smpphycontrol(cam_dev, argc, argv, combinedopt,
6084					      retry_count, timeout);
6085			break;
6086		case CAM_CMD_SMP_PHYLIST:
6087			error = smpphylist(cam_dev, argc, argv, combinedopt,
6088					   retry_count, timeout);
6089			break;
6090		case CAM_CMD_SMP_MANINFO:
6091			error = smpmaninfo(cam_dev, argc, argv, combinedopt,
6092					   retry_count, timeout);
6093			break;
6094		case CAM_CMD_DEBUG:
6095			error = camdebug(argc, argv, combinedopt);
6096			break;
6097		case CAM_CMD_TAG:
6098			error = tagcontrol(cam_dev, argc, argv, combinedopt);
6099			break;
6100		case CAM_CMD_RATE:
6101			error = ratecontrol(cam_dev, retry_count, timeout,
6102					    argc, argv, combinedopt);
6103			break;
6104		case CAM_CMD_FORMAT:
6105			error = scsiformat(cam_dev, argc, argv,
6106					   combinedopt, retry_count, timeout);
6107			break;
6108		case CAM_CMD_REPORTLUNS:
6109			error = scsireportluns(cam_dev, argc, argv,
6110					       combinedopt, retry_count,
6111					       timeout);
6112			break;
6113		case CAM_CMD_READCAP:
6114			error = scsireadcapacity(cam_dev, argc, argv,
6115						 combinedopt, retry_count,
6116						 timeout);
6117			break;
6118		case CAM_CMD_IDLE:
6119		case CAM_CMD_STANDBY:
6120		case CAM_CMD_SLEEP:
6121			error = atapm(cam_dev, argc, argv,
6122						 combinedopt, retry_count,
6123						 timeout);
6124			break;
6125		case CAM_CMD_DOWNLOAD_FW:
6126			error = fwdownload(cam_dev, argc, argv, combinedopt,
6127			    arglist & CAM_ARG_VERBOSE, retry_count, timeout);
6128			break;
6129#endif /* MINIMALISTIC */
6130		case CAM_CMD_USAGE:
6131			usage(1);
6132			break;
6133		default:
6134			usage(0);
6135			error = 1;
6136			break;
6137	}
6138
6139	if (cam_dev != NULL)
6140		cam_close_device(cam_dev);
6141
6142	exit(error);
6143}
6144