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