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