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