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