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