Deleted Added
full compact
camcontrol.c (62361) camcontrol.c (64382)
1/*
2 * Copyright (c) 1997, 1998, 1999, 2000 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 *
1/*
2 * Copyright (c) 1997, 1998, 1999, 2000 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 * $FreeBSD: head/sbin/camcontrol/camcontrol.c 62361 2000-07-01 21:28:49Z n_hibma $
28 * $FreeBSD: head/sbin/camcontrol/camcontrol.c 64382 2000-08-08 06:24:17Z kbyanc $
29 */
30
31#include <sys/ioctl.h>
32#include <sys/types.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <ctype.h>
39#include <err.h>
40
41#include <cam/cam.h>
42#include <cam/cam_debug.h>
43#include <cam/cam_ccb.h>
44#include <cam/scsi/scsi_all.h>
45#include <cam/scsi/scsi_da.h>
46#include <cam/scsi/scsi_pass.h>
47#include <cam/scsi/scsi_message.h>
48#include <camlib.h>
49#include "camcontrol.h"
50
51typedef enum {
52 CAM_ARG_NONE = 0x00000000,
53 CAM_ARG_DEVLIST = 0x00000001,
54 CAM_ARG_TUR = 0x00000002,
55 CAM_ARG_INQUIRY = 0x00000003,
56 CAM_ARG_STARTSTOP = 0x00000004,
57 CAM_ARG_RESCAN = 0x00000005,
58 CAM_ARG_READ_DEFECTS = 0x00000006,
59 CAM_ARG_MODE_PAGE = 0x00000007,
60 CAM_ARG_SCSI_CMD = 0x00000008,
61 CAM_ARG_DEVTREE = 0x00000009,
62 CAM_ARG_USAGE = 0x0000000a,
63 CAM_ARG_DEBUG = 0x0000000b,
64 CAM_ARG_RESET = 0x0000000c,
65 CAM_ARG_FORMAT = 0x0000000d,
66 CAM_ARG_TAG = 0x0000000e,
67 CAM_ARG_RATE = 0x0000000f,
68 CAM_ARG_OPT_MASK = 0x0000000f,
69 CAM_ARG_VERBOSE = 0x00000010,
70 CAM_ARG_DEVICE = 0x00000020,
71 CAM_ARG_BUS = 0x00000040,
72 CAM_ARG_TARGET = 0x00000080,
73 CAM_ARG_LUN = 0x00000100,
74 CAM_ARG_EJECT = 0x00000200,
75 CAM_ARG_UNIT = 0x00000400,
76 CAM_ARG_FORMAT_BLOCK = 0x00000800,
77 CAM_ARG_FORMAT_BFI = 0x00001000,
78 CAM_ARG_FORMAT_PHYS = 0x00002000,
79 CAM_ARG_PLIST = 0x00004000,
80 CAM_ARG_GLIST = 0x00008000,
81 CAM_ARG_GET_SERIAL = 0x00010000,
82 CAM_ARG_GET_STDINQ = 0x00020000,
83 CAM_ARG_GET_XFERRATE = 0x00040000,
84 CAM_ARG_INQ_MASK = 0x00070000,
85 CAM_ARG_MODE_EDIT = 0x00080000,
86 CAM_ARG_PAGE_CNTL = 0x00100000,
87 CAM_ARG_TIMEOUT = 0x00200000,
88 CAM_ARG_CMD_IN = 0x00400000,
89 CAM_ARG_CMD_OUT = 0x00800000,
90 CAM_ARG_DBD = 0x01000000,
91 CAM_ARG_ERR_RECOVER = 0x02000000,
92 CAM_ARG_RETRIES = 0x04000000,
93 CAM_ARG_START_UNIT = 0x08000000,
94 CAM_ARG_DEBUG_INFO = 0x10000000,
95 CAM_ARG_DEBUG_TRACE = 0x20000000,
96 CAM_ARG_DEBUG_SUBTRACE = 0x40000000,
97 CAM_ARG_DEBUG_CDB = 0x80000000,
98 CAM_ARG_FLAG_MASK = 0xfffffff0
99} cam_argmask;
100
101struct camcontrol_opts {
102 char *optname;
103 cam_argmask argnum;
104 const char *subopt;
105};
106
107extern int optreset;
108
109static const char scsicmd_opts[] = "c:i:o:";
110static const char readdefect_opts[] = "f:GP";
111static const char negotiate_opts[] = "acD:O:qR:T:UW:";
112
113struct camcontrol_opts option_table[] = {
114 {"tur", CAM_ARG_TUR, NULL},
115 {"inquiry", CAM_ARG_INQUIRY, "DSR"},
116 {"start", CAM_ARG_STARTSTOP | CAM_ARG_START_UNIT, NULL},
117 {"stop", CAM_ARG_STARTSTOP, NULL},
118 {"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL},
119 {"rescan", CAM_ARG_RESCAN, NULL},
120 {"reset", CAM_ARG_RESET, NULL},
121 {"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts},
122 {"command", CAM_ARG_SCSI_CMD, scsicmd_opts},
123 {"defects", CAM_ARG_READ_DEFECTS, readdefect_opts},
124 {"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
125 {"devlist", CAM_ARG_DEVTREE, NULL},
126 {"periphlist", CAM_ARG_DEVLIST, NULL},
29 */
30
31#include <sys/ioctl.h>
32#include <sys/types.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <ctype.h>
39#include <err.h>
40
41#include <cam/cam.h>
42#include <cam/cam_debug.h>
43#include <cam/cam_ccb.h>
44#include <cam/scsi/scsi_all.h>
45#include <cam/scsi/scsi_da.h>
46#include <cam/scsi/scsi_pass.h>
47#include <cam/scsi/scsi_message.h>
48#include <camlib.h>
49#include "camcontrol.h"
50
51typedef enum {
52 CAM_ARG_NONE = 0x00000000,
53 CAM_ARG_DEVLIST = 0x00000001,
54 CAM_ARG_TUR = 0x00000002,
55 CAM_ARG_INQUIRY = 0x00000003,
56 CAM_ARG_STARTSTOP = 0x00000004,
57 CAM_ARG_RESCAN = 0x00000005,
58 CAM_ARG_READ_DEFECTS = 0x00000006,
59 CAM_ARG_MODE_PAGE = 0x00000007,
60 CAM_ARG_SCSI_CMD = 0x00000008,
61 CAM_ARG_DEVTREE = 0x00000009,
62 CAM_ARG_USAGE = 0x0000000a,
63 CAM_ARG_DEBUG = 0x0000000b,
64 CAM_ARG_RESET = 0x0000000c,
65 CAM_ARG_FORMAT = 0x0000000d,
66 CAM_ARG_TAG = 0x0000000e,
67 CAM_ARG_RATE = 0x0000000f,
68 CAM_ARG_OPT_MASK = 0x0000000f,
69 CAM_ARG_VERBOSE = 0x00000010,
70 CAM_ARG_DEVICE = 0x00000020,
71 CAM_ARG_BUS = 0x00000040,
72 CAM_ARG_TARGET = 0x00000080,
73 CAM_ARG_LUN = 0x00000100,
74 CAM_ARG_EJECT = 0x00000200,
75 CAM_ARG_UNIT = 0x00000400,
76 CAM_ARG_FORMAT_BLOCK = 0x00000800,
77 CAM_ARG_FORMAT_BFI = 0x00001000,
78 CAM_ARG_FORMAT_PHYS = 0x00002000,
79 CAM_ARG_PLIST = 0x00004000,
80 CAM_ARG_GLIST = 0x00008000,
81 CAM_ARG_GET_SERIAL = 0x00010000,
82 CAM_ARG_GET_STDINQ = 0x00020000,
83 CAM_ARG_GET_XFERRATE = 0x00040000,
84 CAM_ARG_INQ_MASK = 0x00070000,
85 CAM_ARG_MODE_EDIT = 0x00080000,
86 CAM_ARG_PAGE_CNTL = 0x00100000,
87 CAM_ARG_TIMEOUT = 0x00200000,
88 CAM_ARG_CMD_IN = 0x00400000,
89 CAM_ARG_CMD_OUT = 0x00800000,
90 CAM_ARG_DBD = 0x01000000,
91 CAM_ARG_ERR_RECOVER = 0x02000000,
92 CAM_ARG_RETRIES = 0x04000000,
93 CAM_ARG_START_UNIT = 0x08000000,
94 CAM_ARG_DEBUG_INFO = 0x10000000,
95 CAM_ARG_DEBUG_TRACE = 0x20000000,
96 CAM_ARG_DEBUG_SUBTRACE = 0x40000000,
97 CAM_ARG_DEBUG_CDB = 0x80000000,
98 CAM_ARG_FLAG_MASK = 0xfffffff0
99} cam_argmask;
100
101struct camcontrol_opts {
102 char *optname;
103 cam_argmask argnum;
104 const char *subopt;
105};
106
107extern int optreset;
108
109static const char scsicmd_opts[] = "c:i:o:";
110static const char readdefect_opts[] = "f:GP";
111static const char negotiate_opts[] = "acD:O:qR:T:UW:";
112
113struct camcontrol_opts option_table[] = {
114 {"tur", CAM_ARG_TUR, NULL},
115 {"inquiry", CAM_ARG_INQUIRY, "DSR"},
116 {"start", CAM_ARG_STARTSTOP | CAM_ARG_START_UNIT, NULL},
117 {"stop", CAM_ARG_STARTSTOP, NULL},
118 {"eject", CAM_ARG_STARTSTOP | CAM_ARG_EJECT, NULL},
119 {"rescan", CAM_ARG_RESCAN, NULL},
120 {"reset", CAM_ARG_RESET, NULL},
121 {"cmd", CAM_ARG_SCSI_CMD, scsicmd_opts},
122 {"command", CAM_ARG_SCSI_CMD, scsicmd_opts},
123 {"defects", CAM_ARG_READ_DEFECTS, readdefect_opts},
124 {"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
125 {"devlist", CAM_ARG_DEVTREE, NULL},
126 {"periphlist", CAM_ARG_DEVLIST, NULL},
127 {"modepage", CAM_ARG_MODE_PAGE, "dem:P:"},
127 {"modepage", CAM_ARG_MODE_PAGE, "bdelm:P:"},
128 {"tags", CAM_ARG_TAG, "N:q"},
129 {"negotiate", CAM_ARG_RATE, negotiate_opts},
130 {"rate", CAM_ARG_RATE, negotiate_opts},
131 {"debug", CAM_ARG_DEBUG, "ITSc"},
132 {"format", CAM_ARG_FORMAT, "qwy"},
133 {"help", CAM_ARG_USAGE, NULL},
134 {"-?", CAM_ARG_USAGE, NULL},
135 {"-h", CAM_ARG_USAGE, NULL},
136 {NULL, 0, NULL}
137};
138
139typedef enum {
140 CC_OR_NOT_FOUND,
141 CC_OR_AMBIGUOUS,
142 CC_OR_FOUND
143} camcontrol_optret;
144
145cam_argmask arglist;
146int bus, target, lun;
147
148
149camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
150static int getdevlist(struct cam_device *device);
151static int getdevtree(void);
152static int testunitready(struct cam_device *device, int retry_count,
153 int timeout, int quiet);
154static int scsistart(struct cam_device *device, int startstop, int loadeject,
155 int retry_count, int timeout);
156static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
157 char *combinedopt, int retry_count, int timeout);
158static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
159static int scsiserial(struct cam_device *device, int retry_count, int timeout);
160static int scsixferrate(struct cam_device *device);
161static int parse_btl(char *tstr, int *bus, int *target, int *lun,
162 cam_argmask *arglist);
163static int dorescan_or_reset(int argc, char **argv, int rescan);
164static int rescan_or_reset_bus(int bus, int rescan);
165static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
166static int readdefects(struct cam_device *device, int argc, char **argv,
167 char *combinedopt, int retry_count, int timeout);
168static void modepage(struct cam_device *device, int argc, char **argv,
169 char *combinedopt, int retry_count, int timeout);
170static int scsicmd(struct cam_device *device, int argc, char **argv,
171 char *combinedopt, int retry_count, int timeout);
172static int tagcontrol(struct cam_device *device, int argc, char **argv,
173 char *combinedopt);
174static void cts_print(struct cam_device *device,
175 struct ccb_trans_settings *cts);
176static void cpi_print(struct ccb_pathinq *cpi);
177static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
178static int get_print_cts(struct cam_device *device, int user_settings,
179 int quiet, struct ccb_trans_settings *cts);
180static int ratecontrol(struct cam_device *device, int retry_count,
181 int timeout, int argc, char **argv, char *combinedopt);
182static int scsiformat(struct cam_device *device, int argc, char **argv,
183 char *combinedopt, int retry_count, int timeout);
184
185camcontrol_optret
186getoption(char *arg, cam_argmask *argnum, char **subopt)
187{
188 struct camcontrol_opts *opts;
189 int num_matches = 0;
190
191 for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
192 opts++) {
193 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
194 *argnum = opts->argnum;
195 *subopt = (char *)opts->subopt;
196 if (++num_matches > 1)
197 return(CC_OR_AMBIGUOUS);
198 }
199 }
200
201 if (num_matches > 0)
202 return(CC_OR_FOUND);
203 else
204 return(CC_OR_NOT_FOUND);
205}
206
207static int
208getdevlist(struct cam_device *device)
209{
210 union ccb *ccb;
211 char status[32];
212 int error = 0;
213
214 ccb = cam_getccb(device);
215
216 ccb->ccb_h.func_code = XPT_GDEVLIST;
217 ccb->ccb_h.flags = CAM_DIR_NONE;
218 ccb->ccb_h.retry_count = 1;
219 ccb->cgdl.index = 0;
220 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
221 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
222 if (cam_send_ccb(device, ccb) < 0) {
223 perror("error getting device list");
224 cam_freeccb(ccb);
225 return(1);
226 }
227
228 status[0] = '\0';
229
230 switch (ccb->cgdl.status) {
231 case CAM_GDEVLIST_MORE_DEVS:
232 strcpy(status, "MORE");
233 break;
234 case CAM_GDEVLIST_LAST_DEVICE:
235 strcpy(status, "LAST");
236 break;
237 case CAM_GDEVLIST_LIST_CHANGED:
238 strcpy(status, "CHANGED");
239 break;
240 case CAM_GDEVLIST_ERROR:
241 strcpy(status, "ERROR");
242 error = 1;
243 break;
244 }
245
246 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
247 ccb->cgdl.periph_name,
248 ccb->cgdl.unit_number,
249 ccb->cgdl.generation,
250 ccb->cgdl.index,
251 status);
252
253 /*
254 * If the list has changed, we need to start over from the
255 * beginning.
256 */
257 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
258 ccb->cgdl.index = 0;
259 }
260
261 cam_freeccb(ccb);
262
263 return(error);
264}
265
266static int
267getdevtree(void)
268{
269 union ccb ccb;
270 int bufsize, i, fd;
271 int need_close = 0;
272 int error = 0;
273 int skip_device = 0;
274
275 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
276 warn("couldn't open %s", XPT_DEVICE);
277 return(1);
278 }
279
280 bzero(&(&ccb.ccb_h)[1],
281 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
282
283 ccb.ccb_h.func_code = XPT_DEV_MATCH;
284 bufsize = sizeof(struct dev_match_result) * 100;
285 ccb.cdm.match_buf_len = bufsize;
286 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
287 ccb.cdm.num_matches = 0;
288
289 /*
290 * We fetch all nodes, since we display most of them in the default
291 * case, and all in the verbose case.
292 */
293 ccb.cdm.num_patterns = 0;
294 ccb.cdm.pattern_buf_len = 0;
295
296 /*
297 * We do the ioctl multiple times if necessary, in case there are
298 * more than 100 nodes in the EDT.
299 */
300 do {
301 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
302 warn("error sending CAMIOCOMMAND ioctl");
303 error = 1;
304 break;
305 }
306
307 if ((ccb.ccb_h.status != CAM_REQ_CMP)
308 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
309 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
310 fprintf(stderr, "got CAM error %#x, CDM error %d\n",
311 ccb.ccb_h.status, ccb.cdm.status);
312 error = 1;
313 break;
314 }
315
316 for (i = 0; i < ccb.cdm.num_matches; i++) {
317 switch(ccb.cdm.matches[i].type) {
318 case DEV_MATCH_BUS: {
319 struct bus_match_result *bus_result;
320
321 /*
322 * Only print the bus information if the
323 * user turns on the verbose flag.
324 */
325 if ((arglist & CAM_ARG_VERBOSE) == 0)
326 break;
327
328 bus_result =
329 &ccb.cdm.matches[i].result.bus_result;
330
331 if (need_close) {
332 fprintf(stdout, ")\n");
333 need_close = 0;
334 }
335
336 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
337 bus_result->path_id,
338 bus_result->dev_name,
339 bus_result->unit_number,
340 bus_result->bus_id);
341 break;
342 }
343 case DEV_MATCH_DEVICE: {
344 struct device_match_result *dev_result;
345 char vendor[16], product[48], revision[16];
346 char tmpstr[256];
347
348 dev_result =
349 &ccb.cdm.matches[i].result.device_result;
350
351 if ((dev_result->flags
352 & DEV_RESULT_UNCONFIGURED)
353 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
354 skip_device = 1;
355 break;
356 } else
357 skip_device = 0;
358
359 cam_strvis(vendor, dev_result->inq_data.vendor,
360 sizeof(dev_result->inq_data.vendor),
361 sizeof(vendor));
362 cam_strvis(product,
363 dev_result->inq_data.product,
364 sizeof(dev_result->inq_data.product),
365 sizeof(product));
366 cam_strvis(revision,
367 dev_result->inq_data.revision,
368 sizeof(dev_result->inq_data.revision),
369 sizeof(revision));
370 sprintf(tmpstr, "<%s %s %s>", vendor, product,
371 revision);
372 if (need_close) {
373 fprintf(stdout, ")\n");
374 need_close = 0;
375 }
376
377 fprintf(stdout, "%-33s at scbus%d "
378 "target %d lun %d (",
379 tmpstr,
380 dev_result->path_id,
381 dev_result->target_id,
382 dev_result->target_lun);
383
384 need_close = 1;
385
386 break;
387 }
388 case DEV_MATCH_PERIPH: {
389 struct periph_match_result *periph_result;
390
391 periph_result =
392 &ccb.cdm.matches[i].result.periph_result;
393
394 if (skip_device != 0)
395 break;
396
397 if (need_close > 1)
398 fprintf(stdout, ",");
399
400 fprintf(stdout, "%s%d",
401 periph_result->periph_name,
402 periph_result->unit_number);
403
404 need_close++;
405 break;
406 }
407 default:
408 fprintf(stdout, "unknown match type\n");
409 break;
410 }
411 }
412
413 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
414 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
415
416 if (need_close)
417 fprintf(stdout, ")\n");
418
419 close(fd);
420
421 return(error);
422}
423
424static int
425testunitready(struct cam_device *device, int retry_count, int timeout,
426 int quiet)
427{
428 int error = 0;
429 union ccb *ccb;
430
431 ccb = cam_getccb(device);
432
433 scsi_test_unit_ready(&ccb->csio,
434 /* retries */ retry_count,
435 /* cbfcnp */ NULL,
436 /* tag_action */ MSG_SIMPLE_Q_TAG,
437 /* sense_len */ SSD_FULL_SIZE,
438 /* timeout */ timeout ? timeout : 5000);
439
440 /* Disable freezing the device queue */
441 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
442
443 if (arglist & CAM_ARG_ERR_RECOVER)
444 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
445
446 if (cam_send_ccb(device, ccb) < 0) {
447 if (quiet == 0)
448 perror("error sending test unit ready");
449
450 if (arglist & CAM_ARG_VERBOSE) {
451 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
452 CAM_SCSI_STATUS_ERROR)
453 scsi_sense_print(device, &ccb->csio, stderr);
454 else
455 fprintf(stderr, "CAM status is %#x\n",
456 ccb->ccb_h.status);
457 }
458
459 cam_freeccb(ccb);
460 return(1);
461 }
462
463 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
464 if (quiet == 0)
465 fprintf(stdout, "Unit is ready\n");
466 } else {
467 if (quiet == 0)
468 fprintf(stdout, "Unit is not ready\n");
469 error = 1;
470
471 if (arglist & CAM_ARG_VERBOSE) {
472 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
473 CAM_SCSI_STATUS_ERROR)
474 scsi_sense_print(device, &ccb->csio, stderr);
475 else
476 fprintf(stderr, "CAM status is %#x\n",
477 ccb->ccb_h.status);
478 }
479 }
480
481 cam_freeccb(ccb);
482
483 return(error);
484}
485
486static int
487scsistart(struct cam_device *device, int startstop, int loadeject,
488 int retry_count, int timeout)
489{
490 union ccb *ccb;
491 int error = 0;
492
493 ccb = cam_getccb(device);
494
495 /*
496 * If we're stopping, send an ordered tag so the drive in question
497 * will finish any previously queued writes before stopping. If
498 * the device isn't capable of tagged queueing, or if tagged
499 * queueing is turned off, the tag action is a no-op.
500 */
501 scsi_start_stop(&ccb->csio,
502 /* retries */ retry_count,
503 /* cbfcnp */ NULL,
504 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
505 MSG_ORDERED_Q_TAG,
506 /* start/stop */ startstop,
507 /* load_eject */ loadeject,
508 /* immediate */ 0,
509 /* sense_len */ SSD_FULL_SIZE,
510 /* timeout */ timeout ? timeout : 120000);
511
512 /* Disable freezing the device queue */
513 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
514
515 if (arglist & CAM_ARG_ERR_RECOVER)
516 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
517
518 if (cam_send_ccb(device, ccb) < 0) {
519 perror("error sending start unit");
520
521 if (arglist & CAM_ARG_VERBOSE) {
522 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
523 CAM_SCSI_STATUS_ERROR)
524 scsi_sense_print(device, &ccb->csio, stderr);
525 else
526 fprintf(stderr, "CAM status is %#x\n",
527 ccb->ccb_h.status);
528 }
529
530 cam_freeccb(ccb);
531 return(1);
532 }
533
534 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
535 if (startstop) {
536 fprintf(stdout, "Unit started successfully");
537 if (loadeject)
538 fprintf(stdout,", Media loaded\n");
539 else
540 fprintf(stdout,"\n");
541 } else {
542 fprintf(stdout, "Unit stopped successfully");
543 if (loadeject)
544 fprintf(stdout, ", Media ejected\n");
545 else
546 fprintf(stdout, "\n");
547 }
548 else {
549 error = 1;
550 if (startstop)
551 fprintf(stdout,
552 "Error received from start unit command\n");
553 else
554 fprintf(stdout,
555 "Error received from stop unit command\n");
556
557 if (arglist & CAM_ARG_VERBOSE) {
558 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
559 CAM_SCSI_STATUS_ERROR)
560 scsi_sense_print(device, &ccb->csio, stderr);
561 else
562 fprintf(stderr, "CAM status is %#x\n",
563 ccb->ccb_h.status);
564 }
565 }
566
567 cam_freeccb(ccb);
568
569 return(error);
570}
571
572static int
573scsidoinquiry(struct cam_device *device, int argc, char **argv,
574 char *combinedopt, int retry_count, int timeout)
575{
576 int c;
577 int error = 0;
578
579 while ((c = getopt(argc, argv, combinedopt)) != -1) {
580 switch(c) {
581 case 'D':
582 arglist |= CAM_ARG_GET_STDINQ;
583 break;
584 case 'R':
585 arglist |= CAM_ARG_GET_XFERRATE;
586 break;
587 case 'S':
588 arglist |= CAM_ARG_GET_SERIAL;
589 break;
590 default:
591 break;
592 }
593 }
594
595 /*
596 * If the user didn't specify any inquiry options, he wants all of
597 * them.
598 */
599 if ((arglist & CAM_ARG_INQ_MASK) == 0)
600 arglist |= CAM_ARG_INQ_MASK;
601
602 if (arglist & CAM_ARG_GET_STDINQ)
603 error = scsiinquiry(device, retry_count, timeout);
604
605 if (error != 0)
606 return(error);
607
608 if (arglist & CAM_ARG_GET_SERIAL)
609 scsiserial(device, retry_count, timeout);
610
611 if (error != 0)
612 return(error);
613
614 if (arglist & CAM_ARG_GET_XFERRATE)
615 error = scsixferrate(device);
616
617 return(error);
618}
619
620static int
621scsiinquiry(struct cam_device *device, int retry_count, int timeout)
622{
623 union ccb *ccb;
624 struct scsi_inquiry_data *inq_buf;
625 int error = 0;
626
627 ccb = cam_getccb(device);
628
629 if (ccb == NULL) {
630 warnx("couldn't allocate CCB");
631 return(1);
632 }
633
634 /* cam_getccb cleans up the header, caller has to zero the payload */
635 bzero(&(&ccb->ccb_h)[1],
636 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
637
638 inq_buf = (struct scsi_inquiry_data *)malloc(
639 sizeof(struct scsi_inquiry_data));
640
641 if (inq_buf == NULL) {
642 cam_freeccb(ccb);
643 warnx("can't malloc memory for inquiry\n");
644 return(1);
645 }
646 bzero(inq_buf, sizeof(*inq_buf));
647
648 /*
649 * Note that although the size of the inquiry buffer is the full
650 * 256 bytes specified in the SCSI spec, we only tell the device
651 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
652 * two reasons for this:
653 *
654 * - The SCSI spec says that when a length field is only 1 byte,
655 * a value of 0 will be interpreted as 256. Therefore
656 * scsi_inquiry() will convert an inq_len (which is passed in as
657 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
658 * to 0. Evidently, very few devices meet the spec in that
659 * regard. Some devices, like many Seagate disks, take the 0 as
660 * 0, and don't return any data. One Pioneer DVD-R drive
661 * returns more data than the command asked for.
662 *
663 * So, since there are numerous devices that just don't work
664 * right with the full inquiry size, we don't send the full size.
665 *
666 * - The second reason not to use the full inquiry data length is
667 * that we don't need it here. The only reason we issue a
668 * standard inquiry is to get the vendor name, device name,
669 * and revision so scsi_print_inquiry() can print them.
670 *
671 * If, at some point in the future, more inquiry data is needed for
672 * some reason, this code should use a procedure similar to the
673 * probe code. i.e., issue a short inquiry, and determine from
674 * the additional length passed back from the device how much
675 * inquiry data the device supports. Once the amount the device
676 * supports is determined, issue an inquiry for that amount and no
677 * more.
678 *
679 * KDM, 2/18/2000
680 */
681 scsi_inquiry(&ccb->csio,
682 /* retries */ retry_count,
683 /* cbfcnp */ NULL,
684 /* tag_action */ MSG_SIMPLE_Q_TAG,
685 /* inq_buf */ (u_int8_t *)inq_buf,
686 /* inq_len */ SHORT_INQUIRY_LENGTH,
687 /* evpd */ 0,
688 /* page_code */ 0,
689 /* sense_len */ SSD_FULL_SIZE,
690 /* timeout */ timeout ? timeout : 5000);
691
692 /* Disable freezing the device queue */
693 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
694
695 if (arglist & CAM_ARG_ERR_RECOVER)
696 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
697
698 if (cam_send_ccb(device, ccb) < 0) {
699 perror("error sending SCSI inquiry");
700
701 if (arglist & CAM_ARG_VERBOSE) {
702 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
703 CAM_SCSI_STATUS_ERROR)
704 scsi_sense_print(device, &ccb->csio, stderr);
705 else
706 fprintf(stderr, "CAM status is %#x\n",
707 ccb->ccb_h.status);
708 }
709
710 cam_freeccb(ccb);
711 return(1);
712 }
713
714 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
715 error = 1;
716
717 if (arglist & CAM_ARG_VERBOSE) {
718 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
719 CAM_SCSI_STATUS_ERROR)
720 scsi_sense_print(device, &ccb->csio, stderr);
721 else
722 fprintf(stderr, "CAM status is %#x\n",
723 ccb->ccb_h.status);
724 }
725 }
726
727 cam_freeccb(ccb);
728
729 if (error != 0) {
730 free(inq_buf);
731 return(error);
732 }
733
734 fprintf(stdout, "%s%d: ", device->device_name,
735 device->dev_unit_num);
736 scsi_print_inquiry(inq_buf);
737
738 free(inq_buf);
739
740 return(0);
741}
742
743static int
744scsiserial(struct cam_device *device, int retry_count, int timeout)
745{
746 union ccb *ccb;
747 struct scsi_vpd_unit_serial_number *serial_buf;
748 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
749 int error = 0;
750
751 ccb = cam_getccb(device);
752
753 if (ccb == NULL) {
754 warnx("couldn't allocate CCB");
755 return(1);
756 }
757
758 /* cam_getccb cleans up the header, caller has to zero the payload */
759 bzero(&(&ccb->ccb_h)[1],
760 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
761
762 serial_buf = (struct scsi_vpd_unit_serial_number *)
763 malloc(sizeof(*serial_buf));
764
765 if (serial_buf == NULL) {
766 cam_freeccb(ccb);
767 warnx("can't malloc memory for serial number");
768 return(1);
769 }
770
771 scsi_inquiry(&ccb->csio,
772 /*retries*/ retry_count,
773 /*cbfcnp*/ NULL,
774 /* tag_action */ MSG_SIMPLE_Q_TAG,
775 /* inq_buf */ (u_int8_t *)serial_buf,
776 /* inq_len */ sizeof(*serial_buf),
777 /* evpd */ 1,
778 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
779 /* sense_len */ SSD_FULL_SIZE,
780 /* timeout */ timeout ? timeout : 5000);
781
782 /* Disable freezing the device queue */
783 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
784
785 if (arglist & CAM_ARG_ERR_RECOVER)
786 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
787
788 if (cam_send_ccb(device, ccb) < 0) {
789 warn("error getting serial number");
790
791 if (arglist & CAM_ARG_VERBOSE) {
792 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
793 CAM_SCSI_STATUS_ERROR)
794 scsi_sense_print(device, &ccb->csio, stderr);
795 else
796 fprintf(stderr, "CAM status is %#x\n",
797 ccb->ccb_h.status);
798 }
799
800 cam_freeccb(ccb);
801 free(serial_buf);
802 return(1);
803 }
804
805 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
806 error = 1;
807
808 if (arglist & CAM_ARG_VERBOSE) {
809 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
810 CAM_SCSI_STATUS_ERROR)
811 scsi_sense_print(device, &ccb->csio, stderr);
812 else
813 fprintf(stderr, "CAM status is %#x\n",
814 ccb->ccb_h.status);
815 }
816 }
817
818 cam_freeccb(ccb);
819
820 if (error != 0) {
821 free(serial_buf);
822 return(error);
823 }
824
825 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
826 serial_num[serial_buf->length] = '\0';
827
828 if ((arglist & CAM_ARG_GET_STDINQ)
829 || (arglist & CAM_ARG_GET_XFERRATE))
830 fprintf(stdout, "%s%d: Serial Number ",
831 device->device_name, device->dev_unit_num);
832
833 fprintf(stdout, "%.60s\n", serial_num);
834
835 free(serial_buf);
836
837 return(0);
838}
839
840static int
841scsixferrate(struct cam_device *device)
842{
843 u_int32_t freq;
844 u_int32_t speed;
845 union ccb *ccb;
846 u_int mb;
847 int retval = 0;
848
849 ccb = cam_getccb(device);
850
851 if (ccb == NULL) {
852 warnx("couldn't allocate CCB");
853 return(1);
854 }
855
856 bzero(&(&ccb->ccb_h)[1],
857 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
858
859 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
860 ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
861
862 if (((retval = cam_send_ccb(device, ccb)) < 0)
863 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
864 char *error_string = "error getting transfer settings";
865
866 if (retval < 0)
867 warn(error_string);
868 else
869 warnx(error_string);
870
871 /*
872 * If there is an error, it won't be a SCSI error since
873 * this isn't a SCSI CCB.
874 */
875 if (arglist & CAM_ARG_VERBOSE)
876 fprintf(stderr, "CAM status is %#x\n",
877 ccb->ccb_h.status);
878
879 retval = 1;
880
881 goto xferrate_bailout;
882
883 }
884
885 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
886 && (ccb->cts.sync_offset != 0)) {
887 freq = scsi_calc_syncsrate(ccb->cts.sync_period);
888 speed = freq;
889 } else {
890 struct ccb_pathinq cpi;
891
892 retval = get_cpi(device, &cpi);
893
894 if (retval != 0)
895 goto xferrate_bailout;
896
897 speed = cpi.base_transfer_speed;
898 freq = 0;
899 }
900
901 fprintf(stdout, "%s%d: ", device->device_name,
902 device->dev_unit_num);
903
904 if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
905 speed *= (0x01 << device->bus_width);
906
907 mb = speed / 1000;
908
909 if (mb > 0)
910 fprintf(stdout, "%d.%03dMB/s transfers ",
911 mb, speed % 1000);
912 else
913 fprintf(stdout, "%dKB/s transfers ",
914 speed);
915
916 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
917 && (ccb->cts.sync_offset != 0))
918 fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
919 freq % 1000, ccb->cts.sync_offset);
920
921 if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
922 && (ccb->cts.bus_width > 0)) {
923 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
924 && (ccb->cts.sync_offset != 0)) {
925 fprintf(stdout, ", ");
926 } else {
927 fprintf(stdout, " (");
928 }
929 fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
930 } else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
931 && (ccb->cts.sync_offset != 0)) {
932 fprintf(stdout, ")");
933 }
934
935 if (((ccb->cts.valid & CCB_TRANS_TQ_VALID) != 0)
936 && (ccb->cts.flags & CCB_TRANS_TAG_ENB))
937 fprintf(stdout, ", Tagged Queueing Enabled");
938
939 fprintf(stdout, "\n");
940
941xferrate_bailout:
942
943 cam_freeccb(ccb);
944
945 return(retval);
946}
947
948/*
949 * Parse out a bus, or a bus, target and lun in the following
950 * format:
951 * bus
952 * bus:target
953 * bus:target:lun
954 *
955 * Returns the number of parsed components, or 0.
956 */
957static int
958parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
959{
960 char *tmpstr;
961 int convs = 0;
962
963 while (isspace(*tstr) && (*tstr != '\0'))
964 tstr++;
965
966 tmpstr = (char *)strtok(tstr, ":");
967 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
968 *bus = strtol(tmpstr, NULL, 0);
969 *arglist |= CAM_ARG_BUS;
970 convs++;
971 tmpstr = (char *)strtok(NULL, ":");
972 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
973 *target = strtol(tmpstr, NULL, 0);
974 *arglist |= CAM_ARG_TARGET;
975 convs++;
976 tmpstr = (char *)strtok(NULL, ":");
977 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
978 *lun = strtol(tmpstr, NULL, 0);
979 *arglist |= CAM_ARG_LUN;
980 convs++;
981 }
982 }
983 }
984
985 return convs;
986}
987
988static int
989dorescan_or_reset(int argc, char **argv, int rescan)
990{
991 static const char *must =
992 "you must specify a bus, or a bus:target:lun to %s";
993 int rv, error = 0;
994 int bus = -1, target = -1, lun = -1;
995
996 if (argc < 3) {
997 warnx(must, rescan? "rescan" : "reset");
998 return(1);
999 }
1000 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1001 if (rv != 1 && rv != 3) {
1002 warnx(must, rescan? "rescan" : "reset");
1003 return(1);
1004 }
1005
1006 if ((arglist & CAM_ARG_BUS)
1007 && (arglist & CAM_ARG_TARGET)
1008 && (arglist & CAM_ARG_LUN))
1009 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1010 else
1011 error = rescan_or_reset_bus(bus, rescan);
1012
1013 return(error);
1014}
1015
1016static int
1017rescan_or_reset_bus(int bus, int rescan)
1018{
1019 union ccb ccb;
1020 int fd;
1021
1022 if (bus < 0) {
1023 warnx("invalid bus number %d", bus);
1024 return(1);
1025 }
1026
1027 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1028 warnx("error opening tranport layer device %s", XPT_DEVICE);
1029 warn("%s", XPT_DEVICE);
1030 return(1);
1031 }
1032
1033 ccb.ccb_h.func_code = rescan? XPT_SCAN_BUS : XPT_RESET_BUS;
1034 ccb.ccb_h.path_id = bus;
1035 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1036 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1037 ccb.crcn.flags = CAM_FLAG_NONE;
1038
1039 /* run this at a low priority */
1040 ccb.ccb_h.pinfo.priority = 5;
1041
1042 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1043 warn("CAMIOCOMMAND ioctl failed");
1044 close(fd);
1045 return(1);
1046 }
1047
1048 close(fd);
1049
1050 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1051 fprintf(stdout, "%s of bus %d was successful\n",
1052 rescan? "Re-scan" : "Reset", bus);
1053 return(0);
1054 } else {
1055 fprintf(stdout, "%s of bus %d returned error %#x\n",
1056 rescan? "Re-scan" : "Reset", bus,
1057 ccb.ccb_h.status & CAM_STATUS_MASK);
1058 return(1);
1059 }
1060}
1061
1062static int
1063scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1064{
1065 union ccb ccb;
1066 struct cam_device *device;
1067 int fd;
1068
1069 device = NULL;
1070
1071 if (bus < 0) {
1072 warnx("invalid bus number %d", bus);
1073 return(1);
1074 }
1075
1076 if (target < 0) {
1077 warnx("invalid target number %d", target);
1078 return(1);
1079 }
1080
1081 if (lun < 0) {
1082 warnx("invalid lun number %d", lun);
1083 return(1);
1084 }
1085
1086 fd = -1;
1087
1088 bzero(&ccb, sizeof(union ccb));
1089
1090 if (scan) {
1091 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1092 warnx("error opening tranport layer device %s\n",
1093 XPT_DEVICE);
1094 warn("%s", XPT_DEVICE);
1095 return(1);
1096 }
1097 } else {
1098 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1099 if (device == NULL) {
1100 warnx("%s", cam_errbuf);
1101 return(1);
1102 }
1103 }
1104
1105 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1106 ccb.ccb_h.path_id = bus;
1107 ccb.ccb_h.target_id = target;
1108 ccb.ccb_h.target_lun = lun;
1109 ccb.ccb_h.timeout = 5000;
1110 ccb.crcn.flags = CAM_FLAG_NONE;
1111
1112 /* run this at a low priority */
1113 ccb.ccb_h.pinfo.priority = 5;
1114
1115 if (scan) {
1116 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1117 warn("CAMIOCOMMAND ioctl failed");
1118 close(fd);
1119 return(1);
1120 }
1121 } else {
1122 if (cam_send_ccb(device, &ccb) < 0) {
1123 warn("error sending XPT_RESET_DEV CCB");
1124 cam_close_device(device);
1125 return(1);
1126 }
1127 }
1128
1129 if (scan)
1130 close(fd);
1131 else
1132 cam_close_device(device);
1133
1134 /*
1135 * An error code of CAM_BDR_SENT is normal for a BDR request.
1136 */
1137 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1138 || ((!scan)
1139 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1140 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1141 scan? "Re-scan" : "Reset", bus, target, lun);
1142 return(0);
1143 } else {
1144 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1145 scan? "Re-scan" : "Reset", bus, target, lun,
1146 ccb.ccb_h.status & CAM_STATUS_MASK);
1147 return(1);
1148 }
1149}
1150
1151static int
1152readdefects(struct cam_device *device, int argc, char **argv,
1153 char *combinedopt, int retry_count, int timeout)
1154{
1155 union ccb *ccb = NULL;
1156 struct scsi_read_defect_data_10 *rdd_cdb;
1157 u_int8_t *defect_list = NULL;
1158 u_int32_t dlist_length = 65000;
1159 u_int32_t returned_length = 0;
1160 u_int32_t num_returned = 0;
1161 u_int8_t returned_format;
1162 register int i;
1163 int c, error = 0;
1164 int lists_specified = 0;
1165
1166 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1167 switch(c){
1168 case 'f':
1169 {
1170 char *tstr;
1171 tstr = optarg;
1172 while (isspace(*tstr) && (*tstr != '\0'))
1173 tstr++;
1174 if (strcmp(tstr, "block") == 0)
1175 arglist |= CAM_ARG_FORMAT_BLOCK;
1176 else if (strcmp(tstr, "bfi") == 0)
1177 arglist |= CAM_ARG_FORMAT_BFI;
1178 else if (strcmp(tstr, "phys") == 0)
1179 arglist |= CAM_ARG_FORMAT_PHYS;
1180 else {
1181 error = 1;
1182 warnx("invalid defect format %s", tstr);
1183 goto defect_bailout;
1184 }
1185 break;
1186 }
1187 case 'G':
1188 arglist |= CAM_ARG_GLIST;
1189 break;
1190 case 'P':
1191 arglist |= CAM_ARG_PLIST;
1192 break;
1193 default:
1194 break;
1195 }
1196 }
1197
1198 ccb = cam_getccb(device);
1199
1200 /*
1201 * Hopefully 65000 bytes is enough to hold the defect list. If it
1202 * isn't, the disk is probably dead already. We'd have to go with
1203 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1204 * to hold them all.
1205 */
1206 defect_list = malloc(dlist_length);
1207
1208 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1209
1210 /*
1211 * cam_getccb() zeros the CCB header only. So we need to zero the
1212 * payload portion of the ccb.
1213 */
1214 bzero(&(&ccb->ccb_h)[1],
1215 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1216
1217 cam_fill_csio(&ccb->csio,
1218 /*retries*/ retry_count,
1219 /*cbfcnp*/ NULL,
1220 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1221 CAM_PASS_ERR_RECOVER : 0),
1222 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1223 /*data_ptr*/ defect_list,
1224 /*dxfer_len*/ dlist_length,
1225 /*sense_len*/ SSD_FULL_SIZE,
1226 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1227 /*timeout*/ timeout ? timeout : 5000);
1228
1229 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1230 if (arglist & CAM_ARG_FORMAT_BLOCK)
1231 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1232 else if (arglist & CAM_ARG_FORMAT_BFI)
1233 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1234 else if (arglist & CAM_ARG_FORMAT_PHYS)
1235 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1236 else {
1237 error = 1;
1238 warnx("no defect list format specified");
1239 goto defect_bailout;
1240 }
1241 if (arglist & CAM_ARG_PLIST) {
1242 rdd_cdb->format |= SRDD10_PLIST;
1243 lists_specified++;
1244 }
1245
1246 if (arglist & CAM_ARG_GLIST) {
1247 rdd_cdb->format |= SRDD10_GLIST;
1248 lists_specified++;
1249 }
1250
1251 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1252
1253 /* Disable freezing the device queue */
1254 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1255
1256 if (cam_send_ccb(device, ccb) < 0) {
1257 perror("error reading defect list");
1258
1259 if (arglist & CAM_ARG_VERBOSE) {
1260 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1261 CAM_SCSI_STATUS_ERROR)
1262 scsi_sense_print(device, &ccb->csio, stderr);
1263 else
1264 fprintf(stderr, "CAM status is %#x\n",
1265 ccb->ccb_h.status);
1266 }
1267
1268 error = 1;
1269 goto defect_bailout;
1270 }
1271
1272 if (arglist & CAM_ARG_VERBOSE)
1273 scsi_sense_print(device, &ccb->csio, stderr);
1274
1275 returned_length = scsi_2btoul(((struct
1276 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1277
1278 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1279 defect_list)->format;
1280
1281 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1282 struct scsi_sense_data *sense;
1283 int error_code, sense_key, asc, ascq;
1284
1285 sense = &ccb->csio.sense_data;
1286 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1287
1288 /*
1289 * According to the SCSI spec, if the disk doesn't support
1290 * the requested format, it will generally return a sense
1291 * key of RECOVERED ERROR, and an additional sense code
1292 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1293 * also check to make sure that the returned length is
1294 * greater than 0, and then print out whatever format the
1295 * disk gave us.
1296 */
1297 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1298 && (asc == 0x1c) && (ascq == 0x00)
1299 && (returned_length > 0)) {
1300 warnx("requested defect format not available");
1301 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1302 case SRDD10_BLOCK_FORMAT:
1303 warnx("Device returned block format");
1304 break;
1305 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1306 warnx("Device returned bytes from index"
1307 " format");
1308 break;
1309 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1310 warnx("Device returned physical sector format");
1311 break;
1312 default:
1313 error = 1;
1314 warnx("Device returned unknown defect"
1315 " data format %#x", returned_format);
1316 goto defect_bailout;
1317 break; /* NOTREACHED */
1318 }
1319 } else {
1320 error = 1;
1321 warnx("Error returned from read defect data command");
1322 goto defect_bailout;
1323 }
1324 }
1325
1326 /*
1327 * XXX KDM I should probably clean up the printout format for the
1328 * disk defects.
1329 */
1330 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1331 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1332 {
1333 struct scsi_defect_desc_phys_sector *dlist;
1334
1335 dlist = (struct scsi_defect_desc_phys_sector *)
1336 (defect_list +
1337 sizeof(struct scsi_read_defect_data_hdr_10));
1338
1339 num_returned = returned_length /
1340 sizeof(struct scsi_defect_desc_phys_sector);
1341
1342 fprintf(stderr, "Got %d defect", num_returned);
1343
1344 if ((lists_specified == 0) || (num_returned == 0)) {
1345 fprintf(stderr, "s.\n");
1346 break;
1347 } else if (num_returned == 1)
1348 fprintf(stderr, ":\n");
1349 else
1350 fprintf(stderr, "s:\n");
1351
1352 for (i = 0; i < num_returned; i++) {
1353 fprintf(stdout, "%d:%d:%d\n",
1354 scsi_3btoul(dlist[i].cylinder),
1355 dlist[i].head,
1356 scsi_4btoul(dlist[i].sector));
1357 }
1358 break;
1359 }
1360 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1361 {
1362 struct scsi_defect_desc_bytes_from_index *dlist;
1363
1364 dlist = (struct scsi_defect_desc_bytes_from_index *)
1365 (defect_list +
1366 sizeof(struct scsi_read_defect_data_hdr_10));
1367
1368 num_returned = returned_length /
1369 sizeof(struct scsi_defect_desc_bytes_from_index);
1370
1371 fprintf(stderr, "Got %d defect", num_returned);
1372
1373 if ((lists_specified == 0) || (num_returned == 0)) {
1374 fprintf(stderr, "s.\n");
1375 break;
1376 } else if (num_returned == 1)
1377 fprintf(stderr, ":\n");
1378 else
1379 fprintf(stderr, "s:\n");
1380
1381 for (i = 0; i < num_returned; i++) {
1382 fprintf(stdout, "%d:%d:%d\n",
1383 scsi_3btoul(dlist[i].cylinder),
1384 dlist[i].head,
1385 scsi_4btoul(dlist[i].bytes_from_index));
1386 }
1387 break;
1388 }
1389 case SRDDH10_BLOCK_FORMAT:
1390 {
1391 struct scsi_defect_desc_block *dlist;
1392
1393 dlist = (struct scsi_defect_desc_block *)(defect_list +
1394 sizeof(struct scsi_read_defect_data_hdr_10));
1395
1396 num_returned = returned_length /
1397 sizeof(struct scsi_defect_desc_block);
1398
1399 fprintf(stderr, "Got %d defect", num_returned);
1400
1401 if ((lists_specified == 0) || (num_returned == 0)) {
1402 fprintf(stderr, "s.\n");
1403 break;
1404 } else if (num_returned == 1)
1405 fprintf(stderr, ":\n");
1406 else
1407 fprintf(stderr, "s:\n");
1408
1409 for (i = 0; i < num_returned; i++)
1410 fprintf(stdout, "%u\n",
1411 scsi_4btoul(dlist[i].address));
1412 break;
1413 }
1414 default:
1415 fprintf(stderr, "Unknown defect format %d\n",
1416 returned_format & SRDDH10_DLIST_FORMAT_MASK);
1417 error = 1;
1418 break;
1419 }
1420defect_bailout:
1421
1422 if (defect_list != NULL)
1423 free(defect_list);
1424
1425 if (ccb != NULL)
1426 cam_freeccb(ccb);
1427
1428 return(error);
1429}
1430
1431#if 0
1432void
1433reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1434{
1435 union ccb *ccb;
1436
1437 ccb = cam_getccb(device);
1438
1439 cam_freeccb(ccb);
1440}
1441#endif
1442
1443void
1444mode_sense(struct cam_device *device, int mode_page, int page_control,
1445 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1446{
1447 union ccb *ccb;
1448 int retval;
1449
1450 ccb = cam_getccb(device);
1451
1452 if (ccb == NULL)
1453 errx(1, "mode_sense: couldn't allocate CCB");
1454
1455 bzero(&(&ccb->ccb_h)[1],
1456 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1457
1458 scsi_mode_sense(&ccb->csio,
1459 /* retries */ retry_count,
1460 /* cbfcnp */ NULL,
1461 /* tag_action */ MSG_SIMPLE_Q_TAG,
1462 /* dbd */ dbd,
1463 /* page_code */ page_control << 6,
1464 /* page */ mode_page,
1465 /* param_buf */ data,
1466 /* param_len */ datalen,
1467 /* sense_len */ SSD_FULL_SIZE,
1468 /* timeout */ timeout ? timeout : 5000);
1469
1470 if (arglist & CAM_ARG_ERR_RECOVER)
1471 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1472
1473 /* Disable freezing the device queue */
1474 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1475
1476 if (((retval = cam_send_ccb(device, ccb)) < 0)
1477 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1478 if (arglist & CAM_ARG_VERBOSE) {
1479 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1480 CAM_SCSI_STATUS_ERROR)
1481 scsi_sense_print(device, &ccb->csio, stderr);
1482 else
1483 fprintf(stderr, "CAM status is %#x\n",
1484 ccb->ccb_h.status);
1485 }
1486 cam_freeccb(ccb);
1487 cam_close_device(device);
1488 if (retval < 0)
1489 err(1, "error sending mode sense command");
1490 else
1491 errx(1, "error sending mode sense command");
1492 }
1493
1494 cam_freeccb(ccb);
1495}
1496
1497void
1498mode_select(struct cam_device *device, int save_pages, int retry_count,
1499 int timeout, u_int8_t *data, int datalen)
1500{
1501 union ccb *ccb;
1502 int retval;
1503
1504 ccb = cam_getccb(device);
1505
1506 if (ccb == NULL)
1507 errx(1, "mode_select: couldn't allocate CCB");
1508
1509 bzero(&(&ccb->ccb_h)[1],
1510 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1511
1512 scsi_mode_select(&ccb->csio,
1513 /* retries */ retry_count,
1514 /* cbfcnp */ NULL,
1515 /* tag_action */ MSG_SIMPLE_Q_TAG,
1516 /* scsi_page_fmt */ 1,
1517 /* save_pages */ save_pages,
1518 /* param_buf */ data,
1519 /* param_len */ datalen,
1520 /* sense_len */ SSD_FULL_SIZE,
1521 /* timeout */ timeout ? timeout : 5000);
1522
1523 if (arglist & CAM_ARG_ERR_RECOVER)
1524 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1525
1526 /* Disable freezing the device queue */
1527 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1528
1529 if (((retval = cam_send_ccb(device, ccb)) < 0)
1530 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1531 if (arglist & CAM_ARG_VERBOSE) {
1532 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1533 CAM_SCSI_STATUS_ERROR)
1534 scsi_sense_print(device, &ccb->csio, stderr);
1535 else
1536 fprintf(stderr, "CAM status is %#x\n",
1537 ccb->ccb_h.status);
1538 }
1539 cam_freeccb(ccb);
1540 cam_close_device(device);
1541
1542 if (retval < 0)
1543 err(1, "error sending mode select command");
1544 else
1545 errx(1, "error sending mode select command");
1546
1547 }
1548
1549 cam_freeccb(ccb);
1550}
1551
1552void
1553modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1554 int retry_count, int timeout)
1555{
1556 int c, mode_page = -1, page_control = 0;
128 {"tags", CAM_ARG_TAG, "N:q"},
129 {"negotiate", CAM_ARG_RATE, negotiate_opts},
130 {"rate", CAM_ARG_RATE, negotiate_opts},
131 {"debug", CAM_ARG_DEBUG, "ITSc"},
132 {"format", CAM_ARG_FORMAT, "qwy"},
133 {"help", CAM_ARG_USAGE, NULL},
134 {"-?", CAM_ARG_USAGE, NULL},
135 {"-h", CAM_ARG_USAGE, NULL},
136 {NULL, 0, NULL}
137};
138
139typedef enum {
140 CC_OR_NOT_FOUND,
141 CC_OR_AMBIGUOUS,
142 CC_OR_FOUND
143} camcontrol_optret;
144
145cam_argmask arglist;
146int bus, target, lun;
147
148
149camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
150static int getdevlist(struct cam_device *device);
151static int getdevtree(void);
152static int testunitready(struct cam_device *device, int retry_count,
153 int timeout, int quiet);
154static int scsistart(struct cam_device *device, int startstop, int loadeject,
155 int retry_count, int timeout);
156static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
157 char *combinedopt, int retry_count, int timeout);
158static int scsiinquiry(struct cam_device *device, int retry_count, int timeout);
159static int scsiserial(struct cam_device *device, int retry_count, int timeout);
160static int scsixferrate(struct cam_device *device);
161static int parse_btl(char *tstr, int *bus, int *target, int *lun,
162 cam_argmask *arglist);
163static int dorescan_or_reset(int argc, char **argv, int rescan);
164static int rescan_or_reset_bus(int bus, int rescan);
165static int scanlun_or_reset_dev(int bus, int target, int lun, int scan);
166static int readdefects(struct cam_device *device, int argc, char **argv,
167 char *combinedopt, int retry_count, int timeout);
168static void modepage(struct cam_device *device, int argc, char **argv,
169 char *combinedopt, int retry_count, int timeout);
170static int scsicmd(struct cam_device *device, int argc, char **argv,
171 char *combinedopt, int retry_count, int timeout);
172static int tagcontrol(struct cam_device *device, int argc, char **argv,
173 char *combinedopt);
174static void cts_print(struct cam_device *device,
175 struct ccb_trans_settings *cts);
176static void cpi_print(struct ccb_pathinq *cpi);
177static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
178static int get_print_cts(struct cam_device *device, int user_settings,
179 int quiet, struct ccb_trans_settings *cts);
180static int ratecontrol(struct cam_device *device, int retry_count,
181 int timeout, int argc, char **argv, char *combinedopt);
182static int scsiformat(struct cam_device *device, int argc, char **argv,
183 char *combinedopt, int retry_count, int timeout);
184
185camcontrol_optret
186getoption(char *arg, cam_argmask *argnum, char **subopt)
187{
188 struct camcontrol_opts *opts;
189 int num_matches = 0;
190
191 for (opts = option_table; (opts != NULL) && (opts->optname != NULL);
192 opts++) {
193 if (strncmp(opts->optname, arg, strlen(arg)) == 0) {
194 *argnum = opts->argnum;
195 *subopt = (char *)opts->subopt;
196 if (++num_matches > 1)
197 return(CC_OR_AMBIGUOUS);
198 }
199 }
200
201 if (num_matches > 0)
202 return(CC_OR_FOUND);
203 else
204 return(CC_OR_NOT_FOUND);
205}
206
207static int
208getdevlist(struct cam_device *device)
209{
210 union ccb *ccb;
211 char status[32];
212 int error = 0;
213
214 ccb = cam_getccb(device);
215
216 ccb->ccb_h.func_code = XPT_GDEVLIST;
217 ccb->ccb_h.flags = CAM_DIR_NONE;
218 ccb->ccb_h.retry_count = 1;
219 ccb->cgdl.index = 0;
220 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS;
221 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) {
222 if (cam_send_ccb(device, ccb) < 0) {
223 perror("error getting device list");
224 cam_freeccb(ccb);
225 return(1);
226 }
227
228 status[0] = '\0';
229
230 switch (ccb->cgdl.status) {
231 case CAM_GDEVLIST_MORE_DEVS:
232 strcpy(status, "MORE");
233 break;
234 case CAM_GDEVLIST_LAST_DEVICE:
235 strcpy(status, "LAST");
236 break;
237 case CAM_GDEVLIST_LIST_CHANGED:
238 strcpy(status, "CHANGED");
239 break;
240 case CAM_GDEVLIST_ERROR:
241 strcpy(status, "ERROR");
242 error = 1;
243 break;
244 }
245
246 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n",
247 ccb->cgdl.periph_name,
248 ccb->cgdl.unit_number,
249 ccb->cgdl.generation,
250 ccb->cgdl.index,
251 status);
252
253 /*
254 * If the list has changed, we need to start over from the
255 * beginning.
256 */
257 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED)
258 ccb->cgdl.index = 0;
259 }
260
261 cam_freeccb(ccb);
262
263 return(error);
264}
265
266static int
267getdevtree(void)
268{
269 union ccb ccb;
270 int bufsize, i, fd;
271 int need_close = 0;
272 int error = 0;
273 int skip_device = 0;
274
275 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
276 warn("couldn't open %s", XPT_DEVICE);
277 return(1);
278 }
279
280 bzero(&(&ccb.ccb_h)[1],
281 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
282
283 ccb.ccb_h.func_code = XPT_DEV_MATCH;
284 bufsize = sizeof(struct dev_match_result) * 100;
285 ccb.cdm.match_buf_len = bufsize;
286 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
287 ccb.cdm.num_matches = 0;
288
289 /*
290 * We fetch all nodes, since we display most of them in the default
291 * case, and all in the verbose case.
292 */
293 ccb.cdm.num_patterns = 0;
294 ccb.cdm.pattern_buf_len = 0;
295
296 /*
297 * We do the ioctl multiple times if necessary, in case there are
298 * more than 100 nodes in the EDT.
299 */
300 do {
301 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
302 warn("error sending CAMIOCOMMAND ioctl");
303 error = 1;
304 break;
305 }
306
307 if ((ccb.ccb_h.status != CAM_REQ_CMP)
308 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
309 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
310 fprintf(stderr, "got CAM error %#x, CDM error %d\n",
311 ccb.ccb_h.status, ccb.cdm.status);
312 error = 1;
313 break;
314 }
315
316 for (i = 0; i < ccb.cdm.num_matches; i++) {
317 switch(ccb.cdm.matches[i].type) {
318 case DEV_MATCH_BUS: {
319 struct bus_match_result *bus_result;
320
321 /*
322 * Only print the bus information if the
323 * user turns on the verbose flag.
324 */
325 if ((arglist & CAM_ARG_VERBOSE) == 0)
326 break;
327
328 bus_result =
329 &ccb.cdm.matches[i].result.bus_result;
330
331 if (need_close) {
332 fprintf(stdout, ")\n");
333 need_close = 0;
334 }
335
336 fprintf(stdout, "scbus%d on %s%d bus %d:\n",
337 bus_result->path_id,
338 bus_result->dev_name,
339 bus_result->unit_number,
340 bus_result->bus_id);
341 break;
342 }
343 case DEV_MATCH_DEVICE: {
344 struct device_match_result *dev_result;
345 char vendor[16], product[48], revision[16];
346 char tmpstr[256];
347
348 dev_result =
349 &ccb.cdm.matches[i].result.device_result;
350
351 if ((dev_result->flags
352 & DEV_RESULT_UNCONFIGURED)
353 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
354 skip_device = 1;
355 break;
356 } else
357 skip_device = 0;
358
359 cam_strvis(vendor, dev_result->inq_data.vendor,
360 sizeof(dev_result->inq_data.vendor),
361 sizeof(vendor));
362 cam_strvis(product,
363 dev_result->inq_data.product,
364 sizeof(dev_result->inq_data.product),
365 sizeof(product));
366 cam_strvis(revision,
367 dev_result->inq_data.revision,
368 sizeof(dev_result->inq_data.revision),
369 sizeof(revision));
370 sprintf(tmpstr, "<%s %s %s>", vendor, product,
371 revision);
372 if (need_close) {
373 fprintf(stdout, ")\n");
374 need_close = 0;
375 }
376
377 fprintf(stdout, "%-33s at scbus%d "
378 "target %d lun %d (",
379 tmpstr,
380 dev_result->path_id,
381 dev_result->target_id,
382 dev_result->target_lun);
383
384 need_close = 1;
385
386 break;
387 }
388 case DEV_MATCH_PERIPH: {
389 struct periph_match_result *periph_result;
390
391 periph_result =
392 &ccb.cdm.matches[i].result.periph_result;
393
394 if (skip_device != 0)
395 break;
396
397 if (need_close > 1)
398 fprintf(stdout, ",");
399
400 fprintf(stdout, "%s%d",
401 periph_result->periph_name,
402 periph_result->unit_number);
403
404 need_close++;
405 break;
406 }
407 default:
408 fprintf(stdout, "unknown match type\n");
409 break;
410 }
411 }
412
413 } while ((ccb.ccb_h.status == CAM_REQ_CMP)
414 && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
415
416 if (need_close)
417 fprintf(stdout, ")\n");
418
419 close(fd);
420
421 return(error);
422}
423
424static int
425testunitready(struct cam_device *device, int retry_count, int timeout,
426 int quiet)
427{
428 int error = 0;
429 union ccb *ccb;
430
431 ccb = cam_getccb(device);
432
433 scsi_test_unit_ready(&ccb->csio,
434 /* retries */ retry_count,
435 /* cbfcnp */ NULL,
436 /* tag_action */ MSG_SIMPLE_Q_TAG,
437 /* sense_len */ SSD_FULL_SIZE,
438 /* timeout */ timeout ? timeout : 5000);
439
440 /* Disable freezing the device queue */
441 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
442
443 if (arglist & CAM_ARG_ERR_RECOVER)
444 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
445
446 if (cam_send_ccb(device, ccb) < 0) {
447 if (quiet == 0)
448 perror("error sending test unit ready");
449
450 if (arglist & CAM_ARG_VERBOSE) {
451 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
452 CAM_SCSI_STATUS_ERROR)
453 scsi_sense_print(device, &ccb->csio, stderr);
454 else
455 fprintf(stderr, "CAM status is %#x\n",
456 ccb->ccb_h.status);
457 }
458
459 cam_freeccb(ccb);
460 return(1);
461 }
462
463 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
464 if (quiet == 0)
465 fprintf(stdout, "Unit is ready\n");
466 } else {
467 if (quiet == 0)
468 fprintf(stdout, "Unit is not ready\n");
469 error = 1;
470
471 if (arglist & CAM_ARG_VERBOSE) {
472 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
473 CAM_SCSI_STATUS_ERROR)
474 scsi_sense_print(device, &ccb->csio, stderr);
475 else
476 fprintf(stderr, "CAM status is %#x\n",
477 ccb->ccb_h.status);
478 }
479 }
480
481 cam_freeccb(ccb);
482
483 return(error);
484}
485
486static int
487scsistart(struct cam_device *device, int startstop, int loadeject,
488 int retry_count, int timeout)
489{
490 union ccb *ccb;
491 int error = 0;
492
493 ccb = cam_getccb(device);
494
495 /*
496 * If we're stopping, send an ordered tag so the drive in question
497 * will finish any previously queued writes before stopping. If
498 * the device isn't capable of tagged queueing, or if tagged
499 * queueing is turned off, the tag action is a no-op.
500 */
501 scsi_start_stop(&ccb->csio,
502 /* retries */ retry_count,
503 /* cbfcnp */ NULL,
504 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG :
505 MSG_ORDERED_Q_TAG,
506 /* start/stop */ startstop,
507 /* load_eject */ loadeject,
508 /* immediate */ 0,
509 /* sense_len */ SSD_FULL_SIZE,
510 /* timeout */ timeout ? timeout : 120000);
511
512 /* Disable freezing the device queue */
513 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
514
515 if (arglist & CAM_ARG_ERR_RECOVER)
516 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
517
518 if (cam_send_ccb(device, ccb) < 0) {
519 perror("error sending start unit");
520
521 if (arglist & CAM_ARG_VERBOSE) {
522 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
523 CAM_SCSI_STATUS_ERROR)
524 scsi_sense_print(device, &ccb->csio, stderr);
525 else
526 fprintf(stderr, "CAM status is %#x\n",
527 ccb->ccb_h.status);
528 }
529
530 cam_freeccb(ccb);
531 return(1);
532 }
533
534 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
535 if (startstop) {
536 fprintf(stdout, "Unit started successfully");
537 if (loadeject)
538 fprintf(stdout,", Media loaded\n");
539 else
540 fprintf(stdout,"\n");
541 } else {
542 fprintf(stdout, "Unit stopped successfully");
543 if (loadeject)
544 fprintf(stdout, ", Media ejected\n");
545 else
546 fprintf(stdout, "\n");
547 }
548 else {
549 error = 1;
550 if (startstop)
551 fprintf(stdout,
552 "Error received from start unit command\n");
553 else
554 fprintf(stdout,
555 "Error received from stop unit command\n");
556
557 if (arglist & CAM_ARG_VERBOSE) {
558 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
559 CAM_SCSI_STATUS_ERROR)
560 scsi_sense_print(device, &ccb->csio, stderr);
561 else
562 fprintf(stderr, "CAM status is %#x\n",
563 ccb->ccb_h.status);
564 }
565 }
566
567 cam_freeccb(ccb);
568
569 return(error);
570}
571
572static int
573scsidoinquiry(struct cam_device *device, int argc, char **argv,
574 char *combinedopt, int retry_count, int timeout)
575{
576 int c;
577 int error = 0;
578
579 while ((c = getopt(argc, argv, combinedopt)) != -1) {
580 switch(c) {
581 case 'D':
582 arglist |= CAM_ARG_GET_STDINQ;
583 break;
584 case 'R':
585 arglist |= CAM_ARG_GET_XFERRATE;
586 break;
587 case 'S':
588 arglist |= CAM_ARG_GET_SERIAL;
589 break;
590 default:
591 break;
592 }
593 }
594
595 /*
596 * If the user didn't specify any inquiry options, he wants all of
597 * them.
598 */
599 if ((arglist & CAM_ARG_INQ_MASK) == 0)
600 arglist |= CAM_ARG_INQ_MASK;
601
602 if (arglist & CAM_ARG_GET_STDINQ)
603 error = scsiinquiry(device, retry_count, timeout);
604
605 if (error != 0)
606 return(error);
607
608 if (arglist & CAM_ARG_GET_SERIAL)
609 scsiserial(device, retry_count, timeout);
610
611 if (error != 0)
612 return(error);
613
614 if (arglist & CAM_ARG_GET_XFERRATE)
615 error = scsixferrate(device);
616
617 return(error);
618}
619
620static int
621scsiinquiry(struct cam_device *device, int retry_count, int timeout)
622{
623 union ccb *ccb;
624 struct scsi_inquiry_data *inq_buf;
625 int error = 0;
626
627 ccb = cam_getccb(device);
628
629 if (ccb == NULL) {
630 warnx("couldn't allocate CCB");
631 return(1);
632 }
633
634 /* cam_getccb cleans up the header, caller has to zero the payload */
635 bzero(&(&ccb->ccb_h)[1],
636 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
637
638 inq_buf = (struct scsi_inquiry_data *)malloc(
639 sizeof(struct scsi_inquiry_data));
640
641 if (inq_buf == NULL) {
642 cam_freeccb(ccb);
643 warnx("can't malloc memory for inquiry\n");
644 return(1);
645 }
646 bzero(inq_buf, sizeof(*inq_buf));
647
648 /*
649 * Note that although the size of the inquiry buffer is the full
650 * 256 bytes specified in the SCSI spec, we only tell the device
651 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are
652 * two reasons for this:
653 *
654 * - The SCSI spec says that when a length field is only 1 byte,
655 * a value of 0 will be interpreted as 256. Therefore
656 * scsi_inquiry() will convert an inq_len (which is passed in as
657 * a u_int32_t, but the field in the CDB is only 1 byte) of 256
658 * to 0. Evidently, very few devices meet the spec in that
659 * regard. Some devices, like many Seagate disks, take the 0 as
660 * 0, and don't return any data. One Pioneer DVD-R drive
661 * returns more data than the command asked for.
662 *
663 * So, since there are numerous devices that just don't work
664 * right with the full inquiry size, we don't send the full size.
665 *
666 * - The second reason not to use the full inquiry data length is
667 * that we don't need it here. The only reason we issue a
668 * standard inquiry is to get the vendor name, device name,
669 * and revision so scsi_print_inquiry() can print them.
670 *
671 * If, at some point in the future, more inquiry data is needed for
672 * some reason, this code should use a procedure similar to the
673 * probe code. i.e., issue a short inquiry, and determine from
674 * the additional length passed back from the device how much
675 * inquiry data the device supports. Once the amount the device
676 * supports is determined, issue an inquiry for that amount and no
677 * more.
678 *
679 * KDM, 2/18/2000
680 */
681 scsi_inquiry(&ccb->csio,
682 /* retries */ retry_count,
683 /* cbfcnp */ NULL,
684 /* tag_action */ MSG_SIMPLE_Q_TAG,
685 /* inq_buf */ (u_int8_t *)inq_buf,
686 /* inq_len */ SHORT_INQUIRY_LENGTH,
687 /* evpd */ 0,
688 /* page_code */ 0,
689 /* sense_len */ SSD_FULL_SIZE,
690 /* timeout */ timeout ? timeout : 5000);
691
692 /* Disable freezing the device queue */
693 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
694
695 if (arglist & CAM_ARG_ERR_RECOVER)
696 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
697
698 if (cam_send_ccb(device, ccb) < 0) {
699 perror("error sending SCSI inquiry");
700
701 if (arglist & CAM_ARG_VERBOSE) {
702 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
703 CAM_SCSI_STATUS_ERROR)
704 scsi_sense_print(device, &ccb->csio, stderr);
705 else
706 fprintf(stderr, "CAM status is %#x\n",
707 ccb->ccb_h.status);
708 }
709
710 cam_freeccb(ccb);
711 return(1);
712 }
713
714 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
715 error = 1;
716
717 if (arglist & CAM_ARG_VERBOSE) {
718 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
719 CAM_SCSI_STATUS_ERROR)
720 scsi_sense_print(device, &ccb->csio, stderr);
721 else
722 fprintf(stderr, "CAM status is %#x\n",
723 ccb->ccb_h.status);
724 }
725 }
726
727 cam_freeccb(ccb);
728
729 if (error != 0) {
730 free(inq_buf);
731 return(error);
732 }
733
734 fprintf(stdout, "%s%d: ", device->device_name,
735 device->dev_unit_num);
736 scsi_print_inquiry(inq_buf);
737
738 free(inq_buf);
739
740 return(0);
741}
742
743static int
744scsiserial(struct cam_device *device, int retry_count, int timeout)
745{
746 union ccb *ccb;
747 struct scsi_vpd_unit_serial_number *serial_buf;
748 char serial_num[SVPD_SERIAL_NUM_SIZE + 1];
749 int error = 0;
750
751 ccb = cam_getccb(device);
752
753 if (ccb == NULL) {
754 warnx("couldn't allocate CCB");
755 return(1);
756 }
757
758 /* cam_getccb cleans up the header, caller has to zero the payload */
759 bzero(&(&ccb->ccb_h)[1],
760 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
761
762 serial_buf = (struct scsi_vpd_unit_serial_number *)
763 malloc(sizeof(*serial_buf));
764
765 if (serial_buf == NULL) {
766 cam_freeccb(ccb);
767 warnx("can't malloc memory for serial number");
768 return(1);
769 }
770
771 scsi_inquiry(&ccb->csio,
772 /*retries*/ retry_count,
773 /*cbfcnp*/ NULL,
774 /* tag_action */ MSG_SIMPLE_Q_TAG,
775 /* inq_buf */ (u_int8_t *)serial_buf,
776 /* inq_len */ sizeof(*serial_buf),
777 /* evpd */ 1,
778 /* page_code */ SVPD_UNIT_SERIAL_NUMBER,
779 /* sense_len */ SSD_FULL_SIZE,
780 /* timeout */ timeout ? timeout : 5000);
781
782 /* Disable freezing the device queue */
783 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
784
785 if (arglist & CAM_ARG_ERR_RECOVER)
786 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
787
788 if (cam_send_ccb(device, ccb) < 0) {
789 warn("error getting serial number");
790
791 if (arglist & CAM_ARG_VERBOSE) {
792 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
793 CAM_SCSI_STATUS_ERROR)
794 scsi_sense_print(device, &ccb->csio, stderr);
795 else
796 fprintf(stderr, "CAM status is %#x\n",
797 ccb->ccb_h.status);
798 }
799
800 cam_freeccb(ccb);
801 free(serial_buf);
802 return(1);
803 }
804
805 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
806 error = 1;
807
808 if (arglist & CAM_ARG_VERBOSE) {
809 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
810 CAM_SCSI_STATUS_ERROR)
811 scsi_sense_print(device, &ccb->csio, stderr);
812 else
813 fprintf(stderr, "CAM status is %#x\n",
814 ccb->ccb_h.status);
815 }
816 }
817
818 cam_freeccb(ccb);
819
820 if (error != 0) {
821 free(serial_buf);
822 return(error);
823 }
824
825 bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
826 serial_num[serial_buf->length] = '\0';
827
828 if ((arglist & CAM_ARG_GET_STDINQ)
829 || (arglist & CAM_ARG_GET_XFERRATE))
830 fprintf(stdout, "%s%d: Serial Number ",
831 device->device_name, device->dev_unit_num);
832
833 fprintf(stdout, "%.60s\n", serial_num);
834
835 free(serial_buf);
836
837 return(0);
838}
839
840static int
841scsixferrate(struct cam_device *device)
842{
843 u_int32_t freq;
844 u_int32_t speed;
845 union ccb *ccb;
846 u_int mb;
847 int retval = 0;
848
849 ccb = cam_getccb(device);
850
851 if (ccb == NULL) {
852 warnx("couldn't allocate CCB");
853 return(1);
854 }
855
856 bzero(&(&ccb->ccb_h)[1],
857 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
858
859 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
860 ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
861
862 if (((retval = cam_send_ccb(device, ccb)) < 0)
863 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
864 char *error_string = "error getting transfer settings";
865
866 if (retval < 0)
867 warn(error_string);
868 else
869 warnx(error_string);
870
871 /*
872 * If there is an error, it won't be a SCSI error since
873 * this isn't a SCSI CCB.
874 */
875 if (arglist & CAM_ARG_VERBOSE)
876 fprintf(stderr, "CAM status is %#x\n",
877 ccb->ccb_h.status);
878
879 retval = 1;
880
881 goto xferrate_bailout;
882
883 }
884
885 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
886 && (ccb->cts.sync_offset != 0)) {
887 freq = scsi_calc_syncsrate(ccb->cts.sync_period);
888 speed = freq;
889 } else {
890 struct ccb_pathinq cpi;
891
892 retval = get_cpi(device, &cpi);
893
894 if (retval != 0)
895 goto xferrate_bailout;
896
897 speed = cpi.base_transfer_speed;
898 freq = 0;
899 }
900
901 fprintf(stdout, "%s%d: ", device->device_name,
902 device->dev_unit_num);
903
904 if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
905 speed *= (0x01 << device->bus_width);
906
907 mb = speed / 1000;
908
909 if (mb > 0)
910 fprintf(stdout, "%d.%03dMB/s transfers ",
911 mb, speed % 1000);
912 else
913 fprintf(stdout, "%dKB/s transfers ",
914 speed);
915
916 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
917 && (ccb->cts.sync_offset != 0))
918 fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
919 freq % 1000, ccb->cts.sync_offset);
920
921 if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
922 && (ccb->cts.bus_width > 0)) {
923 if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
924 && (ccb->cts.sync_offset != 0)) {
925 fprintf(stdout, ", ");
926 } else {
927 fprintf(stdout, " (");
928 }
929 fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
930 } else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
931 && (ccb->cts.sync_offset != 0)) {
932 fprintf(stdout, ")");
933 }
934
935 if (((ccb->cts.valid & CCB_TRANS_TQ_VALID) != 0)
936 && (ccb->cts.flags & CCB_TRANS_TAG_ENB))
937 fprintf(stdout, ", Tagged Queueing Enabled");
938
939 fprintf(stdout, "\n");
940
941xferrate_bailout:
942
943 cam_freeccb(ccb);
944
945 return(retval);
946}
947
948/*
949 * Parse out a bus, or a bus, target and lun in the following
950 * format:
951 * bus
952 * bus:target
953 * bus:target:lun
954 *
955 * Returns the number of parsed components, or 0.
956 */
957static int
958parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglist)
959{
960 char *tmpstr;
961 int convs = 0;
962
963 while (isspace(*tstr) && (*tstr != '\0'))
964 tstr++;
965
966 tmpstr = (char *)strtok(tstr, ":");
967 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
968 *bus = strtol(tmpstr, NULL, 0);
969 *arglist |= CAM_ARG_BUS;
970 convs++;
971 tmpstr = (char *)strtok(NULL, ":");
972 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
973 *target = strtol(tmpstr, NULL, 0);
974 *arglist |= CAM_ARG_TARGET;
975 convs++;
976 tmpstr = (char *)strtok(NULL, ":");
977 if ((tmpstr != NULL) && (*tmpstr != '\0')) {
978 *lun = strtol(tmpstr, NULL, 0);
979 *arglist |= CAM_ARG_LUN;
980 convs++;
981 }
982 }
983 }
984
985 return convs;
986}
987
988static int
989dorescan_or_reset(int argc, char **argv, int rescan)
990{
991 static const char *must =
992 "you must specify a bus, or a bus:target:lun to %s";
993 int rv, error = 0;
994 int bus = -1, target = -1, lun = -1;
995
996 if (argc < 3) {
997 warnx(must, rescan? "rescan" : "reset");
998 return(1);
999 }
1000 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist);
1001 if (rv != 1 && rv != 3) {
1002 warnx(must, rescan? "rescan" : "reset");
1003 return(1);
1004 }
1005
1006 if ((arglist & CAM_ARG_BUS)
1007 && (arglist & CAM_ARG_TARGET)
1008 && (arglist & CAM_ARG_LUN))
1009 error = scanlun_or_reset_dev(bus, target, lun, rescan);
1010 else
1011 error = rescan_or_reset_bus(bus, rescan);
1012
1013 return(error);
1014}
1015
1016static int
1017rescan_or_reset_bus(int bus, int rescan)
1018{
1019 union ccb ccb;
1020 int fd;
1021
1022 if (bus < 0) {
1023 warnx("invalid bus number %d", bus);
1024 return(1);
1025 }
1026
1027 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1028 warnx("error opening tranport layer device %s", XPT_DEVICE);
1029 warn("%s", XPT_DEVICE);
1030 return(1);
1031 }
1032
1033 ccb.ccb_h.func_code = rescan? XPT_SCAN_BUS : XPT_RESET_BUS;
1034 ccb.ccb_h.path_id = bus;
1035 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1036 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1037 ccb.crcn.flags = CAM_FLAG_NONE;
1038
1039 /* run this at a low priority */
1040 ccb.ccb_h.pinfo.priority = 5;
1041
1042 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1043 warn("CAMIOCOMMAND ioctl failed");
1044 close(fd);
1045 return(1);
1046 }
1047
1048 close(fd);
1049
1050 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1051 fprintf(stdout, "%s of bus %d was successful\n",
1052 rescan? "Re-scan" : "Reset", bus);
1053 return(0);
1054 } else {
1055 fprintf(stdout, "%s of bus %d returned error %#x\n",
1056 rescan? "Re-scan" : "Reset", bus,
1057 ccb.ccb_h.status & CAM_STATUS_MASK);
1058 return(1);
1059 }
1060}
1061
1062static int
1063scanlun_or_reset_dev(int bus, int target, int lun, int scan)
1064{
1065 union ccb ccb;
1066 struct cam_device *device;
1067 int fd;
1068
1069 device = NULL;
1070
1071 if (bus < 0) {
1072 warnx("invalid bus number %d", bus);
1073 return(1);
1074 }
1075
1076 if (target < 0) {
1077 warnx("invalid target number %d", target);
1078 return(1);
1079 }
1080
1081 if (lun < 0) {
1082 warnx("invalid lun number %d", lun);
1083 return(1);
1084 }
1085
1086 fd = -1;
1087
1088 bzero(&ccb, sizeof(union ccb));
1089
1090 if (scan) {
1091 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1092 warnx("error opening tranport layer device %s\n",
1093 XPT_DEVICE);
1094 warn("%s", XPT_DEVICE);
1095 return(1);
1096 }
1097 } else {
1098 device = cam_open_btl(bus, target, lun, O_RDWR, NULL);
1099 if (device == NULL) {
1100 warnx("%s", cam_errbuf);
1101 return(1);
1102 }
1103 }
1104
1105 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV;
1106 ccb.ccb_h.path_id = bus;
1107 ccb.ccb_h.target_id = target;
1108 ccb.ccb_h.target_lun = lun;
1109 ccb.ccb_h.timeout = 5000;
1110 ccb.crcn.flags = CAM_FLAG_NONE;
1111
1112 /* run this at a low priority */
1113 ccb.ccb_h.pinfo.priority = 5;
1114
1115 if (scan) {
1116 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) {
1117 warn("CAMIOCOMMAND ioctl failed");
1118 close(fd);
1119 return(1);
1120 }
1121 } else {
1122 if (cam_send_ccb(device, &ccb) < 0) {
1123 warn("error sending XPT_RESET_DEV CCB");
1124 cam_close_device(device);
1125 return(1);
1126 }
1127 }
1128
1129 if (scan)
1130 close(fd);
1131 else
1132 cam_close_device(device);
1133
1134 /*
1135 * An error code of CAM_BDR_SENT is normal for a BDR request.
1136 */
1137 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1138 || ((!scan)
1139 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) {
1140 fprintf(stdout, "%s of %d:%d:%d was successful\n",
1141 scan? "Re-scan" : "Reset", bus, target, lun);
1142 return(0);
1143 } else {
1144 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n",
1145 scan? "Re-scan" : "Reset", bus, target, lun,
1146 ccb.ccb_h.status & CAM_STATUS_MASK);
1147 return(1);
1148 }
1149}
1150
1151static int
1152readdefects(struct cam_device *device, int argc, char **argv,
1153 char *combinedopt, int retry_count, int timeout)
1154{
1155 union ccb *ccb = NULL;
1156 struct scsi_read_defect_data_10 *rdd_cdb;
1157 u_int8_t *defect_list = NULL;
1158 u_int32_t dlist_length = 65000;
1159 u_int32_t returned_length = 0;
1160 u_int32_t num_returned = 0;
1161 u_int8_t returned_format;
1162 register int i;
1163 int c, error = 0;
1164 int lists_specified = 0;
1165
1166 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1167 switch(c){
1168 case 'f':
1169 {
1170 char *tstr;
1171 tstr = optarg;
1172 while (isspace(*tstr) && (*tstr != '\0'))
1173 tstr++;
1174 if (strcmp(tstr, "block") == 0)
1175 arglist |= CAM_ARG_FORMAT_BLOCK;
1176 else if (strcmp(tstr, "bfi") == 0)
1177 arglist |= CAM_ARG_FORMAT_BFI;
1178 else if (strcmp(tstr, "phys") == 0)
1179 arglist |= CAM_ARG_FORMAT_PHYS;
1180 else {
1181 error = 1;
1182 warnx("invalid defect format %s", tstr);
1183 goto defect_bailout;
1184 }
1185 break;
1186 }
1187 case 'G':
1188 arglist |= CAM_ARG_GLIST;
1189 break;
1190 case 'P':
1191 arglist |= CAM_ARG_PLIST;
1192 break;
1193 default:
1194 break;
1195 }
1196 }
1197
1198 ccb = cam_getccb(device);
1199
1200 /*
1201 * Hopefully 65000 bytes is enough to hold the defect list. If it
1202 * isn't, the disk is probably dead already. We'd have to go with
1203 * 12 byte command (i.e. alloc_length is 32 bits instead of 16)
1204 * to hold them all.
1205 */
1206 defect_list = malloc(dlist_length);
1207
1208 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes;
1209
1210 /*
1211 * cam_getccb() zeros the CCB header only. So we need to zero the
1212 * payload portion of the ccb.
1213 */
1214 bzero(&(&ccb->ccb_h)[1],
1215 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1216
1217 cam_fill_csio(&ccb->csio,
1218 /*retries*/ retry_count,
1219 /*cbfcnp*/ NULL,
1220 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ?
1221 CAM_PASS_ERR_RECOVER : 0),
1222 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1223 /*data_ptr*/ defect_list,
1224 /*dxfer_len*/ dlist_length,
1225 /*sense_len*/ SSD_FULL_SIZE,
1226 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10),
1227 /*timeout*/ timeout ? timeout : 5000);
1228
1229 rdd_cdb->opcode = READ_DEFECT_DATA_10;
1230 if (arglist & CAM_ARG_FORMAT_BLOCK)
1231 rdd_cdb->format = SRDD10_BLOCK_FORMAT;
1232 else if (arglist & CAM_ARG_FORMAT_BFI)
1233 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT;
1234 else if (arglist & CAM_ARG_FORMAT_PHYS)
1235 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT;
1236 else {
1237 error = 1;
1238 warnx("no defect list format specified");
1239 goto defect_bailout;
1240 }
1241 if (arglist & CAM_ARG_PLIST) {
1242 rdd_cdb->format |= SRDD10_PLIST;
1243 lists_specified++;
1244 }
1245
1246 if (arglist & CAM_ARG_GLIST) {
1247 rdd_cdb->format |= SRDD10_GLIST;
1248 lists_specified++;
1249 }
1250
1251 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length);
1252
1253 /* Disable freezing the device queue */
1254 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1255
1256 if (cam_send_ccb(device, ccb) < 0) {
1257 perror("error reading defect list");
1258
1259 if (arglist & CAM_ARG_VERBOSE) {
1260 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1261 CAM_SCSI_STATUS_ERROR)
1262 scsi_sense_print(device, &ccb->csio, stderr);
1263 else
1264 fprintf(stderr, "CAM status is %#x\n",
1265 ccb->ccb_h.status);
1266 }
1267
1268 error = 1;
1269 goto defect_bailout;
1270 }
1271
1272 if (arglist & CAM_ARG_VERBOSE)
1273 scsi_sense_print(device, &ccb->csio, stderr);
1274
1275 returned_length = scsi_2btoul(((struct
1276 scsi_read_defect_data_hdr_10 *)defect_list)->length);
1277
1278 returned_format = ((struct scsi_read_defect_data_hdr_10 *)
1279 defect_list)->format;
1280
1281 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1282 struct scsi_sense_data *sense;
1283 int error_code, sense_key, asc, ascq;
1284
1285 sense = &ccb->csio.sense_data;
1286 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
1287
1288 /*
1289 * According to the SCSI spec, if the disk doesn't support
1290 * the requested format, it will generally return a sense
1291 * key of RECOVERED ERROR, and an additional sense code
1292 * of "DEFECT LIST NOT FOUND". So, we check for that, and
1293 * also check to make sure that the returned length is
1294 * greater than 0, and then print out whatever format the
1295 * disk gave us.
1296 */
1297 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
1298 && (asc == 0x1c) && (ascq == 0x00)
1299 && (returned_length > 0)) {
1300 warnx("requested defect format not available");
1301 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) {
1302 case SRDD10_BLOCK_FORMAT:
1303 warnx("Device returned block format");
1304 break;
1305 case SRDD10_BYTES_FROM_INDEX_FORMAT:
1306 warnx("Device returned bytes from index"
1307 " format");
1308 break;
1309 case SRDD10_PHYSICAL_SECTOR_FORMAT:
1310 warnx("Device returned physical sector format");
1311 break;
1312 default:
1313 error = 1;
1314 warnx("Device returned unknown defect"
1315 " data format %#x", returned_format);
1316 goto defect_bailout;
1317 break; /* NOTREACHED */
1318 }
1319 } else {
1320 error = 1;
1321 warnx("Error returned from read defect data command");
1322 goto defect_bailout;
1323 }
1324 }
1325
1326 /*
1327 * XXX KDM I should probably clean up the printout format for the
1328 * disk defects.
1329 */
1330 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){
1331 case SRDDH10_PHYSICAL_SECTOR_FORMAT:
1332 {
1333 struct scsi_defect_desc_phys_sector *dlist;
1334
1335 dlist = (struct scsi_defect_desc_phys_sector *)
1336 (defect_list +
1337 sizeof(struct scsi_read_defect_data_hdr_10));
1338
1339 num_returned = returned_length /
1340 sizeof(struct scsi_defect_desc_phys_sector);
1341
1342 fprintf(stderr, "Got %d defect", num_returned);
1343
1344 if ((lists_specified == 0) || (num_returned == 0)) {
1345 fprintf(stderr, "s.\n");
1346 break;
1347 } else if (num_returned == 1)
1348 fprintf(stderr, ":\n");
1349 else
1350 fprintf(stderr, "s:\n");
1351
1352 for (i = 0; i < num_returned; i++) {
1353 fprintf(stdout, "%d:%d:%d\n",
1354 scsi_3btoul(dlist[i].cylinder),
1355 dlist[i].head,
1356 scsi_4btoul(dlist[i].sector));
1357 }
1358 break;
1359 }
1360 case SRDDH10_BYTES_FROM_INDEX_FORMAT:
1361 {
1362 struct scsi_defect_desc_bytes_from_index *dlist;
1363
1364 dlist = (struct scsi_defect_desc_bytes_from_index *)
1365 (defect_list +
1366 sizeof(struct scsi_read_defect_data_hdr_10));
1367
1368 num_returned = returned_length /
1369 sizeof(struct scsi_defect_desc_bytes_from_index);
1370
1371 fprintf(stderr, "Got %d defect", num_returned);
1372
1373 if ((lists_specified == 0) || (num_returned == 0)) {
1374 fprintf(stderr, "s.\n");
1375 break;
1376 } else if (num_returned == 1)
1377 fprintf(stderr, ":\n");
1378 else
1379 fprintf(stderr, "s:\n");
1380
1381 for (i = 0; i < num_returned; i++) {
1382 fprintf(stdout, "%d:%d:%d\n",
1383 scsi_3btoul(dlist[i].cylinder),
1384 dlist[i].head,
1385 scsi_4btoul(dlist[i].bytes_from_index));
1386 }
1387 break;
1388 }
1389 case SRDDH10_BLOCK_FORMAT:
1390 {
1391 struct scsi_defect_desc_block *dlist;
1392
1393 dlist = (struct scsi_defect_desc_block *)(defect_list +
1394 sizeof(struct scsi_read_defect_data_hdr_10));
1395
1396 num_returned = returned_length /
1397 sizeof(struct scsi_defect_desc_block);
1398
1399 fprintf(stderr, "Got %d defect", num_returned);
1400
1401 if ((lists_specified == 0) || (num_returned == 0)) {
1402 fprintf(stderr, "s.\n");
1403 break;
1404 } else if (num_returned == 1)
1405 fprintf(stderr, ":\n");
1406 else
1407 fprintf(stderr, "s:\n");
1408
1409 for (i = 0; i < num_returned; i++)
1410 fprintf(stdout, "%u\n",
1411 scsi_4btoul(dlist[i].address));
1412 break;
1413 }
1414 default:
1415 fprintf(stderr, "Unknown defect format %d\n",
1416 returned_format & SRDDH10_DLIST_FORMAT_MASK);
1417 error = 1;
1418 break;
1419 }
1420defect_bailout:
1421
1422 if (defect_list != NULL)
1423 free(defect_list);
1424
1425 if (ccb != NULL)
1426 cam_freeccb(ccb);
1427
1428 return(error);
1429}
1430
1431#if 0
1432void
1433reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
1434{
1435 union ccb *ccb;
1436
1437 ccb = cam_getccb(device);
1438
1439 cam_freeccb(ccb);
1440}
1441#endif
1442
1443void
1444mode_sense(struct cam_device *device, int mode_page, int page_control,
1445 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
1446{
1447 union ccb *ccb;
1448 int retval;
1449
1450 ccb = cam_getccb(device);
1451
1452 if (ccb == NULL)
1453 errx(1, "mode_sense: couldn't allocate CCB");
1454
1455 bzero(&(&ccb->ccb_h)[1],
1456 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1457
1458 scsi_mode_sense(&ccb->csio,
1459 /* retries */ retry_count,
1460 /* cbfcnp */ NULL,
1461 /* tag_action */ MSG_SIMPLE_Q_TAG,
1462 /* dbd */ dbd,
1463 /* page_code */ page_control << 6,
1464 /* page */ mode_page,
1465 /* param_buf */ data,
1466 /* param_len */ datalen,
1467 /* sense_len */ SSD_FULL_SIZE,
1468 /* timeout */ timeout ? timeout : 5000);
1469
1470 if (arglist & CAM_ARG_ERR_RECOVER)
1471 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1472
1473 /* Disable freezing the device queue */
1474 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1475
1476 if (((retval = cam_send_ccb(device, ccb)) < 0)
1477 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1478 if (arglist & CAM_ARG_VERBOSE) {
1479 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1480 CAM_SCSI_STATUS_ERROR)
1481 scsi_sense_print(device, &ccb->csio, stderr);
1482 else
1483 fprintf(stderr, "CAM status is %#x\n",
1484 ccb->ccb_h.status);
1485 }
1486 cam_freeccb(ccb);
1487 cam_close_device(device);
1488 if (retval < 0)
1489 err(1, "error sending mode sense command");
1490 else
1491 errx(1, "error sending mode sense command");
1492 }
1493
1494 cam_freeccb(ccb);
1495}
1496
1497void
1498mode_select(struct cam_device *device, int save_pages, int retry_count,
1499 int timeout, u_int8_t *data, int datalen)
1500{
1501 union ccb *ccb;
1502 int retval;
1503
1504 ccb = cam_getccb(device);
1505
1506 if (ccb == NULL)
1507 errx(1, "mode_select: couldn't allocate CCB");
1508
1509 bzero(&(&ccb->ccb_h)[1],
1510 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1511
1512 scsi_mode_select(&ccb->csio,
1513 /* retries */ retry_count,
1514 /* cbfcnp */ NULL,
1515 /* tag_action */ MSG_SIMPLE_Q_TAG,
1516 /* scsi_page_fmt */ 1,
1517 /* save_pages */ save_pages,
1518 /* param_buf */ data,
1519 /* param_len */ datalen,
1520 /* sense_len */ SSD_FULL_SIZE,
1521 /* timeout */ timeout ? timeout : 5000);
1522
1523 if (arglist & CAM_ARG_ERR_RECOVER)
1524 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
1525
1526 /* Disable freezing the device queue */
1527 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
1528
1529 if (((retval = cam_send_ccb(device, ccb)) < 0)
1530 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1531 if (arglist & CAM_ARG_VERBOSE) {
1532 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1533 CAM_SCSI_STATUS_ERROR)
1534 scsi_sense_print(device, &ccb->csio, stderr);
1535 else
1536 fprintf(stderr, "CAM status is %#x\n",
1537 ccb->ccb_h.status);
1538 }
1539 cam_freeccb(ccb);
1540 cam_close_device(device);
1541
1542 if (retval < 0)
1543 err(1, "error sending mode select command");
1544 else
1545 errx(1, "error sending mode select command");
1546
1547 }
1548
1549 cam_freeccb(ccb);
1550}
1551
1552void
1553modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
1554 int retry_count, int timeout)
1555{
1556 int c, mode_page = -1, page_control = 0;
1557 int binary = 0, list = 0;
1557
1558 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1559 switch(c) {
1558
1559 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1560 switch(c) {
1561 case 'b':
1562 binary = 1;
1563 break;
1560 case 'd':
1561 arglist |= CAM_ARG_DBD;
1562 break;
1563 case 'e':
1564 arglist |= CAM_ARG_MODE_EDIT;
1565 break;
1564 case 'd':
1565 arglist |= CAM_ARG_DBD;
1566 break;
1567 case 'e':
1568 arglist |= CAM_ARG_MODE_EDIT;
1569 break;
1570 case 'l':
1571 list = 1;
1572 break;
1566 case 'm':
1567 mode_page = strtol(optarg, NULL, 0);
1568 if (mode_page < 0)
1569 errx(1, "invalid mode page %d", mode_page);
1570 break;
1571 case 'P':
1572 page_control = strtol(optarg, NULL, 0);
1573 if ((page_control < 0) || (page_control > 3))
1574 errx(1, "invalid page control field %d",
1575 page_control);
1576 arglist |= CAM_ARG_PAGE_CNTL;
1577 break;
1578 default:
1579 break;
1580 }
1581 }
1582
1573 case 'm':
1574 mode_page = strtol(optarg, NULL, 0);
1575 if (mode_page < 0)
1576 errx(1, "invalid mode page %d", mode_page);
1577 break;
1578 case 'P':
1579 page_control = strtol(optarg, NULL, 0);
1580 if ((page_control < 0) || (page_control > 3))
1581 errx(1, "invalid page control field %d",
1582 page_control);
1583 arglist |= CAM_ARG_PAGE_CNTL;
1584 break;
1585 default:
1586 break;
1587 }
1588 }
1589
1583 if (mode_page == -1)
1590 if (mode_page == -1 && list == 0)
1584 errx(1, "you must specify a mode page!");
1585
1591 errx(1, "you must specify a mode page!");
1592
1586 mode_edit(device, mode_page, page_control, arglist & CAM_ARG_DBD,
1587 arglist & CAM_ARG_MODE_EDIT, retry_count, timeout);
1593 if (list) {
1594 mode_list(device, page_control, arglist & CAM_ARG_DBD,
1595 retry_count, timeout);
1596 } else {
1597 mode_edit(device, mode_page, page_control,
1598 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
1599 retry_count, timeout);
1600 }
1588}
1589
1590static int
1591scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
1592 int retry_count, int timeout)
1593{
1594 union ccb *ccb;
1595 u_int32_t flags = CAM_DIR_NONE;
1596 u_int8_t *data_ptr = NULL;
1597 u_int8_t cdb[20];
1598 struct get_hook hook;
1599 int c, data_bytes = 0;
1600 int cdb_len = 0;
1601 char *datastr = NULL, *tstr;
1602 int error = 0;
1603 int fd_data = 0;
1604 int retval;
1605
1606 ccb = cam_getccb(device);
1607
1608 if (ccb == NULL) {
1609 warnx("scsicmd: error allocating ccb");
1610 return(1);
1611 }
1612
1613 bzero(&(&ccb->ccb_h)[1],
1614 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1615
1616 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1617 switch(c) {
1618 case 'c':
1619 tstr = optarg;
1620 while (isspace(*tstr) && (*tstr != '\0'))
1621 tstr++;
1622 hook.argc = argc - optind;
1623 hook.argv = argv + optind;
1624 hook.got = 0;
1625 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
1626 iget, &hook);
1627 /*
1628 * Increment optind by the number of arguments the
1629 * encoding routine processed. After each call to
1630 * getopt(3), optind points to the argument that
1631 * getopt should process _next_. In this case,
1632 * that means it points to the first command string
1633 * argument, if there is one. Once we increment
1634 * this, it should point to either the next command
1635 * line argument, or it should be past the end of
1636 * the list.
1637 */
1638 optind += hook.got;
1639 break;
1640 case 'i':
1641 if (arglist & CAM_ARG_CMD_OUT) {
1642 warnx("command must either be "
1643 "read or write, not both");
1644 error = 1;
1645 goto scsicmd_bailout;
1646 }
1647 arglist |= CAM_ARG_CMD_IN;
1648 flags = CAM_DIR_IN;
1649 data_bytes = strtol(optarg, NULL, 0);
1650 if (data_bytes <= 0) {
1651 warnx("invalid number of input bytes %d",
1652 data_bytes);
1653 error = 1;
1654 goto scsicmd_bailout;
1655 }
1656 hook.argc = argc - optind;
1657 hook.argv = argv + optind;
1658 hook.got = 0;
1659 optind++;
1660 datastr = cget(&hook, NULL);
1661 /*
1662 * If the user supplied "-" instead of a format, he
1663 * wants the data to be written to stdout.
1664 */
1665 if ((datastr != NULL)
1666 && (datastr[0] == '-'))
1667 fd_data = 1;
1668
1669 data_ptr = (u_int8_t *)malloc(data_bytes);
1670 break;
1671 case 'o':
1672 if (arglist & CAM_ARG_CMD_IN) {
1673 warnx("command must either be "
1674 "read or write, not both");
1675 error = 1;
1676 goto scsicmd_bailout;
1677 }
1678 arglist |= CAM_ARG_CMD_OUT;
1679 flags = CAM_DIR_OUT;
1680 data_bytes = strtol(optarg, NULL, 0);
1681 if (data_bytes <= 0) {
1682 warnx("invalid number of output bytes %d",
1683 data_bytes);
1684 error = 1;
1685 goto scsicmd_bailout;
1686 }
1687 hook.argc = argc - optind;
1688 hook.argv = argv + optind;
1689 hook.got = 0;
1690 datastr = cget(&hook, NULL);
1691 data_ptr = (u_int8_t *)malloc(data_bytes);
1692 /*
1693 * If the user supplied "-" instead of a format, he
1694 * wants the data to be read from stdin.
1695 */
1696 if ((datastr != NULL)
1697 && (datastr[0] == '-'))
1698 fd_data = 1;
1699 else
1700 buff_encode_visit(data_ptr, data_bytes, datastr,
1701 iget, &hook);
1702 optind += hook.got;
1703 break;
1704 default:
1705 break;
1706 }
1707 }
1708
1709 /*
1710 * If fd_data is set, and we're writing to the device, we need to
1711 * read the data the user wants written from stdin.
1712 */
1713 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
1714 size_t amt_read;
1715 int amt_to_read = data_bytes;
1716 u_int8_t *buf_ptr = data_ptr;
1717
1718 for (amt_read = 0; amt_to_read > 0;
1719 amt_read = read(0, buf_ptr, amt_to_read)) {
1720 if (amt_read == -1) {
1721 warn("error reading data from stdin");
1722 error = 1;
1723 goto scsicmd_bailout;
1724 }
1725 amt_to_read -= amt_read;
1726 buf_ptr += amt_read;
1727 }
1728 }
1729
1730 if (arglist & CAM_ARG_ERR_RECOVER)
1731 flags |= CAM_PASS_ERR_RECOVER;
1732
1733 /* Disable freezing the device queue */
1734 flags |= CAM_DEV_QFRZDIS;
1735
1736 /*
1737 * This is taken from the SCSI-3 draft spec.
1738 * (T10/1157D revision 0.3)
1739 * The top 3 bits of an opcode are the group code. The next 5 bits
1740 * are the command code.
1741 * Group 0: six byte commands
1742 * Group 1: ten byte commands
1743 * Group 2: ten byte commands
1744 * Group 3: reserved
1745 * Group 4: sixteen byte commands
1746 * Group 5: twelve byte commands
1747 * Group 6: vendor specific
1748 * Group 7: vendor specific
1749 */
1750 switch((cdb[0] >> 5) & 0x7) {
1751 case 0:
1752 cdb_len = 6;
1753 break;
1754 case 1:
1755 case 2:
1756 cdb_len = 10;
1757 break;
1758 case 3:
1759 case 6:
1760 case 7:
1761 /* computed by buff_encode_visit */
1762 break;
1763 case 4:
1764 cdb_len = 16;
1765 break;
1766 case 5:
1767 cdb_len = 12;
1768 break;
1769 }
1770
1771 /*
1772 * We should probably use csio_build_visit or something like that
1773 * here, but it's easier to encode arguments as you go. The
1774 * alternative would be skipping the CDB argument and then encoding
1775 * it here, since we've got the data buffer argument by now.
1776 */
1777 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
1778
1779 cam_fill_csio(&ccb->csio,
1780 /*retries*/ retry_count,
1781 /*cbfcnp*/ NULL,
1782 /*flags*/ flags,
1783 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1784 /*data_ptr*/ data_ptr,
1785 /*dxfer_len*/ data_bytes,
1786 /*sense_len*/ SSD_FULL_SIZE,
1787 /*cdb_len*/ cdb_len,
1788 /*timeout*/ timeout ? timeout : 5000);
1789
1790 if (((retval = cam_send_ccb(device, ccb)) < 0)
1791 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1792 if (retval < 0)
1793 warn("error sending command");
1794 else
1795 warnx("error sending command");
1796
1797 if (arglist & CAM_ARG_VERBOSE) {
1798 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1799 CAM_SCSI_STATUS_ERROR)
1800 scsi_sense_print(device, &ccb->csio, stderr);
1801 else
1802 fprintf(stderr, "CAM status is %#x\n",
1803 ccb->ccb_h.status);
1804 }
1805
1806 error = 1;
1807 goto scsicmd_bailout;
1808 }
1809
1810
1811 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1812 && (arglist & CAM_ARG_CMD_IN)
1813 && (data_bytes > 0)) {
1814 if (fd_data == 0) {
1815 buff_decode_visit(data_ptr, data_bytes, datastr,
1816 arg_put, NULL);
1817 fprintf(stdout, "\n");
1818 } else {
1819 size_t amt_written;
1820 int amt_to_write = data_bytes;
1821 u_int8_t *buf_ptr = data_ptr;
1822
1823 for (amt_written = 0; (amt_to_write > 0) &&
1824 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
1825 amt_to_write -= amt_written;
1826 buf_ptr += amt_written;
1827 }
1828 if (amt_written == -1) {
1829 warn("error writing data to stdout");
1830 error = 1;
1831 goto scsicmd_bailout;
1832 } else if ((amt_written == 0)
1833 && (amt_to_write > 0)) {
1834 warnx("only wrote %u bytes out of %u",
1835 data_bytes - amt_to_write, data_bytes);
1836 }
1837 }
1838 }
1839
1840scsicmd_bailout:
1841
1842 if ((data_bytes > 0) && (data_ptr != NULL))
1843 free(data_ptr);
1844
1845 cam_freeccb(ccb);
1846
1847 return(error);
1848}
1849
1850static int
1851camdebug(int argc, char **argv, char *combinedopt)
1852{
1853 int c, fd;
1854 int bus = -1, target = -1, lun = -1;
1855 char *tstr, *tmpstr = NULL;
1856 union ccb ccb;
1857 int error = 0;
1858
1859 bzero(&ccb, sizeof(union ccb));
1860
1861 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1862 switch(c) {
1863 case 'I':
1864 arglist |= CAM_ARG_DEBUG_INFO;
1865 ccb.cdbg.flags |= CAM_DEBUG_INFO;
1866 break;
1867 case 'S':
1868 arglist |= CAM_ARG_DEBUG_SUBTRACE;
1869 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
1870 break;
1871 case 'T':
1872 arglist |= CAM_ARG_DEBUG_TRACE;
1873 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
1874 break;
1875 case 'c':
1876 arglist |= CAM_ARG_DEBUG_CDB;
1877 ccb.cdbg.flags |= CAM_DEBUG_CDB;
1878 break;
1879 default:
1880 break;
1881 }
1882 }
1883
1884 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1885 warnx("error opening transport layer device %s", XPT_DEVICE);
1886 warn("%s", XPT_DEVICE);
1887 return(1);
1888 }
1889 argc -= optind;
1890 argv += optind;
1891
1892 if (argc <= 0) {
1893 warnx("you must specify \"off\", \"all\" or a bus,");
1894 warnx("bus:target, or bus:target:lun");
1895 close(fd);
1896 return(1);
1897 }
1898
1899 tstr = *argv;
1900
1901 while (isspace(*tstr) && (*tstr != '\0'))
1902 tstr++;
1903
1904 if (strncmp(tstr, "off", 3) == 0) {
1905 ccb.cdbg.flags = CAM_DEBUG_NONE;
1906 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_TRACE|
1907 CAM_ARG_DEBUG_SUBTRACE);
1908 } else if (strncmp(tstr, "all", 3) != 0) {
1909 tmpstr = (char *)strtok(tstr, ":");
1910 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1911 bus = strtol(tmpstr, NULL, 0);
1912 arglist |= CAM_ARG_BUS;
1913 tmpstr = (char *)strtok(NULL, ":");
1914 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1915 target = strtol(tmpstr, NULL, 0);
1916 arglist |= CAM_ARG_TARGET;
1917 tmpstr = (char *)strtok(NULL, ":");
1918 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1919 lun = strtol(tmpstr, NULL, 0);
1920 arglist |= CAM_ARG_LUN;
1921 }
1922 }
1923 } else {
1924 error = 1;
1925 warnx("you must specify \"all\", \"off\", or a bus,");
1926 warnx("bus:target, or bus:target:lun to debug");
1927 }
1928 }
1929
1930 if (error == 0) {
1931
1932 ccb.ccb_h.func_code = XPT_DEBUG;
1933 ccb.ccb_h.path_id = bus;
1934 ccb.ccb_h.target_id = target;
1935 ccb.ccb_h.target_lun = lun;
1936
1937 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1938 warn("CAMIOCOMMAND ioctl failed");
1939 error = 1;
1940 }
1941
1942 if (error == 0) {
1943 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
1944 CAM_FUNC_NOTAVAIL) {
1945 warnx("CAM debugging not available");
1946 warnx("you need to put options CAMDEBUG in"
1947 " your kernel config file!");
1948 error = 1;
1949 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
1950 CAM_REQ_CMP) {
1951 warnx("XPT_DEBUG CCB failed with status %#x",
1952 ccb.ccb_h.status);
1953 error = 1;
1954 } else {
1955 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
1956 fprintf(stderr,
1957 "Debugging turned off\n");
1958 } else {
1959 fprintf(stderr,
1960 "Debugging enabled for "
1961 "%d:%d:%d\n",
1962 bus, target, lun);
1963 }
1964 }
1965 }
1966 close(fd);
1967 }
1968
1969 return(error);
1970}
1971
1972static int
1973tagcontrol(struct cam_device *device, int argc, char **argv,
1974 char *combinedopt)
1975{
1976 int c;
1977 union ccb *ccb;
1978 int numtags = -1;
1979 int retval = 0;
1980 int quiet = 0;
1981 char pathstr[1024];
1982
1983 ccb = cam_getccb(device);
1984
1985 if (ccb == NULL) {
1986 warnx("tagcontrol: error allocating ccb");
1987 return(1);
1988 }
1989
1990 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1991 switch(c) {
1992 case 'N':
1993 numtags = strtol(optarg, NULL, 0);
1994 if (numtags < 0) {
1995 warnx("tag count %d is < 0", numtags);
1996 retval = 1;
1997 goto tagcontrol_bailout;
1998 }
1999 break;
2000 case 'q':
2001 quiet++;
2002 break;
2003 default:
2004 break;
2005 }
2006 }
2007
2008 cam_path_string(device, pathstr, sizeof(pathstr));
2009
2010 if (numtags >= 0) {
2011 bzero(&(&ccb->ccb_h)[1],
2012 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2013 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2014 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2015 ccb->crs.openings = numtags;
2016
2017
2018 if (cam_send_ccb(device, ccb) < 0) {
2019 perror("error sending XPT_REL_SIMQ CCB");
2020 retval = 1;
2021 goto tagcontrol_bailout;
2022 }
2023
2024 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2025 warnx("XPT_REL_SIMQ CCB failed, status %#x",
2026 ccb->ccb_h.status);
2027 retval = 1;
2028 goto tagcontrol_bailout;
2029 }
2030
2031
2032 if (quiet == 0)
2033 fprintf(stdout, "%stagged openings now %d\n",
2034 pathstr, ccb->crs.openings);
2035 }
2036
2037 bzero(&(&ccb->ccb_h)[1],
2038 sizeof(struct ccb_getdev) - sizeof(struct ccb_hdr));
2039
2040 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2041
2042 if (cam_send_ccb(device, ccb) < 0) {
2043 perror("error sending XPT_GDEV_STATS CCB");
2044 retval = 1;
2045 goto tagcontrol_bailout;
2046 }
2047
2048 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2049 warnx("XPT_GDEV_STATS CCB failed, status %#x",
2050 ccb->ccb_h.status);
2051 retval = 1;
2052 goto tagcontrol_bailout;
2053 }
2054
2055 if (arglist & CAM_ARG_VERBOSE) {
2056 fprintf(stdout, "%s", pathstr);
2057 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2058 fprintf(stdout, "%s", pathstr);
2059 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2060 fprintf(stdout, "%s", pathstr);
2061 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2062 fprintf(stdout, "%s", pathstr);
2063 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2064 fprintf(stdout, "%s", pathstr);
2065 fprintf(stdout, "held %d\n", ccb->cgds.held);
2066 fprintf(stdout, "%s", pathstr);
2067 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2068 fprintf(stdout, "%s", pathstr);
2069 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2070 } else {
2071 if (quiet == 0) {
2072 fprintf(stdout, "%s", pathstr);
2073 fprintf(stdout, "device openings: ");
2074 }
2075 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2076 ccb->cgds.dev_active);
2077 }
2078
2079tagcontrol_bailout:
2080
2081 cam_freeccb(ccb);
2082 return(retval);
2083}
2084
2085static void
2086cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2087{
2088 char pathstr[1024];
2089
2090 cam_path_string(device, pathstr, sizeof(pathstr));
2091
2092 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
2093
2094 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2095 cts->sync_period);
2096
2097 if (cts->sync_offset != 0) {
2098 u_int freq;
2099
2100 freq = scsi_calc_syncsrate(cts->sync_period);
2101 fprintf(stdout, "%sfrequency: %d.%03dMHz\n", pathstr,
2102 freq / 1000, freq % 1000);
2103 }
2104 }
2105
2106 if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
2107 fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
2108
2109 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
2110 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2111 (0x01 << cts->bus_width) * 8);
2112
2113 if (cts->valid & CCB_TRANS_DISC_VALID)
2114 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2115 (cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
2116 "disabled");
2117
2118 if (cts->valid & CCB_TRANS_TQ_VALID)
2119 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2120 (cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
2121 "disabled");
2122
2123}
2124
2125/*
2126 * Get a path inquiry CCB for the specified device.
2127 */
2128static int
2129get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2130{
2131 union ccb *ccb;
2132 int retval = 0;
2133
2134 ccb = cam_getccb(device);
2135
2136 if (ccb == NULL) {
2137 warnx("get_cpi: couldn't allocate CCB");
2138 return(1);
2139 }
2140
2141 bzero(&(&ccb->ccb_h)[1],
2142 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2143
2144 ccb->ccb_h.func_code = XPT_PATH_INQ;
2145
2146 if (cam_send_ccb(device, ccb) < 0) {
2147 warn("get_cpi: error sending Path Inquiry CCB");
2148
2149 if (arglist & CAM_ARG_VERBOSE)
2150 fprintf(stderr, "CAM status is %#x\n",
2151 ccb->ccb_h.status);
2152
2153 retval = 1;
2154
2155 goto get_cpi_bailout;
2156 }
2157
2158 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2159
2160 if (arglist & CAM_ARG_VERBOSE)
2161 fprintf(stderr, "get_cpi: CAM status is %#x\n",
2162 ccb->ccb_h.status);
2163
2164 retval = 1;
2165
2166 goto get_cpi_bailout;
2167 }
2168
2169 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2170
2171get_cpi_bailout:
2172
2173 cam_freeccb(ccb);
2174
2175 return(retval);
2176}
2177
2178static void
2179cpi_print(struct ccb_pathinq *cpi)
2180{
2181 char adapter_str[1024];
2182 int i;
2183
2184 snprintf(adapter_str, sizeof(adapter_str),
2185 "%s%d:", cpi->dev_name, cpi->unit_number);
2186
2187 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2188 cpi->version_num);
2189
2190 for (i = 1; i < 0xff; i = i << 1) {
2191 char *str;
2192
2193 if ((i & cpi->hba_inquiry) == 0)
2194 continue;
2195
2196 fprintf(stdout, "%s supports ", adapter_str);
2197
2198 switch(i) {
2199 case PI_MDP_ABLE:
2200 str = "MDP message";
2201 break;
2202 case PI_WIDE_32:
2203 str = "32 bit wide SCSI";
2204 break;
2205 case PI_WIDE_16:
2206 str = "16 bit wide SCSI";
2207 break;
2208 case PI_SDTR_ABLE:
2209 str = "SDTR message";
2210 break;
2211 case PI_LINKED_CDB:
2212 str = "linked CDBs";
2213 break;
2214 case PI_TAG_ABLE:
2215 str = "tag queue messages";
2216 break;
2217 case PI_SOFT_RST:
2218 str = "soft reset alternative";
2219 break;
2220 default:
2221 str = "unknown PI bit set";
2222 break;
2223 }
2224 fprintf(stdout, "%s\n", str);
2225 }
2226
2227 for (i = 1; i < 0xff; i = i << 1) {
2228 char *str;
2229
2230 if ((i & cpi->hba_misc) == 0)
2231 continue;
2232
2233 fprintf(stdout, "%s ", adapter_str);
2234
2235 switch(i) {
2236 case PIM_SCANHILO:
2237 str = "bus scans from high ID to low ID";
2238 break;
2239 case PIM_NOREMOVE:
2240 str = "removable devices not included in scan";
2241 break;
2242 case PIM_NOINITIATOR:
2243 str = "initiator role not supported";
2244 break;
2245 case PIM_NOBUSRESET:
2246 str = "user has disabled initial BUS RESET or"
2247 " controller is in target/mixed mode";
2248 break;
2249 default:
2250 str = "unknown PIM bit set";
2251 break;
2252 }
2253 fprintf(stdout, "%s\n", str);
2254 }
2255
2256 for (i = 1; i < 0xff; i = i << 1) {
2257 char *str;
2258
2259 if ((i & cpi->target_sprt) == 0)
2260 continue;
2261
2262 fprintf(stdout, "%s supports ", adapter_str);
2263 switch(i) {
2264 case PIT_PROCESSOR:
2265 str = "target mode processor mode";
2266 break;
2267 case PIT_PHASE:
2268 str = "target mode phase cog. mode";
2269 break;
2270 case PIT_DISCONNECT:
2271 str = "disconnects in target mode";
2272 break;
2273 case PIT_TERM_IO:
2274 str = "terminate I/O message in target mode";
2275 break;
2276 case PIT_GRP_6:
2277 str = "group 6 commands in target mode";
2278 break;
2279 case PIT_GRP_7:
2280 str = "group 7 commands in target mode";
2281 break;
2282 default:
2283 str = "unknown PIT bit set";
2284 break;
2285 }
2286
2287 fprintf(stdout, "%s\n", str);
2288 }
2289 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2290 cpi->hba_eng_cnt);
2291 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2292 cpi->max_target);
2293 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2294 cpi->max_lun);
2295 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2296 adapter_str, cpi->hpath_id);
2297 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2298 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2299 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2300 fprintf(stdout, "%s base transfer speed: ", adapter_str);
2301 if (cpi->base_transfer_speed > 1000)
2302 fprintf(stdout, "%d.%03dMB/sec\n",
2303 cpi->base_transfer_speed / 1000,
2304 cpi->base_transfer_speed % 1000);
2305 else
2306 fprintf(stdout, "%dKB/sec\n",
2307 (cpi->base_transfer_speed % 1000) * 1000);
2308}
2309
2310static int
2311get_print_cts(struct cam_device *device, int user_settings, int quiet,
2312 struct ccb_trans_settings *cts)
2313{
2314 int retval;
2315 union ccb *ccb;
2316
2317 retval = 0;
2318 ccb = cam_getccb(device);
2319
2320 if (ccb == NULL) {
2321 warnx("get_print_cts: error allocating ccb");
2322 return(1);
2323 }
2324
2325 bzero(&(&ccb->ccb_h)[1],
2326 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2327
2328 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2329
2330 if (user_settings == 0)
2331 ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
2332 else
2333 ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
2334
2335 if (cam_send_ccb(device, ccb) < 0) {
2336 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2337 retval = 1;
2338 goto get_print_cts_bailout;
2339 }
2340
2341 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2342 warnx("XPT_GET_TRANS_SETTINGS CCB failed, status %#x",
2343 ccb->ccb_h.status);
2344 retval = 1;
2345 goto get_print_cts_bailout;
2346 }
2347
2348 if (quiet == 0)
2349 cts_print(device, &ccb->cts);
2350
2351 if (cts != NULL)
2352 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2353
2354get_print_cts_bailout:
2355
2356 cam_freeccb(ccb);
2357
2358 return(retval);
2359}
2360
2361static int
2362ratecontrol(struct cam_device *device, int retry_count, int timeout,
2363 int argc, char **argv, char *combinedopt)
2364{
2365 int c;
2366 union ccb *ccb;
2367 int user_settings = 0;
2368 int retval = 0;
2369 int disc_enable = -1, tag_enable = -1;
2370 int offset = -1;
2371 double syncrate = -1;
2372 int bus_width = -1;
2373 int quiet = 0;
2374 int change_settings = 0, send_tur = 0;
2375 struct ccb_pathinq cpi;
2376
2377 ccb = cam_getccb(device);
2378
2379 if (ccb == NULL) {
2380 warnx("ratecontrol: error allocating ccb");
2381 return(1);
2382 }
2383
2384 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2385 switch(c){
2386 case 'a':
2387 send_tur = 1;
2388 break;
2389 case 'c':
2390 user_settings = 0;
2391 break;
2392 case 'D':
2393 if (strncasecmp(optarg, "enable", 6) == 0)
2394 disc_enable = 1;
2395 else if (strncasecmp(optarg, "disable", 7) == 0)
2396 disc_enable = 0;
2397 else {
2398 warnx("-D argument \"%s\" is unknown", optarg);
2399 retval = 1;
2400 goto ratecontrol_bailout;
2401 }
2402 change_settings = 1;
2403 break;
2404 case 'O':
2405 offset = strtol(optarg, NULL, 0);
2406 if (offset < 0) {
2407 warnx("offset value %d is < 0", offset);
2408 retval = 1;
2409 goto ratecontrol_bailout;
2410 }
2411 change_settings = 1;
2412 break;
2413 case 'q':
2414 quiet++;
2415 break;
2416 case 'R':
2417 syncrate = atof(optarg);
2418
2419 if (syncrate < 0) {
2420 warnx("sync rate %f is < 0", syncrate);
2421 retval = 1;
2422 goto ratecontrol_bailout;
2423 }
2424 change_settings = 1;
2425 break;
2426 case 'T':
2427 if (strncasecmp(optarg, "enable", 6) == 0)
2428 tag_enable = 1;
2429 else if (strncasecmp(optarg, "disable", 7) == 0)
2430 tag_enable = 0;
2431 else {
2432 warnx("-T argument \"%s\" is unknown", optarg);
2433 retval = 1;
2434 goto ratecontrol_bailout;
2435 }
2436 change_settings = 1;
2437 break;
2438 case 'U':
2439 user_settings = 1;
2440 break;
2441 case 'W':
2442 bus_width = strtol(optarg, NULL, 0);
2443 if (bus_width < 0) {
2444 warnx("bus width %d is < 0", bus_width);
2445 retval = 1;
2446 goto ratecontrol_bailout;
2447 }
2448 change_settings = 1;
2449 break;
2450 default:
2451 break;
2452 }
2453 }
2454
2455 bzero(&(&ccb->ccb_h)[1],
2456 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2457
2458 /*
2459 * Grab path inquiry information, so we can determine whether
2460 * or not the initiator is capable of the things that the user
2461 * requests.
2462 */
2463 ccb->ccb_h.func_code = XPT_PATH_INQ;
2464
2465 if (cam_send_ccb(device, ccb) < 0) {
2466 perror("error sending XPT_PATH_INQ CCB");
2467 retval = 1;
2468 goto ratecontrol_bailout;
2469 }
2470
2471 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2472 warnx("XPT_PATH_INQ CCB failed, status %#x",
2473 ccb->ccb_h.status);
2474 retval = 1;
2475 goto ratecontrol_bailout;
2476 }
2477
2478 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2479
2480 bzero(&(&ccb->ccb_h)[1],
2481 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2482
2483 if (quiet == 0)
2484 fprintf(stdout, "Current Parameters:\n");
2485
2486 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2487
2488 if (retval != 0)
2489 goto ratecontrol_bailout;
2490
2491 if (arglist & CAM_ARG_VERBOSE)
2492 cpi_print(&cpi);
2493
2494 if (change_settings) {
2495 if (disc_enable != -1) {
2496 ccb->cts.valid |= CCB_TRANS_DISC_VALID;
2497 if (disc_enable == 0)
2498 ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
2499 else
2500 ccb->cts.flags |= CCB_TRANS_DISC_ENB;
2501 } else
2502 ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
2503
2504 if (tag_enable != -1) {
2505 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2506 warnx("HBA does not support tagged queueing, "
2507 "so you cannot modify tag settings");
2508 retval = 1;
2509 goto ratecontrol_bailout;
2510 }
2511
2512 ccb->cts.valid |= CCB_TRANS_TQ_VALID;
2513
2514 if (tag_enable == 0)
2515 ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
2516 else
2517 ccb->cts.flags |= CCB_TRANS_TAG_ENB;
2518 } else
2519 ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
2520
2521 if (offset != -1) {
2522 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2523 warnx("HBA at %s%d is not cable of changing "
2524 "offset", cpi.dev_name,
2525 cpi.unit_number);
2526 retval = 1;
2527 goto ratecontrol_bailout;
2528 }
2529 ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
2530 ccb->cts.sync_offset = offset;
2531 } else
2532 ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
2533
2534 if (syncrate != -1) {
2535 int prelim_sync_period;
2536 u_int freq;
2537
2538 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2539 warnx("HBA at %s%d is not cable of changing "
2540 "transfer rates", cpi.dev_name,
2541 cpi.unit_number);
2542 retval = 1;
2543 goto ratecontrol_bailout;
2544 }
2545
2546 ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
2547
2548 /*
2549 * The sync rate the user gives us is in MHz.
2550 * We need to translate it into KHz for this
2551 * calculation.
2552 */
2553 syncrate *= 1000;
2554
2555 /*
2556 * Next, we calculate a "preliminary" sync period
2557 * in tenths of a nanosecond.
2558 */
2559 if (syncrate == 0)
2560 prelim_sync_period = 0;
2561 else
2562 prelim_sync_period = 10000000 / syncrate;
2563
2564 ccb->cts.sync_period =
2565 scsi_calc_syncparam(prelim_sync_period);
2566
2567 freq = scsi_calc_syncsrate(ccb->cts.sync_period);
2568 } else
2569 ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
2570
2571 /*
2572 * The bus_width argument goes like this:
2573 * 0 == 8 bit
2574 * 1 == 16 bit
2575 * 2 == 32 bit
2576 * Therefore, if you shift the number of bits given on the
2577 * command line right by 4, you should get the correct
2578 * number.
2579 */
2580 if (bus_width != -1) {
2581
2582 /*
2583 * We might as well validate things here with a
2584 * decipherable error message, rather than what
2585 * will probably be an indecipherable error message
2586 * by the time it gets back to us.
2587 */
2588 if ((bus_width == 16)
2589 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2590 warnx("HBA does not support 16 bit bus width");
2591 retval = 1;
2592 goto ratecontrol_bailout;
2593 } else if ((bus_width == 32)
2594 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2595 warnx("HBA does not support 32 bit bus width");
2596 retval = 1;
2597 goto ratecontrol_bailout;
2598 } else if ((bus_width != 8)
2599 && (bus_width != 16)
2600 && (bus_width != 32)) {
2601 warnx("Invalid bus width %d", bus_width);
2602 retval = 1;
2603 goto ratecontrol_bailout;
2604 }
2605
2606 ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
2607 ccb->cts.bus_width = bus_width >> 4;
2608 } else
2609 ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
2610
2611 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2612
2613 if (cam_send_ccb(device, ccb) < 0) {
2614 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2615 retval = 1;
2616 goto ratecontrol_bailout;
2617 }
2618
2619 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2620 warnx("XPT_SET_TRANS_SETTINGS CCB failed, status %#x",
2621 ccb->ccb_h.status);
2622 retval = 1;
2623 goto ratecontrol_bailout;
2624 }
2625 }
2626
2627 if (send_tur) {
2628 retval = testunitready(device, retry_count, timeout,
2629 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2630
2631 /*
2632 * If the TUR didn't succeed, just bail.
2633 */
2634 if (retval != 0) {
2635 if (quiet == 0)
2636 fprintf(stderr, "Test Unit Ready failed\n");
2637 goto ratecontrol_bailout;
2638 }
2639
2640 /*
2641 * If the user wants things quiet, there's no sense in
2642 * getting the transfer settings, if we're not going
2643 * to print them.
2644 */
2645 if (quiet != 0)
2646 goto ratecontrol_bailout;
2647
2648 fprintf(stdout, "New Parameters:\n");
2649 retval = get_print_cts(device, user_settings, 0, NULL);
2650 }
2651
2652ratecontrol_bailout:
2653
2654 cam_freeccb(ccb);
2655 return(retval);
2656}
2657
2658static int
2659scsiformat(struct cam_device *device, int argc, char **argv,
2660 char *combinedopt, int retry_count, int timeout)
2661{
2662 union ccb *ccb;
2663 int c;
2664 int ycount = 0, quiet = 0;
2665 int error = 0, response = 0, retval = 0;
2666 int use_timeout = 10800 * 1000;
2667 int immediate = 1;
2668 struct format_defect_list_header fh;
2669 u_int8_t *data_ptr = NULL;
2670 u_int32_t dxfer_len = 0;
2671 u_int8_t byte2 = 0;
2672 int num_warnings = 0;
2673
2674 ccb = cam_getccb(device);
2675
2676 if (ccb == NULL) {
2677 warnx("scsiformat: error allocating ccb");
2678 return(1);
2679 }
2680
2681 bzero(&(&ccb->ccb_h)[1],
2682 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2683
2684 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2685 switch(c) {
2686 case 'q':
2687 quiet++;
2688 break;
2689 case 'w':
2690 immediate = 0;
2691 break;
2692 case 'y':
2693 ycount++;
2694 break;
2695 }
2696 }
2697
2698 if (quiet == 0) {
2699 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
2700 "following device:\n");
2701
2702 error = scsidoinquiry(device, argc, argv, combinedopt,
2703 retry_count, timeout);
2704
2705 if (error != 0) {
2706 warnx("scsiformat: error sending inquiry");
2707 goto scsiformat_bailout;
2708 }
2709 }
2710
2711 if (ycount == 0) {
2712
2713 do {
2714 char str[1024];
2715
2716 fprintf(stdout, "Are you SURE you want to do "
2717 "this? (yes/no) ");
2718
2719 if (fgets(str, sizeof(str), stdin) != NULL) {
2720
2721 if (strncasecmp(str, "yes", 3) == 0)
2722 response = 1;
2723 else if (strncasecmp(str, "no", 2) == 0)
2724 response = -1;
2725 else {
2726 fprintf(stdout, "Please answer"
2727 " \"yes\" or \"no\"\n");
2728 }
2729 }
2730 } while (response == 0);
2731
2732 if (response == -1) {
2733 error = 1;
2734 goto scsiformat_bailout;
2735 }
2736 }
2737
2738 if (timeout != 0)
2739 use_timeout = timeout;
2740
2741 if (quiet == 0) {
2742 fprintf(stdout, "Current format timeout is %d seconds\n",
2743 use_timeout / 1000);
2744 }
2745
2746 /*
2747 * If the user hasn't disabled questions and didn't specify a
2748 * timeout on the command line, ask them if they want the current
2749 * timeout.
2750 */
2751 if ((ycount == 0)
2752 && (timeout == 0)) {
2753 char str[1024];
2754 int new_timeout = 0;
2755
2756 fprintf(stdout, "Enter new timeout in seconds or press\n"
2757 "return to keep the current timeout [%d] ",
2758 use_timeout / 1000);
2759
2760 if (fgets(str, sizeof(str), stdin) != NULL) {
2761 if (str[0] != '\0')
2762 new_timeout = atoi(str);
2763 }
2764
2765 if (new_timeout != 0) {
2766 use_timeout = new_timeout * 1000;
2767 fprintf(stdout, "Using new timeout value %d\n",
2768 use_timeout / 1000);
2769 }
2770 }
2771
2772 /*
2773 * Keep this outside the if block below to silence any unused
2774 * variable warnings.
2775 */
2776 bzero(&fh, sizeof(fh));
2777
2778 /*
2779 * If we're in immediate mode, we've got to include the format
2780 * header
2781 */
2782 if (immediate != 0) {
2783 fh.byte2 = FU_DLH_IMMED;
2784 data_ptr = (u_int8_t *)&fh;
2785 dxfer_len = sizeof(fh);
2786 byte2 = FU_FMT_DATA;
2787 } else if (quiet == 0) {
2788 fprintf(stdout, "Formatting...");
2789 fflush(stdout);
2790 }
2791
2792 scsi_format_unit(&ccb->csio,
2793 /* retries */ retry_count,
2794 /* cbfcnp */ NULL,
2795 /* tag_action */ MSG_SIMPLE_Q_TAG,
2796 /* byte2 */ byte2,
2797 /* ileave */ 0,
2798 /* data_ptr */ data_ptr,
2799 /* dxfer_len */ dxfer_len,
2800 /* sense_len */ SSD_FULL_SIZE,
2801 /* timeout */ use_timeout);
2802
2803 /* Disable freezing the device queue */
2804 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2805
2806 if (arglist & CAM_ARG_ERR_RECOVER)
2807 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2808
2809 if (((retval = cam_send_ccb(device, ccb)) < 0)
2810 || ((immediate == 0)
2811 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
2812 char *errstr = "error sending format command";
2813
2814 if (retval < 0)
2815 warn(errstr);
2816 else
2817 warnx(errstr);
2818
2819 if (arglist & CAM_ARG_VERBOSE) {
2820 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
2821 CAM_SCSI_STATUS_ERROR)
2822 scsi_sense_print(device, &ccb->csio, stderr);
2823 else
2824 fprintf(stderr, "CAM status is %#x\n",
2825 ccb->ccb_h.status);
2826 }
2827 error = 1;
2828 goto scsiformat_bailout;
2829 }
2830
2831 /*
2832 * If we ran in non-immediate mode, we already checked for errors
2833 * above and printed out any necessary information. If we're in
2834 * immediate mode, we need to loop through and get status
2835 * information periodically.
2836 */
2837 if (immediate == 0) {
2838 if (quiet == 0) {
2839 fprintf(stdout, "Format Complete\n");
2840 }
2841 goto scsiformat_bailout;
2842 }
2843
2844 do {
2845 cam_status status;
2846
2847 bzero(&(&ccb->ccb_h)[1],
2848 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2849
2850 /*
2851 * There's really no need to do error recovery or
2852 * retries here, since we're just going to sit in a
2853 * loop and wait for the device to finish formatting.
2854 */
2855 scsi_test_unit_ready(&ccb->csio,
2856 /* retries */ 0,
2857 /* cbfcnp */ NULL,
2858 /* tag_action */ MSG_SIMPLE_Q_TAG,
2859 /* sense_len */ SSD_FULL_SIZE,
2860 /* timeout */ 5000);
2861
2862 /* Disable freezing the device queue */
2863 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2864
2865 retval = cam_send_ccb(device, ccb);
2866
2867 /*
2868 * If we get an error from the ioctl, bail out. SCSI
2869 * errors are expected.
2870 */
2871 if (retval < 0) {
2872 warn("error sending CAMIOCOMMAND ioctl");
2873 if (arglist & CAM_ARG_VERBOSE) {
2874 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
2875 CAM_SCSI_STATUS_ERROR)
2876 scsi_sense_print(device, &ccb->csio,
2877 stderr);
2878 else
2879 fprintf(stderr, "CAM status is %#x\n",
2880 ccb->ccb_h.status);
2881 }
2882 error = 1;
2883 goto scsiformat_bailout;
2884 }
2885
2886 status = ccb->ccb_h.status & CAM_STATUS_MASK;
2887
2888 if ((status != CAM_REQ_CMP)
2889 && (status == CAM_SCSI_STATUS_ERROR)) {
2890 struct scsi_sense_data *sense;
2891 int error_code, sense_key, asc, ascq;
2892
2893 sense = &ccb->csio.sense_data;
2894 scsi_extract_sense(sense, &error_code, &sense_key,
2895 &asc, &ascq);
2896
2897 /*
2898 * According to the SCSI-2 and SCSI-3 specs, a
2899 * drive that is in the middle of a format should
2900 * return NOT READY with an ASC of "logical unit
2901 * not ready, format in progress". The sense key
2902 * specific bytes will then be a progress indicator.
2903 */
2904 if ((sense_key == SSD_KEY_NOT_READY)
2905 && (asc == 0x04) && (ascq == 0x04)) {
2906 if ((sense->extra_len >= 10)
2907 && ((sense->sense_key_spec[0] &
2908 SSD_SCS_VALID) != 0)
2909 && (quiet == 0)) {
2910 int val;
2911 u_int64_t percentage;
2912
2913 val = scsi_2btoul(
2914 &sense->sense_key_spec[1]);
2915 percentage = 10000 * val;
2916
2917 fprintf(stdout,
2918 "\rFormatting: %qd.%02qd %% "
2919 "(%d/%d) done",
2920 percentage / (0x10000 * 100),
2921 (percentage / 0x10000) % 100,
2922 val, 0x10000);
2923 fflush(stdout);
2924 } else if ((quiet == 0)
2925 && (++num_warnings <= 1)) {
2926 warnx("Unexpected SCSI Sense Key "
2927 "Specific value returned "
2928 "during format:");
2929 scsi_sense_print(device, &ccb->csio,
2930 stderr);
2931 warnx("Unable to print status "
2932 "information, but format will "
2933 "proceed.");
2934 warnx("will exit when format is "
2935 "complete");
2936 }
2937 sleep(1);
2938 } else {
2939 warnx("Unexpected SCSI error during format");
2940 scsi_sense_print(device, &ccb->csio, stderr);
2941 error = 1;
2942 goto scsiformat_bailout;
2943 }
2944
2945 } else if (status != CAM_REQ_CMP) {
2946 warnx("Unexpected CAM status %#x", status);
2947 error = 1;
2948 goto scsiformat_bailout;
2949 }
2950
2951 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
2952
2953 if (quiet == 0)
2954 fprintf(stdout, "\nFormat Complete\n");
2955
2956scsiformat_bailout:
2957
2958 cam_freeccb(ccb);
2959
2960 return(error);
2961}
2962
2963void
2964usage(int verbose)
2965{
2966 fprintf(verbose ? stdout : stderr,
2967"usage: camcontrol <command> [device id][generic args][command args]\n"
2968" camcontrol devlist [-v]\n"
2969" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
2970" camcontrol tur [dev_id][generic args]\n"
2971" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
2972" camcontrol start [dev_id][generic args]\n"
2973" camcontrol stop [dev_id][generic args]\n"
2974" camcontrol eject [dev_id][generic args]\n"
2975" camcontrol rescan <bus[:target:lun]>\n"
2976" camcontrol reset <bus[:target:lun]>\n"
2977" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
1601}
1602
1603static int
1604scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
1605 int retry_count, int timeout)
1606{
1607 union ccb *ccb;
1608 u_int32_t flags = CAM_DIR_NONE;
1609 u_int8_t *data_ptr = NULL;
1610 u_int8_t cdb[20];
1611 struct get_hook hook;
1612 int c, data_bytes = 0;
1613 int cdb_len = 0;
1614 char *datastr = NULL, *tstr;
1615 int error = 0;
1616 int fd_data = 0;
1617 int retval;
1618
1619 ccb = cam_getccb(device);
1620
1621 if (ccb == NULL) {
1622 warnx("scsicmd: error allocating ccb");
1623 return(1);
1624 }
1625
1626 bzero(&(&ccb->ccb_h)[1],
1627 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1628
1629 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1630 switch(c) {
1631 case 'c':
1632 tstr = optarg;
1633 while (isspace(*tstr) && (*tstr != '\0'))
1634 tstr++;
1635 hook.argc = argc - optind;
1636 hook.argv = argv + optind;
1637 hook.got = 0;
1638 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr,
1639 iget, &hook);
1640 /*
1641 * Increment optind by the number of arguments the
1642 * encoding routine processed. After each call to
1643 * getopt(3), optind points to the argument that
1644 * getopt should process _next_. In this case,
1645 * that means it points to the first command string
1646 * argument, if there is one. Once we increment
1647 * this, it should point to either the next command
1648 * line argument, or it should be past the end of
1649 * the list.
1650 */
1651 optind += hook.got;
1652 break;
1653 case 'i':
1654 if (arglist & CAM_ARG_CMD_OUT) {
1655 warnx("command must either be "
1656 "read or write, not both");
1657 error = 1;
1658 goto scsicmd_bailout;
1659 }
1660 arglist |= CAM_ARG_CMD_IN;
1661 flags = CAM_DIR_IN;
1662 data_bytes = strtol(optarg, NULL, 0);
1663 if (data_bytes <= 0) {
1664 warnx("invalid number of input bytes %d",
1665 data_bytes);
1666 error = 1;
1667 goto scsicmd_bailout;
1668 }
1669 hook.argc = argc - optind;
1670 hook.argv = argv + optind;
1671 hook.got = 0;
1672 optind++;
1673 datastr = cget(&hook, NULL);
1674 /*
1675 * If the user supplied "-" instead of a format, he
1676 * wants the data to be written to stdout.
1677 */
1678 if ((datastr != NULL)
1679 && (datastr[0] == '-'))
1680 fd_data = 1;
1681
1682 data_ptr = (u_int8_t *)malloc(data_bytes);
1683 break;
1684 case 'o':
1685 if (arglist & CAM_ARG_CMD_IN) {
1686 warnx("command must either be "
1687 "read or write, not both");
1688 error = 1;
1689 goto scsicmd_bailout;
1690 }
1691 arglist |= CAM_ARG_CMD_OUT;
1692 flags = CAM_DIR_OUT;
1693 data_bytes = strtol(optarg, NULL, 0);
1694 if (data_bytes <= 0) {
1695 warnx("invalid number of output bytes %d",
1696 data_bytes);
1697 error = 1;
1698 goto scsicmd_bailout;
1699 }
1700 hook.argc = argc - optind;
1701 hook.argv = argv + optind;
1702 hook.got = 0;
1703 datastr = cget(&hook, NULL);
1704 data_ptr = (u_int8_t *)malloc(data_bytes);
1705 /*
1706 * If the user supplied "-" instead of a format, he
1707 * wants the data to be read from stdin.
1708 */
1709 if ((datastr != NULL)
1710 && (datastr[0] == '-'))
1711 fd_data = 1;
1712 else
1713 buff_encode_visit(data_ptr, data_bytes, datastr,
1714 iget, &hook);
1715 optind += hook.got;
1716 break;
1717 default:
1718 break;
1719 }
1720 }
1721
1722 /*
1723 * If fd_data is set, and we're writing to the device, we need to
1724 * read the data the user wants written from stdin.
1725 */
1726 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
1727 size_t amt_read;
1728 int amt_to_read = data_bytes;
1729 u_int8_t *buf_ptr = data_ptr;
1730
1731 for (amt_read = 0; amt_to_read > 0;
1732 amt_read = read(0, buf_ptr, amt_to_read)) {
1733 if (amt_read == -1) {
1734 warn("error reading data from stdin");
1735 error = 1;
1736 goto scsicmd_bailout;
1737 }
1738 amt_to_read -= amt_read;
1739 buf_ptr += amt_read;
1740 }
1741 }
1742
1743 if (arglist & CAM_ARG_ERR_RECOVER)
1744 flags |= CAM_PASS_ERR_RECOVER;
1745
1746 /* Disable freezing the device queue */
1747 flags |= CAM_DEV_QFRZDIS;
1748
1749 /*
1750 * This is taken from the SCSI-3 draft spec.
1751 * (T10/1157D revision 0.3)
1752 * The top 3 bits of an opcode are the group code. The next 5 bits
1753 * are the command code.
1754 * Group 0: six byte commands
1755 * Group 1: ten byte commands
1756 * Group 2: ten byte commands
1757 * Group 3: reserved
1758 * Group 4: sixteen byte commands
1759 * Group 5: twelve byte commands
1760 * Group 6: vendor specific
1761 * Group 7: vendor specific
1762 */
1763 switch((cdb[0] >> 5) & 0x7) {
1764 case 0:
1765 cdb_len = 6;
1766 break;
1767 case 1:
1768 case 2:
1769 cdb_len = 10;
1770 break;
1771 case 3:
1772 case 6:
1773 case 7:
1774 /* computed by buff_encode_visit */
1775 break;
1776 case 4:
1777 cdb_len = 16;
1778 break;
1779 case 5:
1780 cdb_len = 12;
1781 break;
1782 }
1783
1784 /*
1785 * We should probably use csio_build_visit or something like that
1786 * here, but it's easier to encode arguments as you go. The
1787 * alternative would be skipping the CDB argument and then encoding
1788 * it here, since we've got the data buffer argument by now.
1789 */
1790 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len);
1791
1792 cam_fill_csio(&ccb->csio,
1793 /*retries*/ retry_count,
1794 /*cbfcnp*/ NULL,
1795 /*flags*/ flags,
1796 /*tag_action*/ MSG_SIMPLE_Q_TAG,
1797 /*data_ptr*/ data_ptr,
1798 /*dxfer_len*/ data_bytes,
1799 /*sense_len*/ SSD_FULL_SIZE,
1800 /*cdb_len*/ cdb_len,
1801 /*timeout*/ timeout ? timeout : 5000);
1802
1803 if (((retval = cam_send_ccb(device, ccb)) < 0)
1804 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
1805 if (retval < 0)
1806 warn("error sending command");
1807 else
1808 warnx("error sending command");
1809
1810 if (arglist & CAM_ARG_VERBOSE) {
1811 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1812 CAM_SCSI_STATUS_ERROR)
1813 scsi_sense_print(device, &ccb->csio, stderr);
1814 else
1815 fprintf(stderr, "CAM status is %#x\n",
1816 ccb->ccb_h.status);
1817 }
1818
1819 error = 1;
1820 goto scsicmd_bailout;
1821 }
1822
1823
1824 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1825 && (arglist & CAM_ARG_CMD_IN)
1826 && (data_bytes > 0)) {
1827 if (fd_data == 0) {
1828 buff_decode_visit(data_ptr, data_bytes, datastr,
1829 arg_put, NULL);
1830 fprintf(stdout, "\n");
1831 } else {
1832 size_t amt_written;
1833 int amt_to_write = data_bytes;
1834 u_int8_t *buf_ptr = data_ptr;
1835
1836 for (amt_written = 0; (amt_to_write > 0) &&
1837 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){
1838 amt_to_write -= amt_written;
1839 buf_ptr += amt_written;
1840 }
1841 if (amt_written == -1) {
1842 warn("error writing data to stdout");
1843 error = 1;
1844 goto scsicmd_bailout;
1845 } else if ((amt_written == 0)
1846 && (amt_to_write > 0)) {
1847 warnx("only wrote %u bytes out of %u",
1848 data_bytes - amt_to_write, data_bytes);
1849 }
1850 }
1851 }
1852
1853scsicmd_bailout:
1854
1855 if ((data_bytes > 0) && (data_ptr != NULL))
1856 free(data_ptr);
1857
1858 cam_freeccb(ccb);
1859
1860 return(error);
1861}
1862
1863static int
1864camdebug(int argc, char **argv, char *combinedopt)
1865{
1866 int c, fd;
1867 int bus = -1, target = -1, lun = -1;
1868 char *tstr, *tmpstr = NULL;
1869 union ccb ccb;
1870 int error = 0;
1871
1872 bzero(&ccb, sizeof(union ccb));
1873
1874 while ((c = getopt(argc, argv, combinedopt)) != -1) {
1875 switch(c) {
1876 case 'I':
1877 arglist |= CAM_ARG_DEBUG_INFO;
1878 ccb.cdbg.flags |= CAM_DEBUG_INFO;
1879 break;
1880 case 'S':
1881 arglist |= CAM_ARG_DEBUG_SUBTRACE;
1882 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE;
1883 break;
1884 case 'T':
1885 arglist |= CAM_ARG_DEBUG_TRACE;
1886 ccb.cdbg.flags |= CAM_DEBUG_TRACE;
1887 break;
1888 case 'c':
1889 arglist |= CAM_ARG_DEBUG_CDB;
1890 ccb.cdbg.flags |= CAM_DEBUG_CDB;
1891 break;
1892 default:
1893 break;
1894 }
1895 }
1896
1897 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
1898 warnx("error opening transport layer device %s", XPT_DEVICE);
1899 warn("%s", XPT_DEVICE);
1900 return(1);
1901 }
1902 argc -= optind;
1903 argv += optind;
1904
1905 if (argc <= 0) {
1906 warnx("you must specify \"off\", \"all\" or a bus,");
1907 warnx("bus:target, or bus:target:lun");
1908 close(fd);
1909 return(1);
1910 }
1911
1912 tstr = *argv;
1913
1914 while (isspace(*tstr) && (*tstr != '\0'))
1915 tstr++;
1916
1917 if (strncmp(tstr, "off", 3) == 0) {
1918 ccb.cdbg.flags = CAM_DEBUG_NONE;
1919 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_TRACE|
1920 CAM_ARG_DEBUG_SUBTRACE);
1921 } else if (strncmp(tstr, "all", 3) != 0) {
1922 tmpstr = (char *)strtok(tstr, ":");
1923 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1924 bus = strtol(tmpstr, NULL, 0);
1925 arglist |= CAM_ARG_BUS;
1926 tmpstr = (char *)strtok(NULL, ":");
1927 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1928 target = strtol(tmpstr, NULL, 0);
1929 arglist |= CAM_ARG_TARGET;
1930 tmpstr = (char *)strtok(NULL, ":");
1931 if ((tmpstr != NULL) && (*tmpstr != '\0')){
1932 lun = strtol(tmpstr, NULL, 0);
1933 arglist |= CAM_ARG_LUN;
1934 }
1935 }
1936 } else {
1937 error = 1;
1938 warnx("you must specify \"all\", \"off\", or a bus,");
1939 warnx("bus:target, or bus:target:lun to debug");
1940 }
1941 }
1942
1943 if (error == 0) {
1944
1945 ccb.ccb_h.func_code = XPT_DEBUG;
1946 ccb.ccb_h.path_id = bus;
1947 ccb.ccb_h.target_id = target;
1948 ccb.ccb_h.target_lun = lun;
1949
1950 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1951 warn("CAMIOCOMMAND ioctl failed");
1952 error = 1;
1953 }
1954
1955 if (error == 0) {
1956 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==
1957 CAM_FUNC_NOTAVAIL) {
1958 warnx("CAM debugging not available");
1959 warnx("you need to put options CAMDEBUG in"
1960 " your kernel config file!");
1961 error = 1;
1962 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) !=
1963 CAM_REQ_CMP) {
1964 warnx("XPT_DEBUG CCB failed with status %#x",
1965 ccb.ccb_h.status);
1966 error = 1;
1967 } else {
1968 if (ccb.cdbg.flags == CAM_DEBUG_NONE) {
1969 fprintf(stderr,
1970 "Debugging turned off\n");
1971 } else {
1972 fprintf(stderr,
1973 "Debugging enabled for "
1974 "%d:%d:%d\n",
1975 bus, target, lun);
1976 }
1977 }
1978 }
1979 close(fd);
1980 }
1981
1982 return(error);
1983}
1984
1985static int
1986tagcontrol(struct cam_device *device, int argc, char **argv,
1987 char *combinedopt)
1988{
1989 int c;
1990 union ccb *ccb;
1991 int numtags = -1;
1992 int retval = 0;
1993 int quiet = 0;
1994 char pathstr[1024];
1995
1996 ccb = cam_getccb(device);
1997
1998 if (ccb == NULL) {
1999 warnx("tagcontrol: error allocating ccb");
2000 return(1);
2001 }
2002
2003 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2004 switch(c) {
2005 case 'N':
2006 numtags = strtol(optarg, NULL, 0);
2007 if (numtags < 0) {
2008 warnx("tag count %d is < 0", numtags);
2009 retval = 1;
2010 goto tagcontrol_bailout;
2011 }
2012 break;
2013 case 'q':
2014 quiet++;
2015 break;
2016 default:
2017 break;
2018 }
2019 }
2020
2021 cam_path_string(device, pathstr, sizeof(pathstr));
2022
2023 if (numtags >= 0) {
2024 bzero(&(&ccb->ccb_h)[1],
2025 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
2026 ccb->ccb_h.func_code = XPT_REL_SIMQ;
2027 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
2028 ccb->crs.openings = numtags;
2029
2030
2031 if (cam_send_ccb(device, ccb) < 0) {
2032 perror("error sending XPT_REL_SIMQ CCB");
2033 retval = 1;
2034 goto tagcontrol_bailout;
2035 }
2036
2037 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2038 warnx("XPT_REL_SIMQ CCB failed, status %#x",
2039 ccb->ccb_h.status);
2040 retval = 1;
2041 goto tagcontrol_bailout;
2042 }
2043
2044
2045 if (quiet == 0)
2046 fprintf(stdout, "%stagged openings now %d\n",
2047 pathstr, ccb->crs.openings);
2048 }
2049
2050 bzero(&(&ccb->ccb_h)[1],
2051 sizeof(struct ccb_getdev) - sizeof(struct ccb_hdr));
2052
2053 ccb->ccb_h.func_code = XPT_GDEV_STATS;
2054
2055 if (cam_send_ccb(device, ccb) < 0) {
2056 perror("error sending XPT_GDEV_STATS CCB");
2057 retval = 1;
2058 goto tagcontrol_bailout;
2059 }
2060
2061 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2062 warnx("XPT_GDEV_STATS CCB failed, status %#x",
2063 ccb->ccb_h.status);
2064 retval = 1;
2065 goto tagcontrol_bailout;
2066 }
2067
2068 if (arglist & CAM_ARG_VERBOSE) {
2069 fprintf(stdout, "%s", pathstr);
2070 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings);
2071 fprintf(stdout, "%s", pathstr);
2072 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active);
2073 fprintf(stdout, "%s", pathstr);
2074 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings);
2075 fprintf(stdout, "%s", pathstr);
2076 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued);
2077 fprintf(stdout, "%s", pathstr);
2078 fprintf(stdout, "held %d\n", ccb->cgds.held);
2079 fprintf(stdout, "%s", pathstr);
2080 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags);
2081 fprintf(stdout, "%s", pathstr);
2082 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags);
2083 } else {
2084 if (quiet == 0) {
2085 fprintf(stdout, "%s", pathstr);
2086 fprintf(stdout, "device openings: ");
2087 }
2088 fprintf(stdout, "%d\n", ccb->cgds.dev_openings +
2089 ccb->cgds.dev_active);
2090 }
2091
2092tagcontrol_bailout:
2093
2094 cam_freeccb(ccb);
2095 return(retval);
2096}
2097
2098static void
2099cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
2100{
2101 char pathstr[1024];
2102
2103 cam_path_string(device, pathstr, sizeof(pathstr));
2104
2105 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
2106
2107 fprintf(stdout, "%ssync parameter: %d\n", pathstr,
2108 cts->sync_period);
2109
2110 if (cts->sync_offset != 0) {
2111 u_int freq;
2112
2113 freq = scsi_calc_syncsrate(cts->sync_period);
2114 fprintf(stdout, "%sfrequency: %d.%03dMHz\n", pathstr,
2115 freq / 1000, freq % 1000);
2116 }
2117 }
2118
2119 if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
2120 fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
2121
2122 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
2123 fprintf(stdout, "%sbus width: %d bits\n", pathstr,
2124 (0x01 << cts->bus_width) * 8);
2125
2126 if (cts->valid & CCB_TRANS_DISC_VALID)
2127 fprintf(stdout, "%sdisconnection is %s\n", pathstr,
2128 (cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
2129 "disabled");
2130
2131 if (cts->valid & CCB_TRANS_TQ_VALID)
2132 fprintf(stdout, "%stagged queueing is %s\n", pathstr,
2133 (cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
2134 "disabled");
2135
2136}
2137
2138/*
2139 * Get a path inquiry CCB for the specified device.
2140 */
2141static int
2142get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
2143{
2144 union ccb *ccb;
2145 int retval = 0;
2146
2147 ccb = cam_getccb(device);
2148
2149 if (ccb == NULL) {
2150 warnx("get_cpi: couldn't allocate CCB");
2151 return(1);
2152 }
2153
2154 bzero(&(&ccb->ccb_h)[1],
2155 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2156
2157 ccb->ccb_h.func_code = XPT_PATH_INQ;
2158
2159 if (cam_send_ccb(device, ccb) < 0) {
2160 warn("get_cpi: error sending Path Inquiry CCB");
2161
2162 if (arglist & CAM_ARG_VERBOSE)
2163 fprintf(stderr, "CAM status is %#x\n",
2164 ccb->ccb_h.status);
2165
2166 retval = 1;
2167
2168 goto get_cpi_bailout;
2169 }
2170
2171 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2172
2173 if (arglist & CAM_ARG_VERBOSE)
2174 fprintf(stderr, "get_cpi: CAM status is %#x\n",
2175 ccb->ccb_h.status);
2176
2177 retval = 1;
2178
2179 goto get_cpi_bailout;
2180 }
2181
2182 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
2183
2184get_cpi_bailout:
2185
2186 cam_freeccb(ccb);
2187
2188 return(retval);
2189}
2190
2191static void
2192cpi_print(struct ccb_pathinq *cpi)
2193{
2194 char adapter_str[1024];
2195 int i;
2196
2197 snprintf(adapter_str, sizeof(adapter_str),
2198 "%s%d:", cpi->dev_name, cpi->unit_number);
2199
2200 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
2201 cpi->version_num);
2202
2203 for (i = 1; i < 0xff; i = i << 1) {
2204 char *str;
2205
2206 if ((i & cpi->hba_inquiry) == 0)
2207 continue;
2208
2209 fprintf(stdout, "%s supports ", adapter_str);
2210
2211 switch(i) {
2212 case PI_MDP_ABLE:
2213 str = "MDP message";
2214 break;
2215 case PI_WIDE_32:
2216 str = "32 bit wide SCSI";
2217 break;
2218 case PI_WIDE_16:
2219 str = "16 bit wide SCSI";
2220 break;
2221 case PI_SDTR_ABLE:
2222 str = "SDTR message";
2223 break;
2224 case PI_LINKED_CDB:
2225 str = "linked CDBs";
2226 break;
2227 case PI_TAG_ABLE:
2228 str = "tag queue messages";
2229 break;
2230 case PI_SOFT_RST:
2231 str = "soft reset alternative";
2232 break;
2233 default:
2234 str = "unknown PI bit set";
2235 break;
2236 }
2237 fprintf(stdout, "%s\n", str);
2238 }
2239
2240 for (i = 1; i < 0xff; i = i << 1) {
2241 char *str;
2242
2243 if ((i & cpi->hba_misc) == 0)
2244 continue;
2245
2246 fprintf(stdout, "%s ", adapter_str);
2247
2248 switch(i) {
2249 case PIM_SCANHILO:
2250 str = "bus scans from high ID to low ID";
2251 break;
2252 case PIM_NOREMOVE:
2253 str = "removable devices not included in scan";
2254 break;
2255 case PIM_NOINITIATOR:
2256 str = "initiator role not supported";
2257 break;
2258 case PIM_NOBUSRESET:
2259 str = "user has disabled initial BUS RESET or"
2260 " controller is in target/mixed mode";
2261 break;
2262 default:
2263 str = "unknown PIM bit set";
2264 break;
2265 }
2266 fprintf(stdout, "%s\n", str);
2267 }
2268
2269 for (i = 1; i < 0xff; i = i << 1) {
2270 char *str;
2271
2272 if ((i & cpi->target_sprt) == 0)
2273 continue;
2274
2275 fprintf(stdout, "%s supports ", adapter_str);
2276 switch(i) {
2277 case PIT_PROCESSOR:
2278 str = "target mode processor mode";
2279 break;
2280 case PIT_PHASE:
2281 str = "target mode phase cog. mode";
2282 break;
2283 case PIT_DISCONNECT:
2284 str = "disconnects in target mode";
2285 break;
2286 case PIT_TERM_IO:
2287 str = "terminate I/O message in target mode";
2288 break;
2289 case PIT_GRP_6:
2290 str = "group 6 commands in target mode";
2291 break;
2292 case PIT_GRP_7:
2293 str = "group 7 commands in target mode";
2294 break;
2295 default:
2296 str = "unknown PIT bit set";
2297 break;
2298 }
2299
2300 fprintf(stdout, "%s\n", str);
2301 }
2302 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
2303 cpi->hba_eng_cnt);
2304 fprintf(stdout, "%s maximum target: %d\n", adapter_str,
2305 cpi->max_target);
2306 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str,
2307 cpi->max_lun);
2308 fprintf(stdout, "%s highest path ID in subsystem: %d\n",
2309 adapter_str, cpi->hpath_id);
2310 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
2311 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
2312 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
2313 fprintf(stdout, "%s base transfer speed: ", adapter_str);
2314 if (cpi->base_transfer_speed > 1000)
2315 fprintf(stdout, "%d.%03dMB/sec\n",
2316 cpi->base_transfer_speed / 1000,
2317 cpi->base_transfer_speed % 1000);
2318 else
2319 fprintf(stdout, "%dKB/sec\n",
2320 (cpi->base_transfer_speed % 1000) * 1000);
2321}
2322
2323static int
2324get_print_cts(struct cam_device *device, int user_settings, int quiet,
2325 struct ccb_trans_settings *cts)
2326{
2327 int retval;
2328 union ccb *ccb;
2329
2330 retval = 0;
2331 ccb = cam_getccb(device);
2332
2333 if (ccb == NULL) {
2334 warnx("get_print_cts: error allocating ccb");
2335 return(1);
2336 }
2337
2338 bzero(&(&ccb->ccb_h)[1],
2339 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2340
2341 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
2342
2343 if (user_settings == 0)
2344 ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
2345 else
2346 ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
2347
2348 if (cam_send_ccb(device, ccb) < 0) {
2349 perror("error sending XPT_GET_TRAN_SETTINGS CCB");
2350 retval = 1;
2351 goto get_print_cts_bailout;
2352 }
2353
2354 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2355 warnx("XPT_GET_TRANS_SETTINGS CCB failed, status %#x",
2356 ccb->ccb_h.status);
2357 retval = 1;
2358 goto get_print_cts_bailout;
2359 }
2360
2361 if (quiet == 0)
2362 cts_print(device, &ccb->cts);
2363
2364 if (cts != NULL)
2365 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
2366
2367get_print_cts_bailout:
2368
2369 cam_freeccb(ccb);
2370
2371 return(retval);
2372}
2373
2374static int
2375ratecontrol(struct cam_device *device, int retry_count, int timeout,
2376 int argc, char **argv, char *combinedopt)
2377{
2378 int c;
2379 union ccb *ccb;
2380 int user_settings = 0;
2381 int retval = 0;
2382 int disc_enable = -1, tag_enable = -1;
2383 int offset = -1;
2384 double syncrate = -1;
2385 int bus_width = -1;
2386 int quiet = 0;
2387 int change_settings = 0, send_tur = 0;
2388 struct ccb_pathinq cpi;
2389
2390 ccb = cam_getccb(device);
2391
2392 if (ccb == NULL) {
2393 warnx("ratecontrol: error allocating ccb");
2394 return(1);
2395 }
2396
2397 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2398 switch(c){
2399 case 'a':
2400 send_tur = 1;
2401 break;
2402 case 'c':
2403 user_settings = 0;
2404 break;
2405 case 'D':
2406 if (strncasecmp(optarg, "enable", 6) == 0)
2407 disc_enable = 1;
2408 else if (strncasecmp(optarg, "disable", 7) == 0)
2409 disc_enable = 0;
2410 else {
2411 warnx("-D argument \"%s\" is unknown", optarg);
2412 retval = 1;
2413 goto ratecontrol_bailout;
2414 }
2415 change_settings = 1;
2416 break;
2417 case 'O':
2418 offset = strtol(optarg, NULL, 0);
2419 if (offset < 0) {
2420 warnx("offset value %d is < 0", offset);
2421 retval = 1;
2422 goto ratecontrol_bailout;
2423 }
2424 change_settings = 1;
2425 break;
2426 case 'q':
2427 quiet++;
2428 break;
2429 case 'R':
2430 syncrate = atof(optarg);
2431
2432 if (syncrate < 0) {
2433 warnx("sync rate %f is < 0", syncrate);
2434 retval = 1;
2435 goto ratecontrol_bailout;
2436 }
2437 change_settings = 1;
2438 break;
2439 case 'T':
2440 if (strncasecmp(optarg, "enable", 6) == 0)
2441 tag_enable = 1;
2442 else if (strncasecmp(optarg, "disable", 7) == 0)
2443 tag_enable = 0;
2444 else {
2445 warnx("-T argument \"%s\" is unknown", optarg);
2446 retval = 1;
2447 goto ratecontrol_bailout;
2448 }
2449 change_settings = 1;
2450 break;
2451 case 'U':
2452 user_settings = 1;
2453 break;
2454 case 'W':
2455 bus_width = strtol(optarg, NULL, 0);
2456 if (bus_width < 0) {
2457 warnx("bus width %d is < 0", bus_width);
2458 retval = 1;
2459 goto ratecontrol_bailout;
2460 }
2461 change_settings = 1;
2462 break;
2463 default:
2464 break;
2465 }
2466 }
2467
2468 bzero(&(&ccb->ccb_h)[1],
2469 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
2470
2471 /*
2472 * Grab path inquiry information, so we can determine whether
2473 * or not the initiator is capable of the things that the user
2474 * requests.
2475 */
2476 ccb->ccb_h.func_code = XPT_PATH_INQ;
2477
2478 if (cam_send_ccb(device, ccb) < 0) {
2479 perror("error sending XPT_PATH_INQ CCB");
2480 retval = 1;
2481 goto ratecontrol_bailout;
2482 }
2483
2484 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2485 warnx("XPT_PATH_INQ CCB failed, status %#x",
2486 ccb->ccb_h.status);
2487 retval = 1;
2488 goto ratecontrol_bailout;
2489 }
2490
2491 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
2492
2493 bzero(&(&ccb->ccb_h)[1],
2494 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
2495
2496 if (quiet == 0)
2497 fprintf(stdout, "Current Parameters:\n");
2498
2499 retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
2500
2501 if (retval != 0)
2502 goto ratecontrol_bailout;
2503
2504 if (arglist & CAM_ARG_VERBOSE)
2505 cpi_print(&cpi);
2506
2507 if (change_settings) {
2508 if (disc_enable != -1) {
2509 ccb->cts.valid |= CCB_TRANS_DISC_VALID;
2510 if (disc_enable == 0)
2511 ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
2512 else
2513 ccb->cts.flags |= CCB_TRANS_DISC_ENB;
2514 } else
2515 ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
2516
2517 if (tag_enable != -1) {
2518 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
2519 warnx("HBA does not support tagged queueing, "
2520 "so you cannot modify tag settings");
2521 retval = 1;
2522 goto ratecontrol_bailout;
2523 }
2524
2525 ccb->cts.valid |= CCB_TRANS_TQ_VALID;
2526
2527 if (tag_enable == 0)
2528 ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
2529 else
2530 ccb->cts.flags |= CCB_TRANS_TAG_ENB;
2531 } else
2532 ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
2533
2534 if (offset != -1) {
2535 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2536 warnx("HBA at %s%d is not cable of changing "
2537 "offset", cpi.dev_name,
2538 cpi.unit_number);
2539 retval = 1;
2540 goto ratecontrol_bailout;
2541 }
2542 ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
2543 ccb->cts.sync_offset = offset;
2544 } else
2545 ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
2546
2547 if (syncrate != -1) {
2548 int prelim_sync_period;
2549 u_int freq;
2550
2551 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
2552 warnx("HBA at %s%d is not cable of changing "
2553 "transfer rates", cpi.dev_name,
2554 cpi.unit_number);
2555 retval = 1;
2556 goto ratecontrol_bailout;
2557 }
2558
2559 ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
2560
2561 /*
2562 * The sync rate the user gives us is in MHz.
2563 * We need to translate it into KHz for this
2564 * calculation.
2565 */
2566 syncrate *= 1000;
2567
2568 /*
2569 * Next, we calculate a "preliminary" sync period
2570 * in tenths of a nanosecond.
2571 */
2572 if (syncrate == 0)
2573 prelim_sync_period = 0;
2574 else
2575 prelim_sync_period = 10000000 / syncrate;
2576
2577 ccb->cts.sync_period =
2578 scsi_calc_syncparam(prelim_sync_period);
2579
2580 freq = scsi_calc_syncsrate(ccb->cts.sync_period);
2581 } else
2582 ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
2583
2584 /*
2585 * The bus_width argument goes like this:
2586 * 0 == 8 bit
2587 * 1 == 16 bit
2588 * 2 == 32 bit
2589 * Therefore, if you shift the number of bits given on the
2590 * command line right by 4, you should get the correct
2591 * number.
2592 */
2593 if (bus_width != -1) {
2594
2595 /*
2596 * We might as well validate things here with a
2597 * decipherable error message, rather than what
2598 * will probably be an indecipherable error message
2599 * by the time it gets back to us.
2600 */
2601 if ((bus_width == 16)
2602 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
2603 warnx("HBA does not support 16 bit bus width");
2604 retval = 1;
2605 goto ratecontrol_bailout;
2606 } else if ((bus_width == 32)
2607 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
2608 warnx("HBA does not support 32 bit bus width");
2609 retval = 1;
2610 goto ratecontrol_bailout;
2611 } else if ((bus_width != 8)
2612 && (bus_width != 16)
2613 && (bus_width != 32)) {
2614 warnx("Invalid bus width %d", bus_width);
2615 retval = 1;
2616 goto ratecontrol_bailout;
2617 }
2618
2619 ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
2620 ccb->cts.bus_width = bus_width >> 4;
2621 } else
2622 ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
2623
2624 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
2625
2626 if (cam_send_ccb(device, ccb) < 0) {
2627 perror("error sending XPT_SET_TRAN_SETTINGS CCB");
2628 retval = 1;
2629 goto ratecontrol_bailout;
2630 }
2631
2632 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2633 warnx("XPT_SET_TRANS_SETTINGS CCB failed, status %#x",
2634 ccb->ccb_h.status);
2635 retval = 1;
2636 goto ratecontrol_bailout;
2637 }
2638 }
2639
2640 if (send_tur) {
2641 retval = testunitready(device, retry_count, timeout,
2642 (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
2643
2644 /*
2645 * If the TUR didn't succeed, just bail.
2646 */
2647 if (retval != 0) {
2648 if (quiet == 0)
2649 fprintf(stderr, "Test Unit Ready failed\n");
2650 goto ratecontrol_bailout;
2651 }
2652
2653 /*
2654 * If the user wants things quiet, there's no sense in
2655 * getting the transfer settings, if we're not going
2656 * to print them.
2657 */
2658 if (quiet != 0)
2659 goto ratecontrol_bailout;
2660
2661 fprintf(stdout, "New Parameters:\n");
2662 retval = get_print_cts(device, user_settings, 0, NULL);
2663 }
2664
2665ratecontrol_bailout:
2666
2667 cam_freeccb(ccb);
2668 return(retval);
2669}
2670
2671static int
2672scsiformat(struct cam_device *device, int argc, char **argv,
2673 char *combinedopt, int retry_count, int timeout)
2674{
2675 union ccb *ccb;
2676 int c;
2677 int ycount = 0, quiet = 0;
2678 int error = 0, response = 0, retval = 0;
2679 int use_timeout = 10800 * 1000;
2680 int immediate = 1;
2681 struct format_defect_list_header fh;
2682 u_int8_t *data_ptr = NULL;
2683 u_int32_t dxfer_len = 0;
2684 u_int8_t byte2 = 0;
2685 int num_warnings = 0;
2686
2687 ccb = cam_getccb(device);
2688
2689 if (ccb == NULL) {
2690 warnx("scsiformat: error allocating ccb");
2691 return(1);
2692 }
2693
2694 bzero(&(&ccb->ccb_h)[1],
2695 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2696
2697 while ((c = getopt(argc, argv, combinedopt)) != -1) {
2698 switch(c) {
2699 case 'q':
2700 quiet++;
2701 break;
2702 case 'w':
2703 immediate = 0;
2704 break;
2705 case 'y':
2706 ycount++;
2707 break;
2708 }
2709 }
2710
2711 if (quiet == 0) {
2712 fprintf(stdout, "You are about to REMOVE ALL DATA from the "
2713 "following device:\n");
2714
2715 error = scsidoinquiry(device, argc, argv, combinedopt,
2716 retry_count, timeout);
2717
2718 if (error != 0) {
2719 warnx("scsiformat: error sending inquiry");
2720 goto scsiformat_bailout;
2721 }
2722 }
2723
2724 if (ycount == 0) {
2725
2726 do {
2727 char str[1024];
2728
2729 fprintf(stdout, "Are you SURE you want to do "
2730 "this? (yes/no) ");
2731
2732 if (fgets(str, sizeof(str), stdin) != NULL) {
2733
2734 if (strncasecmp(str, "yes", 3) == 0)
2735 response = 1;
2736 else if (strncasecmp(str, "no", 2) == 0)
2737 response = -1;
2738 else {
2739 fprintf(stdout, "Please answer"
2740 " \"yes\" or \"no\"\n");
2741 }
2742 }
2743 } while (response == 0);
2744
2745 if (response == -1) {
2746 error = 1;
2747 goto scsiformat_bailout;
2748 }
2749 }
2750
2751 if (timeout != 0)
2752 use_timeout = timeout;
2753
2754 if (quiet == 0) {
2755 fprintf(stdout, "Current format timeout is %d seconds\n",
2756 use_timeout / 1000);
2757 }
2758
2759 /*
2760 * If the user hasn't disabled questions and didn't specify a
2761 * timeout on the command line, ask them if they want the current
2762 * timeout.
2763 */
2764 if ((ycount == 0)
2765 && (timeout == 0)) {
2766 char str[1024];
2767 int new_timeout = 0;
2768
2769 fprintf(stdout, "Enter new timeout in seconds or press\n"
2770 "return to keep the current timeout [%d] ",
2771 use_timeout / 1000);
2772
2773 if (fgets(str, sizeof(str), stdin) != NULL) {
2774 if (str[0] != '\0')
2775 new_timeout = atoi(str);
2776 }
2777
2778 if (new_timeout != 0) {
2779 use_timeout = new_timeout * 1000;
2780 fprintf(stdout, "Using new timeout value %d\n",
2781 use_timeout / 1000);
2782 }
2783 }
2784
2785 /*
2786 * Keep this outside the if block below to silence any unused
2787 * variable warnings.
2788 */
2789 bzero(&fh, sizeof(fh));
2790
2791 /*
2792 * If we're in immediate mode, we've got to include the format
2793 * header
2794 */
2795 if (immediate != 0) {
2796 fh.byte2 = FU_DLH_IMMED;
2797 data_ptr = (u_int8_t *)&fh;
2798 dxfer_len = sizeof(fh);
2799 byte2 = FU_FMT_DATA;
2800 } else if (quiet == 0) {
2801 fprintf(stdout, "Formatting...");
2802 fflush(stdout);
2803 }
2804
2805 scsi_format_unit(&ccb->csio,
2806 /* retries */ retry_count,
2807 /* cbfcnp */ NULL,
2808 /* tag_action */ MSG_SIMPLE_Q_TAG,
2809 /* byte2 */ byte2,
2810 /* ileave */ 0,
2811 /* data_ptr */ data_ptr,
2812 /* dxfer_len */ dxfer_len,
2813 /* sense_len */ SSD_FULL_SIZE,
2814 /* timeout */ use_timeout);
2815
2816 /* Disable freezing the device queue */
2817 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2818
2819 if (arglist & CAM_ARG_ERR_RECOVER)
2820 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
2821
2822 if (((retval = cam_send_ccb(device, ccb)) < 0)
2823 || ((immediate == 0)
2824 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) {
2825 char *errstr = "error sending format command";
2826
2827 if (retval < 0)
2828 warn(errstr);
2829 else
2830 warnx(errstr);
2831
2832 if (arglist & CAM_ARG_VERBOSE) {
2833 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
2834 CAM_SCSI_STATUS_ERROR)
2835 scsi_sense_print(device, &ccb->csio, stderr);
2836 else
2837 fprintf(stderr, "CAM status is %#x\n",
2838 ccb->ccb_h.status);
2839 }
2840 error = 1;
2841 goto scsiformat_bailout;
2842 }
2843
2844 /*
2845 * If we ran in non-immediate mode, we already checked for errors
2846 * above and printed out any necessary information. If we're in
2847 * immediate mode, we need to loop through and get status
2848 * information periodically.
2849 */
2850 if (immediate == 0) {
2851 if (quiet == 0) {
2852 fprintf(stdout, "Format Complete\n");
2853 }
2854 goto scsiformat_bailout;
2855 }
2856
2857 do {
2858 cam_status status;
2859
2860 bzero(&(&ccb->ccb_h)[1],
2861 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2862
2863 /*
2864 * There's really no need to do error recovery or
2865 * retries here, since we're just going to sit in a
2866 * loop and wait for the device to finish formatting.
2867 */
2868 scsi_test_unit_ready(&ccb->csio,
2869 /* retries */ 0,
2870 /* cbfcnp */ NULL,
2871 /* tag_action */ MSG_SIMPLE_Q_TAG,
2872 /* sense_len */ SSD_FULL_SIZE,
2873 /* timeout */ 5000);
2874
2875 /* Disable freezing the device queue */
2876 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
2877
2878 retval = cam_send_ccb(device, ccb);
2879
2880 /*
2881 * If we get an error from the ioctl, bail out. SCSI
2882 * errors are expected.
2883 */
2884 if (retval < 0) {
2885 warn("error sending CAMIOCOMMAND ioctl");
2886 if (arglist & CAM_ARG_VERBOSE) {
2887 if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
2888 CAM_SCSI_STATUS_ERROR)
2889 scsi_sense_print(device, &ccb->csio,
2890 stderr);
2891 else
2892 fprintf(stderr, "CAM status is %#x\n",
2893 ccb->ccb_h.status);
2894 }
2895 error = 1;
2896 goto scsiformat_bailout;
2897 }
2898
2899 status = ccb->ccb_h.status & CAM_STATUS_MASK;
2900
2901 if ((status != CAM_REQ_CMP)
2902 && (status == CAM_SCSI_STATUS_ERROR)) {
2903 struct scsi_sense_data *sense;
2904 int error_code, sense_key, asc, ascq;
2905
2906 sense = &ccb->csio.sense_data;
2907 scsi_extract_sense(sense, &error_code, &sense_key,
2908 &asc, &ascq);
2909
2910 /*
2911 * According to the SCSI-2 and SCSI-3 specs, a
2912 * drive that is in the middle of a format should
2913 * return NOT READY with an ASC of "logical unit
2914 * not ready, format in progress". The sense key
2915 * specific bytes will then be a progress indicator.
2916 */
2917 if ((sense_key == SSD_KEY_NOT_READY)
2918 && (asc == 0x04) && (ascq == 0x04)) {
2919 if ((sense->extra_len >= 10)
2920 && ((sense->sense_key_spec[0] &
2921 SSD_SCS_VALID) != 0)
2922 && (quiet == 0)) {
2923 int val;
2924 u_int64_t percentage;
2925
2926 val = scsi_2btoul(
2927 &sense->sense_key_spec[1]);
2928 percentage = 10000 * val;
2929
2930 fprintf(stdout,
2931 "\rFormatting: %qd.%02qd %% "
2932 "(%d/%d) done",
2933 percentage / (0x10000 * 100),
2934 (percentage / 0x10000) % 100,
2935 val, 0x10000);
2936 fflush(stdout);
2937 } else if ((quiet == 0)
2938 && (++num_warnings <= 1)) {
2939 warnx("Unexpected SCSI Sense Key "
2940 "Specific value returned "
2941 "during format:");
2942 scsi_sense_print(device, &ccb->csio,
2943 stderr);
2944 warnx("Unable to print status "
2945 "information, but format will "
2946 "proceed.");
2947 warnx("will exit when format is "
2948 "complete");
2949 }
2950 sleep(1);
2951 } else {
2952 warnx("Unexpected SCSI error during format");
2953 scsi_sense_print(device, &ccb->csio, stderr);
2954 error = 1;
2955 goto scsiformat_bailout;
2956 }
2957
2958 } else if (status != CAM_REQ_CMP) {
2959 warnx("Unexpected CAM status %#x", status);
2960 error = 1;
2961 goto scsiformat_bailout;
2962 }
2963
2964 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP);
2965
2966 if (quiet == 0)
2967 fprintf(stdout, "\nFormat Complete\n");
2968
2969scsiformat_bailout:
2970
2971 cam_freeccb(ccb);
2972
2973 return(error);
2974}
2975
2976void
2977usage(int verbose)
2978{
2979 fprintf(verbose ? stdout : stderr,
2980"usage: camcontrol <command> [device id][generic args][command args]\n"
2981" camcontrol devlist [-v]\n"
2982" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
2983" camcontrol tur [dev_id][generic args]\n"
2984" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
2985" camcontrol start [dev_id][generic args]\n"
2986" camcontrol stop [dev_id][generic args]\n"
2987" camcontrol eject [dev_id][generic args]\n"
2988" camcontrol rescan <bus[:target:lun]>\n"
2989" camcontrol reset <bus[:target:lun]>\n"
2990" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
2978" camcontrol modepage [dev_id][generic args] <-m page> [-P pagectl]\n"
2979" [-e][-d]\n"
2991" camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
2992" [-P pagectl][-e | -b][-d]\n"
2980" camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n"
2981" [-i len fmt|-o len fmt [args]]\n"
2982" camcontrol debug [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
2983" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
2984" camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
2985" [-D <enable|disable>][-O offset][-q]\n"
2986" [-R syncrate][-v][-T <enable|disable>]\n"
2987" [-U][-W bus_width]\n"
2988" camcontrol format [dev_id][generic args][-q][-w][-y]\n"
2989" camcontrol help\n");
2990 if (!verbose)
2991 return;
2992 fprintf(stdout,
2993"Specify one of the following options:\n"
2994"devlist list all CAM devices\n"
2995"periphlist list all CAM peripheral drivers attached to a device\n"
2996"tur send a test unit ready to the named device\n"
2997"inquiry send a SCSI inquiry command to the named device\n"
2998"start send a Start Unit command to the device\n"
2999"stop send a Stop Unit command to the device\n"
3000"eject send a Stop Unit command to the device with the eject bit set\n"
3001"rescan rescan the given bus, or bus:target:lun\n"
3002"reset reset the given bus, or bus:target:lun\n"
3003"defects read the defect list of the specified device\n"
3004"modepage display or edit (-e) the given mode page\n"
3005"cmd send the given scsi command, may need -i or -o as well\n"
3006"debug turn debugging on/off for a bus, target, or lun, or all devices\n"
3007"tags report or set the number of transaction slots for a device\n"
3008"negotiate report or set device negotiation parameters\n"
3009"format send the SCSI FORMAT UNIT command to the named device\n"
3010"help this message\n"
3011"Device Identifiers:\n"
3012"bus:target specify the bus and target, lun defaults to 0\n"
3013"bus:target:lun specify the bus, target and lun\n"
3014"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
3015"Generic arguments:\n"
3016"-v be verbose, print out sense information\n"
3017"-t timeout command timeout in seconds, overrides default timeout\n"
3018"-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
3019"-u unit specify unit number, e.g. \"0\", \"5\"\n"
3020"-E have the kernel attempt to perform SCSI error recovery\n"
3021"-C count specify the SCSI command retry count (needs -E to work)\n"
3022"modepage arguments:\n"
3023"-m page specify the mode page to view or edit\n"
3024"-e edit the specified mode page\n"
2993" camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n"
2994" [-i len fmt|-o len fmt [args]]\n"
2995" camcontrol debug [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
2996" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
2997" camcontrol negotiate [dev_id][generic args] [-a][-c]\n"
2998" [-D <enable|disable>][-O offset][-q]\n"
2999" [-R syncrate][-v][-T <enable|disable>]\n"
3000" [-U][-W bus_width]\n"
3001" camcontrol format [dev_id][generic args][-q][-w][-y]\n"
3002" camcontrol help\n");
3003 if (!verbose)
3004 return;
3005 fprintf(stdout,
3006"Specify one of the following options:\n"
3007"devlist list all CAM devices\n"
3008"periphlist list all CAM peripheral drivers attached to a device\n"
3009"tur send a test unit ready to the named device\n"
3010"inquiry send a SCSI inquiry command to the named device\n"
3011"start send a Start Unit command to the device\n"
3012"stop send a Stop Unit command to the device\n"
3013"eject send a Stop Unit command to the device with the eject bit set\n"
3014"rescan rescan the given bus, or bus:target:lun\n"
3015"reset reset the given bus, or bus:target:lun\n"
3016"defects read the defect list of the specified device\n"
3017"modepage display or edit (-e) the given mode page\n"
3018"cmd send the given scsi command, may need -i or -o as well\n"
3019"debug turn debugging on/off for a bus, target, or lun, or all devices\n"
3020"tags report or set the number of transaction slots for a device\n"
3021"negotiate report or set device negotiation parameters\n"
3022"format send the SCSI FORMAT UNIT command to the named device\n"
3023"help this message\n"
3024"Device Identifiers:\n"
3025"bus:target specify the bus and target, lun defaults to 0\n"
3026"bus:target:lun specify the bus, target and lun\n"
3027"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n"
3028"Generic arguments:\n"
3029"-v be verbose, print out sense information\n"
3030"-t timeout command timeout in seconds, overrides default timeout\n"
3031"-n dev_name specify device name, e.g. \"da\", \"cd\"\n"
3032"-u unit specify unit number, e.g. \"0\", \"5\"\n"
3033"-E have the kernel attempt to perform SCSI error recovery\n"
3034"-C count specify the SCSI command retry count (needs -E to work)\n"
3035"modepage arguments:\n"
3036"-m page specify the mode page to view or edit\n"
3037"-e edit the specified mode page\n"
3038"-b force view to binary mode\n"
3025"-d disable block descriptors for mode sense\n"
3026"-P pgctl page control field 0-3\n"
3027"defects arguments:\n"
3028"-f format specify defect list format (block, bfi or phys)\n"
3029"-G get the grown defect list\n"
3030"-P get the permanant defect list\n"
3031"inquiry arguments:\n"
3032"-D get the standard inquiry data\n"
3033"-S get the serial number\n"
3034"-R get the transfer rate, etc.\n"
3035"cmd arguments:\n"
3036"-c cdb [args] specify the SCSI CDB\n"
3037"-i len fmt specify input data and input data format\n"
3038"-o len fmt [args] specify output data and output data fmt\n"
3039"debug arguments:\n"
3040"-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3041"-T CAM_DEBUG_TRACE -- routine flow tracking\n"
3042"-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3043"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3044"tags arguments:\n"
3045"-N tags specify the number of tags to use for this device\n"
3046"-q be quiet, don't report the number of tags\n"
3047"-v report a number of tag-related parameters\n"
3048"negotiate arguments:\n"
3049"-a send a test unit ready after negotiation\n"
3050"-c report/set current negotiation settings\n"
3051"-D <arg> \"enable\" or \"disable\" disconnection\n"
3052"-O offset set command delay offset\n"
3053"-q be quiet, don't report anything\n"
3054"-R syncrate synchronization rate in MHz\n"
3055"-T <arg> \"enable\" or \"disable\" tagged queueing\n"
3056"-U report/set user negotiation settings\n"
3057"-W bus_width set the bus width in bits (8, 16 or 32)\n"
3058"-v also print a Path Inquiry CCB for the controller\n"
3059"format arguments:\n"
3060"-q be quiet, don't print status messages\n"
3061"-w don't send immediate format command\n"
3062"-y don't ask any questions\n");
3063}
3064
3065int
3066main(int argc, char **argv)
3067{
3068 int c;
3069 char *device = NULL;
3070 int unit = 0;
3071 struct cam_device *cam_dev = NULL;
3072 int timeout = 0, retry_count = 1;
3073 camcontrol_optret optreturn;
3074 char *tstr;
3075 char *mainopt = "C:En:t:u:v";
3076 char *subopt = NULL;
3077 char combinedopt[256];
3078 int error = 0, optstart = 2;
3079 int devopen = 1;
3080
3081 arglist = CAM_ARG_NONE;
3082
3083 if (argc < 2) {
3084 usage(0);
3085 exit(1);
3086 }
3087
3088 /*
3089 * Get the base option.
3090 */
3091 optreturn = getoption(argv[1], &arglist, &subopt);
3092
3093 if (optreturn == CC_OR_AMBIGUOUS) {
3094 warnx("ambiguous option %s", argv[1]);
3095 usage(0);
3096 exit(1);
3097 } else if (optreturn == CC_OR_NOT_FOUND) {
3098 warnx("option %s not found", argv[1]);
3099 usage(0);
3100 exit(1);
3101 }
3102
3103 /*
3104 * Ahh, getopt(3) is a pain.
3105 *
3106 * This is a gross hack. There really aren't many other good
3107 * options (excuse the pun) for parsing options in a situation like
3108 * this. getopt is kinda braindead, so you end up having to run
3109 * through the options twice, and give each invocation of getopt
3110 * the option string for the other invocation.
3111 *
3112 * You would think that you could just have two groups of options.
3113 * The first group would get parsed by the first invocation of
3114 * getopt, and the second group would get parsed by the second
3115 * invocation of getopt. It doesn't quite work out that way. When
3116 * the first invocation of getopt finishes, it leaves optind pointing
3117 * to the argument _after_ the first argument in the second group.
3118 * So when the second invocation of getopt comes around, it doesn't
3119 * recognize the first argument it gets and then bails out.
3120 *
3121 * A nice alternative would be to have a flag for getopt that says
3122 * "just keep parsing arguments even when you encounter an unknown
3123 * argument", but there isn't one. So there's no real clean way to
3124 * easily parse two sets of arguments without having one invocation
3125 * of getopt know about the other.
3126 *
3127 * Without this hack, the first invocation of getopt would work as
3128 * long as the generic arguments are first, but the second invocation
3129 * (in the subfunction) would fail in one of two ways. In the case
3130 * where you don't set optreset, it would fail because optind may be
3131 * pointing to the argument after the one it should be pointing at.
3132 * In the case where you do set optreset, and reset optind, it would
3133 * fail because getopt would run into the first set of options, which
3134 * it doesn't understand.
3135 *
3136 * All of this would "sort of" work if you could somehow figure out
3137 * whether optind had been incremented one option too far. The
3138 * mechanics of that, however, are more daunting than just giving
3139 * both invocations all of the expect options for either invocation.
3140 *
3141 * Needless to say, I wouldn't mind if someone invented a better
3142 * (non-GPL!) command line parsing interface than getopt. I
3143 * wouldn't mind if someone added more knobs to getopt to make it
3144 * work better. Who knows, I may talk myself into doing it someday,
3145 * if the standards weenies let me. As it is, it just leads to
3146 * hackery like this and causes people to avoid it in some cases.
3147 *
3148 * KDM, September 8th, 1998
3149 */
3150 if (subopt != NULL)
3151 sprintf(combinedopt, "%s%s", mainopt, subopt);
3152 else
3153 sprintf(combinedopt, "%s", mainopt);
3154
3155 /*
3156 * For these options we do not parse optional device arguments and
3157 * we do not open a passthrough device.
3158 */
3159 if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
3160 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
3161 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
3162 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
3163 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
3164 devopen = 0;
3165
3166 if ((devopen == 1)
3167 && (argc > 2 && argv[2][0] != '-')) {
3168 char name[30];
3169 int rv;
3170
3171 /*
3172 * First catch people who try to do things like:
3173 * camcontrol tur /dev/rsd0.ctl
3174 * camcontrol doesn't take device nodes as arguments.
3175 */
3176 if (argv[2][0] == '/') {
3177 warnx("%s is not a valid device identifier", argv[2]);
3178 errx(1, "please read the camcontrol(8) man page");
3179 } else if (isdigit(argv[2][0])) {
3180 /* device specified as bus:target[:lun] */
3181 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3182 if (rv < 2)
3183 errx(1, "numeric device specification must "
3184 "be either bus:target, or "
3185 "bus:target:lun");
3186 optstart++;
3187 } else {
3188 if (cam_get_device(argv[2], name, sizeof name, &unit)
3189 == -1)
3190 errx(1, "%s", cam_errbuf);
3191 device = strdup(name);
3192 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3193 optstart++;
3194 }
3195 }
3196 /*
3197 * Start getopt processing at argv[2/3], since we've already
3198 * accepted argv[1..2] as the command name, and as a possible
3199 * device name.
3200 */
3201 optind = optstart;
3202
3203 /*
3204 * Now we run through the argument list looking for generic
3205 * options, and ignoring options that possibly belong to
3206 * subfunctions.
3207 */
3208 while ((c = getopt(argc, argv, combinedopt))!= -1){
3209 switch(c) {
3210 case 'C':
3211 retry_count = strtol(optarg, NULL, 0);
3212 if (retry_count < 0)
3213 errx(1, "retry count %d is < 0",
3214 retry_count);
3215 arglist |= CAM_ARG_RETRIES;
3216 break;
3217 case 'E':
3218 arglist |= CAM_ARG_ERR_RECOVER;
3219 break;
3220 case 'n':
3221 arglist |= CAM_ARG_DEVICE;
3222 tstr = optarg;
3223 while (isspace(*tstr) && (*tstr != '\0'))
3224 tstr++;
3225 device = (char *)strdup(tstr);
3226 break;
3227 case 't':
3228 timeout = strtol(optarg, NULL, 0);
3229 if (timeout < 0)
3230 errx(1, "invalid timeout %d", timeout);
3231 /* Convert the timeout from seconds to ms */
3232 timeout *= 1000;
3233 arglist |= CAM_ARG_TIMEOUT;
3234 break;
3235 case 'u':
3236 arglist |= CAM_ARG_UNIT;
3237 unit = strtol(optarg, NULL, 0);
3238 break;
3239 case 'v':
3240 arglist |= CAM_ARG_VERBOSE;
3241 break;
3242 default:
3243 break;
3244 }
3245 }
3246
3247 /*
3248 * For most commands we'll want to open the passthrough device
3249 * associated with the specified device. In the case of the rescan
3250 * commands, we don't use a passthrough device at all, just the
3251 * transport layer device.
3252 */
3253 if (devopen == 1) {
3254 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3255 && (((arglist & CAM_ARG_DEVICE) == 0)
3256 || ((arglist & CAM_ARG_UNIT) == 0))) {
3257 errx(1, "subcommand \"%s\" requires a valid device "
3258 "identifier", argv[1]);
3259 }
3260
3261 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3262 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3263 cam_open_spec_device(device,unit,O_RDWR,NULL)))
3264 == NULL)
3265 errx(1,"%s", cam_errbuf);
3266 }
3267
3268 /*
3269 * Reset optind to 2, and reset getopt, so these routines can parse
3270 * the arguments again.
3271 */
3272 optind = optstart;
3273 optreset = 1;
3274
3275 switch(arglist & CAM_ARG_OPT_MASK) {
3276 case CAM_ARG_DEVLIST:
3277 error = getdevlist(cam_dev);
3278 break;
3279 case CAM_ARG_DEVTREE:
3280 error = getdevtree();
3281 break;
3282 case CAM_ARG_TUR:
3283 error = testunitready(cam_dev, retry_count, timeout, 0);
3284 break;
3285 case CAM_ARG_INQUIRY:
3286 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3287 retry_count, timeout);
3288 break;
3289 case CAM_ARG_STARTSTOP:
3290 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3291 arglist & CAM_ARG_EJECT, retry_count,
3292 timeout);
3293 break;
3294 case CAM_ARG_RESCAN:
3295 error = dorescan_or_reset(argc, argv, 1);
3296 break;
3297 case CAM_ARG_RESET:
3298 error = dorescan_or_reset(argc, argv, 0);
3299 break;
3300 case CAM_ARG_READ_DEFECTS:
3301 error = readdefects(cam_dev, argc, argv, combinedopt,
3302 retry_count, timeout);
3303 break;
3304 case CAM_ARG_MODE_PAGE:
3305 modepage(cam_dev, argc, argv, combinedopt,
3306 retry_count, timeout);
3307 break;
3308 case CAM_ARG_SCSI_CMD:
3309 error = scsicmd(cam_dev, argc, argv, combinedopt,
3310 retry_count, timeout);
3311 break;
3312 case CAM_ARG_DEBUG:
3313 error = camdebug(argc, argv, combinedopt);
3314 break;
3315 case CAM_ARG_TAG:
3316 error = tagcontrol(cam_dev, argc, argv, combinedopt);
3317 break;
3318 case CAM_ARG_RATE:
3319 error = ratecontrol(cam_dev, retry_count, timeout,
3320 argc, argv, combinedopt);
3321 break;
3322 case CAM_ARG_FORMAT:
3323 error = scsiformat(cam_dev, argc, argv,
3324 combinedopt, retry_count, timeout);
3325 break;
3326 case CAM_ARG_USAGE:
3327 usage(1);
3328 break;
3329 default:
3330 usage(0);
3331 error = 1;
3332 break;
3333 }
3334
3335 if (cam_dev != NULL)
3336 cam_close_device(cam_dev);
3337
3338 exit(error);
3339}
3039"-d disable block descriptors for mode sense\n"
3040"-P pgctl page control field 0-3\n"
3041"defects arguments:\n"
3042"-f format specify defect list format (block, bfi or phys)\n"
3043"-G get the grown defect list\n"
3044"-P get the permanant defect list\n"
3045"inquiry arguments:\n"
3046"-D get the standard inquiry data\n"
3047"-S get the serial number\n"
3048"-R get the transfer rate, etc.\n"
3049"cmd arguments:\n"
3050"-c cdb [args] specify the SCSI CDB\n"
3051"-i len fmt specify input data and input data format\n"
3052"-o len fmt [args] specify output data and output data fmt\n"
3053"debug arguments:\n"
3054"-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
3055"-T CAM_DEBUG_TRACE -- routine flow tracking\n"
3056"-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
3057"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
3058"tags arguments:\n"
3059"-N tags specify the number of tags to use for this device\n"
3060"-q be quiet, don't report the number of tags\n"
3061"-v report a number of tag-related parameters\n"
3062"negotiate arguments:\n"
3063"-a send a test unit ready after negotiation\n"
3064"-c report/set current negotiation settings\n"
3065"-D <arg> \"enable\" or \"disable\" disconnection\n"
3066"-O offset set command delay offset\n"
3067"-q be quiet, don't report anything\n"
3068"-R syncrate synchronization rate in MHz\n"
3069"-T <arg> \"enable\" or \"disable\" tagged queueing\n"
3070"-U report/set user negotiation settings\n"
3071"-W bus_width set the bus width in bits (8, 16 or 32)\n"
3072"-v also print a Path Inquiry CCB for the controller\n"
3073"format arguments:\n"
3074"-q be quiet, don't print status messages\n"
3075"-w don't send immediate format command\n"
3076"-y don't ask any questions\n");
3077}
3078
3079int
3080main(int argc, char **argv)
3081{
3082 int c;
3083 char *device = NULL;
3084 int unit = 0;
3085 struct cam_device *cam_dev = NULL;
3086 int timeout = 0, retry_count = 1;
3087 camcontrol_optret optreturn;
3088 char *tstr;
3089 char *mainopt = "C:En:t:u:v";
3090 char *subopt = NULL;
3091 char combinedopt[256];
3092 int error = 0, optstart = 2;
3093 int devopen = 1;
3094
3095 arglist = CAM_ARG_NONE;
3096
3097 if (argc < 2) {
3098 usage(0);
3099 exit(1);
3100 }
3101
3102 /*
3103 * Get the base option.
3104 */
3105 optreturn = getoption(argv[1], &arglist, &subopt);
3106
3107 if (optreturn == CC_OR_AMBIGUOUS) {
3108 warnx("ambiguous option %s", argv[1]);
3109 usage(0);
3110 exit(1);
3111 } else if (optreturn == CC_OR_NOT_FOUND) {
3112 warnx("option %s not found", argv[1]);
3113 usage(0);
3114 exit(1);
3115 }
3116
3117 /*
3118 * Ahh, getopt(3) is a pain.
3119 *
3120 * This is a gross hack. There really aren't many other good
3121 * options (excuse the pun) for parsing options in a situation like
3122 * this. getopt is kinda braindead, so you end up having to run
3123 * through the options twice, and give each invocation of getopt
3124 * the option string for the other invocation.
3125 *
3126 * You would think that you could just have two groups of options.
3127 * The first group would get parsed by the first invocation of
3128 * getopt, and the second group would get parsed by the second
3129 * invocation of getopt. It doesn't quite work out that way. When
3130 * the first invocation of getopt finishes, it leaves optind pointing
3131 * to the argument _after_ the first argument in the second group.
3132 * So when the second invocation of getopt comes around, it doesn't
3133 * recognize the first argument it gets and then bails out.
3134 *
3135 * A nice alternative would be to have a flag for getopt that says
3136 * "just keep parsing arguments even when you encounter an unknown
3137 * argument", but there isn't one. So there's no real clean way to
3138 * easily parse two sets of arguments without having one invocation
3139 * of getopt know about the other.
3140 *
3141 * Without this hack, the first invocation of getopt would work as
3142 * long as the generic arguments are first, but the second invocation
3143 * (in the subfunction) would fail in one of two ways. In the case
3144 * where you don't set optreset, it would fail because optind may be
3145 * pointing to the argument after the one it should be pointing at.
3146 * In the case where you do set optreset, and reset optind, it would
3147 * fail because getopt would run into the first set of options, which
3148 * it doesn't understand.
3149 *
3150 * All of this would "sort of" work if you could somehow figure out
3151 * whether optind had been incremented one option too far. The
3152 * mechanics of that, however, are more daunting than just giving
3153 * both invocations all of the expect options for either invocation.
3154 *
3155 * Needless to say, I wouldn't mind if someone invented a better
3156 * (non-GPL!) command line parsing interface than getopt. I
3157 * wouldn't mind if someone added more knobs to getopt to make it
3158 * work better. Who knows, I may talk myself into doing it someday,
3159 * if the standards weenies let me. As it is, it just leads to
3160 * hackery like this and causes people to avoid it in some cases.
3161 *
3162 * KDM, September 8th, 1998
3163 */
3164 if (subopt != NULL)
3165 sprintf(combinedopt, "%s%s", mainopt, subopt);
3166 else
3167 sprintf(combinedopt, "%s", mainopt);
3168
3169 /*
3170 * For these options we do not parse optional device arguments and
3171 * we do not open a passthrough device.
3172 */
3173 if (((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESCAN)
3174 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_RESET)
3175 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEVTREE)
3176 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_USAGE)
3177 || ((arglist & CAM_ARG_OPT_MASK) == CAM_ARG_DEBUG))
3178 devopen = 0;
3179
3180 if ((devopen == 1)
3181 && (argc > 2 && argv[2][0] != '-')) {
3182 char name[30];
3183 int rv;
3184
3185 /*
3186 * First catch people who try to do things like:
3187 * camcontrol tur /dev/rsd0.ctl
3188 * camcontrol doesn't take device nodes as arguments.
3189 */
3190 if (argv[2][0] == '/') {
3191 warnx("%s is not a valid device identifier", argv[2]);
3192 errx(1, "please read the camcontrol(8) man page");
3193 } else if (isdigit(argv[2][0])) {
3194 /* device specified as bus:target[:lun] */
3195 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist);
3196 if (rv < 2)
3197 errx(1, "numeric device specification must "
3198 "be either bus:target, or "
3199 "bus:target:lun");
3200 optstart++;
3201 } else {
3202 if (cam_get_device(argv[2], name, sizeof name, &unit)
3203 == -1)
3204 errx(1, "%s", cam_errbuf);
3205 device = strdup(name);
3206 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT;
3207 optstart++;
3208 }
3209 }
3210 /*
3211 * Start getopt processing at argv[2/3], since we've already
3212 * accepted argv[1..2] as the command name, and as a possible
3213 * device name.
3214 */
3215 optind = optstart;
3216
3217 /*
3218 * Now we run through the argument list looking for generic
3219 * options, and ignoring options that possibly belong to
3220 * subfunctions.
3221 */
3222 while ((c = getopt(argc, argv, combinedopt))!= -1){
3223 switch(c) {
3224 case 'C':
3225 retry_count = strtol(optarg, NULL, 0);
3226 if (retry_count < 0)
3227 errx(1, "retry count %d is < 0",
3228 retry_count);
3229 arglist |= CAM_ARG_RETRIES;
3230 break;
3231 case 'E':
3232 arglist |= CAM_ARG_ERR_RECOVER;
3233 break;
3234 case 'n':
3235 arglist |= CAM_ARG_DEVICE;
3236 tstr = optarg;
3237 while (isspace(*tstr) && (*tstr != '\0'))
3238 tstr++;
3239 device = (char *)strdup(tstr);
3240 break;
3241 case 't':
3242 timeout = strtol(optarg, NULL, 0);
3243 if (timeout < 0)
3244 errx(1, "invalid timeout %d", timeout);
3245 /* Convert the timeout from seconds to ms */
3246 timeout *= 1000;
3247 arglist |= CAM_ARG_TIMEOUT;
3248 break;
3249 case 'u':
3250 arglist |= CAM_ARG_UNIT;
3251 unit = strtol(optarg, NULL, 0);
3252 break;
3253 case 'v':
3254 arglist |= CAM_ARG_VERBOSE;
3255 break;
3256 default:
3257 break;
3258 }
3259 }
3260
3261 /*
3262 * For most commands we'll want to open the passthrough device
3263 * associated with the specified device. In the case of the rescan
3264 * commands, we don't use a passthrough device at all, just the
3265 * transport layer device.
3266 */
3267 if (devopen == 1) {
3268 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0)
3269 && (((arglist & CAM_ARG_DEVICE) == 0)
3270 || ((arglist & CAM_ARG_UNIT) == 0))) {
3271 errx(1, "subcommand \"%s\" requires a valid device "
3272 "identifier", argv[1]);
3273 }
3274
3275 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))?
3276 cam_open_btl(bus, target, lun, O_RDWR, NULL) :
3277 cam_open_spec_device(device,unit,O_RDWR,NULL)))
3278 == NULL)
3279 errx(1,"%s", cam_errbuf);
3280 }
3281
3282 /*
3283 * Reset optind to 2, and reset getopt, so these routines can parse
3284 * the arguments again.
3285 */
3286 optind = optstart;
3287 optreset = 1;
3288
3289 switch(arglist & CAM_ARG_OPT_MASK) {
3290 case CAM_ARG_DEVLIST:
3291 error = getdevlist(cam_dev);
3292 break;
3293 case CAM_ARG_DEVTREE:
3294 error = getdevtree();
3295 break;
3296 case CAM_ARG_TUR:
3297 error = testunitready(cam_dev, retry_count, timeout, 0);
3298 break;
3299 case CAM_ARG_INQUIRY:
3300 error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
3301 retry_count, timeout);
3302 break;
3303 case CAM_ARG_STARTSTOP:
3304 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
3305 arglist & CAM_ARG_EJECT, retry_count,
3306 timeout);
3307 break;
3308 case CAM_ARG_RESCAN:
3309 error = dorescan_or_reset(argc, argv, 1);
3310 break;
3311 case CAM_ARG_RESET:
3312 error = dorescan_or_reset(argc, argv, 0);
3313 break;
3314 case CAM_ARG_READ_DEFECTS:
3315 error = readdefects(cam_dev, argc, argv, combinedopt,
3316 retry_count, timeout);
3317 break;
3318 case CAM_ARG_MODE_PAGE:
3319 modepage(cam_dev, argc, argv, combinedopt,
3320 retry_count, timeout);
3321 break;
3322 case CAM_ARG_SCSI_CMD:
3323 error = scsicmd(cam_dev, argc, argv, combinedopt,
3324 retry_count, timeout);
3325 break;
3326 case CAM_ARG_DEBUG:
3327 error = camdebug(argc, argv, combinedopt);
3328 break;
3329 case CAM_ARG_TAG:
3330 error = tagcontrol(cam_dev, argc, argv, combinedopt);
3331 break;
3332 case CAM_ARG_RATE:
3333 error = ratecontrol(cam_dev, retry_count, timeout,
3334 argc, argv, combinedopt);
3335 break;
3336 case CAM_ARG_FORMAT:
3337 error = scsiformat(cam_dev, argc, argv,
3338 combinedopt, retry_count, timeout);
3339 break;
3340 case CAM_ARG_USAGE:
3341 usage(1);
3342 break;
3343 default:
3344 usage(0);
3345 error = 1;
3346 break;
3347 }
3348
3349 if (cam_dev != NULL)
3350 cam_close_device(cam_dev);
3351
3352 exit(error);
3353}