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