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