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