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