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