camcontrol.c revision 216361
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 216361 2010-12-10 21:38:51Z ken $"); 31 32#include <sys/ioctl.h> 33#include <sys/stdint.h> 34#include <sys/types.h> 35#include <sys/endian.h> 36#include <sys/sbuf.h> 37 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42#include <inttypes.h> 43#include <limits.h> 44#include <fcntl.h> 45#include <ctype.h> 46#include <err.h> 47#include <libutil.h> 48 49#include <cam/cam.h> 50#include <cam/cam_debug.h> 51#include <cam/cam_ccb.h> 52#include <cam/scsi/scsi_all.h> 53#include <cam/scsi/scsi_da.h> 54#include <cam/scsi/scsi_pass.h> 55#include <cam/scsi/scsi_message.h> 56#include <cam/scsi/smp_all.h> 57#include <cam/ata/ata_all.h> 58#include <camlib.h> 59#include "camcontrol.h" 60 61typedef enum { 62 CAM_CMD_NONE = 0x00000000, 63 CAM_CMD_DEVLIST = 0x00000001, 64 CAM_CMD_TUR = 0x00000002, 65 CAM_CMD_INQUIRY = 0x00000003, 66 CAM_CMD_STARTSTOP = 0x00000004, 67 CAM_CMD_RESCAN = 0x00000005, 68 CAM_CMD_READ_DEFECTS = 0x00000006, 69 CAM_CMD_MODE_PAGE = 0x00000007, 70 CAM_CMD_SCSI_CMD = 0x00000008, 71 CAM_CMD_DEVTREE = 0x00000009, 72 CAM_CMD_USAGE = 0x0000000a, 73 CAM_CMD_DEBUG = 0x0000000b, 74 CAM_CMD_RESET = 0x0000000c, 75 CAM_CMD_FORMAT = 0x0000000d, 76 CAM_CMD_TAG = 0x0000000e, 77 CAM_CMD_RATE = 0x0000000f, 78 CAM_CMD_DETACH = 0x00000010, 79 CAM_CMD_REPORTLUNS = 0x00000011, 80 CAM_CMD_READCAP = 0x00000012, 81 CAM_CMD_IDENTIFY = 0x00000013, 82 CAM_CMD_IDLE = 0x00000014, 83 CAM_CMD_STANDBY = 0x00000015, 84 CAM_CMD_SLEEP = 0x00000016, 85 CAM_CMD_SMP_CMD = 0x00000017, 86 CAM_CMD_SMP_RG = 0x00000018, 87 CAM_CMD_SMP_PC = 0x00000019, 88 CAM_CMD_SMP_PHYLIST = 0x0000001a, 89 CAM_CMD_SMP_MANINFO = 0x0000001b 90} cam_cmdmask; 91 92typedef enum { 93 CAM_ARG_NONE = 0x00000000, 94 CAM_ARG_VERBOSE = 0x00000001, 95 CAM_ARG_DEVICE = 0x00000002, 96 CAM_ARG_BUS = 0x00000004, 97 CAM_ARG_TARGET = 0x00000008, 98 CAM_ARG_LUN = 0x00000010, 99 CAM_ARG_EJECT = 0x00000020, 100 CAM_ARG_UNIT = 0x00000040, 101 CAM_ARG_FORMAT_BLOCK = 0x00000080, 102 CAM_ARG_FORMAT_BFI = 0x00000100, 103 CAM_ARG_FORMAT_PHYS = 0x00000200, 104 CAM_ARG_PLIST = 0x00000400, 105 CAM_ARG_GLIST = 0x00000800, 106 CAM_ARG_GET_SERIAL = 0x00001000, 107 CAM_ARG_GET_STDINQ = 0x00002000, 108 CAM_ARG_GET_XFERRATE = 0x00004000, 109 CAM_ARG_INQ_MASK = 0x00007000, 110 CAM_ARG_MODE_EDIT = 0x00008000, 111 CAM_ARG_PAGE_CNTL = 0x00010000, 112 CAM_ARG_TIMEOUT = 0x00020000, 113 CAM_ARG_CMD_IN = 0x00040000, 114 CAM_ARG_CMD_OUT = 0x00080000, 115 CAM_ARG_DBD = 0x00100000, 116 CAM_ARG_ERR_RECOVER = 0x00200000, 117 CAM_ARG_RETRIES = 0x00400000, 118 CAM_ARG_START_UNIT = 0x00800000, 119 CAM_ARG_DEBUG_INFO = 0x01000000, 120 CAM_ARG_DEBUG_TRACE = 0x02000000, 121 CAM_ARG_DEBUG_SUBTRACE = 0x04000000, 122 CAM_ARG_DEBUG_CDB = 0x08000000, 123 CAM_ARG_DEBUG_XPT = 0x10000000, 124 CAM_ARG_DEBUG_PERIPH = 0x20000000, 125} cam_argmask; 126 127struct camcontrol_opts { 128 const char *optname; 129 uint32_t cmdnum; 130 cam_argmask argnum; 131 const char *subopt; 132}; 133 134#ifndef MINIMALISTIC 135static const char scsicmd_opts[] = "a:c:dfi:o:r"; 136static const char readdefect_opts[] = "f:GP"; 137static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; 138static const char smprg_opts[] = "l"; 139static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:"; 140static const char smpphylist_opts[] = "lq"; 141#endif 142 143struct camcontrol_opts option_table[] = { 144#ifndef MINIMALISTIC 145 {"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL}, 146 {"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"}, 147 {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL}, 148 {"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL}, 149 {"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL}, 150 {"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL}, 151 {"eject", CAM_CMD_STARTSTOP, CAM_ARG_EJECT, NULL}, 152 {"reportluns", CAM_CMD_REPORTLUNS, CAM_ARG_NONE, "clr:"}, 153 {"readcapacity", CAM_CMD_READCAP, CAM_ARG_NONE, "bhHNqs"}, 154#endif /* MINIMALISTIC */ 155 {"rescan", CAM_CMD_RESCAN, CAM_ARG_NONE, NULL}, 156 {"reset", CAM_CMD_RESET, CAM_ARG_NONE, NULL}, 157#ifndef MINIMALISTIC 158 {"cmd", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts}, 159 {"command", CAM_CMD_SCSI_CMD, CAM_ARG_NONE, scsicmd_opts}, 160 {"smpcmd", CAM_CMD_SMP_CMD, CAM_ARG_NONE, "r:R:"}, 161 {"smprg", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts}, 162 {"smpreportgeneral", CAM_CMD_SMP_RG, CAM_ARG_NONE, smprg_opts}, 163 {"smppc", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts}, 164 {"smpphycontrol", CAM_CMD_SMP_PC, CAM_ARG_NONE, smppc_opts}, 165 {"smpplist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts}, 166 {"smpphylist", CAM_CMD_SMP_PHYLIST, CAM_ARG_NONE, smpphylist_opts}, 167 {"smpmaninfo", CAM_CMD_SMP_MANINFO, CAM_ARG_NONE, "l"}, 168 {"defects", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts}, 169 {"defectlist", CAM_CMD_READ_DEFECTS, CAM_ARG_NONE, readdefect_opts}, 170#endif /* MINIMALISTIC */ 171 {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL}, 172#ifndef MINIMALISTIC 173 {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL}, 174 {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"}, 175 {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"}, 176 {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, 177 {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, 178 {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"}, 179 {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"}, 180 {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"}, 181 {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"}, 182 {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""}, 183#endif /* MINIMALISTIC */ 184 {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 185 {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 186 {"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, 187 {NULL, 0, 0, NULL} 188}; 189 190typedef enum { 191 CC_OR_NOT_FOUND, 192 CC_OR_AMBIGUOUS, 193 CC_OR_FOUND 194} camcontrol_optret; 195 196struct cam_devitem { 197 struct device_match_result dev_match; 198 int num_periphs; 199 struct periph_match_result *periph_matches; 200 struct scsi_vpd_device_id *device_id; 201 int device_id_len; 202 STAILQ_ENTRY(cam_devitem) links; 203}; 204 205struct cam_devlist { 206 STAILQ_HEAD(, cam_devitem) dev_queue; 207 path_id_t path_id; 208}; 209 210cam_cmdmask cmdlist; 211cam_argmask arglist; 212 213camcontrol_optret getoption(struct camcontrol_opts *table, char *arg, 214 uint32_t *cmdnum, cam_argmask *argnum, 215 const char **subopt); 216#ifndef MINIMALISTIC 217static int getdevlist(struct cam_device *device); 218#endif /* MINIMALISTIC */ 219static int getdevtree(void); 220#ifndef MINIMALISTIC 221static int testunitready(struct cam_device *device, int retry_count, 222 int timeout, int quiet); 223static int scsistart(struct cam_device *device, int startstop, int loadeject, 224 int retry_count, int timeout); 225static int scsidoinquiry(struct cam_device *device, int argc, char **argv, 226 char *combinedopt, int retry_count, int timeout); 227static int scsiinquiry(struct cam_device *device, int retry_count, int timeout); 228static int scsiserial(struct cam_device *device, int retry_count, int timeout); 229static int camxferrate(struct cam_device *device); 230#endif /* MINIMALISTIC */ 231static int parse_btl(char *tstr, int *bus, int *target, int *lun, 232 cam_argmask *arglst); 233static int dorescan_or_reset(int argc, char **argv, int rescan); 234static int rescan_or_reset_bus(int bus, int rescan); 235static int scanlun_or_reset_dev(int bus, int target, int lun, int scan); 236#ifndef MINIMALISTIC 237static int readdefects(struct cam_device *device, int argc, char **argv, 238 char *combinedopt, int retry_count, int timeout); 239static void modepage(struct cam_device *device, int argc, char **argv, 240 char *combinedopt, int retry_count, int timeout); 241static int scsicmd(struct cam_device *device, int argc, char **argv, 242 char *combinedopt, int retry_count, int timeout); 243static int smpcmd(struct cam_device *device, int argc, char **argv, 244 char *combinedopt, int retry_count, int timeout); 245static int smpreportgeneral(struct cam_device *device, int argc, char **argv, 246 char *combinedopt, int retry_count, int timeout); 247static int smpphycontrol(struct cam_device *device, int argc, char **argv, 248 char *combinedopt, int retry_count, int timeout); 249static int smpmaninfo(struct cam_device *device, int argc, char **argv, 250 char *combinedopt, int retry_count, int timeout); 251static int getdevid(struct cam_devitem *item); 252static int buildbusdevlist(struct cam_devlist *devlist); 253static void freebusdevlist(struct cam_devlist *devlist); 254static struct cam_devitem *findsasdevice(struct cam_devlist *devlist, 255 uint64_t sasaddr); 256static int smpphylist(struct cam_device *device, int argc, char **argv, 257 char *combinedopt, int retry_count, int timeout); 258static int tagcontrol(struct cam_device *device, int argc, char **argv, 259 char *combinedopt); 260static void cts_print(struct cam_device *device, 261 struct ccb_trans_settings *cts); 262static void cpi_print(struct ccb_pathinq *cpi); 263static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi); 264static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd); 265static int get_print_cts(struct cam_device *device, int user_settings, 266 int quiet, struct ccb_trans_settings *cts); 267static int ratecontrol(struct cam_device *device, int retry_count, 268 int timeout, int argc, char **argv, char *combinedopt); 269static int scsiformat(struct cam_device *device, int argc, char **argv, 270 char *combinedopt, int retry_count, int timeout); 271static int scsireportluns(struct cam_device *device, int argc, char **argv, 272 char *combinedopt, int retry_count, int timeout); 273static int scsireadcapacity(struct cam_device *device, int argc, char **argv, 274 char *combinedopt, int retry_count, int timeout); 275static int atapm(struct cam_device *device, int argc, char **argv, 276 char *combinedopt, int retry_count, int timeout); 277#endif /* MINIMALISTIC */ 278#ifndef min 279#define min(a,b) (((a)<(b))?(a):(b)) 280#endif 281#ifndef max 282#define max(a,b) (((a)>(b))?(a):(b)) 283#endif 284 285camcontrol_optret 286getoption(struct camcontrol_opts *table, char *arg, uint32_t *cmdnum, 287 cam_argmask *argnum, const char **subopt) 288{ 289 struct camcontrol_opts *opts; 290 int num_matches = 0; 291 292 for (opts = table; (opts != NULL) && (opts->optname != NULL); 293 opts++) { 294 if (strncmp(opts->optname, arg, strlen(arg)) == 0) { 295 *cmdnum = opts->cmdnum; 296 *argnum = opts->argnum; 297 *subopt = opts->subopt; 298 if (++num_matches > 1) 299 return(CC_OR_AMBIGUOUS); 300 } 301 } 302 303 if (num_matches > 0) 304 return(CC_OR_FOUND); 305 else 306 return(CC_OR_NOT_FOUND); 307} 308 309#ifndef MINIMALISTIC 310static int 311getdevlist(struct cam_device *device) 312{ 313 union ccb *ccb; 314 char status[32]; 315 int error = 0; 316 317 ccb = cam_getccb(device); 318 319 ccb->ccb_h.func_code = XPT_GDEVLIST; 320 ccb->ccb_h.flags = CAM_DIR_NONE; 321 ccb->ccb_h.retry_count = 1; 322 ccb->cgdl.index = 0; 323 ccb->cgdl.status = CAM_GDEVLIST_MORE_DEVS; 324 while (ccb->cgdl.status == CAM_GDEVLIST_MORE_DEVS) { 325 if (cam_send_ccb(device, ccb) < 0) { 326 perror("error getting device list"); 327 cam_freeccb(ccb); 328 return(1); 329 } 330 331 status[0] = '\0'; 332 333 switch (ccb->cgdl.status) { 334 case CAM_GDEVLIST_MORE_DEVS: 335 strcpy(status, "MORE"); 336 break; 337 case CAM_GDEVLIST_LAST_DEVICE: 338 strcpy(status, "LAST"); 339 break; 340 case CAM_GDEVLIST_LIST_CHANGED: 341 strcpy(status, "CHANGED"); 342 break; 343 case CAM_GDEVLIST_ERROR: 344 strcpy(status, "ERROR"); 345 error = 1; 346 break; 347 } 348 349 fprintf(stdout, "%s%d: generation: %d index: %d status: %s\n", 350 ccb->cgdl.periph_name, 351 ccb->cgdl.unit_number, 352 ccb->cgdl.generation, 353 ccb->cgdl.index, 354 status); 355 356 /* 357 * If the list has changed, we need to start over from the 358 * beginning. 359 */ 360 if (ccb->cgdl.status == CAM_GDEVLIST_LIST_CHANGED) 361 ccb->cgdl.index = 0; 362 } 363 364 cam_freeccb(ccb); 365 366 return(error); 367} 368#endif /* MINIMALISTIC */ 369 370static int 371getdevtree(void) 372{ 373 union ccb ccb; 374 int bufsize, fd; 375 unsigned int i; 376 int need_close = 0; 377 int error = 0; 378 int skip_device = 0; 379 380 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 381 warn("couldn't open %s", XPT_DEVICE); 382 return(1); 383 } 384 385 bzero(&ccb, sizeof(union ccb)); 386 387 ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 388 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 389 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 390 391 ccb.ccb_h.func_code = XPT_DEV_MATCH; 392 bufsize = sizeof(struct dev_match_result) * 100; 393 ccb.cdm.match_buf_len = bufsize; 394 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 395 if (ccb.cdm.matches == NULL) { 396 warnx("can't malloc memory for matches"); 397 close(fd); 398 return(1); 399 } 400 ccb.cdm.num_matches = 0; 401 402 /* 403 * We fetch all nodes, since we display most of them in the default 404 * case, and all in the verbose case. 405 */ 406 ccb.cdm.num_patterns = 0; 407 ccb.cdm.pattern_buf_len = 0; 408 409 /* 410 * We do the ioctl multiple times if necessary, in case there are 411 * more than 100 nodes in the EDT. 412 */ 413 do { 414 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 415 warn("error sending CAMIOCOMMAND ioctl"); 416 error = 1; 417 break; 418 } 419 420 if ((ccb.ccb_h.status != CAM_REQ_CMP) 421 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 422 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 423 warnx("got CAM error %#x, CDM error %d\n", 424 ccb.ccb_h.status, ccb.cdm.status); 425 error = 1; 426 break; 427 } 428 429 for (i = 0; i < ccb.cdm.num_matches; i++) { 430 switch (ccb.cdm.matches[i].type) { 431 case DEV_MATCH_BUS: { 432 struct bus_match_result *bus_result; 433 434 /* 435 * Only print the bus information if the 436 * user turns on the verbose flag. 437 */ 438 if ((arglist & CAM_ARG_VERBOSE) == 0) 439 break; 440 441 bus_result = 442 &ccb.cdm.matches[i].result.bus_result; 443 444 if (need_close) { 445 fprintf(stdout, ")\n"); 446 need_close = 0; 447 } 448 449 fprintf(stdout, "scbus%d on %s%d bus %d:\n", 450 bus_result->path_id, 451 bus_result->dev_name, 452 bus_result->unit_number, 453 bus_result->bus_id); 454 break; 455 } 456 case DEV_MATCH_DEVICE: { 457 struct device_match_result *dev_result; 458 char vendor[16], product[48], revision[16]; 459 char tmpstr[256]; 460 461 dev_result = 462 &ccb.cdm.matches[i].result.device_result; 463 464 if ((dev_result->flags 465 & DEV_RESULT_UNCONFIGURED) 466 && ((arglist & CAM_ARG_VERBOSE) == 0)) { 467 skip_device = 1; 468 break; 469 } else 470 skip_device = 0; 471 472 if (dev_result->protocol == PROTO_SCSI) { 473 cam_strvis(vendor, dev_result->inq_data.vendor, 474 sizeof(dev_result->inq_data.vendor), 475 sizeof(vendor)); 476 cam_strvis(product, 477 dev_result->inq_data.product, 478 sizeof(dev_result->inq_data.product), 479 sizeof(product)); 480 cam_strvis(revision, 481 dev_result->inq_data.revision, 482 sizeof(dev_result->inq_data.revision), 483 sizeof(revision)); 484 sprintf(tmpstr, "<%s %s %s>", vendor, product, 485 revision); 486 } else if (dev_result->protocol == PROTO_ATA || 487 dev_result->protocol == PROTO_SATAPM) { 488 cam_strvis(product, 489 dev_result->ident_data.model, 490 sizeof(dev_result->ident_data.model), 491 sizeof(product)); 492 cam_strvis(revision, 493 dev_result->ident_data.revision, 494 sizeof(dev_result->ident_data.revision), 495 sizeof(revision)); 496 sprintf(tmpstr, "<%s %s>", product, 497 revision); 498 } else { 499 sprintf(tmpstr, "<>"); 500 } 501 if (need_close) { 502 fprintf(stdout, ")\n"); 503 need_close = 0; 504 } 505 506 fprintf(stdout, "%-33s at scbus%d " 507 "target %d lun %d (", 508 tmpstr, 509 dev_result->path_id, 510 dev_result->target_id, 511 dev_result->target_lun); 512 513 need_close = 1; 514 515 break; 516 } 517 case DEV_MATCH_PERIPH: { 518 struct periph_match_result *periph_result; 519 520 periph_result = 521 &ccb.cdm.matches[i].result.periph_result; 522 523 if (skip_device != 0) 524 break; 525 526 if (need_close > 1) 527 fprintf(stdout, ","); 528 529 fprintf(stdout, "%s%d", 530 periph_result->periph_name, 531 periph_result->unit_number); 532 533 need_close++; 534 break; 535 } 536 default: 537 fprintf(stdout, "unknown match type\n"); 538 break; 539 } 540 } 541 542 } while ((ccb.ccb_h.status == CAM_REQ_CMP) 543 && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 544 545 if (need_close) 546 fprintf(stdout, ")\n"); 547 548 close(fd); 549 550 return(error); 551} 552 553#ifndef MINIMALISTIC 554static int 555testunitready(struct cam_device *device, int retry_count, int timeout, 556 int quiet) 557{ 558 int error = 0; 559 union ccb *ccb; 560 561 ccb = cam_getccb(device); 562 563 scsi_test_unit_ready(&ccb->csio, 564 /* retries */ retry_count, 565 /* cbfcnp */ NULL, 566 /* tag_action */ MSG_SIMPLE_Q_TAG, 567 /* sense_len */ SSD_FULL_SIZE, 568 /* timeout */ timeout ? timeout : 5000); 569 570 /* Disable freezing the device queue */ 571 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 572 573 if (arglist & CAM_ARG_ERR_RECOVER) 574 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 575 576 if (cam_send_ccb(device, ccb) < 0) { 577 if (quiet == 0) 578 perror("error sending test unit ready"); 579 580 if (arglist & CAM_ARG_VERBOSE) { 581 cam_error_print(device, ccb, CAM_ESF_ALL, 582 CAM_EPF_ALL, stderr); 583 } 584 585 cam_freeccb(ccb); 586 return(1); 587 } 588 589 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 590 if (quiet == 0) 591 fprintf(stdout, "Unit is ready\n"); 592 } else { 593 if (quiet == 0) 594 fprintf(stdout, "Unit is not ready\n"); 595 error = 1; 596 597 if (arglist & CAM_ARG_VERBOSE) { 598 cam_error_print(device, ccb, CAM_ESF_ALL, 599 CAM_EPF_ALL, stderr); 600 } 601 } 602 603 cam_freeccb(ccb); 604 605 return(error); 606} 607 608static int 609scsistart(struct cam_device *device, int startstop, int loadeject, 610 int retry_count, int timeout) 611{ 612 union ccb *ccb; 613 int error = 0; 614 615 ccb = cam_getccb(device); 616 617 /* 618 * If we're stopping, send an ordered tag so the drive in question 619 * will finish any previously queued writes before stopping. If 620 * the device isn't capable of tagged queueing, or if tagged 621 * queueing is turned off, the tag action is a no-op. 622 */ 623 scsi_start_stop(&ccb->csio, 624 /* retries */ retry_count, 625 /* cbfcnp */ NULL, 626 /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG : 627 MSG_ORDERED_Q_TAG, 628 /* start/stop */ startstop, 629 /* load_eject */ loadeject, 630 /* immediate */ 0, 631 /* sense_len */ SSD_FULL_SIZE, 632 /* timeout */ timeout ? timeout : 120000); 633 634 /* Disable freezing the device queue */ 635 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 636 637 if (arglist & CAM_ARG_ERR_RECOVER) 638 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 639 640 if (cam_send_ccb(device, ccb) < 0) { 641 perror("error sending start unit"); 642 643 if (arglist & CAM_ARG_VERBOSE) { 644 cam_error_print(device, ccb, CAM_ESF_ALL, 645 CAM_EPF_ALL, stderr); 646 } 647 648 cam_freeccb(ccb); 649 return(1); 650 } 651 652 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 653 if (startstop) { 654 fprintf(stdout, "Unit started successfully"); 655 if (loadeject) 656 fprintf(stdout,", Media loaded\n"); 657 else 658 fprintf(stdout,"\n"); 659 } else { 660 fprintf(stdout, "Unit stopped successfully"); 661 if (loadeject) 662 fprintf(stdout, ", Media ejected\n"); 663 else 664 fprintf(stdout, "\n"); 665 } 666 else { 667 error = 1; 668 if (startstop) 669 fprintf(stdout, 670 "Error received from start unit command\n"); 671 else 672 fprintf(stdout, 673 "Error received from stop unit command\n"); 674 675 if (arglist & CAM_ARG_VERBOSE) { 676 cam_error_print(device, ccb, CAM_ESF_ALL, 677 CAM_EPF_ALL, stderr); 678 } 679 } 680 681 cam_freeccb(ccb); 682 683 return(error); 684} 685 686static int 687scsidoinquiry(struct cam_device *device, int argc, char **argv, 688 char *combinedopt, int retry_count, int timeout) 689{ 690 int c; 691 int error = 0; 692 693 while ((c = getopt(argc, argv, combinedopt)) != -1) { 694 switch(c) { 695 case 'D': 696 arglist |= CAM_ARG_GET_STDINQ; 697 break; 698 case 'R': 699 arglist |= CAM_ARG_GET_XFERRATE; 700 break; 701 case 'S': 702 arglist |= CAM_ARG_GET_SERIAL; 703 break; 704 default: 705 break; 706 } 707 } 708 709 /* 710 * If the user didn't specify any inquiry options, he wants all of 711 * them. 712 */ 713 if ((arglist & CAM_ARG_INQ_MASK) == 0) 714 arglist |= CAM_ARG_INQ_MASK; 715 716 if (arglist & CAM_ARG_GET_STDINQ) 717 error = scsiinquiry(device, retry_count, timeout); 718 719 if (error != 0) 720 return(error); 721 722 if (arglist & CAM_ARG_GET_SERIAL) 723 scsiserial(device, retry_count, timeout); 724 725 if (error != 0) 726 return(error); 727 728 if (arglist & CAM_ARG_GET_XFERRATE) 729 error = camxferrate(device); 730 731 return(error); 732} 733 734static int 735scsiinquiry(struct cam_device *device, int retry_count, int timeout) 736{ 737 union ccb *ccb; 738 struct scsi_inquiry_data *inq_buf; 739 int error = 0; 740 741 ccb = cam_getccb(device); 742 743 if (ccb == NULL) { 744 warnx("couldn't allocate CCB"); 745 return(1); 746 } 747 748 /* cam_getccb cleans up the header, caller has to zero the payload */ 749 bzero(&(&ccb->ccb_h)[1], 750 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 751 752 inq_buf = (struct scsi_inquiry_data *)malloc( 753 sizeof(struct scsi_inquiry_data)); 754 755 if (inq_buf == NULL) { 756 cam_freeccb(ccb); 757 warnx("can't malloc memory for inquiry\n"); 758 return(1); 759 } 760 bzero(inq_buf, sizeof(*inq_buf)); 761 762 /* 763 * Note that although the size of the inquiry buffer is the full 764 * 256 bytes specified in the SCSI spec, we only tell the device 765 * that we have allocated SHORT_INQUIRY_LENGTH bytes. There are 766 * two reasons for this: 767 * 768 * - The SCSI spec says that when a length field is only 1 byte, 769 * a value of 0 will be interpreted as 256. Therefore 770 * scsi_inquiry() will convert an inq_len (which is passed in as 771 * a u_int32_t, but the field in the CDB is only 1 byte) of 256 772 * to 0. Evidently, very few devices meet the spec in that 773 * regard. Some devices, like many Seagate disks, take the 0 as 774 * 0, and don't return any data. One Pioneer DVD-R drive 775 * returns more data than the command asked for. 776 * 777 * So, since there are numerous devices that just don't work 778 * right with the full inquiry size, we don't send the full size. 779 * 780 * - The second reason not to use the full inquiry data length is 781 * that we don't need it here. The only reason we issue a 782 * standard inquiry is to get the vendor name, device name, 783 * and revision so scsi_print_inquiry() can print them. 784 * 785 * If, at some point in the future, more inquiry data is needed for 786 * some reason, this code should use a procedure similar to the 787 * probe code. i.e., issue a short inquiry, and determine from 788 * the additional length passed back from the device how much 789 * inquiry data the device supports. Once the amount the device 790 * supports is determined, issue an inquiry for that amount and no 791 * more. 792 * 793 * KDM, 2/18/2000 794 */ 795 scsi_inquiry(&ccb->csio, 796 /* retries */ retry_count, 797 /* cbfcnp */ NULL, 798 /* tag_action */ MSG_SIMPLE_Q_TAG, 799 /* inq_buf */ (u_int8_t *)inq_buf, 800 /* inq_len */ SHORT_INQUIRY_LENGTH, 801 /* evpd */ 0, 802 /* page_code */ 0, 803 /* sense_len */ SSD_FULL_SIZE, 804 /* timeout */ timeout ? timeout : 5000); 805 806 /* Disable freezing the device queue */ 807 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 808 809 if (arglist & CAM_ARG_ERR_RECOVER) 810 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 811 812 if (cam_send_ccb(device, ccb) < 0) { 813 perror("error sending SCSI inquiry"); 814 815 if (arglist & CAM_ARG_VERBOSE) { 816 cam_error_print(device, ccb, CAM_ESF_ALL, 817 CAM_EPF_ALL, stderr); 818 } 819 820 cam_freeccb(ccb); 821 return(1); 822 } 823 824 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 825 error = 1; 826 827 if (arglist & CAM_ARG_VERBOSE) { 828 cam_error_print(device, ccb, CAM_ESF_ALL, 829 CAM_EPF_ALL, stderr); 830 } 831 } 832 833 cam_freeccb(ccb); 834 835 if (error != 0) { 836 free(inq_buf); 837 return(error); 838 } 839 840 fprintf(stdout, "%s%d: ", device->device_name, 841 device->dev_unit_num); 842 scsi_print_inquiry(inq_buf); 843 844 free(inq_buf); 845 846 return(0); 847} 848 849static int 850scsiserial(struct cam_device *device, int retry_count, int timeout) 851{ 852 union ccb *ccb; 853 struct scsi_vpd_unit_serial_number *serial_buf; 854 char serial_num[SVPD_SERIAL_NUM_SIZE + 1]; 855 int error = 0; 856 857 ccb = cam_getccb(device); 858 859 if (ccb == NULL) { 860 warnx("couldn't allocate CCB"); 861 return(1); 862 } 863 864 /* cam_getccb cleans up the header, caller has to zero the payload */ 865 bzero(&(&ccb->ccb_h)[1], 866 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 867 868 serial_buf = (struct scsi_vpd_unit_serial_number *) 869 malloc(sizeof(*serial_buf)); 870 871 if (serial_buf == NULL) { 872 cam_freeccb(ccb); 873 warnx("can't malloc memory for serial number"); 874 return(1); 875 } 876 877 scsi_inquiry(&ccb->csio, 878 /*retries*/ retry_count, 879 /*cbfcnp*/ NULL, 880 /* tag_action */ MSG_SIMPLE_Q_TAG, 881 /* inq_buf */ (u_int8_t *)serial_buf, 882 /* inq_len */ sizeof(*serial_buf), 883 /* evpd */ 1, 884 /* page_code */ SVPD_UNIT_SERIAL_NUMBER, 885 /* sense_len */ SSD_FULL_SIZE, 886 /* timeout */ timeout ? timeout : 5000); 887 888 /* Disable freezing the device queue */ 889 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 890 891 if (arglist & CAM_ARG_ERR_RECOVER) 892 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 893 894 if (cam_send_ccb(device, ccb) < 0) { 895 warn("error getting serial number"); 896 897 if (arglist & CAM_ARG_VERBOSE) { 898 cam_error_print(device, ccb, CAM_ESF_ALL, 899 CAM_EPF_ALL, stderr); 900 } 901 902 cam_freeccb(ccb); 903 free(serial_buf); 904 return(1); 905 } 906 907 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 908 error = 1; 909 910 if (arglist & CAM_ARG_VERBOSE) { 911 cam_error_print(device, ccb, CAM_ESF_ALL, 912 CAM_EPF_ALL, stderr); 913 } 914 } 915 916 cam_freeccb(ccb); 917 918 if (error != 0) { 919 free(serial_buf); 920 return(error); 921 } 922 923 bcopy(serial_buf->serial_num, serial_num, serial_buf->length); 924 serial_num[serial_buf->length] = '\0'; 925 926 if ((arglist & CAM_ARG_GET_STDINQ) 927 || (arglist & CAM_ARG_GET_XFERRATE)) 928 fprintf(stdout, "%s%d: Serial Number ", 929 device->device_name, device->dev_unit_num); 930 931 fprintf(stdout, "%.60s\n", serial_num); 932 933 free(serial_buf); 934 935 return(0); 936} 937 938static int 939camxferrate(struct cam_device *device) 940{ 941 struct ccb_pathinq cpi; 942 u_int32_t freq = 0; 943 u_int32_t speed = 0; 944 union ccb *ccb; 945 u_int mb; 946 int retval = 0; 947 948 if ((retval = get_cpi(device, &cpi)) != 0) 949 return (1); 950 951 ccb = cam_getccb(device); 952 953 if (ccb == NULL) { 954 warnx("couldn't allocate CCB"); 955 return(1); 956 } 957 958 bzero(&(&ccb->ccb_h)[1], 959 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr)); 960 961 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 962 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS; 963 964 if (((retval = cam_send_ccb(device, ccb)) < 0) 965 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 966 const char error_string[] = "error getting transfer settings"; 967 968 if (retval < 0) 969 warn(error_string); 970 else 971 warnx(error_string); 972 973 if (arglist & CAM_ARG_VERBOSE) 974 cam_error_print(device, ccb, CAM_ESF_ALL, 975 CAM_EPF_ALL, stderr); 976 977 retval = 1; 978 979 goto xferrate_bailout; 980 981 } 982 983 speed = cpi.base_transfer_speed; 984 freq = 0; 985 if (ccb->cts.transport == XPORT_SPI) { 986 struct ccb_trans_settings_spi *spi = 987 &ccb->cts.xport_specific.spi; 988 989 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 990 freq = scsi_calc_syncsrate(spi->sync_period); 991 speed = freq; 992 } 993 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 994 speed *= (0x01 << spi->bus_width); 995 } 996 } else if (ccb->cts.transport == XPORT_FC) { 997 struct ccb_trans_settings_fc *fc = 998 &ccb->cts.xport_specific.fc; 999 1000 if (fc->valid & CTS_FC_VALID_SPEED) 1001 speed = fc->bitrate; 1002 } else if (ccb->cts.transport == XPORT_SAS) { 1003 struct ccb_trans_settings_sas *sas = 1004 &ccb->cts.xport_specific.sas; 1005 1006 if (sas->valid & CTS_SAS_VALID_SPEED) 1007 speed = sas->bitrate; 1008 } else if (ccb->cts.transport == XPORT_ATA) { 1009 struct ccb_trans_settings_ata *ata = 1010 &ccb->cts.xport_specific.ata; 1011 1012 if (ata->valid & CTS_ATA_VALID_MODE) 1013 speed = ata_mode2speed(ata->mode); 1014 } else if (ccb->cts.transport == XPORT_SATA) { 1015 struct ccb_trans_settings_sata *sata = 1016 &ccb->cts.xport_specific.sata; 1017 1018 if (sata->valid & CTS_SATA_VALID_REVISION) 1019 speed = ata_revision2speed(sata->revision); 1020 } 1021 1022 mb = speed / 1000; 1023 if (mb > 0) { 1024 fprintf(stdout, "%s%d: %d.%03dMB/s transfers", 1025 device->device_name, device->dev_unit_num, 1026 mb, speed % 1000); 1027 } else { 1028 fprintf(stdout, "%s%d: %dKB/s transfers", 1029 device->device_name, device->dev_unit_num, 1030 speed); 1031 } 1032 1033 if (ccb->cts.transport == XPORT_SPI) { 1034 struct ccb_trans_settings_spi *spi = 1035 &ccb->cts.xport_specific.spi; 1036 1037 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1038 && (spi->sync_offset != 0)) 1039 fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000, 1040 freq % 1000, spi->sync_offset); 1041 1042 if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) 1043 && (spi->bus_width > 0)) { 1044 if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1045 && (spi->sync_offset != 0)) { 1046 fprintf(stdout, ", "); 1047 } else { 1048 fprintf(stdout, " ("); 1049 } 1050 fprintf(stdout, "%dbit)", 8 * (0x01 << spi->bus_width)); 1051 } else if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) 1052 && (spi->sync_offset != 0)) { 1053 fprintf(stdout, ")"); 1054 } 1055 } else if (ccb->cts.transport == XPORT_ATA) { 1056 struct ccb_trans_settings_ata *ata = 1057 &ccb->cts.xport_specific.ata; 1058 1059 printf(" ("); 1060 if (ata->valid & CTS_ATA_VALID_MODE) 1061 printf("%s, ", ata_mode2string(ata->mode)); 1062 if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0) 1063 printf("ATAPI %dbytes, ", ata->atapi); 1064 if (ata->valid & CTS_ATA_VALID_BYTECOUNT) 1065 printf("PIO %dbytes", ata->bytecount); 1066 printf(")"); 1067 } else if (ccb->cts.transport == XPORT_SATA) { 1068 struct ccb_trans_settings_sata *sata = 1069 &ccb->cts.xport_specific.sata; 1070 1071 printf(" ("); 1072 if (sata->valid & CTS_SATA_VALID_REVISION) 1073 printf("SATA %d.x, ", sata->revision); 1074 else 1075 printf("SATA, "); 1076 if (sata->valid & CTS_SATA_VALID_MODE) 1077 printf("%s, ", ata_mode2string(sata->mode)); 1078 if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0) 1079 printf("ATAPI %dbytes, ", sata->atapi); 1080 if (sata->valid & CTS_SATA_VALID_BYTECOUNT) 1081 printf("PIO %dbytes", sata->bytecount); 1082 printf(")"); 1083 } 1084 1085 if (ccb->cts.protocol == PROTO_SCSI) { 1086 struct ccb_trans_settings_scsi *scsi = 1087 &ccb->cts.proto_specific.scsi; 1088 if (scsi->valid & CTS_SCSI_VALID_TQ) { 1089 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) { 1090 fprintf(stdout, ", Command Queueing Enabled"); 1091 } 1092 } 1093 } 1094 1095 fprintf(stdout, "\n"); 1096 1097xferrate_bailout: 1098 1099 cam_freeccb(ccb); 1100 1101 return(retval); 1102} 1103 1104static void 1105atacapprint(struct ata_params *parm) 1106{ 1107 u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | 1108 ((u_int32_t)parm->lba_size_2 << 16); 1109 1110 u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | 1111 ((u_int64_t)parm->lba_size48_2 << 16) | 1112 ((u_int64_t)parm->lba_size48_3 << 32) | 1113 ((u_int64_t)parm->lba_size48_4 << 48); 1114 1115 printf("\n"); 1116 printf("protocol "); 1117 printf("ATA/ATAPI-%d", ata_version(parm->version_major)); 1118 if (parm->satacapabilities && parm->satacapabilities != 0xffff) { 1119 if (parm->satacapabilities & ATA_SATA_GEN3) 1120 printf(" SATA 3.x\n"); 1121 else if (parm->satacapabilities & ATA_SATA_GEN2) 1122 printf(" SATA 2.x\n"); 1123 else if (parm->satacapabilities & ATA_SATA_GEN1) 1124 printf(" SATA 1.x\n"); 1125 else 1126 printf(" SATA\n"); 1127 } 1128 else 1129 printf("\n"); 1130 printf("device model %.40s\n", parm->model); 1131 printf("firmware revision %.8s\n", parm->revision); 1132 printf("serial number %.20s\n", parm->serial); 1133 if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) { 1134 printf("WWN %02x%02x%02x%02x\n", 1135 parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]); 1136 } 1137 if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) { 1138 printf("media serial number %.30s\n", 1139 parm->media_serial); 1140 } 1141 1142 printf("cylinders %d\n", parm->cylinders); 1143 printf("heads %d\n", parm->heads); 1144 printf("sectors/track %d\n", parm->sectors); 1145 printf("sector size logical %u, physical %lu, offset %lu\n", 1146 ata_logical_sector_size(parm), 1147 (unsigned long)ata_physical_sector_size(parm), 1148 (unsigned long)ata_logical_sector_offset(parm)); 1149 1150 if (parm->config == ATA_PROTO_CFA || 1151 (parm->support.command2 & ATA_SUPPORT_CFA)) 1152 printf("CFA supported\n"); 1153 1154 printf("LBA%ssupported ", 1155 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not "); 1156 if (lbasize) 1157 printf("%d sectors\n", lbasize); 1158 else 1159 printf("\n"); 1160 1161 printf("LBA48%ssupported ", 1162 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not "); 1163 if (lbasize48) 1164 printf("%ju sectors\n", (uintmax_t)lbasize48); 1165 else 1166 printf("\n"); 1167 1168 printf("PIO supported PIO"); 1169 switch (ata_max_pmode(parm)) { 1170 case ATA_PIO4: 1171 printf("4"); 1172 break; 1173 case ATA_PIO3: 1174 printf("3"); 1175 break; 1176 case ATA_PIO2: 1177 printf("2"); 1178 break; 1179 case ATA_PIO1: 1180 printf("1"); 1181 break; 1182 default: 1183 printf("0"); 1184 } 1185 if ((parm->capabilities1 & ATA_SUPPORT_IORDY) == 0) 1186 printf(" w/o IORDY"); 1187 printf("\n"); 1188 1189 printf("DMA%ssupported ", 1190 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not "); 1191 if (parm->capabilities1 & ATA_SUPPORT_DMA) { 1192 if (parm->mwdmamodes & 0xff) { 1193 printf("WDMA"); 1194 if (parm->mwdmamodes & 0x04) 1195 printf("2"); 1196 else if (parm->mwdmamodes & 0x02) 1197 printf("1"); 1198 else if (parm->mwdmamodes & 0x01) 1199 printf("0"); 1200 printf(" "); 1201 } 1202 if ((parm->atavalid & ATA_FLAG_88) && 1203 (parm->udmamodes & 0xff)) { 1204 printf("UDMA"); 1205 if (parm->udmamodes & 0x40) 1206 printf("6"); 1207 else if (parm->udmamodes & 0x20) 1208 printf("5"); 1209 else if (parm->udmamodes & 0x10) 1210 printf("4"); 1211 else if (parm->udmamodes & 0x08) 1212 printf("3"); 1213 else if (parm->udmamodes & 0x04) 1214 printf("2"); 1215 else if (parm->udmamodes & 0x02) 1216 printf("1"); 1217 else if (parm->udmamodes & 0x01) 1218 printf("0"); 1219 printf(" "); 1220 } 1221 } 1222 printf("\n"); 1223 1224 if (parm->media_rotation_rate == 1) { 1225 printf("media RPM non-rotating\n"); 1226 } else if (parm->media_rotation_rate >= 0x0401 && 1227 parm->media_rotation_rate <= 0xFFFE) { 1228 printf("media RPM %d\n", 1229 parm->media_rotation_rate); 1230 } 1231 1232 printf("\nFeature " 1233 "Support Enabled Value Vendor\n"); 1234 printf("read ahead %s %s\n", 1235 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no", 1236 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no"); 1237 printf("write cache %s %s\n", 1238 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no", 1239 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no"); 1240 printf("flush cache %s %s\n", 1241 parm->support.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no", 1242 parm->enabled.command2 & ATA_SUPPORT_FLUSHCACHE ? "yes" : "no"); 1243 printf("overlap %s\n", 1244 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? "yes" : "no"); 1245 printf("Tagged Command Queuing (TCQ) %s %s", 1246 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no", 1247 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no"); 1248 if (parm->support.command2 & ATA_SUPPORT_QUEUED) { 1249 printf(" %d tags\n", 1250 ATA_QUEUE_LEN(parm->queue) + 1); 1251 } else 1252 printf("\n"); 1253 printf("Native Command Queuing (NCQ) "); 1254 if (parm->satacapabilities != 0xffff && 1255 (parm->satacapabilities & ATA_SUPPORT_NCQ)) { 1256 printf("yes %d tags\n", 1257 ATA_QUEUE_LEN(parm->queue) + 1); 1258 } else 1259 printf("no\n"); 1260 printf("SMART %s %s\n", 1261 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no", 1262 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no"); 1263 printf("microcode download %s %s\n", 1264 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no", 1265 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no"); 1266 printf("security %s %s\n", 1267 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no", 1268 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no"); 1269 printf("power management %s %s\n", 1270 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no", 1271 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no"); 1272 printf("advanced power management %s %s", 1273 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no", 1274 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no"); 1275 if (parm->support.command2 & ATA_SUPPORT_APM) { 1276 printf(" %d/0x%02X\n", 1277 parm->apm_value, parm->apm_value); 1278 } else 1279 printf("\n"); 1280 printf("automatic acoustic management %s %s", 1281 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no", 1282 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no"); 1283 if (parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC) { 1284 printf(" %d/0x%02X %d/0x%02X\n", 1285 ATA_ACOUSTIC_CURRENT(parm->acoustic), 1286 ATA_ACOUSTIC_CURRENT(parm->acoustic), 1287 ATA_ACOUSTIC_VENDOR(parm->acoustic), 1288 ATA_ACOUSTIC_VENDOR(parm->acoustic)); 1289 } else 1290 printf("\n"); 1291 printf("media status notification %s %s\n", 1292 parm->support.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no", 1293 parm->enabled.command2 & ATA_SUPPORT_NOTIFY ? "yes" : "no"); 1294 printf("power-up in Standby %s %s\n", 1295 parm->support.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no", 1296 parm->enabled.command2 & ATA_SUPPORT_STANDBY ? "yes" : "no"); 1297 printf("write-read-verify %s %s", 1298 parm->support2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no", 1299 parm->enabled2 & ATA_SUPPORT_WRITEREADVERIFY ? "yes" : "no"); 1300 if (parm->support2 & ATA_SUPPORT_WRITEREADVERIFY) { 1301 printf(" %d/0x%x\n", 1302 parm->wrv_mode, parm->wrv_mode); 1303 } else 1304 printf("\n"); 1305 printf("unload %s %s\n", 1306 parm->support.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no", 1307 parm->enabled.extension & ATA_SUPPORT_UNLOAD ? "yes" : "no"); 1308 printf("free-fall %s %s\n", 1309 parm->support2 & ATA_SUPPORT_FREEFALL ? "yes" : "no", 1310 parm->enabled2 & ATA_SUPPORT_FREEFALL ? "yes" : "no"); 1311 printf("data set management (TRIM) %s\n", 1312 parm->support_dsm & ATA_SUPPORT_DSM_TRIM ? "yes" : "no"); 1313} 1314 1315static int 1316ataidentify(struct cam_device *device, int retry_count, int timeout) 1317{ 1318 union ccb *ccb; 1319 struct ata_params *ident_buf; 1320 struct ccb_getdev cgd; 1321 u_int i, error = 0; 1322 int16_t *ptr; 1323 1324 if (get_cgd(device, &cgd) != 0) { 1325 warnx("couldn't get CGD"); 1326 return(1); 1327 } 1328 ccb = cam_getccb(device); 1329 1330 if (ccb == NULL) { 1331 warnx("couldn't allocate CCB"); 1332 return(1); 1333 } 1334 1335 /* cam_getccb cleans up the header, caller has to zero the payload */ 1336 bzero(&(&ccb->ccb_h)[1], 1337 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); 1338 1339 ptr = (uint16_t *)malloc(sizeof(struct ata_params)); 1340 1341 if (ptr == NULL) { 1342 cam_freeccb(ccb); 1343 warnx("can't malloc memory for identify\n"); 1344 return(1); 1345 } 1346 bzero(ptr, sizeof(struct ata_params)); 1347 1348 cam_fill_ataio(&ccb->ataio, 1349 retry_count, 1350 NULL, 1351 /*flags*/CAM_DIR_IN, 1352 MSG_SIMPLE_Q_TAG, 1353 /*data_ptr*/(u_int8_t *)ptr, 1354 /*dxfer_len*/sizeof(struct ata_params), 1355 timeout ? timeout : 30 * 1000); 1356 if (cgd.protocol == PROTO_ATA) 1357 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0); 1358 else 1359 ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); 1360 1361 /* Disable freezing the device queue */ 1362 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 1363 1364 if (arglist & CAM_ARG_ERR_RECOVER) 1365 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 1366 1367 if (cam_send_ccb(device, ccb) < 0) { 1368 perror("error sending ATA identify"); 1369 1370 if (arglist & CAM_ARG_VERBOSE) { 1371 cam_error_print(device, ccb, CAM_ESF_ALL, 1372 CAM_EPF_ALL, stderr); 1373 } 1374 1375 free(ptr); 1376 cam_freeccb(ccb); 1377 return(1); 1378 } 1379 1380 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1381 error = 1; 1382 1383 if (arglist & CAM_ARG_VERBOSE) { 1384 cam_error_print(device, ccb, CAM_ESF_ALL, 1385 CAM_EPF_ALL, stderr); 1386 } 1387 } 1388 1389 cam_freeccb(ccb); 1390 1391 if (error != 0) { 1392 free(ptr); 1393 return(error); 1394 } 1395 1396 for (i = 0; i < sizeof(struct ata_params) / 2; i++) 1397 ptr[i] = le16toh(ptr[i]); 1398 if (arglist & CAM_ARG_VERBOSE) { 1399 fprintf(stdout, "%s%d: Raw identify data:\n", 1400 device->device_name, device->dev_unit_num); 1401 for (i = 0; i < sizeof(struct ata_params) / 2; i++) { 1402 if ((i % 8) == 0) 1403 fprintf(stdout, " %3d: ", i); 1404 fprintf(stdout, "%04x ", (uint16_t)ptr[i]); 1405 if ((i % 8) == 7) 1406 fprintf(stdout, "\n"); 1407 } 1408 } 1409 ident_buf = (struct ata_params *)ptr; 1410 if (strncmp(ident_buf->model, "FX", 2) && 1411 strncmp(ident_buf->model, "NEC", 3) && 1412 strncmp(ident_buf->model, "Pioneer", 7) && 1413 strncmp(ident_buf->model, "SHARP", 5)) { 1414 ata_bswap(ident_buf->model, sizeof(ident_buf->model)); 1415 ata_bswap(ident_buf->revision, sizeof(ident_buf->revision)); 1416 ata_bswap(ident_buf->serial, sizeof(ident_buf->serial)); 1417 ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial)); 1418 } 1419 ata_btrim(ident_buf->model, sizeof(ident_buf->model)); 1420 ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model)); 1421 ata_btrim(ident_buf->revision, sizeof(ident_buf->revision)); 1422 ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision)); 1423 ata_btrim(ident_buf->serial, sizeof(ident_buf->serial)); 1424 ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial)); 1425 ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial)); 1426 ata_bpack(ident_buf->media_serial, ident_buf->media_serial, 1427 sizeof(ident_buf->media_serial)); 1428 1429 fprintf(stdout, "%s%d: ", device->device_name, 1430 device->dev_unit_num); 1431 ata_print_ident(ident_buf); 1432 camxferrate(device); 1433 atacapprint(ident_buf); 1434 1435 free(ident_buf); 1436 1437 return(0); 1438} 1439#endif /* MINIMALISTIC */ 1440 1441/* 1442 * Parse out a bus, or a bus, target and lun in the following 1443 * format: 1444 * bus 1445 * bus:target 1446 * bus:target:lun 1447 * 1448 * Returns the number of parsed components, or 0. 1449 */ 1450static int 1451parse_btl(char *tstr, int *bus, int *target, int *lun, cam_argmask *arglst) 1452{ 1453 char *tmpstr; 1454 int convs = 0; 1455 1456 while (isspace(*tstr) && (*tstr != '\0')) 1457 tstr++; 1458 1459 tmpstr = (char *)strtok(tstr, ":"); 1460 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 1461 *bus = strtol(tmpstr, NULL, 0); 1462 *arglst |= CAM_ARG_BUS; 1463 convs++; 1464 tmpstr = (char *)strtok(NULL, ":"); 1465 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 1466 *target = strtol(tmpstr, NULL, 0); 1467 *arglst |= CAM_ARG_TARGET; 1468 convs++; 1469 tmpstr = (char *)strtok(NULL, ":"); 1470 if ((tmpstr != NULL) && (*tmpstr != '\0')) { 1471 *lun = strtol(tmpstr, NULL, 0); 1472 *arglst |= CAM_ARG_LUN; 1473 convs++; 1474 } 1475 } 1476 } 1477 1478 return convs; 1479} 1480 1481static int 1482dorescan_or_reset(int argc, char **argv, int rescan) 1483{ 1484 static const char must[] = 1485 "you must specify \"all\", a bus, or a bus:target:lun to %s"; 1486 int rv, error = 0; 1487 int bus = -1, target = -1, lun = -1; 1488 char *tstr; 1489 1490 if (argc < 3) { 1491 warnx(must, rescan? "rescan" : "reset"); 1492 return(1); 1493 } 1494 1495 tstr = argv[optind]; 1496 while (isspace(*tstr) && (*tstr != '\0')) 1497 tstr++; 1498 if (strncasecmp(tstr, "all", strlen("all")) == 0) 1499 arglist |= CAM_ARG_BUS; 1500 else { 1501 rv = parse_btl(argv[optind], &bus, &target, &lun, &arglist); 1502 if (rv != 1 && rv != 3) { 1503 warnx(must, rescan? "rescan" : "reset"); 1504 return(1); 1505 } 1506 } 1507 1508 if ((arglist & CAM_ARG_BUS) 1509 && (arglist & CAM_ARG_TARGET) 1510 && (arglist & CAM_ARG_LUN)) 1511 error = scanlun_or_reset_dev(bus, target, lun, rescan); 1512 else 1513 error = rescan_or_reset_bus(bus, rescan); 1514 1515 return(error); 1516} 1517 1518static int 1519rescan_or_reset_bus(int bus, int rescan) 1520{ 1521 union ccb ccb, matchccb; 1522 int fd, retval; 1523 int bufsize; 1524 1525 retval = 0; 1526 1527 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 1528 warnx("error opening transport layer device %s", XPT_DEVICE); 1529 warn("%s", XPT_DEVICE); 1530 return(1); 1531 } 1532 1533 if (bus != -1) { 1534 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : XPT_RESET_BUS; 1535 ccb.ccb_h.path_id = bus; 1536 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 1537 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 1538 ccb.crcn.flags = CAM_FLAG_NONE; 1539 1540 /* run this at a low priority */ 1541 ccb.ccb_h.pinfo.priority = 5; 1542 1543 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 1544 warn("CAMIOCOMMAND ioctl failed"); 1545 close(fd); 1546 return(1); 1547 } 1548 1549 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1550 fprintf(stdout, "%s of bus %d was successful\n", 1551 rescan ? "Re-scan" : "Reset", bus); 1552 } else { 1553 fprintf(stdout, "%s of bus %d returned error %#x\n", 1554 rescan ? "Re-scan" : "Reset", bus, 1555 ccb.ccb_h.status & CAM_STATUS_MASK); 1556 retval = 1; 1557 } 1558 1559 close(fd); 1560 return(retval); 1561 1562 } 1563 1564 1565 /* 1566 * The right way to handle this is to modify the xpt so that it can 1567 * handle a wildcarded bus in a rescan or reset CCB. At the moment 1568 * that isn't implemented, so instead we enumerate the busses and 1569 * send the rescan or reset to those busses in the case where the 1570 * given bus is -1 (wildcard). We don't send a rescan or reset 1571 * to the xpt bus; sending a rescan to the xpt bus is effectively a 1572 * no-op, sending a rescan to the xpt bus would result in a status of 1573 * CAM_REQ_INVALID. 1574 */ 1575 bzero(&(&matchccb.ccb_h)[1], 1576 sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr)); 1577 matchccb.ccb_h.func_code = XPT_DEV_MATCH; 1578 matchccb.ccb_h.path_id = CAM_BUS_WILDCARD; 1579 bufsize = sizeof(struct dev_match_result) * 20; 1580 matchccb.cdm.match_buf_len = bufsize; 1581 matchccb.cdm.matches=(struct dev_match_result *)malloc(bufsize); 1582 if (matchccb.cdm.matches == NULL) { 1583 warnx("can't malloc memory for matches"); 1584 retval = 1; 1585 goto bailout; 1586 } 1587 matchccb.cdm.num_matches = 0; 1588 1589 matchccb.cdm.num_patterns = 1; 1590 matchccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern); 1591 1592 matchccb.cdm.patterns = (struct dev_match_pattern *)malloc( 1593 matchccb.cdm.pattern_buf_len); 1594 if (matchccb.cdm.patterns == NULL) { 1595 warnx("can't malloc memory for patterns"); 1596 retval = 1; 1597 goto bailout; 1598 } 1599 matchccb.cdm.patterns[0].type = DEV_MATCH_BUS; 1600 matchccb.cdm.patterns[0].pattern.bus_pattern.flags = BUS_MATCH_ANY; 1601 1602 do { 1603 unsigned int i; 1604 1605 if (ioctl(fd, CAMIOCOMMAND, &matchccb) == -1) { 1606 warn("CAMIOCOMMAND ioctl failed"); 1607 retval = 1; 1608 goto bailout; 1609 } 1610 1611 if ((matchccb.ccb_h.status != CAM_REQ_CMP) 1612 || ((matchccb.cdm.status != CAM_DEV_MATCH_LAST) 1613 && (matchccb.cdm.status != CAM_DEV_MATCH_MORE))) { 1614 warnx("got CAM error %#x, CDM error %d\n", 1615 matchccb.ccb_h.status, matchccb.cdm.status); 1616 retval = 1; 1617 goto bailout; 1618 } 1619 1620 for (i = 0; i < matchccb.cdm.num_matches; i++) { 1621 struct bus_match_result *bus_result; 1622 1623 /* This shouldn't happen. */ 1624 if (matchccb.cdm.matches[i].type != DEV_MATCH_BUS) 1625 continue; 1626 1627 bus_result = &matchccb.cdm.matches[i].result.bus_result; 1628 1629 /* 1630 * We don't want to rescan or reset the xpt bus. 1631 * See above. 1632 */ 1633 if ((int)bus_result->path_id == -1) 1634 continue; 1635 1636 ccb.ccb_h.func_code = rescan ? XPT_SCAN_BUS : 1637 XPT_RESET_BUS; 1638 ccb.ccb_h.path_id = bus_result->path_id; 1639 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 1640 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 1641 ccb.crcn.flags = CAM_FLAG_NONE; 1642 1643 /* run this at a low priority */ 1644 ccb.ccb_h.pinfo.priority = 5; 1645 1646 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 1647 warn("CAMIOCOMMAND ioctl failed"); 1648 retval = 1; 1649 goto bailout; 1650 } 1651 1652 if ((ccb.ccb_h.status & CAM_STATUS_MASK) ==CAM_REQ_CMP){ 1653 fprintf(stdout, "%s of bus %d was successful\n", 1654 rescan? "Re-scan" : "Reset", 1655 bus_result->path_id); 1656 } else { 1657 /* 1658 * Don't bail out just yet, maybe the other 1659 * rescan or reset commands will complete 1660 * successfully. 1661 */ 1662 fprintf(stderr, "%s of bus %d returned error " 1663 "%#x\n", rescan? "Re-scan" : "Reset", 1664 bus_result->path_id, 1665 ccb.ccb_h.status & CAM_STATUS_MASK); 1666 retval = 1; 1667 } 1668 } 1669 } while ((matchccb.ccb_h.status == CAM_REQ_CMP) 1670 && (matchccb.cdm.status == CAM_DEV_MATCH_MORE)); 1671 1672bailout: 1673 1674 if (fd != -1) 1675 close(fd); 1676 1677 if (matchccb.cdm.patterns != NULL) 1678 free(matchccb.cdm.patterns); 1679 if (matchccb.cdm.matches != NULL) 1680 free(matchccb.cdm.matches); 1681 1682 return(retval); 1683} 1684 1685static int 1686scanlun_or_reset_dev(int bus, int target, int lun, int scan) 1687{ 1688 union ccb ccb; 1689 struct cam_device *device; 1690 int fd; 1691 1692 device = NULL; 1693 1694 if (bus < 0) { 1695 warnx("invalid bus number %d", bus); 1696 return(1); 1697 } 1698 1699 if (target < 0) { 1700 warnx("invalid target number %d", target); 1701 return(1); 1702 } 1703 1704 if (lun < 0) { 1705 warnx("invalid lun number %d", lun); 1706 return(1); 1707 } 1708 1709 fd = -1; 1710 1711 bzero(&ccb, sizeof(union ccb)); 1712 1713 if (scan) { 1714 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 1715 warnx("error opening transport layer device %s\n", 1716 XPT_DEVICE); 1717 warn("%s", XPT_DEVICE); 1718 return(1); 1719 } 1720 } else { 1721 device = cam_open_btl(bus, target, lun, O_RDWR, NULL); 1722 if (device == NULL) { 1723 warnx("%s", cam_errbuf); 1724 return(1); 1725 } 1726 } 1727 1728 ccb.ccb_h.func_code = (scan)? XPT_SCAN_LUN : XPT_RESET_DEV; 1729 ccb.ccb_h.path_id = bus; 1730 ccb.ccb_h.target_id = target; 1731 ccb.ccb_h.target_lun = lun; 1732 ccb.ccb_h.timeout = 5000; 1733 ccb.crcn.flags = CAM_FLAG_NONE; 1734 1735 /* run this at a low priority */ 1736 ccb.ccb_h.pinfo.priority = 5; 1737 1738 if (scan) { 1739 if (ioctl(fd, CAMIOCOMMAND, &ccb) < 0) { 1740 warn("CAMIOCOMMAND ioctl failed"); 1741 close(fd); 1742 return(1); 1743 } 1744 } else { 1745 if (cam_send_ccb(device, &ccb) < 0) { 1746 warn("error sending XPT_RESET_DEV CCB"); 1747 cam_close_device(device); 1748 return(1); 1749 } 1750 } 1751 1752 if (scan) 1753 close(fd); 1754 else 1755 cam_close_device(device); 1756 1757 /* 1758 * An error code of CAM_BDR_SENT is normal for a BDR request. 1759 */ 1760 if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 1761 || ((!scan) 1762 && ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_BDR_SENT))) { 1763 fprintf(stdout, "%s of %d:%d:%d was successful\n", 1764 scan? "Re-scan" : "Reset", bus, target, lun); 1765 return(0); 1766 } else { 1767 fprintf(stdout, "%s of %d:%d:%d returned error %#x\n", 1768 scan? "Re-scan" : "Reset", bus, target, lun, 1769 ccb.ccb_h.status & CAM_STATUS_MASK); 1770 return(1); 1771 } 1772} 1773 1774#ifndef MINIMALISTIC 1775static int 1776readdefects(struct cam_device *device, int argc, char **argv, 1777 char *combinedopt, int retry_count, int timeout) 1778{ 1779 union ccb *ccb = NULL; 1780 struct scsi_read_defect_data_10 *rdd_cdb; 1781 u_int8_t *defect_list = NULL; 1782 u_int32_t dlist_length = 65000; 1783 u_int32_t returned_length = 0; 1784 u_int32_t num_returned = 0; 1785 u_int8_t returned_format; 1786 unsigned int i; 1787 int c, error = 0; 1788 int lists_specified = 0; 1789 1790 while ((c = getopt(argc, argv, combinedopt)) != -1) { 1791 switch(c){ 1792 case 'f': 1793 { 1794 char *tstr; 1795 tstr = optarg; 1796 while (isspace(*tstr) && (*tstr != '\0')) 1797 tstr++; 1798 if (strcmp(tstr, "block") == 0) 1799 arglist |= CAM_ARG_FORMAT_BLOCK; 1800 else if (strcmp(tstr, "bfi") == 0) 1801 arglist |= CAM_ARG_FORMAT_BFI; 1802 else if (strcmp(tstr, "phys") == 0) 1803 arglist |= CAM_ARG_FORMAT_PHYS; 1804 else { 1805 error = 1; 1806 warnx("invalid defect format %s", tstr); 1807 goto defect_bailout; 1808 } 1809 break; 1810 } 1811 case 'G': 1812 arglist |= CAM_ARG_GLIST; 1813 break; 1814 case 'P': 1815 arglist |= CAM_ARG_PLIST; 1816 break; 1817 default: 1818 break; 1819 } 1820 } 1821 1822 ccb = cam_getccb(device); 1823 1824 /* 1825 * Hopefully 65000 bytes is enough to hold the defect list. If it 1826 * isn't, the disk is probably dead already. We'd have to go with 1827 * 12 byte command (i.e. alloc_length is 32 bits instead of 16) 1828 * to hold them all. 1829 */ 1830 defect_list = malloc(dlist_length); 1831 if (defect_list == NULL) { 1832 warnx("can't malloc memory for defect list"); 1833 error = 1; 1834 goto defect_bailout; 1835 } 1836 1837 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes; 1838 1839 /* 1840 * cam_getccb() zeros the CCB header only. So we need to zero the 1841 * payload portion of the ccb. 1842 */ 1843 bzero(&(&ccb->ccb_h)[1], 1844 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 1845 1846 cam_fill_csio(&ccb->csio, 1847 /*retries*/ retry_count, 1848 /*cbfcnp*/ NULL, 1849 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ? 1850 CAM_PASS_ERR_RECOVER : 0), 1851 /*tag_action*/ MSG_SIMPLE_Q_TAG, 1852 /*data_ptr*/ defect_list, 1853 /*dxfer_len*/ dlist_length, 1854 /*sense_len*/ SSD_FULL_SIZE, 1855 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10), 1856 /*timeout*/ timeout ? timeout : 5000); 1857 1858 rdd_cdb->opcode = READ_DEFECT_DATA_10; 1859 if (arglist & CAM_ARG_FORMAT_BLOCK) 1860 rdd_cdb->format = SRDD10_BLOCK_FORMAT; 1861 else if (arglist & CAM_ARG_FORMAT_BFI) 1862 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT; 1863 else if (arglist & CAM_ARG_FORMAT_PHYS) 1864 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT; 1865 else { 1866 error = 1; 1867 warnx("no defect list format specified"); 1868 goto defect_bailout; 1869 } 1870 if (arglist & CAM_ARG_PLIST) { 1871 rdd_cdb->format |= SRDD10_PLIST; 1872 lists_specified++; 1873 } 1874 1875 if (arglist & CAM_ARG_GLIST) { 1876 rdd_cdb->format |= SRDD10_GLIST; 1877 lists_specified++; 1878 } 1879 1880 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length); 1881 1882 /* Disable freezing the device queue */ 1883 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 1884 1885 if (cam_send_ccb(device, ccb) < 0) { 1886 perror("error reading defect list"); 1887 1888 if (arglist & CAM_ARG_VERBOSE) { 1889 cam_error_print(device, ccb, CAM_ESF_ALL, 1890 CAM_EPF_ALL, stderr); 1891 } 1892 1893 error = 1; 1894 goto defect_bailout; 1895 } 1896 1897 returned_length = scsi_2btoul(((struct 1898 scsi_read_defect_data_hdr_10 *)defect_list)->length); 1899 1900 returned_format = ((struct scsi_read_defect_data_hdr_10 *) 1901 defect_list)->format; 1902 1903 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 1904 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) 1905 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 1906 struct scsi_sense_data *sense; 1907 int error_code, sense_key, asc, ascq; 1908 1909 sense = &ccb->csio.sense_data; 1910 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 1911 1912 /* 1913 * According to the SCSI spec, if the disk doesn't support 1914 * the requested format, it will generally return a sense 1915 * key of RECOVERED ERROR, and an additional sense code 1916 * of "DEFECT LIST NOT FOUND". So, we check for that, and 1917 * also check to make sure that the returned length is 1918 * greater than 0, and then print out whatever format the 1919 * disk gave us. 1920 */ 1921 if ((sense_key == SSD_KEY_RECOVERED_ERROR) 1922 && (asc == 0x1c) && (ascq == 0x00) 1923 && (returned_length > 0)) { 1924 warnx("requested defect format not available"); 1925 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) { 1926 case SRDD10_BLOCK_FORMAT: 1927 warnx("Device returned block format"); 1928 break; 1929 case SRDD10_BYTES_FROM_INDEX_FORMAT: 1930 warnx("Device returned bytes from index" 1931 " format"); 1932 break; 1933 case SRDD10_PHYSICAL_SECTOR_FORMAT: 1934 warnx("Device returned physical sector format"); 1935 break; 1936 default: 1937 error = 1; 1938 warnx("Device returned unknown defect" 1939 " data format %#x", returned_format); 1940 goto defect_bailout; 1941 break; /* NOTREACHED */ 1942 } 1943 } else { 1944 error = 1; 1945 warnx("Error returned from read defect data command"); 1946 if (arglist & CAM_ARG_VERBOSE) 1947 cam_error_print(device, ccb, CAM_ESF_ALL, 1948 CAM_EPF_ALL, stderr); 1949 goto defect_bailout; 1950 } 1951 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1952 error = 1; 1953 warnx("Error returned from read defect data command"); 1954 if (arglist & CAM_ARG_VERBOSE) 1955 cam_error_print(device, ccb, CAM_ESF_ALL, 1956 CAM_EPF_ALL, stderr); 1957 goto defect_bailout; 1958 } 1959 1960 /* 1961 * XXX KDM I should probably clean up the printout format for the 1962 * disk defects. 1963 */ 1964 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){ 1965 case SRDDH10_PHYSICAL_SECTOR_FORMAT: 1966 { 1967 struct scsi_defect_desc_phys_sector *dlist; 1968 1969 dlist = (struct scsi_defect_desc_phys_sector *) 1970 (defect_list + 1971 sizeof(struct scsi_read_defect_data_hdr_10)); 1972 1973 num_returned = returned_length / 1974 sizeof(struct scsi_defect_desc_phys_sector); 1975 1976 fprintf(stderr, "Got %d defect", num_returned); 1977 1978 if ((lists_specified == 0) || (num_returned == 0)) { 1979 fprintf(stderr, "s.\n"); 1980 break; 1981 } else if (num_returned == 1) 1982 fprintf(stderr, ":\n"); 1983 else 1984 fprintf(stderr, "s:\n"); 1985 1986 for (i = 0; i < num_returned; i++) { 1987 fprintf(stdout, "%d:%d:%d\n", 1988 scsi_3btoul(dlist[i].cylinder), 1989 dlist[i].head, 1990 scsi_4btoul(dlist[i].sector)); 1991 } 1992 break; 1993 } 1994 case SRDDH10_BYTES_FROM_INDEX_FORMAT: 1995 { 1996 struct scsi_defect_desc_bytes_from_index *dlist; 1997 1998 dlist = (struct scsi_defect_desc_bytes_from_index *) 1999 (defect_list + 2000 sizeof(struct scsi_read_defect_data_hdr_10)); 2001 2002 num_returned = returned_length / 2003 sizeof(struct scsi_defect_desc_bytes_from_index); 2004 2005 fprintf(stderr, "Got %d defect", num_returned); 2006 2007 if ((lists_specified == 0) || (num_returned == 0)) { 2008 fprintf(stderr, "s.\n"); 2009 break; 2010 } else if (num_returned == 1) 2011 fprintf(stderr, ":\n"); 2012 else 2013 fprintf(stderr, "s:\n"); 2014 2015 for (i = 0; i < num_returned; i++) { 2016 fprintf(stdout, "%d:%d:%d\n", 2017 scsi_3btoul(dlist[i].cylinder), 2018 dlist[i].head, 2019 scsi_4btoul(dlist[i].bytes_from_index)); 2020 } 2021 break; 2022 } 2023 case SRDDH10_BLOCK_FORMAT: 2024 { 2025 struct scsi_defect_desc_block *dlist; 2026 2027 dlist = (struct scsi_defect_desc_block *)(defect_list + 2028 sizeof(struct scsi_read_defect_data_hdr_10)); 2029 2030 num_returned = returned_length / 2031 sizeof(struct scsi_defect_desc_block); 2032 2033 fprintf(stderr, "Got %d defect", num_returned); 2034 2035 if ((lists_specified == 0) || (num_returned == 0)) { 2036 fprintf(stderr, "s.\n"); 2037 break; 2038 } else if (num_returned == 1) 2039 fprintf(stderr, ":\n"); 2040 else 2041 fprintf(stderr, "s:\n"); 2042 2043 for (i = 0; i < num_returned; i++) 2044 fprintf(stdout, "%u\n", 2045 scsi_4btoul(dlist[i].address)); 2046 break; 2047 } 2048 default: 2049 fprintf(stderr, "Unknown defect format %d\n", 2050 returned_format & SRDDH10_DLIST_FORMAT_MASK); 2051 error = 1; 2052 break; 2053 } 2054defect_bailout: 2055 2056 if (defect_list != NULL) 2057 free(defect_list); 2058 2059 if (ccb != NULL) 2060 cam_freeccb(ccb); 2061 2062 return(error); 2063} 2064#endif /* MINIMALISTIC */ 2065 2066#if 0 2067void 2068reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks) 2069{ 2070 union ccb *ccb; 2071 2072 ccb = cam_getccb(device); 2073 2074 cam_freeccb(ccb); 2075} 2076#endif 2077 2078#ifndef MINIMALISTIC 2079void 2080mode_sense(struct cam_device *device, int mode_page, int page_control, 2081 int dbd, int retry_count, int timeout, u_int8_t *data, int datalen) 2082{ 2083 union ccb *ccb; 2084 int retval; 2085 2086 ccb = cam_getccb(device); 2087 2088 if (ccb == NULL) 2089 errx(1, "mode_sense: couldn't allocate CCB"); 2090 2091 bzero(&(&ccb->ccb_h)[1], 2092 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 2093 2094 scsi_mode_sense(&ccb->csio, 2095 /* retries */ retry_count, 2096 /* cbfcnp */ NULL, 2097 /* tag_action */ MSG_SIMPLE_Q_TAG, 2098 /* dbd */ dbd, 2099 /* page_code */ page_control << 6, 2100 /* page */ mode_page, 2101 /* param_buf */ data, 2102 /* param_len */ datalen, 2103 /* sense_len */ SSD_FULL_SIZE, 2104 /* timeout */ timeout ? timeout : 5000); 2105 2106 if (arglist & CAM_ARG_ERR_RECOVER) 2107 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 2108 2109 /* Disable freezing the device queue */ 2110 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 2111 2112 if (((retval = cam_send_ccb(device, ccb)) < 0) 2113 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 2114 if (arglist & CAM_ARG_VERBOSE) { 2115 cam_error_print(device, ccb, CAM_ESF_ALL, 2116 CAM_EPF_ALL, stderr); 2117 } 2118 cam_freeccb(ccb); 2119 cam_close_device(device); 2120 if (retval < 0) 2121 err(1, "error sending mode sense command"); 2122 else 2123 errx(1, "error sending mode sense command"); 2124 } 2125 2126 cam_freeccb(ccb); 2127} 2128 2129void 2130mode_select(struct cam_device *device, int save_pages, int retry_count, 2131 int timeout, u_int8_t *data, int datalen) 2132{ 2133 union ccb *ccb; 2134 int retval; 2135 2136 ccb = cam_getccb(device); 2137 2138 if (ccb == NULL) 2139 errx(1, "mode_select: couldn't allocate CCB"); 2140 2141 bzero(&(&ccb->ccb_h)[1], 2142 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 2143 2144 scsi_mode_select(&ccb->csio, 2145 /* retries */ retry_count, 2146 /* cbfcnp */ NULL, 2147 /* tag_action */ MSG_SIMPLE_Q_TAG, 2148 /* scsi_page_fmt */ 1, 2149 /* save_pages */ save_pages, 2150 /* param_buf */ data, 2151 /* param_len */ datalen, 2152 /* sense_len */ SSD_FULL_SIZE, 2153 /* timeout */ timeout ? timeout : 5000); 2154 2155 if (arglist & CAM_ARG_ERR_RECOVER) 2156 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 2157 2158 /* Disable freezing the device queue */ 2159 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 2160 2161 if (((retval = cam_send_ccb(device, ccb)) < 0) 2162 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 2163 if (arglist & CAM_ARG_VERBOSE) { 2164 cam_error_print(device, ccb, CAM_ESF_ALL, 2165 CAM_EPF_ALL, stderr); 2166 } 2167 cam_freeccb(ccb); 2168 cam_close_device(device); 2169 2170 if (retval < 0) 2171 err(1, "error sending mode select command"); 2172 else 2173 errx(1, "error sending mode select command"); 2174 2175 } 2176 2177 cam_freeccb(ccb); 2178} 2179 2180void 2181modepage(struct cam_device *device, int argc, char **argv, char *combinedopt, 2182 int retry_count, int timeout) 2183{ 2184 int c, mode_page = -1, page_control = 0; 2185 int binary = 0, list = 0; 2186 2187 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2188 switch(c) { 2189 case 'b': 2190 binary = 1; 2191 break; 2192 case 'd': 2193 arglist |= CAM_ARG_DBD; 2194 break; 2195 case 'e': 2196 arglist |= CAM_ARG_MODE_EDIT; 2197 break; 2198 case 'l': 2199 list = 1; 2200 break; 2201 case 'm': 2202 mode_page = strtol(optarg, NULL, 0); 2203 if (mode_page < 0) 2204 errx(1, "invalid mode page %d", mode_page); 2205 break; 2206 case 'P': 2207 page_control = strtol(optarg, NULL, 0); 2208 if ((page_control < 0) || (page_control > 3)) 2209 errx(1, "invalid page control field %d", 2210 page_control); 2211 arglist |= CAM_ARG_PAGE_CNTL; 2212 break; 2213 default: 2214 break; 2215 } 2216 } 2217 2218 if (mode_page == -1 && list == 0) 2219 errx(1, "you must specify a mode page!"); 2220 2221 if (list) { 2222 mode_list(device, page_control, arglist & CAM_ARG_DBD, 2223 retry_count, timeout); 2224 } else { 2225 mode_edit(device, mode_page, page_control, 2226 arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary, 2227 retry_count, timeout); 2228 } 2229} 2230 2231static int 2232scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, 2233 int retry_count, int timeout) 2234{ 2235 union ccb *ccb; 2236 u_int32_t flags = CAM_DIR_NONE; 2237 u_int8_t *data_ptr = NULL; 2238 u_int8_t cdb[20]; 2239 u_int8_t atacmd[12]; 2240 struct get_hook hook; 2241 int c, data_bytes = 0; 2242 int cdb_len = 0; 2243 int atacmd_len = 0; 2244 int dmacmd = 0; 2245 int fpdmacmd = 0; 2246 int need_res = 0; 2247 char *datastr = NULL, *tstr, *resstr = NULL; 2248 int error = 0; 2249 int fd_data = 0, fd_res = 0; 2250 int retval; 2251 2252 ccb = cam_getccb(device); 2253 2254 if (ccb == NULL) { 2255 warnx("scsicmd: error allocating ccb"); 2256 return(1); 2257 } 2258 2259 bzero(&(&ccb->ccb_h)[1], 2260 sizeof(union ccb) - sizeof(struct ccb_hdr)); 2261 2262 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2263 switch(c) { 2264 case 'a': 2265 tstr = optarg; 2266 while (isspace(*tstr) && (*tstr != '\0')) 2267 tstr++; 2268 hook.argc = argc - optind; 2269 hook.argv = argv + optind; 2270 hook.got = 0; 2271 atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr, 2272 iget, &hook); 2273 /* 2274 * Increment optind by the number of arguments the 2275 * encoding routine processed. After each call to 2276 * getopt(3), optind points to the argument that 2277 * getopt should process _next_. In this case, 2278 * that means it points to the first command string 2279 * argument, if there is one. Once we increment 2280 * this, it should point to either the next command 2281 * line argument, or it should be past the end of 2282 * the list. 2283 */ 2284 optind += hook.got; 2285 break; 2286 case 'c': 2287 tstr = optarg; 2288 while (isspace(*tstr) && (*tstr != '\0')) 2289 tstr++; 2290 hook.argc = argc - optind; 2291 hook.argv = argv + optind; 2292 hook.got = 0; 2293 cdb_len = buff_encode_visit(cdb, sizeof(cdb), tstr, 2294 iget, &hook); 2295 /* 2296 * Increment optind by the number of arguments the 2297 * encoding routine processed. After each call to 2298 * getopt(3), optind points to the argument that 2299 * getopt should process _next_. In this case, 2300 * that means it points to the first command string 2301 * argument, if there is one. Once we increment 2302 * this, it should point to either the next command 2303 * line argument, or it should be past the end of 2304 * the list. 2305 */ 2306 optind += hook.got; 2307 break; 2308 case 'd': 2309 dmacmd = 1; 2310 break; 2311 case 'f': 2312 fpdmacmd = 1; 2313 break; 2314 case 'i': 2315 if (arglist & CAM_ARG_CMD_OUT) { 2316 warnx("command must either be " 2317 "read or write, not both"); 2318 error = 1; 2319 goto scsicmd_bailout; 2320 } 2321 arglist |= CAM_ARG_CMD_IN; 2322 flags = CAM_DIR_IN; 2323 data_bytes = strtol(optarg, NULL, 0); 2324 if (data_bytes <= 0) { 2325 warnx("invalid number of input bytes %d", 2326 data_bytes); 2327 error = 1; 2328 goto scsicmd_bailout; 2329 } 2330 hook.argc = argc - optind; 2331 hook.argv = argv + optind; 2332 hook.got = 0; 2333 optind++; 2334 datastr = cget(&hook, NULL); 2335 /* 2336 * If the user supplied "-" instead of a format, he 2337 * wants the data to be written to stdout. 2338 */ 2339 if ((datastr != NULL) 2340 && (datastr[0] == '-')) 2341 fd_data = 1; 2342 2343 data_ptr = (u_int8_t *)malloc(data_bytes); 2344 if (data_ptr == NULL) { 2345 warnx("can't malloc memory for data_ptr"); 2346 error = 1; 2347 goto scsicmd_bailout; 2348 } 2349 break; 2350 case 'o': 2351 if (arglist & CAM_ARG_CMD_IN) { 2352 warnx("command must either be " 2353 "read or write, not both"); 2354 error = 1; 2355 goto scsicmd_bailout; 2356 } 2357 arglist |= CAM_ARG_CMD_OUT; 2358 flags = CAM_DIR_OUT; 2359 data_bytes = strtol(optarg, NULL, 0); 2360 if (data_bytes <= 0) { 2361 warnx("invalid number of output bytes %d", 2362 data_bytes); 2363 error = 1; 2364 goto scsicmd_bailout; 2365 } 2366 hook.argc = argc - optind; 2367 hook.argv = argv + optind; 2368 hook.got = 0; 2369 datastr = cget(&hook, NULL); 2370 data_ptr = (u_int8_t *)malloc(data_bytes); 2371 if (data_ptr == NULL) { 2372 warnx("can't malloc memory for data_ptr"); 2373 error = 1; 2374 goto scsicmd_bailout; 2375 } 2376 bzero(data_ptr, data_bytes); 2377 /* 2378 * If the user supplied "-" instead of a format, he 2379 * wants the data to be read from stdin. 2380 */ 2381 if ((datastr != NULL) 2382 && (datastr[0] == '-')) 2383 fd_data = 1; 2384 else 2385 buff_encode_visit(data_ptr, data_bytes, datastr, 2386 iget, &hook); 2387 optind += hook.got; 2388 break; 2389 case 'r': 2390 need_res = 1; 2391 hook.argc = argc - optind; 2392 hook.argv = argv + optind; 2393 hook.got = 0; 2394 resstr = cget(&hook, NULL); 2395 if ((resstr != NULL) && (resstr[0] == '-')) 2396 fd_res = 1; 2397 optind += hook.got; 2398 break; 2399 default: 2400 break; 2401 } 2402 } 2403 2404 /* 2405 * If fd_data is set, and we're writing to the device, we need to 2406 * read the data the user wants written from stdin. 2407 */ 2408 if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) { 2409 ssize_t amt_read; 2410 int amt_to_read = data_bytes; 2411 u_int8_t *buf_ptr = data_ptr; 2412 2413 for (amt_read = 0; amt_to_read > 0; 2414 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { 2415 if (amt_read == -1) { 2416 warn("error reading data from stdin"); 2417 error = 1; 2418 goto scsicmd_bailout; 2419 } 2420 amt_to_read -= amt_read; 2421 buf_ptr += amt_read; 2422 } 2423 } 2424 2425 if (arglist & CAM_ARG_ERR_RECOVER) 2426 flags |= CAM_PASS_ERR_RECOVER; 2427 2428 /* Disable freezing the device queue */ 2429 flags |= CAM_DEV_QFRZDIS; 2430 2431 if (cdb_len) { 2432 /* 2433 * This is taken from the SCSI-3 draft spec. 2434 * (T10/1157D revision 0.3) 2435 * The top 3 bits of an opcode are the group code. 2436 * The next 5 bits are the command code. 2437 * Group 0: six byte commands 2438 * Group 1: ten byte commands 2439 * Group 2: ten byte commands 2440 * Group 3: reserved 2441 * Group 4: sixteen byte commands 2442 * Group 5: twelve byte commands 2443 * Group 6: vendor specific 2444 * Group 7: vendor specific 2445 */ 2446 switch((cdb[0] >> 5) & 0x7) { 2447 case 0: 2448 cdb_len = 6; 2449 break; 2450 case 1: 2451 case 2: 2452 cdb_len = 10; 2453 break; 2454 case 3: 2455 case 6: 2456 case 7: 2457 /* computed by buff_encode_visit */ 2458 break; 2459 case 4: 2460 cdb_len = 16; 2461 break; 2462 case 5: 2463 cdb_len = 12; 2464 break; 2465 } 2466 2467 /* 2468 * We should probably use csio_build_visit or something like that 2469 * here, but it's easier to encode arguments as you go. The 2470 * alternative would be skipping the CDB argument and then encoding 2471 * it here, since we've got the data buffer argument by now. 2472 */ 2473 bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len); 2474 2475 cam_fill_csio(&ccb->csio, 2476 /*retries*/ retry_count, 2477 /*cbfcnp*/ NULL, 2478 /*flags*/ flags, 2479 /*tag_action*/ MSG_SIMPLE_Q_TAG, 2480 /*data_ptr*/ data_ptr, 2481 /*dxfer_len*/ data_bytes, 2482 /*sense_len*/ SSD_FULL_SIZE, 2483 /*cdb_len*/ cdb_len, 2484 /*timeout*/ timeout ? timeout : 5000); 2485 } else { 2486 atacmd_len = 12; 2487 bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len); 2488 if (need_res) 2489 ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; 2490 if (dmacmd) 2491 ccb->ataio.cmd.flags |= CAM_ATAIO_DMA; 2492 if (fpdmacmd) 2493 ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA; 2494 2495 cam_fill_ataio(&ccb->ataio, 2496 /*retries*/ retry_count, 2497 /*cbfcnp*/ NULL, 2498 /*flags*/ flags, 2499 /*tag_action*/ 0, 2500 /*data_ptr*/ data_ptr, 2501 /*dxfer_len*/ data_bytes, 2502 /*timeout*/ timeout ? timeout : 5000); 2503 } 2504 2505 if (((retval = cam_send_ccb(device, ccb)) < 0) 2506 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 2507 const char *warnstr = "error sending command"; 2508 2509 if (retval < 0) 2510 warn(warnstr); 2511 else 2512 warnx(warnstr); 2513 2514 if (arglist & CAM_ARG_VERBOSE) { 2515 cam_error_print(device, ccb, CAM_ESF_ALL, 2516 CAM_EPF_ALL, stderr); 2517 } 2518 2519 error = 1; 2520 goto scsicmd_bailout; 2521 } 2522 2523 if (atacmd_len && need_res) { 2524 if (fd_res == 0) { 2525 buff_decode_visit(&ccb->ataio.res.status, 11, resstr, 2526 arg_put, NULL); 2527 fprintf(stdout, "\n"); 2528 } else { 2529 fprintf(stdout, 2530 "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", 2531 ccb->ataio.res.status, 2532 ccb->ataio.res.error, 2533 ccb->ataio.res.lba_low, 2534 ccb->ataio.res.lba_mid, 2535 ccb->ataio.res.lba_high, 2536 ccb->ataio.res.device, 2537 ccb->ataio.res.lba_low_exp, 2538 ccb->ataio.res.lba_mid_exp, 2539 ccb->ataio.res.lba_high_exp, 2540 ccb->ataio.res.sector_count, 2541 ccb->ataio.res.sector_count_exp); 2542 fflush(stdout); 2543 } 2544 } 2545 2546 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 2547 && (arglist & CAM_ARG_CMD_IN) 2548 && (data_bytes > 0)) { 2549 if (fd_data == 0) { 2550 buff_decode_visit(data_ptr, data_bytes, datastr, 2551 arg_put, NULL); 2552 fprintf(stdout, "\n"); 2553 } else { 2554 ssize_t amt_written; 2555 int amt_to_write = data_bytes; 2556 u_int8_t *buf_ptr = data_ptr; 2557 2558 for (amt_written = 0; (amt_to_write > 0) && 2559 (amt_written =write(1, buf_ptr,amt_to_write))> 0;){ 2560 amt_to_write -= amt_written; 2561 buf_ptr += amt_written; 2562 } 2563 if (amt_written == -1) { 2564 warn("error writing data to stdout"); 2565 error = 1; 2566 goto scsicmd_bailout; 2567 } else if ((amt_written == 0) 2568 && (amt_to_write > 0)) { 2569 warnx("only wrote %u bytes out of %u", 2570 data_bytes - amt_to_write, data_bytes); 2571 } 2572 } 2573 } 2574 2575scsicmd_bailout: 2576 2577 if ((data_bytes > 0) && (data_ptr != NULL)) 2578 free(data_ptr); 2579 2580 cam_freeccb(ccb); 2581 2582 return(error); 2583} 2584 2585static int 2586camdebug(int argc, char **argv, char *combinedopt) 2587{ 2588 int c, fd; 2589 int bus = -1, target = -1, lun = -1; 2590 char *tstr, *tmpstr = NULL; 2591 union ccb ccb; 2592 int error = 0; 2593 2594 bzero(&ccb, sizeof(union ccb)); 2595 2596 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2597 switch(c) { 2598 case 'I': 2599 arglist |= CAM_ARG_DEBUG_INFO; 2600 ccb.cdbg.flags |= CAM_DEBUG_INFO; 2601 break; 2602 case 'P': 2603 arglist |= CAM_ARG_DEBUG_PERIPH; 2604 ccb.cdbg.flags |= CAM_DEBUG_PERIPH; 2605 break; 2606 case 'S': 2607 arglist |= CAM_ARG_DEBUG_SUBTRACE; 2608 ccb.cdbg.flags |= CAM_DEBUG_SUBTRACE; 2609 break; 2610 case 'T': 2611 arglist |= CAM_ARG_DEBUG_TRACE; 2612 ccb.cdbg.flags |= CAM_DEBUG_TRACE; 2613 break; 2614 case 'X': 2615 arglist |= CAM_ARG_DEBUG_XPT; 2616 ccb.cdbg.flags |= CAM_DEBUG_XPT; 2617 break; 2618 case 'c': 2619 arglist |= CAM_ARG_DEBUG_CDB; 2620 ccb.cdbg.flags |= CAM_DEBUG_CDB; 2621 break; 2622 default: 2623 break; 2624 } 2625 } 2626 2627 if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) { 2628 warnx("error opening transport layer device %s", XPT_DEVICE); 2629 warn("%s", XPT_DEVICE); 2630 return(1); 2631 } 2632 argc -= optind; 2633 argv += optind; 2634 2635 if (argc <= 0) { 2636 warnx("you must specify \"off\", \"all\" or a bus,"); 2637 warnx("bus:target, or bus:target:lun"); 2638 close(fd); 2639 return(1); 2640 } 2641 2642 tstr = *argv; 2643 2644 while (isspace(*tstr) && (*tstr != '\0')) 2645 tstr++; 2646 2647 if (strncmp(tstr, "off", 3) == 0) { 2648 ccb.cdbg.flags = CAM_DEBUG_NONE; 2649 arglist &= ~(CAM_ARG_DEBUG_INFO|CAM_ARG_DEBUG_PERIPH| 2650 CAM_ARG_DEBUG_TRACE|CAM_ARG_DEBUG_SUBTRACE| 2651 CAM_ARG_DEBUG_XPT); 2652 } else if (strncmp(tstr, "all", 3) != 0) { 2653 tmpstr = (char *)strtok(tstr, ":"); 2654 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 2655 bus = strtol(tmpstr, NULL, 0); 2656 arglist |= CAM_ARG_BUS; 2657 tmpstr = (char *)strtok(NULL, ":"); 2658 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 2659 target = strtol(tmpstr, NULL, 0); 2660 arglist |= CAM_ARG_TARGET; 2661 tmpstr = (char *)strtok(NULL, ":"); 2662 if ((tmpstr != NULL) && (*tmpstr != '\0')){ 2663 lun = strtol(tmpstr, NULL, 0); 2664 arglist |= CAM_ARG_LUN; 2665 } 2666 } 2667 } else { 2668 error = 1; 2669 warnx("you must specify \"all\", \"off\", or a bus,"); 2670 warnx("bus:target, or bus:target:lun to debug"); 2671 } 2672 } 2673 2674 if (error == 0) { 2675 2676 ccb.ccb_h.func_code = XPT_DEBUG; 2677 ccb.ccb_h.path_id = bus; 2678 ccb.ccb_h.target_id = target; 2679 ccb.ccb_h.target_lun = lun; 2680 2681 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 2682 warn("CAMIOCOMMAND ioctl failed"); 2683 error = 1; 2684 } 2685 2686 if (error == 0) { 2687 if ((ccb.ccb_h.status & CAM_STATUS_MASK) == 2688 CAM_FUNC_NOTAVAIL) { 2689 warnx("CAM debugging not available"); 2690 warnx("you need to put options CAMDEBUG in" 2691 " your kernel config file!"); 2692 error = 1; 2693 } else if ((ccb.ccb_h.status & CAM_STATUS_MASK) != 2694 CAM_REQ_CMP) { 2695 warnx("XPT_DEBUG CCB failed with status %#x", 2696 ccb.ccb_h.status); 2697 error = 1; 2698 } else { 2699 if (ccb.cdbg.flags == CAM_DEBUG_NONE) { 2700 fprintf(stderr, 2701 "Debugging turned off\n"); 2702 } else { 2703 fprintf(stderr, 2704 "Debugging enabled for " 2705 "%d:%d:%d\n", 2706 bus, target, lun); 2707 } 2708 } 2709 } 2710 close(fd); 2711 } 2712 2713 return(error); 2714} 2715 2716static int 2717tagcontrol(struct cam_device *device, int argc, char **argv, 2718 char *combinedopt) 2719{ 2720 int c; 2721 union ccb *ccb; 2722 int numtags = -1; 2723 int retval = 0; 2724 int quiet = 0; 2725 char pathstr[1024]; 2726 2727 ccb = cam_getccb(device); 2728 2729 if (ccb == NULL) { 2730 warnx("tagcontrol: error allocating ccb"); 2731 return(1); 2732 } 2733 2734 while ((c = getopt(argc, argv, combinedopt)) != -1) { 2735 switch(c) { 2736 case 'N': 2737 numtags = strtol(optarg, NULL, 0); 2738 if (numtags < 0) { 2739 warnx("tag count %d is < 0", numtags); 2740 retval = 1; 2741 goto tagcontrol_bailout; 2742 } 2743 break; 2744 case 'q': 2745 quiet++; 2746 break; 2747 default: 2748 break; 2749 } 2750 } 2751 2752 cam_path_string(device, pathstr, sizeof(pathstr)); 2753 2754 if (numtags >= 0) { 2755 bzero(&(&ccb->ccb_h)[1], 2756 sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr)); 2757 ccb->ccb_h.func_code = XPT_REL_SIMQ; 2758 ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS; 2759 ccb->crs.openings = numtags; 2760 2761 2762 if (cam_send_ccb(device, ccb) < 0) { 2763 perror("error sending XPT_REL_SIMQ CCB"); 2764 retval = 1; 2765 goto tagcontrol_bailout; 2766 } 2767 2768 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2769 warnx("XPT_REL_SIMQ CCB failed"); 2770 cam_error_print(device, ccb, CAM_ESF_ALL, 2771 CAM_EPF_ALL, stderr); 2772 retval = 1; 2773 goto tagcontrol_bailout; 2774 } 2775 2776 2777 if (quiet == 0) 2778 fprintf(stdout, "%stagged openings now %d\n", 2779 pathstr, ccb->crs.openings); 2780 } 2781 2782 bzero(&(&ccb->ccb_h)[1], 2783 sizeof(struct ccb_getdevstats) - sizeof(struct ccb_hdr)); 2784 2785 ccb->ccb_h.func_code = XPT_GDEV_STATS; 2786 2787 if (cam_send_ccb(device, ccb) < 0) { 2788 perror("error sending XPT_GDEV_STATS CCB"); 2789 retval = 1; 2790 goto tagcontrol_bailout; 2791 } 2792 2793 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2794 warnx("XPT_GDEV_STATS CCB failed"); 2795 cam_error_print(device, ccb, CAM_ESF_ALL, 2796 CAM_EPF_ALL, stderr); 2797 retval = 1; 2798 goto tagcontrol_bailout; 2799 } 2800 2801 if (arglist & CAM_ARG_VERBOSE) { 2802 fprintf(stdout, "%s", pathstr); 2803 fprintf(stdout, "dev_openings %d\n", ccb->cgds.dev_openings); 2804 fprintf(stdout, "%s", pathstr); 2805 fprintf(stdout, "dev_active %d\n", ccb->cgds.dev_active); 2806 fprintf(stdout, "%s", pathstr); 2807 fprintf(stdout, "devq_openings %d\n", ccb->cgds.devq_openings); 2808 fprintf(stdout, "%s", pathstr); 2809 fprintf(stdout, "devq_queued %d\n", ccb->cgds.devq_queued); 2810 fprintf(stdout, "%s", pathstr); 2811 fprintf(stdout, "held %d\n", ccb->cgds.held); 2812 fprintf(stdout, "%s", pathstr); 2813 fprintf(stdout, "mintags %d\n", ccb->cgds.mintags); 2814 fprintf(stdout, "%s", pathstr); 2815 fprintf(stdout, "maxtags %d\n", ccb->cgds.maxtags); 2816 } else { 2817 if (quiet == 0) { 2818 fprintf(stdout, "%s", pathstr); 2819 fprintf(stdout, "device openings: "); 2820 } 2821 fprintf(stdout, "%d\n", ccb->cgds.dev_openings + 2822 ccb->cgds.dev_active); 2823 } 2824 2825tagcontrol_bailout: 2826 2827 cam_freeccb(ccb); 2828 return(retval); 2829} 2830 2831static void 2832cts_print(struct cam_device *device, struct ccb_trans_settings *cts) 2833{ 2834 char pathstr[1024]; 2835 2836 cam_path_string(device, pathstr, sizeof(pathstr)); 2837 2838 if (cts->transport == XPORT_SPI) { 2839 struct ccb_trans_settings_spi *spi = 2840 &cts->xport_specific.spi; 2841 2842 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { 2843 2844 fprintf(stdout, "%ssync parameter: %d\n", pathstr, 2845 spi->sync_period); 2846 2847 if (spi->sync_offset != 0) { 2848 u_int freq; 2849 2850 freq = scsi_calc_syncsrate(spi->sync_period); 2851 fprintf(stdout, "%sfrequency: %d.%03dMHz\n", 2852 pathstr, freq / 1000, freq % 1000); 2853 } 2854 } 2855 2856 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) { 2857 fprintf(stdout, "%soffset: %d\n", pathstr, 2858 spi->sync_offset); 2859 } 2860 2861 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) { 2862 fprintf(stdout, "%sbus width: %d bits\n", pathstr, 2863 (0x01 << spi->bus_width) * 8); 2864 } 2865 2866 if (spi->valid & CTS_SPI_VALID_DISC) { 2867 fprintf(stdout, "%sdisconnection is %s\n", pathstr, 2868 (spi->flags & CTS_SPI_FLAGS_DISC_ENB) ? 2869 "enabled" : "disabled"); 2870 } 2871 } 2872 if (cts->transport == XPORT_ATA) { 2873 struct ccb_trans_settings_ata *ata = 2874 &cts->xport_specific.ata; 2875 2876 if ((ata->valid & CTS_ATA_VALID_MODE) != 0) { 2877 fprintf(stdout, "%sATA mode: %s\n", pathstr, 2878 ata_mode2string(ata->mode)); 2879 } 2880 if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) { 2881 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr, 2882 ata->atapi); 2883 } 2884 if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) { 2885 fprintf(stdout, "%sPIO transaction length: %d\n", 2886 pathstr, ata->bytecount); 2887 } 2888 } 2889 if (cts->transport == XPORT_SATA) { 2890 struct ccb_trans_settings_sata *sata = 2891 &cts->xport_specific.sata; 2892 2893 if ((sata->valid & CTS_SATA_VALID_REVISION) != 0) { 2894 fprintf(stdout, "%sSATA revision: %d.x\n", pathstr, 2895 sata->revision); 2896 } 2897 if ((sata->valid & CTS_SATA_VALID_MODE) != 0) { 2898 fprintf(stdout, "%sATA mode: %s\n", pathstr, 2899 ata_mode2string(sata->mode)); 2900 } 2901 if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) { 2902 fprintf(stdout, "%sATAPI packet length: %d\n", pathstr, 2903 sata->atapi); 2904 } 2905 if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) { 2906 fprintf(stdout, "%sPIO transaction length: %d\n", 2907 pathstr, sata->bytecount); 2908 } 2909 if ((sata->valid & CTS_SATA_VALID_PM) != 0) { 2910 fprintf(stdout, "%sPMP presence: %d\n", pathstr, 2911 sata->pm_present); 2912 } 2913 if ((sata->valid & CTS_SATA_VALID_TAGS) != 0) { 2914 fprintf(stdout, "%sNumber of tags: %d\n", pathstr, 2915 sata->tags); 2916 } 2917 if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) { 2918 fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr, 2919 sata->caps); 2920 } 2921 } 2922 if (cts->protocol == PROTO_SCSI) { 2923 struct ccb_trans_settings_scsi *scsi= 2924 &cts->proto_specific.scsi; 2925 2926 if (scsi->valid & CTS_SCSI_VALID_TQ) { 2927 fprintf(stdout, "%stagged queueing is %s\n", pathstr, 2928 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) ? 2929 "enabled" : "disabled"); 2930 } 2931 } 2932 2933} 2934 2935/* 2936 * Get a path inquiry CCB for the specified device. 2937 */ 2938static int 2939get_cpi(struct cam_device *device, struct ccb_pathinq *cpi) 2940{ 2941 union ccb *ccb; 2942 int retval = 0; 2943 2944 ccb = cam_getccb(device); 2945 if (ccb == NULL) { 2946 warnx("get_cpi: couldn't allocate CCB"); 2947 return(1); 2948 } 2949 bzero(&(&ccb->ccb_h)[1], 2950 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); 2951 ccb->ccb_h.func_code = XPT_PATH_INQ; 2952 if (cam_send_ccb(device, ccb) < 0) { 2953 warn("get_cpi: error sending Path Inquiry CCB"); 2954 if (arglist & CAM_ARG_VERBOSE) 2955 cam_error_print(device, ccb, CAM_ESF_ALL, 2956 CAM_EPF_ALL, stderr); 2957 retval = 1; 2958 goto get_cpi_bailout; 2959 } 2960 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2961 if (arglist & CAM_ARG_VERBOSE) 2962 cam_error_print(device, ccb, CAM_ESF_ALL, 2963 CAM_EPF_ALL, stderr); 2964 retval = 1; 2965 goto get_cpi_bailout; 2966 } 2967 bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq)); 2968 2969get_cpi_bailout: 2970 cam_freeccb(ccb); 2971 return(retval); 2972} 2973 2974/* 2975 * Get a get device CCB for the specified device. 2976 */ 2977static int 2978get_cgd(struct cam_device *device, struct ccb_getdev *cgd) 2979{ 2980 union ccb *ccb; 2981 int retval = 0; 2982 2983 ccb = cam_getccb(device); 2984 if (ccb == NULL) { 2985 warnx("get_cgd: couldn't allocate CCB"); 2986 return(1); 2987 } 2988 bzero(&(&ccb->ccb_h)[1], 2989 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); 2990 ccb->ccb_h.func_code = XPT_GDEV_TYPE; 2991 if (cam_send_ccb(device, ccb) < 0) { 2992 warn("get_cgd: error sending Path Inquiry CCB"); 2993 if (arglist & CAM_ARG_VERBOSE) 2994 cam_error_print(device, ccb, CAM_ESF_ALL, 2995 CAM_EPF_ALL, stderr); 2996 retval = 1; 2997 goto get_cgd_bailout; 2998 } 2999 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3000 if (arglist & CAM_ARG_VERBOSE) 3001 cam_error_print(device, ccb, CAM_ESF_ALL, 3002 CAM_EPF_ALL, stderr); 3003 retval = 1; 3004 goto get_cgd_bailout; 3005 } 3006 bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev)); 3007 3008get_cgd_bailout: 3009 cam_freeccb(ccb); 3010 return(retval); 3011} 3012 3013static void 3014cpi_print(struct ccb_pathinq *cpi) 3015{ 3016 char adapter_str[1024]; 3017 int i; 3018 3019 snprintf(adapter_str, sizeof(adapter_str), 3020 "%s%d:", cpi->dev_name, cpi->unit_number); 3021 3022 fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str, 3023 cpi->version_num); 3024 3025 for (i = 1; i < 0xff; i = i << 1) { 3026 const char *str; 3027 3028 if ((i & cpi->hba_inquiry) == 0) 3029 continue; 3030 3031 fprintf(stdout, "%s supports ", adapter_str); 3032 3033 switch(i) { 3034 case PI_MDP_ABLE: 3035 str = "MDP message"; 3036 break; 3037 case PI_WIDE_32: 3038 str = "32 bit wide SCSI"; 3039 break; 3040 case PI_WIDE_16: 3041 str = "16 bit wide SCSI"; 3042 break; 3043 case PI_SDTR_ABLE: 3044 str = "SDTR message"; 3045 break; 3046 case PI_LINKED_CDB: 3047 str = "linked CDBs"; 3048 break; 3049 case PI_TAG_ABLE: 3050 str = "tag queue messages"; 3051 break; 3052 case PI_SOFT_RST: 3053 str = "soft reset alternative"; 3054 break; 3055 case PI_SATAPM: 3056 str = "SATA Port Multiplier"; 3057 break; 3058 default: 3059 str = "unknown PI bit set"; 3060 break; 3061 } 3062 fprintf(stdout, "%s\n", str); 3063 } 3064 3065 for (i = 1; i < 0xff; i = i << 1) { 3066 const char *str; 3067 3068 if ((i & cpi->hba_misc) == 0) 3069 continue; 3070 3071 fprintf(stdout, "%s ", adapter_str); 3072 3073 switch(i) { 3074 case PIM_SCANHILO: 3075 str = "bus scans from high ID to low ID"; 3076 break; 3077 case PIM_NOREMOVE: 3078 str = "removable devices not included in scan"; 3079 break; 3080 case PIM_NOINITIATOR: 3081 str = "initiator role not supported"; 3082 break; 3083 case PIM_NOBUSRESET: 3084 str = "user has disabled initial BUS RESET or" 3085 " controller is in target/mixed mode"; 3086 break; 3087 case PIM_NO_6_BYTE: 3088 str = "do not send 6-byte commands"; 3089 break; 3090 case PIM_SEQSCAN: 3091 str = "scan bus sequentially"; 3092 break; 3093 default: 3094 str = "unknown PIM bit set"; 3095 break; 3096 } 3097 fprintf(stdout, "%s\n", str); 3098 } 3099 3100 for (i = 1; i < 0xff; i = i << 1) { 3101 const char *str; 3102 3103 if ((i & cpi->target_sprt) == 0) 3104 continue; 3105 3106 fprintf(stdout, "%s supports ", adapter_str); 3107 switch(i) { 3108 case PIT_PROCESSOR: 3109 str = "target mode processor mode"; 3110 break; 3111 case PIT_PHASE: 3112 str = "target mode phase cog. mode"; 3113 break; 3114 case PIT_DISCONNECT: 3115 str = "disconnects in target mode"; 3116 break; 3117 case PIT_TERM_IO: 3118 str = "terminate I/O message in target mode"; 3119 break; 3120 case PIT_GRP_6: 3121 str = "group 6 commands in target mode"; 3122 break; 3123 case PIT_GRP_7: 3124 str = "group 7 commands in target mode"; 3125 break; 3126 default: 3127 str = "unknown PIT bit set"; 3128 break; 3129 } 3130 3131 fprintf(stdout, "%s\n", str); 3132 } 3133 fprintf(stdout, "%s HBA engine count: %d\n", adapter_str, 3134 cpi->hba_eng_cnt); 3135 fprintf(stdout, "%s maximum target: %d\n", adapter_str, 3136 cpi->max_target); 3137 fprintf(stdout, "%s maximum LUN: %d\n", adapter_str, 3138 cpi->max_lun); 3139 fprintf(stdout, "%s highest path ID in subsystem: %d\n", 3140 adapter_str, cpi->hpath_id); 3141 fprintf(stdout, "%s initiator ID: %d\n", adapter_str, 3142 cpi->initiator_id); 3143 fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid); 3144 fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid); 3145 fprintf(stdout, "%s HBA vendor ID: 0x%04x\n", 3146 adapter_str, cpi->hba_vendor); 3147 fprintf(stdout, "%s HBA device ID: 0x%04x\n", 3148 adapter_str, cpi->hba_device); 3149 fprintf(stdout, "%s HBA subvendor ID: 0x%04x\n", 3150 adapter_str, cpi->hba_subvendor); 3151 fprintf(stdout, "%s HBA subdevice ID: 0x%04x\n", 3152 adapter_str, cpi->hba_subdevice); 3153 fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id); 3154 fprintf(stdout, "%s base transfer speed: ", adapter_str); 3155 if (cpi->base_transfer_speed > 1000) 3156 fprintf(stdout, "%d.%03dMB/sec\n", 3157 cpi->base_transfer_speed / 1000, 3158 cpi->base_transfer_speed % 1000); 3159 else 3160 fprintf(stdout, "%dKB/sec\n", 3161 (cpi->base_transfer_speed % 1000) * 1000); 3162 fprintf(stdout, "%s maximum transfer size: %u bytes\n", 3163 adapter_str, cpi->maxio); 3164} 3165 3166static int 3167get_print_cts(struct cam_device *device, int user_settings, int quiet, 3168 struct ccb_trans_settings *cts) 3169{ 3170 int retval; 3171 union ccb *ccb; 3172 3173 retval = 0; 3174 ccb = cam_getccb(device); 3175 3176 if (ccb == NULL) { 3177 warnx("get_print_cts: error allocating ccb"); 3178 return(1); 3179 } 3180 3181 bzero(&(&ccb->ccb_h)[1], 3182 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr)); 3183 3184 ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; 3185 3186 if (user_settings == 0) 3187 ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS; 3188 else 3189 ccb->cts.type = CTS_TYPE_USER_SETTINGS; 3190 3191 if (cam_send_ccb(device, ccb) < 0) { 3192 perror("error sending XPT_GET_TRAN_SETTINGS CCB"); 3193 if (arglist & CAM_ARG_VERBOSE) 3194 cam_error_print(device, ccb, CAM_ESF_ALL, 3195 CAM_EPF_ALL, stderr); 3196 retval = 1; 3197 goto get_print_cts_bailout; 3198 } 3199 3200 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3201 warnx("XPT_GET_TRANS_SETTINGS CCB failed"); 3202 if (arglist & CAM_ARG_VERBOSE) 3203 cam_error_print(device, ccb, CAM_ESF_ALL, 3204 CAM_EPF_ALL, stderr); 3205 retval = 1; 3206 goto get_print_cts_bailout; 3207 } 3208 3209 if (quiet == 0) 3210 cts_print(device, &ccb->cts); 3211 3212 if (cts != NULL) 3213 bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings)); 3214 3215get_print_cts_bailout: 3216 3217 cam_freeccb(ccb); 3218 3219 return(retval); 3220} 3221 3222static int 3223ratecontrol(struct cam_device *device, int retry_count, int timeout, 3224 int argc, char **argv, char *combinedopt) 3225{ 3226 int c; 3227 union ccb *ccb; 3228 int user_settings = 0; 3229 int retval = 0; 3230 int disc_enable = -1, tag_enable = -1; 3231 int mode = -1; 3232 int offset = -1; 3233 double syncrate = -1; 3234 int bus_width = -1; 3235 int quiet = 0; 3236 int change_settings = 0, send_tur = 0; 3237 struct ccb_pathinq cpi; 3238 3239 ccb = cam_getccb(device); 3240 if (ccb == NULL) { 3241 warnx("ratecontrol: error allocating ccb"); 3242 return(1); 3243 } 3244 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3245 switch(c){ 3246 case 'a': 3247 send_tur = 1; 3248 break; 3249 case 'c': 3250 user_settings = 0; 3251 break; 3252 case 'D': 3253 if (strncasecmp(optarg, "enable", 6) == 0) 3254 disc_enable = 1; 3255 else if (strncasecmp(optarg, "disable", 7) == 0) 3256 disc_enable = 0; 3257 else { 3258 warnx("-D argument \"%s\" is unknown", optarg); 3259 retval = 1; 3260 goto ratecontrol_bailout; 3261 } 3262 change_settings = 1; 3263 break; 3264 case 'M': 3265 mode = ata_string2mode(optarg); 3266 if (mode < 0) { 3267 warnx("unknown mode '%s'", optarg); 3268 retval = 1; 3269 goto ratecontrol_bailout; 3270 } 3271 change_settings = 1; 3272 break; 3273 case 'O': 3274 offset = strtol(optarg, NULL, 0); 3275 if (offset < 0) { 3276 warnx("offset value %d is < 0", offset); 3277 retval = 1; 3278 goto ratecontrol_bailout; 3279 } 3280 change_settings = 1; 3281 break; 3282 case 'q': 3283 quiet++; 3284 break; 3285 case 'R': 3286 syncrate = atof(optarg); 3287 if (syncrate < 0) { 3288 warnx("sync rate %f is < 0", syncrate); 3289 retval = 1; 3290 goto ratecontrol_bailout; 3291 } 3292 change_settings = 1; 3293 break; 3294 case 'T': 3295 if (strncasecmp(optarg, "enable", 6) == 0) 3296 tag_enable = 1; 3297 else if (strncasecmp(optarg, "disable", 7) == 0) 3298 tag_enable = 0; 3299 else { 3300 warnx("-T argument \"%s\" is unknown", optarg); 3301 retval = 1; 3302 goto ratecontrol_bailout; 3303 } 3304 change_settings = 1; 3305 break; 3306 case 'U': 3307 user_settings = 1; 3308 break; 3309 case 'W': 3310 bus_width = strtol(optarg, NULL, 0); 3311 if (bus_width < 0) { 3312 warnx("bus width %d is < 0", bus_width); 3313 retval = 1; 3314 goto ratecontrol_bailout; 3315 } 3316 change_settings = 1; 3317 break; 3318 default: 3319 break; 3320 } 3321 } 3322 bzero(&(&ccb->ccb_h)[1], 3323 sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); 3324 /* 3325 * Grab path inquiry information, so we can determine whether 3326 * or not the initiator is capable of the things that the user 3327 * requests. 3328 */ 3329 ccb->ccb_h.func_code = XPT_PATH_INQ; 3330 if (cam_send_ccb(device, ccb) < 0) { 3331 perror("error sending XPT_PATH_INQ CCB"); 3332 if (arglist & CAM_ARG_VERBOSE) { 3333 cam_error_print(device, ccb, CAM_ESF_ALL, 3334 CAM_EPF_ALL, stderr); 3335 } 3336 retval = 1; 3337 goto ratecontrol_bailout; 3338 } 3339 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3340 warnx("XPT_PATH_INQ CCB failed"); 3341 if (arglist & CAM_ARG_VERBOSE) { 3342 cam_error_print(device, ccb, CAM_ESF_ALL, 3343 CAM_EPF_ALL, stderr); 3344 } 3345 retval = 1; 3346 goto ratecontrol_bailout; 3347 } 3348 bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq)); 3349 bzero(&(&ccb->ccb_h)[1], 3350 sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr)); 3351 if (quiet == 0) { 3352 fprintf(stdout, "%s parameters:\n", 3353 user_settings ? "User" : "Current"); 3354 } 3355 retval = get_print_cts(device, user_settings, quiet, &ccb->cts); 3356 if (retval != 0) 3357 goto ratecontrol_bailout; 3358 3359 if (arglist & CAM_ARG_VERBOSE) 3360 cpi_print(&cpi); 3361 3362 if (change_settings) { 3363 int didsettings = 0; 3364 struct ccb_trans_settings_spi *spi = NULL; 3365 struct ccb_trans_settings_ata *ata = NULL; 3366 struct ccb_trans_settings_sata *sata = NULL; 3367 struct ccb_trans_settings_scsi *scsi = NULL; 3368 3369 if (ccb->cts.transport == XPORT_SPI) 3370 spi = &ccb->cts.xport_specific.spi; 3371 if (ccb->cts.transport == XPORT_ATA) 3372 ata = &ccb->cts.xport_specific.ata; 3373 if (ccb->cts.transport == XPORT_SATA) 3374 sata = &ccb->cts.xport_specific.sata; 3375 if (ccb->cts.protocol == PROTO_SCSI) 3376 scsi = &ccb->cts.proto_specific.scsi; 3377 ccb->cts.xport_specific.valid = 0; 3378 ccb->cts.proto_specific.valid = 0; 3379 if (spi && disc_enable != -1) { 3380 spi->valid |= CTS_SPI_VALID_DISC; 3381 if (disc_enable == 0) 3382 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 3383 else 3384 spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 3385 } 3386 if (scsi && tag_enable != -1) { 3387 if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) { 3388 warnx("HBA does not support tagged queueing, " 3389 "so you cannot modify tag settings"); 3390 retval = 1; 3391 goto ratecontrol_bailout; 3392 } 3393 scsi->valid |= CTS_SCSI_VALID_TQ; 3394 if (tag_enable == 0) 3395 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 3396 else 3397 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 3398 didsettings++; 3399 } 3400 if (spi && offset != -1) { 3401 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 3402 warnx("HBA is not capable of changing offset"); 3403 retval = 1; 3404 goto ratecontrol_bailout; 3405 } 3406 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 3407 spi->sync_offset = offset; 3408 didsettings++; 3409 } 3410 if (spi && syncrate != -1) { 3411 int prelim_sync_period; 3412 u_int freq; 3413 3414 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 3415 warnx("HBA is not capable of changing " 3416 "transfer rates"); 3417 retval = 1; 3418 goto ratecontrol_bailout; 3419 } 3420 spi->valid |= CTS_SPI_VALID_SYNC_RATE; 3421 /* 3422 * The sync rate the user gives us is in MHz. 3423 * We need to translate it into KHz for this 3424 * calculation. 3425 */ 3426 syncrate *= 1000; 3427 /* 3428 * Next, we calculate a "preliminary" sync period 3429 * in tenths of a nanosecond. 3430 */ 3431 if (syncrate == 0) 3432 prelim_sync_period = 0; 3433 else 3434 prelim_sync_period = 10000000 / syncrate; 3435 spi->sync_period = 3436 scsi_calc_syncparam(prelim_sync_period); 3437 freq = scsi_calc_syncsrate(spi->sync_period); 3438 didsettings++; 3439 } 3440 if (sata && syncrate != -1) { 3441 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 3442 warnx("HBA is not capable of changing " 3443 "transfer rates"); 3444 retval = 1; 3445 goto ratecontrol_bailout; 3446 } 3447 sata->revision = ata_speed2revision(syncrate * 100); 3448 if (sata->revision < 0) { 3449 warnx("Invalid rate %f", syncrate); 3450 retval = 1; 3451 goto ratecontrol_bailout; 3452 } 3453 sata->valid |= CTS_SATA_VALID_REVISION; 3454 didsettings++; 3455 } 3456 if ((ata || sata) && mode != -1) { 3457 if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { 3458 warnx("HBA is not capable of changing " 3459 "transfer rates"); 3460 retval = 1; 3461 goto ratecontrol_bailout; 3462 } 3463 if (ata) { 3464 ata->mode = mode; 3465 ata->valid |= CTS_ATA_VALID_MODE; 3466 } else { 3467 sata->mode = mode; 3468 sata->valid |= CTS_SATA_VALID_MODE; 3469 } 3470 didsettings++; 3471 } 3472 /* 3473 * The bus_width argument goes like this: 3474 * 0 == 8 bit 3475 * 1 == 16 bit 3476 * 2 == 32 bit 3477 * Therefore, if you shift the number of bits given on the 3478 * command line right by 4, you should get the correct 3479 * number. 3480 */ 3481 if (spi && bus_width != -1) { 3482 /* 3483 * We might as well validate things here with a 3484 * decipherable error message, rather than what 3485 * will probably be an indecipherable error message 3486 * by the time it gets back to us. 3487 */ 3488 if ((bus_width == 16) 3489 && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) { 3490 warnx("HBA does not support 16 bit bus width"); 3491 retval = 1; 3492 goto ratecontrol_bailout; 3493 } else if ((bus_width == 32) 3494 && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) { 3495 warnx("HBA does not support 32 bit bus width"); 3496 retval = 1; 3497 goto ratecontrol_bailout; 3498 } else if ((bus_width != 8) 3499 && (bus_width != 16) 3500 && (bus_width != 32)) { 3501 warnx("Invalid bus width %d", bus_width); 3502 retval = 1; 3503 goto ratecontrol_bailout; 3504 } 3505 spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 3506 spi->bus_width = bus_width >> 4; 3507 didsettings++; 3508 } 3509 if (didsettings == 0) { 3510 goto ratecontrol_bailout; 3511 } 3512 if (!user_settings && (ata || sata)) { 3513 warnx("You can modify only user settings for ATA/SATA"); 3514 retval = 1; 3515 goto ratecontrol_bailout; 3516 } 3517 ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; 3518 if (cam_send_ccb(device, ccb) < 0) { 3519 perror("error sending XPT_SET_TRAN_SETTINGS CCB"); 3520 if (arglist & CAM_ARG_VERBOSE) { 3521 cam_error_print(device, ccb, CAM_ESF_ALL, 3522 CAM_EPF_ALL, stderr); 3523 } 3524 retval = 1; 3525 goto ratecontrol_bailout; 3526 } 3527 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3528 warnx("XPT_SET_TRANS_SETTINGS CCB failed"); 3529 if (arglist & CAM_ARG_VERBOSE) { 3530 cam_error_print(device, ccb, CAM_ESF_ALL, 3531 CAM_EPF_ALL, stderr); 3532 } 3533 retval = 1; 3534 goto ratecontrol_bailout; 3535 } 3536 } 3537 if (send_tur) { 3538 retval = testunitready(device, retry_count, timeout, 3539 (arglist & CAM_ARG_VERBOSE) ? 0 : 1); 3540 /* 3541 * If the TUR didn't succeed, just bail. 3542 */ 3543 if (retval != 0) { 3544 if (quiet == 0) 3545 fprintf(stderr, "Test Unit Ready failed\n"); 3546 goto ratecontrol_bailout; 3547 } 3548 /* 3549 * If the user wants things quiet, there's no sense in 3550 * getting the transfer settings, if we're not going 3551 * to print them. 3552 */ 3553 if (quiet != 0) 3554 goto ratecontrol_bailout; 3555 fprintf(stdout, "New parameters:\n"); 3556 retval = get_print_cts(device, user_settings, 0, NULL); 3557 } 3558 3559ratecontrol_bailout: 3560 cam_freeccb(ccb); 3561 return(retval); 3562} 3563 3564static int 3565scsiformat(struct cam_device *device, int argc, char **argv, 3566 char *combinedopt, int retry_count, int timeout) 3567{ 3568 union ccb *ccb; 3569 int c; 3570 int ycount = 0, quiet = 0; 3571 int error = 0, response = 0, retval = 0; 3572 int use_timeout = 10800 * 1000; 3573 int immediate = 1; 3574 struct format_defect_list_header fh; 3575 u_int8_t *data_ptr = NULL; 3576 u_int32_t dxfer_len = 0; 3577 u_int8_t byte2 = 0; 3578 int num_warnings = 0; 3579 int reportonly = 0; 3580 3581 ccb = cam_getccb(device); 3582 3583 if (ccb == NULL) { 3584 warnx("scsiformat: error allocating ccb"); 3585 return(1); 3586 } 3587 3588 bzero(&(&ccb->ccb_h)[1], 3589 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 3590 3591 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3592 switch(c) { 3593 case 'q': 3594 quiet++; 3595 break; 3596 case 'r': 3597 reportonly = 1; 3598 break; 3599 case 'w': 3600 immediate = 0; 3601 break; 3602 case 'y': 3603 ycount++; 3604 break; 3605 } 3606 } 3607 3608 if (reportonly) 3609 goto doreport; 3610 3611 if (quiet == 0) { 3612 fprintf(stdout, "You are about to REMOVE ALL DATA from the " 3613 "following device:\n"); 3614 3615 error = scsidoinquiry(device, argc, argv, combinedopt, 3616 retry_count, timeout); 3617 3618 if (error != 0) { 3619 warnx("scsiformat: error sending inquiry"); 3620 goto scsiformat_bailout; 3621 } 3622 } 3623 3624 if (ycount == 0) { 3625 3626 do { 3627 char str[1024]; 3628 3629 fprintf(stdout, "Are you SURE you want to do " 3630 "this? (yes/no) "); 3631 3632 if (fgets(str, sizeof(str), stdin) != NULL) { 3633 3634 if (strncasecmp(str, "yes", 3) == 0) 3635 response = 1; 3636 else if (strncasecmp(str, "no", 2) == 0) 3637 response = -1; 3638 else { 3639 fprintf(stdout, "Please answer" 3640 " \"yes\" or \"no\"\n"); 3641 } 3642 } 3643 } while (response == 0); 3644 3645 if (response == -1) { 3646 error = 1; 3647 goto scsiformat_bailout; 3648 } 3649 } 3650 3651 if (timeout != 0) 3652 use_timeout = timeout; 3653 3654 if (quiet == 0) { 3655 fprintf(stdout, "Current format timeout is %d seconds\n", 3656 use_timeout / 1000); 3657 } 3658 3659 /* 3660 * If the user hasn't disabled questions and didn't specify a 3661 * timeout on the command line, ask them if they want the current 3662 * timeout. 3663 */ 3664 if ((ycount == 0) 3665 && (timeout == 0)) { 3666 char str[1024]; 3667 int new_timeout = 0; 3668 3669 fprintf(stdout, "Enter new timeout in seconds or press\n" 3670 "return to keep the current timeout [%d] ", 3671 use_timeout / 1000); 3672 3673 if (fgets(str, sizeof(str), stdin) != NULL) { 3674 if (str[0] != '\0') 3675 new_timeout = atoi(str); 3676 } 3677 3678 if (new_timeout != 0) { 3679 use_timeout = new_timeout * 1000; 3680 fprintf(stdout, "Using new timeout value %d\n", 3681 use_timeout / 1000); 3682 } 3683 } 3684 3685 /* 3686 * Keep this outside the if block below to silence any unused 3687 * variable warnings. 3688 */ 3689 bzero(&fh, sizeof(fh)); 3690 3691 /* 3692 * If we're in immediate mode, we've got to include the format 3693 * header 3694 */ 3695 if (immediate != 0) { 3696 fh.byte2 = FU_DLH_IMMED; 3697 data_ptr = (u_int8_t *)&fh; 3698 dxfer_len = sizeof(fh); 3699 byte2 = FU_FMT_DATA; 3700 } else if (quiet == 0) { 3701 fprintf(stdout, "Formatting..."); 3702 fflush(stdout); 3703 } 3704 3705 scsi_format_unit(&ccb->csio, 3706 /* retries */ retry_count, 3707 /* cbfcnp */ NULL, 3708 /* tag_action */ MSG_SIMPLE_Q_TAG, 3709 /* byte2 */ byte2, 3710 /* ileave */ 0, 3711 /* data_ptr */ data_ptr, 3712 /* dxfer_len */ dxfer_len, 3713 /* sense_len */ SSD_FULL_SIZE, 3714 /* timeout */ use_timeout); 3715 3716 /* Disable freezing the device queue */ 3717 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3718 3719 if (arglist & CAM_ARG_ERR_RECOVER) 3720 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 3721 3722 if (((retval = cam_send_ccb(device, ccb)) < 0) 3723 || ((immediate == 0) 3724 && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP))) { 3725 const char errstr[] = "error sending format command"; 3726 3727 if (retval < 0) 3728 warn(errstr); 3729 else 3730 warnx(errstr); 3731 3732 if (arglist & CAM_ARG_VERBOSE) { 3733 cam_error_print(device, ccb, CAM_ESF_ALL, 3734 CAM_EPF_ALL, stderr); 3735 } 3736 error = 1; 3737 goto scsiformat_bailout; 3738 } 3739 3740 /* 3741 * If we ran in non-immediate mode, we already checked for errors 3742 * above and printed out any necessary information. If we're in 3743 * immediate mode, we need to loop through and get status 3744 * information periodically. 3745 */ 3746 if (immediate == 0) { 3747 if (quiet == 0) { 3748 fprintf(stdout, "Format Complete\n"); 3749 } 3750 goto scsiformat_bailout; 3751 } 3752 3753doreport: 3754 do { 3755 cam_status status; 3756 3757 bzero(&(&ccb->ccb_h)[1], 3758 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 3759 3760 /* 3761 * There's really no need to do error recovery or 3762 * retries here, since we're just going to sit in a 3763 * loop and wait for the device to finish formatting. 3764 */ 3765 scsi_test_unit_ready(&ccb->csio, 3766 /* retries */ 0, 3767 /* cbfcnp */ NULL, 3768 /* tag_action */ MSG_SIMPLE_Q_TAG, 3769 /* sense_len */ SSD_FULL_SIZE, 3770 /* timeout */ 5000); 3771 3772 /* Disable freezing the device queue */ 3773 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3774 3775 retval = cam_send_ccb(device, ccb); 3776 3777 /* 3778 * If we get an error from the ioctl, bail out. SCSI 3779 * errors are expected. 3780 */ 3781 if (retval < 0) { 3782 warn("error sending CAMIOCOMMAND ioctl"); 3783 if (arglist & CAM_ARG_VERBOSE) { 3784 cam_error_print(device, ccb, CAM_ESF_ALL, 3785 CAM_EPF_ALL, stderr); 3786 } 3787 error = 1; 3788 goto scsiformat_bailout; 3789 } 3790 3791 status = ccb->ccb_h.status & CAM_STATUS_MASK; 3792 3793 if ((status != CAM_REQ_CMP) 3794 && (status == CAM_SCSI_STATUS_ERROR) 3795 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 3796 struct scsi_sense_data *sense; 3797 int error_code, sense_key, asc, ascq; 3798 3799 sense = &ccb->csio.sense_data; 3800 scsi_extract_sense(sense, &error_code, &sense_key, 3801 &asc, &ascq); 3802 3803 /* 3804 * According to the SCSI-2 and SCSI-3 specs, a 3805 * drive that is in the middle of a format should 3806 * return NOT READY with an ASC of "logical unit 3807 * not ready, format in progress". The sense key 3808 * specific bytes will then be a progress indicator. 3809 */ 3810 if ((sense_key == SSD_KEY_NOT_READY) 3811 && (asc == 0x04) && (ascq == 0x04)) { 3812 if ((sense->extra_len >= 10) 3813 && ((sense->sense_key_spec[0] & 3814 SSD_SCS_VALID) != 0) 3815 && (quiet == 0)) { 3816 int val; 3817 u_int64_t percentage; 3818 3819 val = scsi_2btoul( 3820 &sense->sense_key_spec[1]); 3821 percentage = 10000 * val; 3822 3823 fprintf(stdout, 3824 "\rFormatting: %ju.%02u %% " 3825 "(%d/%d) done", 3826 (uintmax_t)(percentage / 3827 (0x10000 * 100)), 3828 (unsigned)((percentage / 3829 0x10000) % 100), 3830 val, 0x10000); 3831 fflush(stdout); 3832 } else if ((quiet == 0) 3833 && (++num_warnings <= 1)) { 3834 warnx("Unexpected SCSI Sense Key " 3835 "Specific value returned " 3836 "during format:"); 3837 scsi_sense_print(device, &ccb->csio, 3838 stderr); 3839 warnx("Unable to print status " 3840 "information, but format will " 3841 "proceed."); 3842 warnx("will exit when format is " 3843 "complete"); 3844 } 3845 sleep(1); 3846 } else { 3847 warnx("Unexpected SCSI error during format"); 3848 cam_error_print(device, ccb, CAM_ESF_ALL, 3849 CAM_EPF_ALL, stderr); 3850 error = 1; 3851 goto scsiformat_bailout; 3852 } 3853 3854 } else if (status != CAM_REQ_CMP) { 3855 warnx("Unexpected CAM status %#x", status); 3856 if (arglist & CAM_ARG_VERBOSE) 3857 cam_error_print(device, ccb, CAM_ESF_ALL, 3858 CAM_EPF_ALL, stderr); 3859 error = 1; 3860 goto scsiformat_bailout; 3861 } 3862 3863 } while((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP); 3864 3865 if (quiet == 0) 3866 fprintf(stdout, "\nFormat Complete\n"); 3867 3868scsiformat_bailout: 3869 3870 cam_freeccb(ccb); 3871 3872 return(error); 3873} 3874 3875static int 3876scsireportluns(struct cam_device *device, int argc, char **argv, 3877 char *combinedopt, int retry_count, int timeout) 3878{ 3879 union ccb *ccb; 3880 int c, countonly, lunsonly; 3881 struct scsi_report_luns_data *lundata; 3882 int alloc_len; 3883 uint8_t report_type; 3884 uint32_t list_len, i, j; 3885 int retval; 3886 3887 retval = 0; 3888 lundata = NULL; 3889 report_type = RPL_REPORT_DEFAULT; 3890 ccb = cam_getccb(device); 3891 3892 if (ccb == NULL) { 3893 warnx("%s: error allocating ccb", __func__); 3894 return (1); 3895 } 3896 3897 bzero(&(&ccb->ccb_h)[1], 3898 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 3899 3900 countonly = 0; 3901 lunsonly = 0; 3902 3903 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3904 switch (c) { 3905 case 'c': 3906 countonly++; 3907 break; 3908 case 'l': 3909 lunsonly++; 3910 break; 3911 case 'r': 3912 if (strcasecmp(optarg, "default") == 0) 3913 report_type = RPL_REPORT_DEFAULT; 3914 else if (strcasecmp(optarg, "wellknown") == 0) 3915 report_type = RPL_REPORT_WELLKNOWN; 3916 else if (strcasecmp(optarg, "all") == 0) 3917 report_type = RPL_REPORT_ALL; 3918 else { 3919 warnx("%s: invalid report type \"%s\"", 3920 __func__, optarg); 3921 retval = 1; 3922 goto bailout; 3923 } 3924 break; 3925 default: 3926 break; 3927 } 3928 } 3929 3930 if ((countonly != 0) 3931 && (lunsonly != 0)) { 3932 warnx("%s: you can only specify one of -c or -l", __func__); 3933 retval = 1; 3934 goto bailout; 3935 } 3936 /* 3937 * According to SPC-4, the allocation length must be at least 16 3938 * bytes -- enough for the header and one LUN. 3939 */ 3940 alloc_len = sizeof(*lundata) + 8; 3941 3942retry: 3943 3944 lundata = malloc(alloc_len); 3945 3946 if (lundata == NULL) { 3947 warn("%s: error mallocing %d bytes", __func__, alloc_len); 3948 retval = 1; 3949 goto bailout; 3950 } 3951 3952 scsi_report_luns(&ccb->csio, 3953 /*retries*/ retry_count, 3954 /*cbfcnp*/ NULL, 3955 /*tag_action*/ MSG_SIMPLE_Q_TAG, 3956 /*select_report*/ report_type, 3957 /*rpl_buf*/ lundata, 3958 /*alloc_len*/ alloc_len, 3959 /*sense_len*/ SSD_FULL_SIZE, 3960 /*timeout*/ timeout ? timeout : 5000); 3961 3962 /* Disable freezing the device queue */ 3963 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3964 3965 if (arglist & CAM_ARG_ERR_RECOVER) 3966 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 3967 3968 if (cam_send_ccb(device, ccb) < 0) { 3969 warn("error sending REPORT LUNS command"); 3970 3971 if (arglist & CAM_ARG_VERBOSE) 3972 cam_error_print(device, ccb, CAM_ESF_ALL, 3973 CAM_EPF_ALL, stderr); 3974 3975 retval = 1; 3976 goto bailout; 3977 } 3978 3979 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3980 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 3981 retval = 1; 3982 goto bailout; 3983 } 3984 3985 3986 list_len = scsi_4btoul(lundata->length); 3987 3988 /* 3989 * If we need to list the LUNs, and our allocation 3990 * length was too short, reallocate and retry. 3991 */ 3992 if ((countonly == 0) 3993 && (list_len > (alloc_len - sizeof(*lundata)))) { 3994 alloc_len = list_len + sizeof(*lundata); 3995 free(lundata); 3996 goto retry; 3997 } 3998 3999 if (lunsonly == 0) 4000 fprintf(stdout, "%u LUN%s found\n", list_len / 8, 4001 ((list_len / 8) > 1) ? "s" : ""); 4002 4003 if (countonly != 0) 4004 goto bailout; 4005 4006 for (i = 0; i < (list_len / 8); i++) { 4007 int no_more; 4008 4009 no_more = 0; 4010 for (j = 0; j < sizeof(lundata->luns[i].lundata); j += 2) { 4011 if (j != 0) 4012 fprintf(stdout, ","); 4013 switch (lundata->luns[i].lundata[j] & 4014 RPL_LUNDATA_ATYP_MASK) { 4015 case RPL_LUNDATA_ATYP_PERIPH: 4016 if ((lundata->luns[i].lundata[j] & 4017 RPL_LUNDATA_PERIPH_BUS_MASK) != 0) 4018 fprintf(stdout, "%d:", 4019 lundata->luns[i].lundata[j] & 4020 RPL_LUNDATA_PERIPH_BUS_MASK); 4021 else if ((j == 0) 4022 && ((lundata->luns[i].lundata[j+2] & 4023 RPL_LUNDATA_PERIPH_BUS_MASK) == 0)) 4024 no_more = 1; 4025 4026 fprintf(stdout, "%d", 4027 lundata->luns[i].lundata[j+1]); 4028 break; 4029 case RPL_LUNDATA_ATYP_FLAT: { 4030 uint8_t tmplun[2]; 4031 tmplun[0] = lundata->luns[i].lundata[j] & 4032 RPL_LUNDATA_FLAT_LUN_MASK; 4033 tmplun[1] = lundata->luns[i].lundata[j+1]; 4034 4035 fprintf(stdout, "%d", scsi_2btoul(tmplun)); 4036 no_more = 1; 4037 break; 4038 } 4039 case RPL_LUNDATA_ATYP_LUN: 4040 fprintf(stdout, "%d:%d:%d", 4041 (lundata->luns[i].lundata[j+1] & 4042 RPL_LUNDATA_LUN_BUS_MASK) >> 5, 4043 lundata->luns[i].lundata[j] & 4044 RPL_LUNDATA_LUN_TARG_MASK, 4045 lundata->luns[i].lundata[j+1] & 4046 RPL_LUNDATA_LUN_LUN_MASK); 4047 break; 4048 case RPL_LUNDATA_ATYP_EXTLUN: { 4049 int field_len, field_len_code, eam_code; 4050 4051 eam_code = lundata->luns[i].lundata[j] & 4052 RPL_LUNDATA_EXT_EAM_MASK; 4053 field_len_code = (lundata->luns[i].lundata[j] & 4054 RPL_LUNDATA_EXT_LEN_MASK) >> 4; 4055 field_len = field_len_code * 2; 4056 4057 if ((eam_code == RPL_LUNDATA_EXT_EAM_WK) 4058 && (field_len_code == 0x00)) { 4059 fprintf(stdout, "%d", 4060 lundata->luns[i].lundata[j+1]); 4061 } else if ((eam_code == 4062 RPL_LUNDATA_EXT_EAM_NOT_SPEC) 4063 && (field_len_code == 0x03)) { 4064 uint8_t tmp_lun[8]; 4065 4066 /* 4067 * This format takes up all 8 bytes. 4068 * If we aren't starting at offset 0, 4069 * that's a bug. 4070 */ 4071 if (j != 0) { 4072 fprintf(stdout, "Invalid " 4073 "offset %d for " 4074 "Extended LUN not " 4075 "specified format", j); 4076 no_more = 1; 4077 break; 4078 } 4079 bzero(tmp_lun, sizeof(tmp_lun)); 4080 bcopy(&lundata->luns[i].lundata[j+1], 4081 &tmp_lun[1], sizeof(tmp_lun) - 1); 4082 fprintf(stdout, "%#jx", 4083 (intmax_t)scsi_8btou64(tmp_lun)); 4084 no_more = 1; 4085 } else { 4086 fprintf(stderr, "Unknown Extended LUN" 4087 "Address method %#x, length " 4088 "code %#x", eam_code, 4089 field_len_code); 4090 no_more = 1; 4091 } 4092 break; 4093 } 4094 default: 4095 fprintf(stderr, "Unknown LUN address method " 4096 "%#x\n", lundata->luns[i].lundata[0] & 4097 RPL_LUNDATA_ATYP_MASK); 4098 break; 4099 } 4100 /* 4101 * For the flat addressing method, there are no 4102 * other levels after it. 4103 */ 4104 if (no_more != 0) 4105 break; 4106 } 4107 fprintf(stdout, "\n"); 4108 } 4109 4110bailout: 4111 4112 cam_freeccb(ccb); 4113 4114 free(lundata); 4115 4116 return (retval); 4117} 4118 4119static int 4120scsireadcapacity(struct cam_device *device, int argc, char **argv, 4121 char *combinedopt, int retry_count, int timeout) 4122{ 4123 union ccb *ccb; 4124 int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten; 4125 struct scsi_read_capacity_data rcap; 4126 struct scsi_read_capacity_data_long rcaplong; 4127 uint64_t maxsector; 4128 uint32_t block_len; 4129 int retval; 4130 int c; 4131 4132 blocksizeonly = 0; 4133 humanize = 0; 4134 numblocks = 0; 4135 quiet = 0; 4136 sizeonly = 0; 4137 baseten = 0; 4138 retval = 0; 4139 4140 ccb = cam_getccb(device); 4141 4142 if (ccb == NULL) { 4143 warnx("%s: error allocating ccb", __func__); 4144 return (1); 4145 } 4146 4147 bzero(&(&ccb->ccb_h)[1], 4148 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 4149 4150 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4151 switch (c) { 4152 case 'b': 4153 blocksizeonly++; 4154 break; 4155 case 'h': 4156 humanize++; 4157 baseten = 0; 4158 break; 4159 case 'H': 4160 humanize++; 4161 baseten++; 4162 break; 4163 case 'N': 4164 numblocks++; 4165 break; 4166 case 'q': 4167 quiet++; 4168 break; 4169 case 's': 4170 sizeonly++; 4171 break; 4172 default: 4173 break; 4174 } 4175 } 4176 4177 if ((blocksizeonly != 0) 4178 && (numblocks != 0)) { 4179 warnx("%s: you can only specify one of -b or -N", __func__); 4180 retval = 1; 4181 goto bailout; 4182 } 4183 4184 if ((blocksizeonly != 0) 4185 && (sizeonly != 0)) { 4186 warnx("%s: you can only specify one of -b or -s", __func__); 4187 retval = 1; 4188 goto bailout; 4189 } 4190 4191 if ((humanize != 0) 4192 && (quiet != 0)) { 4193 warnx("%s: you can only specify one of -h/-H or -q", __func__); 4194 retval = 1; 4195 goto bailout; 4196 } 4197 4198 if ((humanize != 0) 4199 && (blocksizeonly != 0)) { 4200 warnx("%s: you can only specify one of -h/-H or -b", __func__); 4201 retval = 1; 4202 goto bailout; 4203 } 4204 4205 scsi_read_capacity(&ccb->csio, 4206 /*retries*/ retry_count, 4207 /*cbfcnp*/ NULL, 4208 /*tag_action*/ MSG_SIMPLE_Q_TAG, 4209 &rcap, 4210 SSD_FULL_SIZE, 4211 /*timeout*/ timeout ? timeout : 5000); 4212 4213 /* Disable freezing the device queue */ 4214 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 4215 4216 if (arglist & CAM_ARG_ERR_RECOVER) 4217 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 4218 4219 if (cam_send_ccb(device, ccb) < 0) { 4220 warn("error sending READ CAPACITY command"); 4221 4222 if (arglist & CAM_ARG_VERBOSE) 4223 cam_error_print(device, ccb, CAM_ESF_ALL, 4224 CAM_EPF_ALL, stderr); 4225 4226 retval = 1; 4227 goto bailout; 4228 } 4229 4230 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 4231 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 4232 retval = 1; 4233 goto bailout; 4234 } 4235 4236 maxsector = scsi_4btoul(rcap.addr); 4237 block_len = scsi_4btoul(rcap.length); 4238 4239 /* 4240 * A last block of 2^32-1 means that the true capacity is over 2TB, 4241 * and we need to issue the long READ CAPACITY to get the real 4242 * capacity. Otherwise, we're all set. 4243 */ 4244 if (maxsector != 0xffffffff) 4245 goto do_print; 4246 4247 scsi_read_capacity_16(&ccb->csio, 4248 /*retries*/ retry_count, 4249 /*cbfcnp*/ NULL, 4250 /*tag_action*/ MSG_SIMPLE_Q_TAG, 4251 /*lba*/ 0, 4252 /*reladdr*/ 0, 4253 /*pmi*/ 0, 4254 &rcaplong, 4255 /*sense_len*/ SSD_FULL_SIZE, 4256 /*timeout*/ timeout ? timeout : 5000); 4257 4258 /* Disable freezing the device queue */ 4259 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 4260 4261 if (arglist & CAM_ARG_ERR_RECOVER) 4262 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 4263 4264 if (cam_send_ccb(device, ccb) < 0) { 4265 warn("error sending READ CAPACITY (16) command"); 4266 4267 if (arglist & CAM_ARG_VERBOSE) 4268 cam_error_print(device, ccb, CAM_ESF_ALL, 4269 CAM_EPF_ALL, stderr); 4270 4271 retval = 1; 4272 goto bailout; 4273 } 4274 4275 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 4276 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 4277 retval = 1; 4278 goto bailout; 4279 } 4280 4281 maxsector = scsi_8btou64(rcaplong.addr); 4282 block_len = scsi_4btoul(rcaplong.length); 4283 4284do_print: 4285 if (blocksizeonly == 0) { 4286 /* 4287 * Humanize implies !quiet, and also implies numblocks. 4288 */ 4289 if (humanize != 0) { 4290 char tmpstr[6]; 4291 int64_t tmpbytes; 4292 int ret; 4293 4294 tmpbytes = (maxsector + 1) * block_len; 4295 ret = humanize_number(tmpstr, sizeof(tmpstr), 4296 tmpbytes, "", HN_AUTOSCALE, 4297 HN_B | HN_DECIMAL | 4298 ((baseten != 0) ? 4299 HN_DIVISOR_1000 : 0)); 4300 if (ret == -1) { 4301 warnx("%s: humanize_number failed!", __func__); 4302 retval = 1; 4303 goto bailout; 4304 } 4305 fprintf(stdout, "Device Size: %s%s", tmpstr, 4306 (sizeonly == 0) ? ", " : "\n"); 4307 } else if (numblocks != 0) { 4308 fprintf(stdout, "%s%ju%s", (quiet == 0) ? 4309 "Blocks: " : "", (uintmax_t)maxsector + 1, 4310 (sizeonly == 0) ? ", " : "\n"); 4311 } else { 4312 fprintf(stdout, "%s%ju%s", (quiet == 0) ? 4313 "Last Block: " : "", (uintmax_t)maxsector, 4314 (sizeonly == 0) ? ", " : "\n"); 4315 } 4316 } 4317 if (sizeonly == 0) 4318 fprintf(stdout, "%s%u%s\n", (quiet == 0) ? 4319 "Block Length: " : "", block_len, (quiet == 0) ? 4320 " bytes" : ""); 4321bailout: 4322 cam_freeccb(ccb); 4323 4324 return (retval); 4325} 4326 4327static int 4328smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, 4329 int retry_count, int timeout) 4330{ 4331 int c, error; 4332 union ccb *ccb; 4333 uint8_t *smp_request = NULL, *smp_response = NULL; 4334 int request_size = 0, response_size = 0; 4335 int fd_request = 0, fd_response = 0; 4336 char *datastr = NULL; 4337 struct get_hook hook; 4338 int retval; 4339 int flags = 0; 4340 4341 /* 4342 * Note that at the moment we don't support sending SMP CCBs to 4343 * devices that aren't probed by CAM. 4344 */ 4345 ccb = cam_getccb(device); 4346 if (ccb == NULL) { 4347 warnx("%s: error allocating CCB", __func__); 4348 return (1); 4349 } 4350 4351 bzero(&(&ccb->ccb_h)[1], 4352 sizeof(union ccb) - sizeof(struct ccb_hdr)); 4353 4354 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4355 switch (c) { 4356 case 'R': 4357 arglist |= CAM_ARG_CMD_IN; 4358 response_size = strtol(optarg, NULL, 0); 4359 if (response_size <= 0) { 4360 warnx("invalid number of response bytes %d", 4361 response_size); 4362 error = 1; 4363 goto smpcmd_bailout; 4364 } 4365 hook.argc = argc - optind; 4366 hook.argv = argv + optind; 4367 hook.got = 0; 4368 optind++; 4369 datastr = cget(&hook, NULL); 4370 /* 4371 * If the user supplied "-" instead of a format, he 4372 * wants the data to be written to stdout. 4373 */ 4374 if ((datastr != NULL) 4375 && (datastr[0] == '-')) 4376 fd_response = 1; 4377 4378 smp_response = (u_int8_t *)malloc(response_size); 4379 if (smp_response == NULL) { 4380 warn("can't malloc memory for SMP response"); 4381 error = 1; 4382 goto smpcmd_bailout; 4383 } 4384 break; 4385 case 'r': 4386 arglist |= CAM_ARG_CMD_OUT; 4387 request_size = strtol(optarg, NULL, 0); 4388 if (request_size <= 0) { 4389 warnx("invalid number of request bytes %d", 4390 request_size); 4391 error = 1; 4392 goto smpcmd_bailout; 4393 } 4394 hook.argc = argc - optind; 4395 hook.argv = argv + optind; 4396 hook.got = 0; 4397 datastr = cget(&hook, NULL); 4398 smp_request = (u_int8_t *)malloc(request_size); 4399 if (smp_request == NULL) { 4400 warn("can't malloc memory for SMP request"); 4401 error = 1; 4402 goto smpcmd_bailout; 4403 } 4404 bzero(smp_request, request_size); 4405 /* 4406 * If the user supplied "-" instead of a format, he 4407 * wants the data to be read from stdin. 4408 */ 4409 if ((datastr != NULL) 4410 && (datastr[0] == '-')) 4411 fd_request = 1; 4412 else 4413 buff_encode_visit(smp_request, request_size, 4414 datastr, 4415 iget, &hook); 4416 optind += hook.got; 4417 break; 4418 default: 4419 break; 4420 } 4421 } 4422 4423 /* 4424 * If fd_data is set, and we're writing to the device, we need to 4425 * read the data the user wants written from stdin. 4426 */ 4427 if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) { 4428 ssize_t amt_read; 4429 int amt_to_read = request_size; 4430 u_int8_t *buf_ptr = smp_request; 4431 4432 for (amt_read = 0; amt_to_read > 0; 4433 amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) { 4434 if (amt_read == -1) { 4435 warn("error reading data from stdin"); 4436 error = 1; 4437 goto smpcmd_bailout; 4438 } 4439 amt_to_read -= amt_read; 4440 buf_ptr += amt_read; 4441 } 4442 } 4443 4444 if (((arglist & CAM_ARG_CMD_IN) == 0) 4445 || ((arglist & CAM_ARG_CMD_OUT) == 0)) { 4446 warnx("%s: need both the request (-r) and response (-R) " 4447 "arguments", __func__); 4448 error = 1; 4449 goto smpcmd_bailout; 4450 } 4451 4452 flags |= CAM_DEV_QFRZDIS; 4453 4454 cam_fill_smpio(&ccb->smpio, 4455 /*retries*/ retry_count, 4456 /*cbfcnp*/ NULL, 4457 /*flags*/ flags, 4458 /*smp_request*/ smp_request, 4459 /*smp_request_len*/ request_size, 4460 /*smp_response*/ smp_response, 4461 /*smp_response_len*/ response_size, 4462 /*timeout*/ timeout ? timeout : 5000); 4463 4464 ccb->smpio.flags = SMP_FLAG_NONE; 4465 4466 if (((retval = cam_send_ccb(device, ccb)) < 0) 4467 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4468 const char *warnstr = "error sending command"; 4469 4470 if (retval < 0) 4471 warn(warnstr); 4472 else 4473 warnx(warnstr); 4474 4475 if (arglist & CAM_ARG_VERBOSE) { 4476 cam_error_print(device, ccb, CAM_ESF_ALL, 4477 CAM_EPF_ALL, stderr); 4478 } 4479 } 4480 4481 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 4482 && (response_size > 0)) { 4483 if (fd_response == 0) { 4484 buff_decode_visit(smp_response, response_size, 4485 datastr, arg_put, NULL); 4486 fprintf(stdout, "\n"); 4487 } else { 4488 ssize_t amt_written; 4489 int amt_to_write = response_size; 4490 u_int8_t *buf_ptr = smp_response; 4491 4492 for (amt_written = 0; (amt_to_write > 0) && 4493 (amt_written = write(STDOUT_FILENO, buf_ptr, 4494 amt_to_write)) > 0;){ 4495 amt_to_write -= amt_written; 4496 buf_ptr += amt_written; 4497 } 4498 if (amt_written == -1) { 4499 warn("error writing data to stdout"); 4500 error = 1; 4501 goto smpcmd_bailout; 4502 } else if ((amt_written == 0) 4503 && (amt_to_write > 0)) { 4504 warnx("only wrote %u bytes out of %u", 4505 response_size - amt_to_write, 4506 response_size); 4507 } 4508 } 4509 } 4510smpcmd_bailout: 4511 if (ccb != NULL) 4512 cam_freeccb(ccb); 4513 4514 if (smp_request != NULL) 4515 free(smp_request); 4516 4517 if (smp_response != NULL) 4518 free(smp_response); 4519 4520 return (error); 4521} 4522 4523static int 4524smpreportgeneral(struct cam_device *device, int argc, char **argv, 4525 char *combinedopt, int retry_count, int timeout) 4526{ 4527 union ccb *ccb; 4528 struct smp_report_general_request *request = NULL; 4529 struct smp_report_general_response *response = NULL; 4530 struct sbuf *sb = NULL; 4531 int error = 0; 4532 int c, long_response = 0; 4533 int retval; 4534 4535 /* 4536 * Note that at the moment we don't support sending SMP CCBs to 4537 * devices that aren't probed by CAM. 4538 */ 4539 ccb = cam_getccb(device); 4540 if (ccb == NULL) { 4541 warnx("%s: error allocating CCB", __func__); 4542 return (1); 4543 } 4544 4545 bzero(&(&ccb->ccb_h)[1], 4546 sizeof(union ccb) - sizeof(struct ccb_hdr)); 4547 4548 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4549 switch (c) { 4550 case 'l': 4551 long_response = 1; 4552 break; 4553 default: 4554 break; 4555 } 4556 } 4557 request = malloc(sizeof(*request)); 4558 if (request == NULL) { 4559 warn("%s: unable to allocate %zd bytes", __func__, 4560 sizeof(*request)); 4561 error = 1; 4562 goto bailout; 4563 } 4564 4565 response = malloc(sizeof(*response)); 4566 if (response == NULL) { 4567 warn("%s: unable to allocate %zd bytes", __func__, 4568 sizeof(*response)); 4569 error = 1; 4570 goto bailout; 4571 } 4572 4573try_long: 4574 smp_report_general(&ccb->smpio, 4575 retry_count, 4576 /*cbfcnp*/ NULL, 4577 request, 4578 /*request_len*/ sizeof(*request), 4579 (uint8_t *)response, 4580 /*response_len*/ sizeof(*response), 4581 /*long_response*/ long_response, 4582 timeout); 4583 4584 if (((retval = cam_send_ccb(device, ccb)) < 0) 4585 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4586 const char *warnstr = "error sending command"; 4587 4588 if (retval < 0) 4589 warn(warnstr); 4590 else 4591 warnx(warnstr); 4592 4593 if (arglist & CAM_ARG_VERBOSE) { 4594 cam_error_print(device, ccb, CAM_ESF_ALL, 4595 CAM_EPF_ALL, stderr); 4596 } 4597 error = 1; 4598 goto bailout; 4599 } 4600 4601 /* 4602 * If the device supports the long response bit, try again and see 4603 * if we can get all of the data. 4604 */ 4605 if ((response->long_response & SMP_RG_LONG_RESPONSE) 4606 && (long_response == 0)) { 4607 ccb->ccb_h.status = CAM_REQ_INPROG; 4608 bzero(&(&ccb->ccb_h)[1], 4609 sizeof(union ccb) - sizeof(struct ccb_hdr)); 4610 long_response = 1; 4611 goto try_long; 4612 } 4613 4614 /* 4615 * XXX KDM detect and decode SMP errors here. 4616 */ 4617 sb = sbuf_new_auto(); 4618 if (sb == NULL) { 4619 warnx("%s: error allocating sbuf", __func__); 4620 goto bailout; 4621 } 4622 4623 smp_report_general_sbuf(response, sizeof(*response), sb); 4624 4625 sbuf_finish(sb); 4626 4627 printf("%s", sbuf_data(sb)); 4628 4629bailout: 4630 if (ccb != NULL) 4631 cam_freeccb(ccb); 4632 4633 if (request != NULL) 4634 free(request); 4635 4636 if (response != NULL) 4637 free(response); 4638 4639 if (sb != NULL) 4640 sbuf_delete(sb); 4641 4642 return (error); 4643} 4644 4645struct camcontrol_opts phy_ops[] = { 4646 {"nop", SMP_PC_PHY_OP_NOP, CAM_ARG_NONE, NULL}, 4647 {"linkreset", SMP_PC_PHY_OP_LINK_RESET, CAM_ARG_NONE, NULL}, 4648 {"hardreset", SMP_PC_PHY_OP_HARD_RESET, CAM_ARG_NONE, NULL}, 4649 {"disable", SMP_PC_PHY_OP_DISABLE, CAM_ARG_NONE, NULL}, 4650 {"clearerrlog", SMP_PC_PHY_OP_CLEAR_ERR_LOG, CAM_ARG_NONE, NULL}, 4651 {"clearaffiliation", SMP_PC_PHY_OP_CLEAR_AFFILIATON, CAM_ARG_NONE,NULL}, 4652 {"sataportsel", SMP_PC_PHY_OP_TRANS_SATA_PSS, CAM_ARG_NONE, NULL}, 4653 {"clearitnl", SMP_PC_PHY_OP_CLEAR_STP_ITN_LS, CAM_ARG_NONE, NULL}, 4654 {"setdevname", SMP_PC_PHY_OP_SET_ATT_DEV_NAME, CAM_ARG_NONE, NULL}, 4655 {NULL, 0, 0, NULL} 4656}; 4657 4658static int 4659smpphycontrol(struct cam_device *device, int argc, char **argv, 4660 char *combinedopt, int retry_count, int timeout) 4661{ 4662 union ccb *ccb; 4663 struct smp_phy_control_request *request = NULL; 4664 struct smp_phy_control_response *response = NULL; 4665 int long_response = 0; 4666 int retval = 0; 4667 int phy = -1; 4668 uint32_t phy_operation = SMP_PC_PHY_OP_NOP; 4669 int phy_op_set = 0; 4670 uint64_t attached_dev_name = 0; 4671 int dev_name_set = 0; 4672 uint32_t min_plr = 0, max_plr = 0; 4673 uint32_t pp_timeout_val = 0; 4674 int slumber_partial = 0; 4675 int set_pp_timeout_val = 0; 4676 int c; 4677 4678 /* 4679 * Note that at the moment we don't support sending SMP CCBs to 4680 * devices that aren't probed by CAM. 4681 */ 4682 ccb = cam_getccb(device); 4683 if (ccb == NULL) { 4684 warnx("%s: error allocating CCB", __func__); 4685 return (1); 4686 } 4687 4688 bzero(&(&ccb->ccb_h)[1], 4689 sizeof(union ccb) - sizeof(struct ccb_hdr)); 4690 4691 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4692 switch (c) { 4693 case 'a': 4694 case 'A': 4695 case 's': 4696 case 'S': { 4697 int enable = -1; 4698 4699 if (strcasecmp(optarg, "enable") == 0) 4700 enable = 1; 4701 else if (strcasecmp(optarg, "disable") == 0) 4702 enable = 2; 4703 else { 4704 warnx("%s: Invalid argument %s", __func__, 4705 optarg); 4706 retval = 1; 4707 goto bailout; 4708 } 4709 switch (c) { 4710 case 's': 4711 slumber_partial |= enable << 4712 SMP_PC_SAS_SLUMBER_SHIFT; 4713 break; 4714 case 'S': 4715 slumber_partial |= enable << 4716 SMP_PC_SAS_PARTIAL_SHIFT; 4717 break; 4718 case 'a': 4719 slumber_partial |= enable << 4720 SMP_PC_SATA_SLUMBER_SHIFT; 4721 break; 4722 case 'A': 4723 slumber_partial |= enable << 4724 SMP_PC_SATA_PARTIAL_SHIFT; 4725 break; 4726 default: 4727 warnx("%s: programmer error", __func__); 4728 retval = 1; 4729 goto bailout; 4730 break; /*NOTREACHED*/ 4731 } 4732 break; 4733 } 4734 case 'd': 4735 attached_dev_name = (uintmax_t)strtoumax(optarg, 4736 NULL,0); 4737 dev_name_set = 1; 4738 break; 4739 case 'l': 4740 long_response = 1; 4741 break; 4742 case 'm': 4743 /* 4744 * We don't do extensive checking here, so this 4745 * will continue to work when new speeds come out. 4746 */ 4747 min_plr = strtoul(optarg, NULL, 0); 4748 if ((min_plr == 0) 4749 || (min_plr > 0xf)) { 4750 warnx("%s: invalid link rate %x", 4751 __func__, min_plr); 4752 retval = 1; 4753 goto bailout; 4754 } 4755 break; 4756 case 'M': 4757 /* 4758 * We don't do extensive checking here, so this 4759 * will continue to work when new speeds come out. 4760 */ 4761 max_plr = strtoul(optarg, NULL, 0); 4762 if ((max_plr == 0) 4763 || (max_plr > 0xf)) { 4764 warnx("%s: invalid link rate %x", 4765 __func__, max_plr); 4766 retval = 1; 4767 goto bailout; 4768 } 4769 break; 4770 case 'o': { 4771 camcontrol_optret optreturn; 4772 cam_argmask argnums; 4773 const char *subopt; 4774 4775 if (phy_op_set != 0) { 4776 warnx("%s: only one phy operation argument " 4777 "(-o) allowed", __func__); 4778 retval = 1; 4779 goto bailout; 4780 } 4781 4782 phy_op_set = 1; 4783 4784 /* 4785 * Allow the user to specify the phy operation 4786 * numerically, as well as with a name. This will 4787 * future-proof it a bit, so options that are added 4788 * in future specs can be used. 4789 */ 4790 if (isdigit(optarg[0])) { 4791 phy_operation = strtoul(optarg, NULL, 0); 4792 if ((phy_operation == 0) 4793 || (phy_operation > 0xff)) { 4794 warnx("%s: invalid phy operation %#x", 4795 __func__, phy_operation); 4796 retval = 1; 4797 goto bailout; 4798 } 4799 break; 4800 } 4801 optreturn = getoption(phy_ops, optarg, &phy_operation, 4802 &argnums, &subopt); 4803 4804 if (optreturn == CC_OR_AMBIGUOUS) { 4805 warnx("%s: ambiguous option %s", __func__, 4806 optarg); 4807 usage(0); 4808 retval = 1; 4809 goto bailout; 4810 } else if (optreturn == CC_OR_NOT_FOUND) { 4811 warnx("%s: option %s not found", __func__, 4812 optarg); 4813 usage(0); 4814 retval = 1; 4815 goto bailout; 4816 } 4817 break; 4818 } 4819 case 'p': 4820 phy = atoi(optarg); 4821 break; 4822 case 'T': 4823 pp_timeout_val = strtoul(optarg, NULL, 0); 4824 if (pp_timeout_val > 15) { 4825 warnx("%s: invalid partial pathway timeout " 4826 "value %u, need a value less than 16", 4827 __func__, pp_timeout_val); 4828 retval = 1; 4829 goto bailout; 4830 } 4831 set_pp_timeout_val = 1; 4832 break; 4833 default: 4834 break; 4835 } 4836 } 4837 4838 if (phy == -1) { 4839 warnx("%s: a PHY (-p phy) argument is required",__func__); 4840 retval = 1; 4841 goto bailout; 4842 } 4843 4844 if (((dev_name_set != 0) 4845 && (phy_operation != SMP_PC_PHY_OP_SET_ATT_DEV_NAME)) 4846 || ((phy_operation == SMP_PC_PHY_OP_SET_ATT_DEV_NAME) 4847 && (dev_name_set == 0))) { 4848 warnx("%s: -d name and -o setdevname arguments both " 4849 "required to set device name", __func__); 4850 retval = 1; 4851 goto bailout; 4852 } 4853 4854 request = malloc(sizeof(*request)); 4855 if (request == NULL) { 4856 warn("%s: unable to allocate %zd bytes", __func__, 4857 sizeof(*request)); 4858 retval = 1; 4859 goto bailout; 4860 } 4861 4862 response = malloc(sizeof(*response)); 4863 if (response == NULL) { 4864 warn("%s: unable to allocate %zd bytes", __func__, 4865 sizeof(*request)); 4866 retval = 1; 4867 goto bailout; 4868 } 4869 4870 smp_phy_control(&ccb->smpio, 4871 retry_count, 4872 /*cbfcnp*/ NULL, 4873 request, 4874 sizeof(*request), 4875 (uint8_t *)response, 4876 sizeof(*response), 4877 long_response, 4878 /*expected_exp_change_count*/ 0, 4879 phy, 4880 phy_operation, 4881 (set_pp_timeout_val != 0) ? 1 : 0, 4882 attached_dev_name, 4883 min_plr, 4884 max_plr, 4885 slumber_partial, 4886 pp_timeout_val, 4887 timeout); 4888 4889 if (((retval = cam_send_ccb(device, ccb)) < 0) 4890 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4891 const char *warnstr = "error sending command"; 4892 4893 if (retval < 0) 4894 warn(warnstr); 4895 else 4896 warnx(warnstr); 4897 4898 if (arglist & CAM_ARG_VERBOSE) { 4899 /* 4900 * Use CAM_EPF_NORMAL so we only get one line of 4901 * SMP command decoding. 4902 */ 4903 cam_error_print(device, ccb, CAM_ESF_ALL, 4904 CAM_EPF_NORMAL, stderr); 4905 } 4906 retval = 1; 4907 goto bailout; 4908 } 4909 4910 /* XXX KDM print out something here for success? */ 4911bailout: 4912 if (ccb != NULL) 4913 cam_freeccb(ccb); 4914 4915 if (request != NULL) 4916 free(request); 4917 4918 if (response != NULL) 4919 free(response); 4920 4921 return (retval); 4922} 4923 4924static int 4925smpmaninfo(struct cam_device *device, int argc, char **argv, 4926 char *combinedopt, int retry_count, int timeout) 4927{ 4928 union ccb *ccb; 4929 struct smp_report_manuf_info_request request; 4930 struct smp_report_manuf_info_response response; 4931 struct sbuf *sb = NULL; 4932 int long_response = 0; 4933 int retval = 0; 4934 int c; 4935 4936 /* 4937 * Note that at the moment we don't support sending SMP CCBs to 4938 * devices that aren't probed by CAM. 4939 */ 4940 ccb = cam_getccb(device); 4941 if (ccb == NULL) { 4942 warnx("%s: error allocating CCB", __func__); 4943 return (1); 4944 } 4945 4946 bzero(&(&ccb->ccb_h)[1], 4947 sizeof(union ccb) - sizeof(struct ccb_hdr)); 4948 4949 while ((c = getopt(argc, argv, combinedopt)) != -1) { 4950 switch (c) { 4951 case 'l': 4952 long_response = 1; 4953 break; 4954 default: 4955 break; 4956 } 4957 } 4958 bzero(&request, sizeof(request)); 4959 bzero(&response, sizeof(response)); 4960 4961 smp_report_manuf_info(&ccb->smpio, 4962 retry_count, 4963 /*cbfcnp*/ NULL, 4964 &request, 4965 sizeof(request), 4966 (uint8_t *)&response, 4967 sizeof(response), 4968 long_response, 4969 timeout); 4970 4971 if (((retval = cam_send_ccb(device, ccb)) < 0) 4972 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 4973 const char *warnstr = "error sending command"; 4974 4975 if (retval < 0) 4976 warn(warnstr); 4977 else 4978 warnx(warnstr); 4979 4980 if (arglist & CAM_ARG_VERBOSE) { 4981 cam_error_print(device, ccb, CAM_ESF_ALL, 4982 CAM_EPF_ALL, stderr); 4983 } 4984 retval = 1; 4985 goto bailout; 4986 } 4987 4988 sb = sbuf_new_auto(); 4989 if (sb == NULL) { 4990 warnx("%s: error allocating sbuf", __func__); 4991 goto bailout; 4992 } 4993 4994 smp_report_manuf_info_sbuf(&response, sizeof(response), sb); 4995 4996 sbuf_finish(sb); 4997 4998 printf("%s", sbuf_data(sb)); 4999 5000bailout: 5001 5002 if (ccb != NULL) 5003 cam_freeccb(ccb); 5004 5005 if (sb != NULL) 5006 sbuf_delete(sb); 5007 5008 return (retval); 5009} 5010 5011static int 5012getdevid(struct cam_devitem *item) 5013{ 5014 int retval = 0; 5015 union ccb *ccb = NULL; 5016 5017 struct cam_device *dev; 5018 5019 dev = cam_open_btl(item->dev_match.path_id, 5020 item->dev_match.target_id, 5021 item->dev_match.target_lun, O_RDWR, NULL); 5022 5023 if (dev == NULL) { 5024 warnx("%s", cam_errbuf); 5025 retval = 1; 5026 goto bailout; 5027 } 5028 5029 item->device_id_len = 0; 5030 5031 ccb = cam_getccb(dev); 5032 if (ccb == NULL) { 5033 warnx("%s: error allocating CCB", __func__); 5034 retval = 1; 5035 goto bailout; 5036 } 5037 5038 bzero(&(&ccb->ccb_h)[1], 5039 sizeof(union ccb) - sizeof(struct ccb_hdr)); 5040 5041 /* 5042 * On the first try, we just probe for the size of the data, and 5043 * then allocate that much memory and try again. 5044 */ 5045retry: 5046 ccb->ccb_h.func_code = XPT_GDEV_ADVINFO; 5047 ccb->ccb_h.flags = CAM_DIR_IN; 5048 ccb->cgdai.flags = CGDAI_FLAG_PROTO; 5049 ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID; 5050 ccb->cgdai.bufsiz = item->device_id_len; 5051 if (item->device_id_len != 0) 5052 ccb->cgdai.buf = (uint8_t *)item->device_id; 5053 5054 if (cam_send_ccb(dev, ccb) < 0) { 5055 warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__); 5056 retval = 1; 5057 goto bailout; 5058 } 5059 5060 if (ccb->ccb_h.status != CAM_REQ_CMP) { 5061 warnx("%s: CAM status %#x", __func__, ccb->ccb_h.status); 5062 retval = 1; 5063 goto bailout; 5064 } 5065 5066 if (item->device_id_len == 0) { 5067 /* 5068 * This is our first time through. Allocate the buffer, 5069 * and then go back to get the data. 5070 */ 5071 if (ccb->cgdai.provsiz == 0) { 5072 warnx("%s: invalid .provsiz field returned with " 5073 "XPT_GDEV_ADVINFO CCB", __func__); 5074 retval = 1; 5075 goto bailout; 5076 } 5077 item->device_id_len = ccb->cgdai.provsiz; 5078 item->device_id = malloc(item->device_id_len); 5079 if (item->device_id == NULL) { 5080 warn("%s: unable to allocate %d bytes", __func__, 5081 item->device_id_len); 5082 retval = 1; 5083 goto bailout; 5084 } 5085 ccb->ccb_h.status = CAM_REQ_INPROG; 5086 goto retry; 5087 } 5088 5089bailout: 5090 if (dev != NULL) 5091 cam_close_device(dev); 5092 5093 if (ccb != NULL) 5094 cam_freeccb(ccb); 5095 5096 return (retval); 5097} 5098 5099/* 5100 * XXX KDM merge this code with getdevtree()? 5101 */ 5102static int 5103buildbusdevlist(struct cam_devlist *devlist) 5104{ 5105 union ccb ccb; 5106 int bufsize, fd = -1; 5107 struct dev_match_pattern *patterns; 5108 struct cam_devitem *item = NULL; 5109 int skip_device = 0; 5110 int retval = 0; 5111 5112 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 5113 warn("couldn't open %s", XPT_DEVICE); 5114 return(1); 5115 } 5116 5117 bzero(&ccb, sizeof(union ccb)); 5118 5119 ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 5120 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 5121 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 5122 5123 ccb.ccb_h.func_code = XPT_DEV_MATCH; 5124 bufsize = sizeof(struct dev_match_result) * 100; 5125 ccb.cdm.match_buf_len = bufsize; 5126 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 5127 if (ccb.cdm.matches == NULL) { 5128 warnx("can't malloc memory for matches"); 5129 close(fd); 5130 return(1); 5131 } 5132 ccb.cdm.num_matches = 0; 5133 ccb.cdm.num_patterns = 2; 5134 ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern) * 5135 ccb.cdm.num_patterns; 5136 5137 patterns = (struct dev_match_pattern *)malloc(ccb.cdm.pattern_buf_len); 5138 if (patterns == NULL) { 5139 warnx("can't malloc memory for patterns"); 5140 retval = 1; 5141 goto bailout; 5142 } 5143 5144 ccb.cdm.patterns = patterns; 5145 bzero(patterns, ccb.cdm.pattern_buf_len); 5146 5147 patterns[0].type = DEV_MATCH_DEVICE; 5148 patterns[0].pattern.device_pattern.flags = DEV_MATCH_PATH; 5149 patterns[0].pattern.device_pattern.path_id = devlist->path_id; 5150 patterns[1].type = DEV_MATCH_PERIPH; 5151 patterns[1].pattern.periph_pattern.flags = PERIPH_MATCH_PATH; 5152 patterns[1].pattern.periph_pattern.path_id = devlist->path_id; 5153 5154 /* 5155 * We do the ioctl multiple times if necessary, in case there are 5156 * more than 100 nodes in the EDT. 5157 */ 5158 do { 5159 unsigned int i; 5160 5161 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 5162 warn("error sending CAMIOCOMMAND ioctl"); 5163 retval = 1; 5164 goto bailout; 5165 } 5166 5167 if ((ccb.ccb_h.status != CAM_REQ_CMP) 5168 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 5169 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 5170 warnx("got CAM error %#x, CDM error %d\n", 5171 ccb.ccb_h.status, ccb.cdm.status); 5172 retval = 1; 5173 goto bailout; 5174 } 5175 5176 for (i = 0; i < ccb.cdm.num_matches; i++) { 5177 switch (ccb.cdm.matches[i].type) { 5178 case DEV_MATCH_DEVICE: { 5179 struct device_match_result *dev_result; 5180 5181 dev_result = 5182 &ccb.cdm.matches[i].result.device_result; 5183 5184 if (dev_result->flags & 5185 DEV_RESULT_UNCONFIGURED) { 5186 skip_device = 1; 5187 break; 5188 } else 5189 skip_device = 0; 5190 5191 item = malloc(sizeof(*item)); 5192 if (item == NULL) { 5193 warn("%s: unable to allocate %zd bytes", 5194 __func__, sizeof(*item)); 5195 retval = 1; 5196 goto bailout; 5197 } 5198 bzero(item, sizeof(*item)); 5199 bcopy(dev_result, &item->dev_match, 5200 sizeof(*dev_result)); 5201 STAILQ_INSERT_TAIL(&devlist->dev_queue, item, 5202 links); 5203 5204 if (getdevid(item) != 0) { 5205 retval = 1; 5206 goto bailout; 5207 } 5208 break; 5209 } 5210 case DEV_MATCH_PERIPH: { 5211 struct periph_match_result *periph_result; 5212 5213 periph_result = 5214 &ccb.cdm.matches[i].result.periph_result; 5215 5216 if (skip_device != 0) 5217 break; 5218 item->num_periphs++; 5219 item->periph_matches = realloc( 5220 item->periph_matches, 5221 item->num_periphs * 5222 sizeof(struct periph_match_result)); 5223 if (item->periph_matches == NULL) { 5224 warn("%s: error allocating periph " 5225 "list", __func__); 5226 retval = 1; 5227 goto bailout; 5228 } 5229 bcopy(periph_result, &item->periph_matches[ 5230 item->num_periphs - 1], 5231 sizeof(*periph_result)); 5232 break; 5233 } 5234 default: 5235 fprintf(stderr, "%s: unexpected match " 5236 "type %d\n", __func__, 5237 ccb.cdm.matches[i].type); 5238 retval = 1; 5239 goto bailout; 5240 break; /*NOTREACHED*/ 5241 } 5242 } 5243 } while ((ccb.ccb_h.status == CAM_REQ_CMP) 5244 && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 5245bailout: 5246 5247 if (fd != -1) 5248 close(fd); 5249 5250 free(patterns); 5251 5252 free(ccb.cdm.matches); 5253 5254 if (retval != 0) 5255 freebusdevlist(devlist); 5256 5257 return (retval); 5258} 5259 5260static void 5261freebusdevlist(struct cam_devlist *devlist) 5262{ 5263 struct cam_devitem *item, *item2; 5264 5265 STAILQ_FOREACH_SAFE(item, &devlist->dev_queue, links, item2) { 5266 STAILQ_REMOVE(&devlist->dev_queue, item, cam_devitem, 5267 links); 5268 free(item->device_id); 5269 free(item->periph_matches); 5270 free(item); 5271 } 5272} 5273 5274static struct cam_devitem * 5275findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr) 5276{ 5277 struct cam_devitem *item; 5278 5279 STAILQ_FOREACH(item, &devlist->dev_queue, links) { 5280 uint8_t *item_addr; 5281 5282 /* 5283 * XXX KDM look for LUN IDs as well? 5284 */ 5285 item_addr = scsi_get_sas_addr(item->device_id, 5286 item->device_id_len); 5287 if (item_addr == NULL) 5288 continue; 5289 5290 if (scsi_8btou64(item_addr) == sasaddr) 5291 return (item); 5292 } 5293 5294 return (NULL); 5295} 5296 5297static int 5298smpphylist(struct cam_device *device, int argc, char **argv, 5299 char *combinedopt, int retry_count, int timeout) 5300{ 5301 struct smp_report_general_request *rgrequest = NULL; 5302 struct smp_report_general_response *rgresponse = NULL; 5303 struct smp_discover_request *disrequest = NULL; 5304 struct smp_discover_response *disresponse = NULL; 5305 struct cam_devlist devlist; 5306 union ccb *ccb; 5307 int long_response = 0; 5308 int num_phys = 0; 5309 int quiet = 0; 5310 int retval; 5311 int i, c; 5312 5313 /* 5314 * Note that at the moment we don't support sending SMP CCBs to 5315 * devices that aren't probed by CAM. 5316 */ 5317 ccb = cam_getccb(device); 5318 if (ccb == NULL) { 5319 warnx("%s: error allocating CCB", __func__); 5320 return (1); 5321 } 5322 5323 bzero(&(&ccb->ccb_h)[1], 5324 sizeof(union ccb) - sizeof(struct ccb_hdr)); 5325 5326 rgrequest = malloc(sizeof(*rgrequest)); 5327 if (rgrequest == NULL) { 5328 warn("%s: unable to allocate %zd bytes", __func__, 5329 sizeof(*rgrequest)); 5330 retval = 1; 5331 goto bailout; 5332 } 5333 5334 rgresponse = malloc(sizeof(*rgresponse)); 5335 if (rgresponse == NULL) { 5336 warn("%s: unable to allocate %zd bytes", __func__, 5337 sizeof(*rgresponse)); 5338 retval = 1; 5339 goto bailout; 5340 } 5341 5342 while ((c = getopt(argc, argv, combinedopt)) != -1) { 5343 switch (c) { 5344 case 'l': 5345 long_response = 1; 5346 break; 5347 case 'q': 5348 quiet = 1; 5349 break; 5350 default: 5351 break; 5352 } 5353 } 5354 5355 smp_report_general(&ccb->smpio, 5356 retry_count, 5357 /*cbfcnp*/ NULL, 5358 rgrequest, 5359 /*request_len*/ sizeof(*rgrequest), 5360 (uint8_t *)rgresponse, 5361 /*response_len*/ sizeof(*rgresponse), 5362 /*long_response*/ long_response, 5363 timeout); 5364 5365 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 5366 5367 if (((retval = cam_send_ccb(device, ccb)) < 0) 5368 || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { 5369 const char *warnstr = "error sending command"; 5370 5371 if (retval < 0) 5372 warn(warnstr); 5373 else 5374 warnx(warnstr); 5375 5376 if (arglist & CAM_ARG_VERBOSE) { 5377 cam_error_print(device, ccb, CAM_ESF_ALL, 5378 CAM_EPF_ALL, stderr); 5379 } 5380 retval = 1; 5381 goto bailout; 5382 } 5383 5384 num_phys = rgresponse->num_phys; 5385 5386 if (num_phys == 0) { 5387 if (quiet == 0) 5388 fprintf(stdout, "%s: No Phys reported\n", __func__); 5389 retval = 1; 5390 goto bailout; 5391 } 5392 5393 STAILQ_INIT(&devlist.dev_queue); 5394 devlist.path_id = device->path_id; 5395 5396 retval = buildbusdevlist(&devlist); 5397 if (retval != 0) 5398 goto bailout; 5399 5400 if (quiet == 0) { 5401 fprintf(stdout, "%d PHYs:\n", num_phys); 5402 fprintf(stdout, "PHY Attached SAS Address\n"); 5403 } 5404 5405 disrequest = malloc(sizeof(*disrequest)); 5406 if (disrequest == NULL) { 5407 warn("%s: unable to allocate %zd bytes", __func__, 5408 sizeof(*disrequest)); 5409 retval = 1; 5410 goto bailout; 5411 } 5412 5413 disresponse = malloc(sizeof(*disresponse)); 5414 if (disresponse == NULL) { 5415 warn("%s: unable to allocate %zd bytes", __func__, 5416 sizeof(*disresponse)); 5417 retval = 1; 5418 goto bailout; 5419 } 5420 5421 for (i = 0; i < num_phys; i++) { 5422 struct cam_devitem *item; 5423 struct device_match_result *dev_match; 5424 char vendor[16], product[48], revision[16]; 5425 char tmpstr[256]; 5426 int j; 5427 5428 bzero(&(&ccb->ccb_h)[1], 5429 sizeof(union ccb) - sizeof(struct ccb_hdr)); 5430 5431 ccb->ccb_h.status = CAM_REQ_INPROG; 5432 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 5433 5434 smp_discover(&ccb->smpio, 5435 retry_count, 5436 /*cbfcnp*/ NULL, 5437 disrequest, 5438 sizeof(*disrequest), 5439 (uint8_t *)disresponse, 5440 sizeof(*disresponse), 5441 long_response, 5442 /*ignore_zone_group*/ 0, 5443 /*phy*/ i, 5444 timeout); 5445 5446 if (((retval = cam_send_ccb(device, ccb)) < 0) 5447 || (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 5448 && (disresponse->function_result != SMP_FR_PHY_VACANT))) { 5449 const char *warnstr = "error sending command"; 5450 5451 if (retval < 0) 5452 warn(warnstr); 5453 else 5454 warnx(warnstr); 5455 5456 if (arglist & CAM_ARG_VERBOSE) { 5457 cam_error_print(device, ccb, CAM_ESF_ALL, 5458 CAM_EPF_ALL, stderr); 5459 } 5460 retval = 1; 5461 goto bailout; 5462 } 5463 5464 if (disresponse->function_result == SMP_FR_PHY_VACANT) { 5465 if (quiet == 0) 5466 fprintf(stdout, "%3d <vacant>\n", i); 5467 continue; 5468 } 5469 5470 item = findsasdevice(&devlist, 5471 scsi_8btou64(disresponse->attached_sas_address)); 5472 5473 if ((quiet == 0) 5474 || (item != NULL)) { 5475 fprintf(stdout, "%3d 0x%016jx", i, 5476 (uintmax_t)scsi_8btou64( 5477 disresponse->attached_sas_address)); 5478 if (item == NULL) { 5479 fprintf(stdout, "\n"); 5480 continue; 5481 } 5482 } else if (quiet != 0) 5483 continue; 5484 5485 dev_match = &item->dev_match; 5486 5487 if (dev_match->protocol == PROTO_SCSI) { 5488 cam_strvis(vendor, dev_match->inq_data.vendor, 5489 sizeof(dev_match->inq_data.vendor), 5490 sizeof(vendor)); 5491 cam_strvis(product, dev_match->inq_data.product, 5492 sizeof(dev_match->inq_data.product), 5493 sizeof(product)); 5494 cam_strvis(revision, dev_match->inq_data.revision, 5495 sizeof(dev_match->inq_data.revision), 5496 sizeof(revision)); 5497 sprintf(tmpstr, "<%s %s %s>", vendor, product, 5498 revision); 5499 } else if ((dev_match->protocol == PROTO_ATA) 5500 || (dev_match->protocol == PROTO_SATAPM)) { 5501 cam_strvis(product, dev_match->ident_data.model, 5502 sizeof(dev_match->ident_data.model), 5503 sizeof(product)); 5504 cam_strvis(revision, dev_match->ident_data.revision, 5505 sizeof(dev_match->ident_data.revision), 5506 sizeof(revision)); 5507 sprintf(tmpstr, "<%s %s>", product, revision); 5508 } else { 5509 sprintf(tmpstr, "<>"); 5510 } 5511 fprintf(stdout, " %-33s ", tmpstr); 5512 5513 /* 5514 * If we have 0 periphs, that's a bug... 5515 */ 5516 if (item->num_periphs == 0) { 5517 fprintf(stdout, "\n"); 5518 continue; 5519 } 5520 5521 fprintf(stdout, "("); 5522 for (j = 0; j < item->num_periphs; j++) { 5523 if (j > 0) 5524 fprintf(stdout, ","); 5525 5526 fprintf(stdout, "%s%d", 5527 item->periph_matches[j].periph_name, 5528 item->periph_matches[j].unit_number); 5529 5530 } 5531 fprintf(stdout, ")\n"); 5532 } 5533bailout: 5534 if (ccb != NULL) 5535 cam_freeccb(ccb); 5536 5537 free(rgrequest); 5538 5539 free(rgresponse); 5540 5541 free(disrequest); 5542 5543 free(disresponse); 5544 5545 freebusdevlist(&devlist); 5546 5547 return (retval); 5548} 5549 5550static int 5551atapm(struct cam_device *device, int argc, char **argv, 5552 char *combinedopt, int retry_count, int timeout) 5553{ 5554 union ccb *ccb; 5555 int retval = 0; 5556 int t = -1; 5557 int c; 5558 u_char cmd, sc; 5559 5560 ccb = cam_getccb(device); 5561 5562 if (ccb == NULL) { 5563 warnx("%s: error allocating ccb", __func__); 5564 return (1); 5565 } 5566 5567 while ((c = getopt(argc, argv, combinedopt)) != -1) { 5568 switch (c) { 5569 case 't': 5570 t = atoi(optarg); 5571 break; 5572 default: 5573 break; 5574 } 5575 } 5576 if (strcmp(argv[1], "idle") == 0) { 5577 if (t == -1) 5578 cmd = ATA_IDLE_IMMEDIATE; 5579 else 5580 cmd = ATA_IDLE_CMD; 5581 } else if (strcmp(argv[1], "standby") == 0) { 5582 if (t == -1) 5583 cmd = ATA_STANDBY_IMMEDIATE; 5584 else 5585 cmd = ATA_STANDBY_CMD; 5586 } else { 5587 cmd = ATA_SLEEP; 5588 t = -1; 5589 } 5590 5591 if (t < 0) 5592 sc = 0; 5593 else if (t <= (240 * 5)) 5594 sc = (t + 4) / 5; 5595 else if (t <= (252 * 5)) 5596 /* special encoding for 21 minutes */ 5597 sc = 252; 5598 else if (t <= (11 * 30 * 60)) 5599 sc = (t - 1) / (30 * 60) + 241; 5600 else 5601 sc = 253; 5602 5603 cam_fill_ataio(&ccb->ataio, 5604 retry_count, 5605 NULL, 5606 /*flags*/CAM_DIR_NONE, 5607 MSG_SIMPLE_Q_TAG, 5608 /*data_ptr*/NULL, 5609 /*dxfer_len*/0, 5610 timeout ? timeout : 30 * 1000); 5611 ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc); 5612 5613 /* Disable freezing the device queue */ 5614 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 5615 5616 if (arglist & CAM_ARG_ERR_RECOVER) 5617 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 5618 5619 if (cam_send_ccb(device, ccb) < 0) { 5620 warn("error sending command"); 5621 5622 if (arglist & CAM_ARG_VERBOSE) 5623 cam_error_print(device, ccb, CAM_ESF_ALL, 5624 CAM_EPF_ALL, stderr); 5625 5626 retval = 1; 5627 goto bailout; 5628 } 5629 5630 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 5631 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); 5632 retval = 1; 5633 goto bailout; 5634 } 5635bailout: 5636 cam_freeccb(ccb); 5637 return (retval); 5638} 5639 5640#endif /* MINIMALISTIC */ 5641 5642void 5643usage(int verbose) 5644{ 5645 fprintf(verbose ? stdout : stderr, 5646"usage: camcontrol <command> [device id][generic args][command args]\n" 5647" camcontrol devlist [-v]\n" 5648#ifndef MINIMALISTIC 5649" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n" 5650" camcontrol tur [dev_id][generic args]\n" 5651" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n" 5652" camcontrol identify [dev_id][generic args] [-v]\n" 5653" camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n" 5654" camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n" 5655" [-q] [-s]\n" 5656" camcontrol start [dev_id][generic args]\n" 5657" camcontrol stop [dev_id][generic args]\n" 5658" camcontrol load [dev_id][generic args]\n" 5659" camcontrol eject [dev_id][generic args]\n" 5660#endif /* MINIMALISTIC */ 5661" camcontrol rescan <all | bus[:target:lun]>\n" 5662" camcontrol reset <all | bus[:target:lun]>\n" 5663#ifndef MINIMALISTIC 5664" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" 5665" camcontrol modepage [dev_id][generic args] <-m page | -l>\n" 5666" [-P pagectl][-e | -b][-d]\n" 5667" camcontrol cmd [dev_id][generic args]\n" 5668" <-a cmd [args] | -c cmd [args]>\n" 5669" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n" 5670" camcontrol smpcmd [dev_id][generic args]\n" 5671" <-r len fmt [args]> <-R len fmt [args]>\n" 5672" camcontrol smprg [dev_id][generic args][-l]\n" 5673" camcontrol smppc [dev_id][generic args] <-p phy> [-l]\n" 5674" [-o operation][-d name][-m rate][-M rate]\n" 5675" [-T pp_timeout][-a enable|disable]\n" 5676" [-A enable|disable][-s enable|disable]\n" 5677" [-S enable|disable]\n" 5678" camcontrol smpphylist [dev_id][generic args][-l][-q]\n" 5679" camcontrol smpmaninfo [dev_id][generic args][-l]\n" 5680" camcontrol debug [-I][-P][-T][-S][-X][-c]\n" 5681" <all|bus[:target[:lun]]|off>\n" 5682" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" 5683" camcontrol negotiate [dev_id][generic args] [-a][-c]\n" 5684" [-D <enable|disable>][-M mode][-O offset]\n" 5685" [-q][-R syncrate][-v][-T <enable|disable>]\n" 5686" [-U][-W bus_width]\n" 5687" camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n" 5688" camcontrol idle [dev_id][generic args][-t time]\n" 5689" camcontrol standby [dev_id][generic args][-t time]\n" 5690" camcontrol sleep [dev_id][generic args]\n" 5691#endif /* MINIMALISTIC */ 5692" camcontrol help\n"); 5693 if (!verbose) 5694 return; 5695#ifndef MINIMALISTIC 5696 fprintf(stdout, 5697"Specify one of the following options:\n" 5698"devlist list all CAM devices\n" 5699"periphlist list all CAM peripheral drivers attached to a device\n" 5700"tur send a test unit ready to the named device\n" 5701"inquiry send a SCSI inquiry command to the named device\n" 5702"identify send a ATA identify command to the named device\n" 5703"reportluns send a SCSI report luns command to the device\n" 5704"readcap send a SCSI read capacity command to the device\n" 5705"start send a Start Unit command to the device\n" 5706"stop send a Stop Unit command to the device\n" 5707"load send a Start Unit command to the device with the load bit set\n" 5708"eject send a Stop Unit command to the device with the eject bit set\n" 5709"rescan rescan all busses, the given bus, or bus:target:lun\n" 5710"reset reset all busses, the given bus, or bus:target:lun\n" 5711"defects read the defect list of the specified device\n" 5712"modepage display or edit (-e) the given mode page\n" 5713"cmd send the given SCSI command, may need -i or -o as well\n" 5714"smpcmd send the given SMP command, requires -o and -i\n" 5715"smprg send the SMP Report General command\n" 5716"smppc send the SMP PHY Control command, requires -p\n" 5717"smpphylist display phys attached to a SAS expander\n" 5718"smpmaninfo send the SMP Report Manufacturer Info command\n" 5719"debug turn debugging on/off for a bus, target, or lun, or all devices\n" 5720"tags report or set the number of transaction slots for a device\n" 5721"negotiate report or set device negotiation parameters\n" 5722"format send the SCSI FORMAT UNIT command to the named device\n" 5723"idle send the ATA IDLE command to the named device\n" 5724"standby send the ATA STANDBY command to the named device\n" 5725"sleep send the ATA SLEEP command to the named device\n" 5726"help this message\n" 5727"Device Identifiers:\n" 5728"bus:target specify the bus and target, lun defaults to 0\n" 5729"bus:target:lun specify the bus, target and lun\n" 5730"deviceUNIT specify the device name, like \"da4\" or \"cd2\"\n" 5731"Generic arguments:\n" 5732"-v be verbose, print out sense information\n" 5733"-t timeout command timeout in seconds, overrides default timeout\n" 5734"-n dev_name specify device name, e.g. \"da\", \"cd\"\n" 5735"-u unit specify unit number, e.g. \"0\", \"5\"\n" 5736"-E have the kernel attempt to perform SCSI error recovery\n" 5737"-C count specify the SCSI command retry count (needs -E to work)\n" 5738"modepage arguments:\n" 5739"-l list all available mode pages\n" 5740"-m page specify the mode page to view or edit\n" 5741"-e edit the specified mode page\n" 5742"-b force view to binary mode\n" 5743"-d disable block descriptors for mode sense\n" 5744"-P pgctl page control field 0-3\n" 5745"defects arguments:\n" 5746"-f format specify defect list format (block, bfi or phys)\n" 5747"-G get the grown defect list\n" 5748"-P get the permanant defect list\n" 5749"inquiry arguments:\n" 5750"-D get the standard inquiry data\n" 5751"-S get the serial number\n" 5752"-R get the transfer rate, etc.\n" 5753"reportluns arguments:\n" 5754"-c only report a count of available LUNs\n" 5755"-l only print out luns, and not a count\n" 5756"-r <reporttype> specify \"default\", \"wellknown\" or \"all\"\n" 5757"readcap arguments\n" 5758"-b only report the blocksize\n" 5759"-h human readable device size, base 2\n" 5760"-H human readable device size, base 10\n" 5761"-N print the number of blocks instead of last block\n" 5762"-q quiet, print numbers only\n" 5763"-s only report the last block/device size\n" 5764"cmd arguments:\n" 5765"-c cdb [args] specify the SCSI CDB\n" 5766"-i len fmt specify input data and input data format\n" 5767"-o len fmt [args] specify output data and output data fmt\n" 5768"smpcmd arguments:\n" 5769"-r len fmt [args] specify the SMP command to be sent\n" 5770"-R len fmt [args] specify SMP response format\n" 5771"smprg arguments:\n" 5772"-l specify the long response format\n" 5773"smppc arguments:\n" 5774"-p phy specify the PHY to operate on\n" 5775"-l specify the long request/response format\n" 5776"-o operation specify the phy control operation\n" 5777"-d name set the attached device name\n" 5778"-m rate set the minimum physical link rate\n" 5779"-M rate set the maximum physical link rate\n" 5780"-T pp_timeout set the partial pathway timeout value\n" 5781"-a enable|disable enable or disable SATA slumber\n" 5782"-A enable|disable enable or disable SATA partial phy power\n" 5783"-s enable|disable enable or disable SAS slumber\n" 5784"-S enable|disable enable or disable SAS partial phy power\n" 5785"smpphylist arguments:\n" 5786"-l specify the long response format\n" 5787"-q only print phys with attached devices\n" 5788"smpmaninfo arguments:\n" 5789"-l specify the long response format\n" 5790"debug arguments:\n" 5791"-I CAM_DEBUG_INFO -- scsi commands, errors, data\n" 5792"-T CAM_DEBUG_TRACE -- routine flow tracking\n" 5793"-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n" 5794"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n" 5795"tags arguments:\n" 5796"-N tags specify the number of tags to use for this device\n" 5797"-q be quiet, don't report the number of tags\n" 5798"-v report a number of tag-related parameters\n" 5799"negotiate arguments:\n" 5800"-a send a test unit ready after negotiation\n" 5801"-c report/set current negotiation settings\n" 5802"-D <arg> \"enable\" or \"disable\" disconnection\n" 5803"-M mode set ATA mode\n" 5804"-O offset set command delay offset\n" 5805"-q be quiet, don't report anything\n" 5806"-R syncrate synchronization rate in MHz\n" 5807"-T <arg> \"enable\" or \"disable\" tagged queueing\n" 5808"-U report/set user negotiation settings\n" 5809"-W bus_width set the bus width in bits (8, 16 or 32)\n" 5810"-v also print a Path Inquiry CCB for the controller\n" 5811"format arguments:\n" 5812"-q be quiet, don't print status messages\n" 5813"-r run in report only mode\n" 5814"-w don't send immediate format command\n" 5815"-y don't ask any questions\n" 5816"idle/standby arguments:\n" 5817"-t <arg> number of seconds before respective state.\n"); 5818#endif /* MINIMALISTIC */ 5819} 5820 5821int 5822main(int argc, char **argv) 5823{ 5824 int c; 5825 char *device = NULL; 5826 int unit = 0; 5827 struct cam_device *cam_dev = NULL; 5828 int timeout = 0, retry_count = 1; 5829 camcontrol_optret optreturn; 5830 char *tstr; 5831 const char *mainopt = "C:En:t:u:v"; 5832 const char *subopt = NULL; 5833 char combinedopt[256]; 5834 int error = 0, optstart = 2; 5835 int devopen = 1; 5836#ifndef MINIMALISTIC 5837 int bus, target, lun; 5838#endif /* MINIMALISTIC */ 5839 5840 cmdlist = CAM_CMD_NONE; 5841 arglist = CAM_ARG_NONE; 5842 5843 if (argc < 2) { 5844 usage(0); 5845 exit(1); 5846 } 5847 5848 /* 5849 * Get the base option. 5850 */ 5851 optreturn = getoption(option_table,argv[1], &cmdlist, &arglist,&subopt); 5852 5853 if (optreturn == CC_OR_AMBIGUOUS) { 5854 warnx("ambiguous option %s", argv[1]); 5855 usage(0); 5856 exit(1); 5857 } else if (optreturn == CC_OR_NOT_FOUND) { 5858 warnx("option %s not found", argv[1]); 5859 usage(0); 5860 exit(1); 5861 } 5862 5863 /* 5864 * Ahh, getopt(3) is a pain. 5865 * 5866 * This is a gross hack. There really aren't many other good 5867 * options (excuse the pun) for parsing options in a situation like 5868 * this. getopt is kinda braindead, so you end up having to run 5869 * through the options twice, and give each invocation of getopt 5870 * the option string for the other invocation. 5871 * 5872 * You would think that you could just have two groups of options. 5873 * The first group would get parsed by the first invocation of 5874 * getopt, and the second group would get parsed by the second 5875 * invocation of getopt. It doesn't quite work out that way. When 5876 * the first invocation of getopt finishes, it leaves optind pointing 5877 * to the argument _after_ the first argument in the second group. 5878 * So when the second invocation of getopt comes around, it doesn't 5879 * recognize the first argument it gets and then bails out. 5880 * 5881 * A nice alternative would be to have a flag for getopt that says 5882 * "just keep parsing arguments even when you encounter an unknown 5883 * argument", but there isn't one. So there's no real clean way to 5884 * easily parse two sets of arguments without having one invocation 5885 * of getopt know about the other. 5886 * 5887 * Without this hack, the first invocation of getopt would work as 5888 * long as the generic arguments are first, but the second invocation 5889 * (in the subfunction) would fail in one of two ways. In the case 5890 * where you don't set optreset, it would fail because optind may be 5891 * pointing to the argument after the one it should be pointing at. 5892 * In the case where you do set optreset, and reset optind, it would 5893 * fail because getopt would run into the first set of options, which 5894 * it doesn't understand. 5895 * 5896 * All of this would "sort of" work if you could somehow figure out 5897 * whether optind had been incremented one option too far. The 5898 * mechanics of that, however, are more daunting than just giving 5899 * both invocations all of the expect options for either invocation. 5900 * 5901 * Needless to say, I wouldn't mind if someone invented a better 5902 * (non-GPL!) command line parsing interface than getopt. I 5903 * wouldn't mind if someone added more knobs to getopt to make it 5904 * work better. Who knows, I may talk myself into doing it someday, 5905 * if the standards weenies let me. As it is, it just leads to 5906 * hackery like this and causes people to avoid it in some cases. 5907 * 5908 * KDM, September 8th, 1998 5909 */ 5910 if (subopt != NULL) 5911 sprintf(combinedopt, "%s%s", mainopt, subopt); 5912 else 5913 sprintf(combinedopt, "%s", mainopt); 5914 5915 /* 5916 * For these options we do not parse optional device arguments and 5917 * we do not open a passthrough device. 5918 */ 5919 if ((cmdlist == CAM_CMD_RESCAN) 5920 || (cmdlist == CAM_CMD_RESET) 5921 || (cmdlist == CAM_CMD_DEVTREE) 5922 || (cmdlist == CAM_CMD_USAGE) 5923 || (cmdlist == CAM_CMD_DEBUG)) 5924 devopen = 0; 5925 5926#ifndef MINIMALISTIC 5927 if ((devopen == 1) 5928 && (argc > 2 && argv[2][0] != '-')) { 5929 char name[30]; 5930 int rv; 5931 5932 if (isdigit(argv[2][0])) { 5933 /* device specified as bus:target[:lun] */ 5934 rv = parse_btl(argv[2], &bus, &target, &lun, &arglist); 5935 if (rv < 2) 5936 errx(1, "numeric device specification must " 5937 "be either bus:target, or " 5938 "bus:target:lun"); 5939 /* default to 0 if lun was not specified */ 5940 if ((arglist & CAM_ARG_LUN) == 0) { 5941 lun = 0; 5942 arglist |= CAM_ARG_LUN; 5943 } 5944 optstart++; 5945 } else { 5946 if (cam_get_device(argv[2], name, sizeof name, &unit) 5947 == -1) 5948 errx(1, "%s", cam_errbuf); 5949 device = strdup(name); 5950 arglist |= CAM_ARG_DEVICE | CAM_ARG_UNIT; 5951 optstart++; 5952 } 5953 } 5954#endif /* MINIMALISTIC */ 5955 /* 5956 * Start getopt processing at argv[2/3], since we've already 5957 * accepted argv[1..2] as the command name, and as a possible 5958 * device name. 5959 */ 5960 optind = optstart; 5961 5962 /* 5963 * Now we run through the argument list looking for generic 5964 * options, and ignoring options that possibly belong to 5965 * subfunctions. 5966 */ 5967 while ((c = getopt(argc, argv, combinedopt))!= -1){ 5968 switch(c) { 5969 case 'C': 5970 retry_count = strtol(optarg, NULL, 0); 5971 if (retry_count < 0) 5972 errx(1, "retry count %d is < 0", 5973 retry_count); 5974 arglist |= CAM_ARG_RETRIES; 5975 break; 5976 case 'E': 5977 arglist |= CAM_ARG_ERR_RECOVER; 5978 break; 5979 case 'n': 5980 arglist |= CAM_ARG_DEVICE; 5981 tstr = optarg; 5982 while (isspace(*tstr) && (*tstr != '\0')) 5983 tstr++; 5984 device = (char *)strdup(tstr); 5985 break; 5986 case 't': 5987 timeout = strtol(optarg, NULL, 0); 5988 if (timeout < 0) 5989 errx(1, "invalid timeout %d", timeout); 5990 /* Convert the timeout from seconds to ms */ 5991 timeout *= 1000; 5992 arglist |= CAM_ARG_TIMEOUT; 5993 break; 5994 case 'u': 5995 arglist |= CAM_ARG_UNIT; 5996 unit = strtol(optarg, NULL, 0); 5997 break; 5998 case 'v': 5999 arglist |= CAM_ARG_VERBOSE; 6000 break; 6001 default: 6002 break; 6003 } 6004 } 6005 6006#ifndef MINIMALISTIC 6007 /* 6008 * For most commands we'll want to open the passthrough device 6009 * associated with the specified device. In the case of the rescan 6010 * commands, we don't use a passthrough device at all, just the 6011 * transport layer device. 6012 */ 6013 if (devopen == 1) { 6014 if (((arglist & (CAM_ARG_BUS|CAM_ARG_TARGET)) == 0) 6015 && (((arglist & CAM_ARG_DEVICE) == 0) 6016 || ((arglist & CAM_ARG_UNIT) == 0))) { 6017 errx(1, "subcommand \"%s\" requires a valid device " 6018 "identifier", argv[1]); 6019 } 6020 6021 if ((cam_dev = ((arglist & (CAM_ARG_BUS | CAM_ARG_TARGET))? 6022 cam_open_btl(bus, target, lun, O_RDWR, NULL) : 6023 cam_open_spec_device(device,unit,O_RDWR,NULL))) 6024 == NULL) 6025 errx(1,"%s", cam_errbuf); 6026 } 6027#endif /* MINIMALISTIC */ 6028 6029 /* 6030 * Reset optind to 2, and reset getopt, so these routines can parse 6031 * the arguments again. 6032 */ 6033 optind = optstart; 6034 optreset = 1; 6035 6036 switch(cmdlist) { 6037#ifndef MINIMALISTIC 6038 case CAM_CMD_DEVLIST: 6039 error = getdevlist(cam_dev); 6040 break; 6041#endif /* MINIMALISTIC */ 6042 case CAM_CMD_DEVTREE: 6043 error = getdevtree(); 6044 break; 6045#ifndef MINIMALISTIC 6046 case CAM_CMD_TUR: 6047 error = testunitready(cam_dev, retry_count, timeout, 0); 6048 break; 6049 case CAM_CMD_INQUIRY: 6050 error = scsidoinquiry(cam_dev, argc, argv, combinedopt, 6051 retry_count, timeout); 6052 break; 6053 case CAM_CMD_IDENTIFY: 6054 error = ataidentify(cam_dev, retry_count, timeout); 6055 break; 6056 case CAM_CMD_STARTSTOP: 6057 error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT, 6058 arglist & CAM_ARG_EJECT, retry_count, 6059 timeout); 6060 break; 6061#endif /* MINIMALISTIC */ 6062 case CAM_CMD_RESCAN: 6063 error = dorescan_or_reset(argc, argv, 1); 6064 break; 6065 case CAM_CMD_RESET: 6066 error = dorescan_or_reset(argc, argv, 0); 6067 break; 6068#ifndef MINIMALISTIC 6069 case CAM_CMD_READ_DEFECTS: 6070 error = readdefects(cam_dev, argc, argv, combinedopt, 6071 retry_count, timeout); 6072 break; 6073 case CAM_CMD_MODE_PAGE: 6074 modepage(cam_dev, argc, argv, combinedopt, 6075 retry_count, timeout); 6076 break; 6077 case CAM_CMD_SCSI_CMD: 6078 error = scsicmd(cam_dev, argc, argv, combinedopt, 6079 retry_count, timeout); 6080 break; 6081 case CAM_CMD_SMP_CMD: 6082 error = smpcmd(cam_dev, argc, argv, combinedopt, 6083 retry_count, timeout); 6084 break; 6085 case CAM_CMD_SMP_RG: 6086 error = smpreportgeneral(cam_dev, argc, argv, 6087 combinedopt, retry_count, 6088 timeout); 6089 break; 6090 case CAM_CMD_SMP_PC: 6091 error = smpphycontrol(cam_dev, argc, argv, combinedopt, 6092 retry_count, timeout); 6093 break; 6094 case CAM_CMD_SMP_PHYLIST: 6095 error = smpphylist(cam_dev, argc, argv, combinedopt, 6096 retry_count, timeout); 6097 break; 6098 case CAM_CMD_SMP_MANINFO: 6099 error = smpmaninfo(cam_dev, argc, argv, combinedopt, 6100 retry_count, timeout); 6101 break; 6102 case CAM_CMD_DEBUG: 6103 error = camdebug(argc, argv, combinedopt); 6104 break; 6105 case CAM_CMD_TAG: 6106 error = tagcontrol(cam_dev, argc, argv, combinedopt); 6107 break; 6108 case CAM_CMD_RATE: 6109 error = ratecontrol(cam_dev, retry_count, timeout, 6110 argc, argv, combinedopt); 6111 break; 6112 case CAM_CMD_FORMAT: 6113 error = scsiformat(cam_dev, argc, argv, 6114 combinedopt, retry_count, timeout); 6115 break; 6116 case CAM_CMD_REPORTLUNS: 6117 error = scsireportluns(cam_dev, argc, argv, 6118 combinedopt, retry_count, 6119 timeout); 6120 break; 6121 case CAM_CMD_READCAP: 6122 error = scsireadcapacity(cam_dev, argc, argv, 6123 combinedopt, retry_count, 6124 timeout); 6125 break; 6126 case CAM_CMD_IDLE: 6127 case CAM_CMD_STANDBY: 6128 case CAM_CMD_SLEEP: 6129 error = atapm(cam_dev, argc, argv, 6130 combinedopt, retry_count, 6131 timeout); 6132 break; 6133#endif /* MINIMALISTIC */ 6134 case CAM_CMD_USAGE: 6135 usage(1); 6136 break; 6137 default: 6138 usage(0); 6139 error = 1; 6140 break; 6141 } 6142 6143 if (cam_dev != NULL) 6144 cam_close_device(cam_dev); 6145 6146 exit(error); 6147} 6148