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