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