1/* 2 * Copyright (c) 1999-2018 Douglas Gilbert. 3 * All rights reserved. 4 * Use of this source code is governed by a BSD-style 5 * license that can be found in the BSD_LICENSE file. 6 */ 7 8/* 9 * CONTENTS 10 * Some SCSI commands are executed in many contexts and hence began 11 * to appear in several sg3_utils utilities. This files centralizes 12 * some of the low level command execution code. In most cases the 13 * interpretation of the command response is left to the each 14 * utility. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <stdarg.h> 20#include <string.h> 21#include <unistd.h> 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include "sg_lib.h" 28#include "sg_cmds_basic.h" 29#include "sg_pt.h" 30#include "sg_unaligned.h" 31 32 33 34#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */ 35#define EBUFF_SZ 256 36 37#define DEF_PT_TIMEOUT 60 /* 60 seconds */ 38#define START_PT_TIMEOUT 120 /* 120 seconds == 2 minutes */ 39#define LONG_PT_TIMEOUT 7200 /* 7,200 seconds == 120 minutes */ 40 41#define SYNCHRONIZE_CACHE_CMD 0x35 42#define SYNCHRONIZE_CACHE_CMDLEN 10 43#define SERVICE_ACTION_IN_16_CMD 0x9e 44#define SERVICE_ACTION_IN_16_CMDLEN 16 45#define READ_CAPACITY_16_SA 0x10 46#define READ_CAPACITY_10_CMD 0x25 47#define READ_CAPACITY_10_CMDLEN 10 48#define MODE_SENSE6_CMD 0x1a 49#define MODE_SENSE6_CMDLEN 6 50#define MODE_SENSE10_CMD 0x5a 51#define MODE_SENSE10_CMDLEN 10 52#define MODE_SELECT6_CMD 0x15 53#define MODE_SELECT6_CMDLEN 6 54#define MODE_SELECT10_CMD 0x55 55#define MODE_SELECT10_CMDLEN 10 56#define LOG_SENSE_CMD 0x4d 57#define LOG_SENSE_CMDLEN 10 58#define LOG_SELECT_CMD 0x4c 59#define LOG_SELECT_CMDLEN 10 60#define START_STOP_CMD 0x1b 61#define START_STOP_CMDLEN 6 62#define PREVENT_ALLOW_CMD 0x1e 63#define PREVENT_ALLOW_CMDLEN 6 64 65#define MODE6_RESP_HDR_LEN 4 66#define MODE10_RESP_HDR_LEN 8 67#define MODE_RESP_ARB_LEN 1024 68 69#define INQUIRY_RESP_INITIAL_LEN 36 70 71 72#if defined(__GNUC__) || defined(__clang__) 73static int pr2ws(const char * fmt, ...) 74 __attribute__ ((format (printf, 1, 2))); 75#else 76static int pr2ws(const char * fmt, ...); 77#endif 78 79 80static int 81pr2ws(const char * fmt, ...) 82{ 83 va_list args; 84 int n; 85 86 va_start(args, fmt); 87 n = vfprintf(sg_warnings_strm ? sg_warnings_strm : stderr, fmt, args); 88 va_end(args); 89 return n; 90} 91 92static struct sg_pt_base * 93create_pt_obj(const char * cname) 94{ 95 struct sg_pt_base * ptvp = construct_scsi_pt_obj(); 96 if (NULL == ptvp) 97 pr2ws("%s: out of memory\n", cname); 98 return ptvp; 99} 100 101/* Invokes a SCSI SYNCHRONIZE CACHE (10) command. Return of 0 -> success, 102 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 103int 104sg_ll_sync_cache_10(int sg_fd, bool sync_nv, bool immed, int group, 105 unsigned int lba, unsigned int count, bool noisy, 106 int verbose) 107{ 108 static const char * const cdb_name_s = "synchronize cache(10)"; 109 int res, ret, k, sense_cat; 110 unsigned char sc_cdb[SYNCHRONIZE_CACHE_CMDLEN] = 111 {SYNCHRONIZE_CACHE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 112 unsigned char sense_b[SENSE_BUFF_LEN]; 113 struct sg_pt_base * ptvp; 114 115 if (sync_nv) 116 sc_cdb[1] |= 4; 117 if (immed) 118 sc_cdb[1] |= 2; 119 sg_put_unaligned_be32((uint32_t)lba, sc_cdb + 2); 120 sc_cdb[6] = group & 0x1f; 121 if (count > 0xffff) { 122 pr2ws("count too big\n"); 123 return -1; 124 } 125 sg_put_unaligned_be16((int16_t)count, sc_cdb + 7); 126 127 if (verbose) { 128 pr2ws(" %s cdb: ", cdb_name_s); 129 for (k = 0; k < SYNCHRONIZE_CACHE_CMDLEN; ++k) 130 pr2ws("%02x ", sc_cdb[k]); 131 pr2ws("\n"); 132 } 133 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 134 return -1; 135 set_scsi_pt_cdb(ptvp, sc_cdb, sizeof(sc_cdb)); 136 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 137 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 138 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 139 noisy, verbose, &sense_cat); 140 if (-1 == ret) { 141 int os_err = get_scsi_pt_os_err(ptvp); 142 143 if ((os_err > 0) && (os_err < 47)) 144 ret = SG_LIB_OS_BASE_ERR + os_err; 145 } else if (-2 == ret) { 146 switch (sense_cat) { 147 case SG_LIB_CAT_RECOVERED: 148 case SG_LIB_CAT_NO_SENSE: 149 ret = 0; 150 break; 151 default: 152 ret = sense_cat; 153 break; 154 } 155 } else 156 ret = 0; 157 158 destruct_scsi_pt_obj(ptvp); 159 return ret; 160} 161 162/* Invokes a SCSI READ CAPACITY (16) command. Returns 0 -> success, 163 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 164int 165sg_ll_readcap_16(int sg_fd, bool pmi, uint64_t llba, void * resp, 166 int mx_resp_len, bool noisy, int verbose) 167{ 168 static const char * const cdb_name_s = "read capacity(16)"; 169 int k, ret, res, sense_cat; 170 unsigned char rc_cdb[SERVICE_ACTION_IN_16_CMDLEN] = 171 {SERVICE_ACTION_IN_16_CMD, READ_CAPACITY_16_SA, 172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 173 unsigned char sense_b[SENSE_BUFF_LEN]; 174 struct sg_pt_base * ptvp; 175 176 if (pmi) { /* lbs only valid when pmi set */ 177 rc_cdb[14] |= 1; 178 sg_put_unaligned_be64(llba, rc_cdb + 2); 179 } 180 /* Allocation length, no guidance in SBC-2 rev 15b */ 181 sg_put_unaligned_be32((uint32_t)mx_resp_len, rc_cdb + 10); 182 if (verbose) { 183 pr2ws(" %s cdb: ", cdb_name_s); 184 for (k = 0; k < SERVICE_ACTION_IN_16_CMDLEN; ++k) 185 pr2ws("%02x ", rc_cdb[k]); 186 pr2ws("\n"); 187 } 188 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 189 return -1; 190 set_scsi_pt_cdb(ptvp, rc_cdb, sizeof(rc_cdb)); 191 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 192 set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); 193 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 194 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b, 195 noisy, verbose, &sense_cat); 196 if (-1 == ret) { 197 int os_err = get_scsi_pt_os_err(ptvp); 198 199 if ((os_err > 0) && (os_err < 47)) 200 ret = SG_LIB_OS_BASE_ERR + os_err; 201 } else if (-2 == ret) { 202 switch (sense_cat) { 203 case SG_LIB_CAT_RECOVERED: 204 case SG_LIB_CAT_NO_SENSE: 205 ret = 0; 206 break; 207 default: 208 ret = sense_cat; 209 break; 210 } 211 } else 212 ret = 0; 213 214 destruct_scsi_pt_obj(ptvp); 215 return ret; 216} 217 218/* Invokes a SCSI READ CAPACITY (10) command. Returns 0 -> success, 219 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 220int 221sg_ll_readcap_10(int sg_fd, bool pmi, unsigned int lba, void * resp, 222 int mx_resp_len, bool noisy, int verbose) 223{ 224 static const char * const cdb_name_s = "read capacity(10)"; 225 int k, ret, res, sense_cat; 226 unsigned char rc_cdb[READ_CAPACITY_10_CMDLEN] = 227 {READ_CAPACITY_10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 228 unsigned char sense_b[SENSE_BUFF_LEN]; 229 struct sg_pt_base * ptvp; 230 231 if (pmi) { /* lbs only valid when pmi set */ 232 rc_cdb[8] |= 1; 233 sg_put_unaligned_be32((uint32_t)lba, rc_cdb + 2); 234 } 235 if (verbose) { 236 pr2ws(" %s cdb: ", cdb_name_s); 237 for (k = 0; k < READ_CAPACITY_10_CMDLEN; ++k) 238 pr2ws("%02x ", rc_cdb[k]); 239 pr2ws("\n"); 240 } 241 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 242 return -1; 243 set_scsi_pt_cdb(ptvp, rc_cdb, sizeof(rc_cdb)); 244 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 245 set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); 246 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 247 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b, 248 noisy, verbose, &sense_cat); 249 if (-1 == ret) { 250 int os_err = get_scsi_pt_os_err(ptvp); 251 252 if ((os_err > 0) && (os_err < 47)) 253 ret = SG_LIB_OS_BASE_ERR + os_err; 254 } else if (-2 == ret) { 255 switch (sense_cat) { 256 case SG_LIB_CAT_RECOVERED: 257 case SG_LIB_CAT_NO_SENSE: 258 ret = 0; 259 break; 260 default: 261 ret = sense_cat; 262 break; 263 } 264 } else 265 ret = 0; 266 267 destruct_scsi_pt_obj(ptvp); 268 return ret; 269} 270 271/* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success, 272 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 273int 274sg_ll_mode_sense6(int sg_fd, bool dbd, int pc, int pg_code, int sub_pg_code, 275 void * resp, int mx_resp_len, bool noisy, int verbose) 276{ 277 static const char * const cdb_name_s = "mode sense(6)"; 278 int res, ret, k, sense_cat, resid; 279 unsigned char modes_cdb[MODE_SENSE6_CMDLEN] = 280 {MODE_SENSE6_CMD, 0, 0, 0, 0, 0}; 281 unsigned char sense_b[SENSE_BUFF_LEN]; 282 struct sg_pt_base * ptvp; 283 284 modes_cdb[1] = (unsigned char)(dbd ? 0x8 : 0); 285 modes_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); 286 modes_cdb[3] = (unsigned char)(sub_pg_code & 0xff); 287 modes_cdb[4] = (unsigned char)(mx_resp_len & 0xff); 288 if (mx_resp_len > 0xff) { 289 pr2ws("mx_resp_len too big\n"); 290 return -1; 291 } 292 if (verbose) { 293 pr2ws(" %s cdb: ", cdb_name_s); 294 for (k = 0; k < MODE_SENSE6_CMDLEN; ++k) 295 pr2ws("%02x ", modes_cdb[k]); 296 pr2ws("\n"); 297 } 298 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 299 return -1; 300 set_scsi_pt_cdb(ptvp, modes_cdb, sizeof(modes_cdb)); 301 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 302 set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); 303 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 304 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b, 305 noisy, verbose, &sense_cat); 306 resid = get_scsi_pt_resid(ptvp); 307 if (-1 == ret) { 308 int os_err = get_scsi_pt_os_err(ptvp); 309 310 if ((os_err > 0) && (os_err < 47)) 311 ret = SG_LIB_OS_BASE_ERR + os_err; 312 } else if (-2 == ret) { 313 switch (sense_cat) { 314 case SG_LIB_CAT_RECOVERED: 315 case SG_LIB_CAT_NO_SENSE: 316 ret = 0; 317 break; 318 default: 319 ret = sense_cat; 320 break; 321 } 322 } else { 323 if ((verbose > 2) && (ret > 0)) { 324 pr2ws(" %s: response", cdb_name_s); 325 if (3 == verbose) { 326 pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : "")); 327 hex2stderr((const uint8_t *)resp, (ret > 256 ? 256 : ret), 328 -1); 329 } else { 330 pr2ws(":\n"); 331 hex2stderr((const uint8_t *)resp, ret, 0); 332 } 333 } 334 ret = 0; 335 } 336 destruct_scsi_pt_obj(ptvp); 337 338 if (resid > 0) { 339 if (resid > mx_resp_len) { 340 pr2ws("%s: resid (%d) should never exceed requested len=%d\n", 341 cdb_name_s, resid, mx_resp_len); 342 return ret ? ret : SG_LIB_CAT_MALFORMED; 343 } 344 /* zero unfilled section of response buffer */ 345 memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); 346 } 347 return ret; 348} 349 350/* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, 351 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 352int 353sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code, 354 int sub_pg_code, void * resp, int mx_resp_len, 355 bool noisy, int verbose) 356{ 357 return sg_ll_mode_sense10_v2(sg_fd, llbaa, dbd, pc, pg_code, sub_pg_code, 358 resp, mx_resp_len, 0, NULL, noisy, verbose); 359} 360 361/* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, 362 * various SG_LIB_CAT_* positive values or -1 -> other errors. 363 * Adds the ability to set the command abort timeout 364 * and the ability to report the residual count. If timeout_secs is zero 365 * or less the default command abort timeout (60 seconds) is used. 366 * If residp is non-NULL then the residual value is written where residp 367 * points. A residual value of 0 implies mx_resp_len bytes have be written 368 * where resp points. If the residual value equals mx_resp_len then no 369 * bytes have been written. */ 370int 371sg_ll_mode_sense10_v2(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code, 372 int sub_pg_code, void * resp, int mx_resp_len, 373 int timeout_secs, int * residp, bool noisy, int verbose) 374{ 375 int res, ret, k, sense_cat, resid; 376 static const char * const cdb_name_s = "mode sense(10)"; 377 struct sg_pt_base * ptvp; 378 unsigned char modes_cdb[MODE_SENSE10_CMDLEN] = 379 {MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 380 unsigned char sense_b[SENSE_BUFF_LEN]; 381 382 modes_cdb[1] = (unsigned char)((dbd ? 0x8 : 0) | (llbaa ? 0x10 : 0)); 383 modes_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); 384 modes_cdb[3] = (unsigned char)(sub_pg_code & 0xff); 385 sg_put_unaligned_be16((int16_t)mx_resp_len, modes_cdb + 7); 386 if (mx_resp_len > 0xffff) { 387 pr2ws("mx_resp_len too big\n"); 388 goto gen_err; 389 } 390 if (verbose) { 391 pr2ws(" %s cdb: ", cdb_name_s); 392 for (k = 0; k < MODE_SENSE10_CMDLEN; ++k) 393 pr2ws("%02x ", modes_cdb[k]); 394 pr2ws("\n"); 395 } 396 if (timeout_secs <= 0) 397 timeout_secs = DEF_PT_TIMEOUT; 398 399 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 400 goto gen_err; 401 set_scsi_pt_cdb(ptvp, modes_cdb, sizeof(modes_cdb)); 402 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 403 set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len); 404 res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose); 405 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b, 406 noisy, verbose, &sense_cat); 407 resid = get_scsi_pt_resid(ptvp); 408 if (residp) 409 *residp = resid; 410 if (-1 == ret) { 411 int os_err = get_scsi_pt_os_err(ptvp); 412 413 if ((os_err > 0) && (os_err < 47)) 414 ret = SG_LIB_OS_BASE_ERR + os_err; 415 } else if (-2 == ret) { 416 switch (sense_cat) { 417 case SG_LIB_CAT_RECOVERED: 418 case SG_LIB_CAT_NO_SENSE: 419 ret = 0; 420 break; 421 default: 422 ret = sense_cat; 423 break; 424 } 425 } else { 426 if ((verbose > 2) && (ret > 0)) { 427 pr2ws(" %s: response", cdb_name_s); 428 if (3 == verbose) { 429 pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : "")); 430 hex2stderr((const uint8_t *)resp, (ret > 256 ? 256 : ret), 431 -1); 432 } else { 433 pr2ws(":\n"); 434 hex2stderr((const uint8_t *)resp, ret, 0); 435 } 436 } 437 ret = 0; 438 } 439 destruct_scsi_pt_obj(ptvp); 440 441 if (resid > 0) { 442 if (resid > mx_resp_len) { 443 pr2ws("%s: resid (%d) should never exceed requested len=%d\n", 444 cdb_name_s, resid, mx_resp_len); 445 return ret ? ret : SG_LIB_CAT_MALFORMED; 446 } 447 /* zero unfilled section of response buffer */ 448 memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); 449 } 450 return ret; 451gen_err: 452 if (residp) 453 *residp = 0; 454 return -1; 455} 456 457/* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success, 458 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 459int 460sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, int param_len, 461 bool noisy, int verbose) 462{ 463 static const char * const cdb_name_s = "mode select(6)"; 464 int res, ret, k, sense_cat; 465 unsigned char modes_cdb[MODE_SELECT6_CMDLEN] = 466 {MODE_SELECT6_CMD, 0, 0, 0, 0, 0}; 467 unsigned char sense_b[SENSE_BUFF_LEN]; 468 struct sg_pt_base * ptvp; 469 470 modes_cdb[1] = (unsigned char)((pf ? 0x10 : 0x0) | (sp ? 0x1 : 0x0)); 471 modes_cdb[4] = (unsigned char)(param_len & 0xff); 472 if (param_len > 0xff) { 473 pr2ws("%s: param_len too big\n", cdb_name_s); 474 return -1; 475 } 476 if (verbose) { 477 pr2ws(" %s cdb: ", cdb_name_s); 478 for (k = 0; k < MODE_SELECT6_CMDLEN; ++k) 479 pr2ws("%02x ", modes_cdb[k]); 480 pr2ws("\n"); 481 } 482 if (verbose > 1) { 483 pr2ws(" %s parameter list\n", cdb_name_s); 484 hex2stderr((const uint8_t *)paramp, param_len, -1); 485 } 486 487 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 488 return -1; 489 set_scsi_pt_cdb(ptvp, modes_cdb, sizeof(modes_cdb)); 490 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 491 set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); 492 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 493 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 494 noisy, verbose, &sense_cat); 495 if (-1 == ret) { 496 int os_err = get_scsi_pt_os_err(ptvp); 497 498 if ((os_err > 0) && (os_err < 47)) 499 ret = SG_LIB_OS_BASE_ERR + os_err; 500 } else if (-2 == ret) { 501 switch (sense_cat) { 502 case SG_LIB_CAT_RECOVERED: 503 case SG_LIB_CAT_NO_SENSE: 504 ret = 0; 505 break; 506 default: 507 ret = sense_cat; 508 break; 509 } 510 } else 511 ret = 0; 512 513 destruct_scsi_pt_obj(ptvp); 514 return ret; 515} 516 517/* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success, 518 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 519int 520sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp, int param_len, 521 bool noisy, int verbose) 522{ 523 static const char * const cdb_name_s = "mode select(10)"; 524 int res, ret, k, sense_cat; 525 unsigned char modes_cdb[MODE_SELECT10_CMDLEN] = 526 {MODE_SELECT10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 527 unsigned char sense_b[SENSE_BUFF_LEN]; 528 struct sg_pt_base * ptvp; 529 530 modes_cdb[1] = (unsigned char)((pf ? 0x10 : 0x0) | (sp ? 0x1 : 0x0)); 531 sg_put_unaligned_be16((int16_t)param_len, modes_cdb + 7); 532 if (param_len > 0xffff) { 533 pr2ws("%s: param_len too big\n", cdb_name_s); 534 return -1; 535 } 536 if (verbose) { 537 pr2ws(" %s cdb: ", cdb_name_s); 538 for (k = 0; k < MODE_SELECT10_CMDLEN; ++k) 539 pr2ws("%02x ", modes_cdb[k]); 540 pr2ws("\n"); 541 } 542 if (verbose > 1) { 543 pr2ws(" %s parameter list\n", cdb_name_s); 544 hex2stderr((const uint8_t *)paramp, param_len, -1); 545 } 546 547 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 548 return -1; 549 set_scsi_pt_cdb(ptvp, modes_cdb, sizeof(modes_cdb)); 550 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 551 set_scsi_pt_data_out(ptvp, (unsigned char *)paramp, param_len); 552 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 553 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 554 noisy, verbose, &sense_cat); 555 if (-1 == ret) { 556 int os_err = get_scsi_pt_os_err(ptvp); 557 558 if ((os_err > 0) && (os_err < 47)) 559 ret = SG_LIB_OS_BASE_ERR + os_err; 560 } else if (-2 == ret) { 561 switch (sense_cat) { 562 case SG_LIB_CAT_RECOVERED: 563 case SG_LIB_CAT_NO_SENSE: 564 ret = 0; 565 break; 566 default: 567 ret = sense_cat; 568 break; 569 } 570 } else 571 ret = 0; 572 573 destruct_scsi_pt_obj(ptvp); 574 return ret; 575} 576 577/* MODE SENSE commands yield a response that has header then zero or more 578 * block descriptors followed by mode pages. In most cases users are 579 * interested in the first mode page. This function returns the (byte) 580 * offset of the start of the first mode page. Set mode_sense_6 to true for 581 * MODE SENSE (6) and false for MODE SENSE (10). Returns >= 0 is successful 582 * or -1 if failure. If there is a failure a message is written to err_buff 583 * if it is non-NULL and err_buff_len > 0. */ 584int 585sg_mode_page_offset(const unsigned char * resp, int resp_len, 586 bool mode_sense_6, char * err_buff, int err_buff_len) 587{ 588 int bd_len, calc_len, offset; 589 bool err_buff_ok = ((err_buff_len > 0) && err_buff); 590 591 if ((NULL == resp) || (resp_len < 4)) 592 goto too_short; 593 if (mode_sense_6) { 594 calc_len = resp[0] + 1; 595 bd_len = resp[3]; 596 offset = bd_len + MODE6_RESP_HDR_LEN; 597 } else { /* Mode sense(10) */ 598 if (resp_len < 8) 599 goto too_short; 600 calc_len = sg_get_unaligned_be16(resp) + 2; 601 bd_len = sg_get_unaligned_be16(resp + 6); 602 /* LongLBA doesn't change this calculation */ 603 offset = bd_len + MODE10_RESP_HDR_LEN; 604 } 605 if ((offset + 2) > calc_len) { 606 if (err_buff_ok) 607 snprintf(err_buff, err_buff_len, "calculated response " 608 "length too small, offset=%d calc_len=%d bd_len=%d\n", 609 offset, calc_len, bd_len); 610 offset = -1; 611 } 612 return offset; 613too_short: 614 if (err_buff_ok) 615 snprintf(err_buff, err_buff_len, "given MS(%d) response length (%d) " 616 "too short\n", (mode_sense_6 ? 6 : 10), resp_len); 617 return -1; 618} 619 620/* MODE SENSE commands yield a response that has header then zero or more 621 * block descriptors followed by mode pages. This functions returns the 622 * length (in bytes) of those three components. Note that the return value 623 * can exceed resp_len in which case the MODE SENSE command should be 624 * re-issued with a larger response buffer. If bd_lenp is non-NULL and if 625 * successful the block descriptor length (in bytes) is written to *bd_lenp. 626 * Set mode_sense_6 to true for MODE SENSE (6) and false for MODE SENSE (10) 627 * responses. Returns -1 if there is an error (e.g. response too short). */ 628int 629sg_msense_calc_length(const unsigned char * resp, int resp_len, 630 bool mode_sense_6, int * bd_lenp) 631{ 632 int calc_len; 633 634 if (NULL == resp) 635 goto an_err; 636 if (mode_sense_6) { 637 if (resp_len < 4) 638 goto an_err; 639 calc_len = resp[0] + 1; 640 } else { 641 if (resp_len < 8) 642 goto an_err; 643 calc_len = sg_get_unaligned_be16(resp + 0) + 2; 644 } 645 if (bd_lenp) 646 *bd_lenp = mode_sense_6 ? resp[3] : sg_get_unaligned_be16(resp + 6); 647 return calc_len; 648an_err: 649 if (bd_lenp) 650 *bd_lenp = 0; 651 return -1; 652} 653 654/* Fetches current, changeable, default and/or saveable modes pages as 655 * indicated by pcontrol_arr for given pg_code and sub_pg_code. If 656 * mode6==false then use MODE SENSE (10) else use MODE SENSE (6). If 657 * flexible set and mode data length seems wrong then try and 658 * fix (compensating hack for bad device or driver). pcontrol_arr 659 * should have 4 elements for output of current, changeable, default 660 * and saved values respectively. Each element should be NULL or 661 * at least mx_mpage_len bytes long. 662 * Return of 0 -> overall success, various SG_LIB_CAT_* positive values or 663 * -1 -> other errors. 664 * If success_mask pointer is not NULL then first zeros it. Then set bits 665 * 0, 1, 2 and/or 3 if the current, changeable, default and saved values 666 * respectively have been fetched. If error on current page 667 * then stops and returns that error; otherwise continues if an error is 668 * detected but returns the first error encountered. */ 669int 670sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code, 671 bool dbd, bool flexible, int mx_mpage_len, 672 int * success_mask, void * pcontrol_arr[], 673 int * reported_lenp, int verbose) 674{ 675 bool resp_mode6; 676 int k, n, res, offset, calc_len, xfer_len; 677 int resid = 0; 678 const int msense10_hlen = MODE10_RESP_HDR_LEN; 679 unsigned char buff[MODE_RESP_ARB_LEN]; 680 char ebuff[EBUFF_SZ]; 681 int first_err = 0; 682 683 if (success_mask) 684 *success_mask = 0; 685 if (reported_lenp) 686 *reported_lenp = 0; 687 if (mx_mpage_len < 4) 688 return 0; 689 memset(ebuff, 0, sizeof(ebuff)); 690 /* first try to find length of current page response */ 691 memset(buff, 0, msense10_hlen); 692 if (mode6) /* want first 8 bytes just in case */ 693 res = sg_ll_mode_sense6(sg_fd, dbd, 0 /* pc */, pg_code, 694 sub_pg_code, buff, msense10_hlen, true, 695 verbose); 696 else /* MODE SENSE(10) obviously */ 697 res = sg_ll_mode_sense10_v2(sg_fd, false /* llbaa */, dbd, 698 0 /* pc */, pg_code, sub_pg_code, buff, 699 msense10_hlen, 0, &resid, true, verbose); 700 if (0 != res) 701 return res; 702 n = buff[0]; 703 if (reported_lenp) { 704 int m; 705 706 m = sg_msense_calc_length(buff, msense10_hlen, mode6, NULL) - resid; 707 if (m < 0) /* Grrr, this should not happen */ 708 m = 0; 709 *reported_lenp = m; 710 } 711 resp_mode6 = mode6; 712 if (flexible) { 713 if (mode6 && (n < 3)) { 714 resp_mode6 = false; 715 if (verbose) 716 pr2ws(">>> msense(6) but resp[0]=%d so try msense(10) " 717 "response processing\n", n); 718 } 719 if ((! mode6) && (n > 5)) { 720 if ((n > 11) && (0 == (n % 2)) && (0 == buff[4]) && 721 (0 == buff[5]) && (0 == buff[6])) { 722 buff[1] = n; 723 buff[0] = 0; 724 if (verbose) 725 pr2ws(">>> msense(10) but resp[0]=%d and not msense(6) " 726 "response so fix length\n", n); 727 } else 728 resp_mode6 = true; 729 } 730 } 731 if (verbose && (resp_mode6 != mode6)) 732 pr2ws(">>> msense(%d) but resp[0]=%d so switch response " 733 "processing\n", (mode6 ? 6 : 10), buff[0]); 734 calc_len = sg_msense_calc_length(buff, msense10_hlen, resp_mode6, NULL); 735 if (calc_len > MODE_RESP_ARB_LEN) 736 calc_len = MODE_RESP_ARB_LEN; 737 offset = sg_mode_page_offset(buff, calc_len, resp_mode6, ebuff, EBUFF_SZ); 738 if (offset < 0) { 739 if (('\0' != ebuff[0]) && (verbose > 0)) 740 pr2ws("%s: %s\n", __func__, ebuff); 741 return SG_LIB_CAT_MALFORMED; 742 } 743 xfer_len = calc_len - offset; 744 if (xfer_len > mx_mpage_len) 745 xfer_len = mx_mpage_len; 746 747 for (k = 0; k < 4; ++k) { 748 if (NULL == pcontrol_arr[k]) 749 continue; 750 memset(pcontrol_arr[k], 0, mx_mpage_len); 751 resid = 0; 752 if (mode6) 753 res = sg_ll_mode_sense6(sg_fd, dbd, k /* pc */, 754 pg_code, sub_pg_code, buff, 755 calc_len, true, verbose); 756 else 757 res = sg_ll_mode_sense10_v2(sg_fd, false /* llbaa */, dbd, 758 k /* pc */, pg_code, sub_pg_code, 759 buff, calc_len, 0, &resid, true, 760 verbose); 761 if (res || resid) { 762 if (0 == first_err) { 763 if (res) 764 first_err = res; 765 else { 766 first_err = -49; /* unexpected resid != 0 */ 767 if (verbose) 768 pr2ws("%s: unexpected resid=%d, page=0x%x, " 769 "pcontrol=%d\n", __func__, resid, pg_code, k); 770 } 771 } 772 if (0 == k) 773 break; /* if problem on current page, it won't improve */ 774 else 775 continue; 776 } 777 if (xfer_len > 0) 778 memcpy(pcontrol_arr[k], buff + offset, xfer_len); 779 if (success_mask) 780 *success_mask |= (1 << k); 781 } 782 return first_err; 783} 784 785/* Invokes a SCSI LOG SENSE command. Return of 0 -> success, 786 * various SG_LIB_CAT_* positive values or -1 -> other errors. */ 787int 788sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code, 789 int subpg_code, int paramp, unsigned char * resp, 790 int mx_resp_len, bool noisy, int verbose) 791{ 792 return sg_ll_log_sense_v2(sg_fd, ppc, sp, pc, pg_code, subpg_code, 793 paramp, resp, mx_resp_len, 0, NULL, noisy, 794 verbose); 795} 796 797/* Invokes a SCSI LOG SENSE command. Return of 0 -> success, 798 * various SG_LIB_CAT_* positive values or -1 -> other errors. 799 * Adds the ability to set the command abort timeout 800 * and the ability to report the residual count. If timeout_secs is zero 801 * or less the default command abort timeout (60 seconds) is used. 802 * If residp is non-NULL then the residual value is written where residp 803 * points. A residual value of 0 implies mx_resp_len bytes have be written 804 * where resp points. If the residual value equals mx_resp_len then no 805 * bytes have been written. */ 806int 807sg_ll_log_sense_v2(int sg_fd, bool ppc, bool sp, int pc, int pg_code, 808 int subpg_code, int paramp, unsigned char * resp, 809 int mx_resp_len, int timeout_secs, int * residp, 810 bool noisy, int verbose) 811{ 812 static const char * const cdb_name_s = "log sense"; 813 int res, ret, k, sense_cat, resid; 814 unsigned char logs_cdb[LOG_SENSE_CMDLEN] = 815 {LOG_SENSE_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 816 unsigned char sense_b[SENSE_BUFF_LEN]; 817 struct sg_pt_base * ptvp; 818 819 if (mx_resp_len > 0xffff) { 820 pr2ws("mx_resp_len too big\n"); 821 goto gen_err; 822 } 823 logs_cdb[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0)); 824 logs_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); 825 logs_cdb[3] = (unsigned char)(subpg_code & 0xff); 826 sg_put_unaligned_be16((int16_t)paramp, logs_cdb + 5); 827 sg_put_unaligned_be16((int16_t)mx_resp_len, logs_cdb + 7); 828 if (verbose) { 829 pr2ws(" %s cdb: ", cdb_name_s); 830 for (k = 0; k < LOG_SENSE_CMDLEN; ++k) 831 pr2ws("%02x ", logs_cdb[k]); 832 pr2ws("\n"); 833 } 834 if (timeout_secs <= 0) 835 timeout_secs = DEF_PT_TIMEOUT; 836 837 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 838 goto gen_err; 839 set_scsi_pt_cdb(ptvp, logs_cdb, sizeof(logs_cdb)); 840 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 841 set_scsi_pt_data_in(ptvp, resp, mx_resp_len); 842 res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose); 843 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, 844 sense_b, noisy, verbose, &sense_cat); 845 resid = get_scsi_pt_resid(ptvp); 846 if (residp) 847 *residp = resid; 848 if (-1 == ret) { 849 int os_err = get_scsi_pt_os_err(ptvp); 850 851 if ((os_err > 0) && (os_err < 47)) 852 ret = SG_LIB_OS_BASE_ERR + os_err; 853 } else if (-2 == ret) { 854 switch (sense_cat) { 855 case SG_LIB_CAT_RECOVERED: 856 case SG_LIB_CAT_NO_SENSE: 857 ret = 0; 858 break; 859 default: 860 ret = sense_cat; 861 break; 862 } 863 } else { 864 if ((mx_resp_len > 3) && (ret < 4)) { 865 /* resid indicates LOG SENSE response length bad, so zero it */ 866 resp[2] = 0; 867 resp[3] = 0; 868 } 869 ret = 0; 870 } 871 destruct_scsi_pt_obj(ptvp); 872 873 if (resid > 0) { 874 if (resid > mx_resp_len) { 875 pr2ws("%s: resid (%d) should never exceed requested len=%d\n", 876 cdb_name_s, resid, mx_resp_len); 877 return ret ? ret : SG_LIB_CAT_MALFORMED; 878 } 879 /* zero unfilled section of response buffer */ 880 memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid); 881 } 882 return ret; 883gen_err: 884 if (residp) 885 *residp = 0; 886 return -1; 887} 888 889/* Invokes a SCSI LOG SELECT command. Return of 0 -> success, 890 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 891int 892sg_ll_log_select(int sg_fd, bool pcr, bool sp, int pc, int pg_code, 893 int subpg_code, unsigned char * paramp, int param_len, 894 bool noisy, int verbose) 895{ 896 static const char * const cdb_name_s = "log select"; 897 int res, ret, k, sense_cat; 898 unsigned char logs_cdb[LOG_SELECT_CMDLEN] = 899 {LOG_SELECT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 900 unsigned char sense_b[SENSE_BUFF_LEN]; 901 struct sg_pt_base * ptvp; 902 903 if (param_len > 0xffff) { 904 pr2ws("%s: param_len too big\n", cdb_name_s); 905 return -1; 906 } 907 logs_cdb[1] = (unsigned char)((pcr ? 2 : 0) | (sp ? 1 : 0)); 908 logs_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f)); 909 logs_cdb[3] = (unsigned char)(subpg_code & 0xff); 910 sg_put_unaligned_be16((int16_t)param_len, logs_cdb + 7); 911 if (verbose) { 912 pr2ws(" %s cdb: ", cdb_name_s); 913 for (k = 0; k < LOG_SELECT_CMDLEN; ++k) 914 pr2ws("%02x ", logs_cdb[k]); 915 pr2ws("\n"); 916 } 917 if ((verbose > 1) && (param_len > 0)) { 918 pr2ws(" %s parameter list\n", cdb_name_s); 919 hex2stderr(paramp, param_len, -1); 920 } 921 922 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 923 return -1; 924 set_scsi_pt_cdb(ptvp, logs_cdb, sizeof(logs_cdb)); 925 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 926 set_scsi_pt_data_out(ptvp, paramp, param_len); 927 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 928 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 929 noisy, verbose, &sense_cat); 930 if (-1 == ret) { 931 int os_err = get_scsi_pt_os_err(ptvp); 932 933 if ((os_err > 0) && (os_err < 47)) 934 ret = SG_LIB_OS_BASE_ERR + os_err; 935 } else if (-2 == ret) { 936 switch (sense_cat) { 937 case SG_LIB_CAT_RECOVERED: 938 case SG_LIB_CAT_NO_SENSE: 939 ret = 0; 940 break; 941 default: 942 ret = sense_cat; 943 break; 944 } 945 } else 946 ret = 0; 947 948 destruct_scsi_pt_obj(ptvp); 949 return ret; 950} 951 952/* Invokes a SCSI START STOP UNIT command (SBC + MMC). 953 * Return of 0 -> success, 954 * various SG_LIB_CAT_* positive values or -1 -> other errors. 955 * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and 956 * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) 957 * and fl(mmc) one bit field. This is the cause of the awkardly named 958 * pc_mod__fl_num and noflush__fl arguments to this function. 959 * */ 960int 961sg_ll_start_stop_unit(int sg_fd, bool immed, int pc_mod__fl_num, 962 int power_cond, bool noflush__fl, bool loej, bool start, 963 bool noisy, int verbose) 964{ 965 static const char * const cdb_name_s = "start stop unit"; 966 int k, res, ret, sense_cat; 967 struct sg_pt_base * ptvp; 968 unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0}; 969 unsigned char sense_b[SENSE_BUFF_LEN]; 970 971 if (immed) 972 ssuBlk[1] = 0x1; 973 ssuBlk[3] = pc_mod__fl_num & 0xf; /* bits 2 and 3 are reserved in MMC */ 974 ssuBlk[4] = ((power_cond & 0xf) << 4); 975 if (noflush__fl) 976 ssuBlk[4] |= 0x4; 977 if (loej) 978 ssuBlk[4] |= 0x2; 979 if (start) 980 ssuBlk[4] |= 0x1; 981 if (verbose) { 982 pr2ws(" %s command:", cdb_name_s); 983 for (k = 0; k < (int)sizeof(ssuBlk); ++k) 984 pr2ws(" %02x", ssuBlk[k]); 985 pr2ws("\n"); 986 } 987 988 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 989 return -1; 990 set_scsi_pt_cdb(ptvp, ssuBlk, sizeof(ssuBlk)); 991 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 992 res = do_scsi_pt(ptvp, sg_fd, START_PT_TIMEOUT, verbose); 993 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 994 noisy, verbose, &sense_cat); 995 if (-1 == ret) { 996 int os_err = get_scsi_pt_os_err(ptvp); 997 998 if ((os_err > 0) && (os_err < 47)) 999 ret = SG_LIB_OS_BASE_ERR + os_err; 1000 } else if (-2 == ret) { 1001 switch (sense_cat) { 1002 case SG_LIB_CAT_RECOVERED: 1003 case SG_LIB_CAT_NO_SENSE: 1004 ret = 0; 1005 break; 1006 default: 1007 ret = sense_cat; 1008 break; 1009 } 1010 } else 1011 ret = 0; 1012 destruct_scsi_pt_obj(ptvp); 1013 return ret; 1014} 1015 1016/* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command 1017 * [was in SPC-3 but displaced from SPC-4 into SBC-3, MMC-5, SSC-3] 1018 * prevent==0 allows removal, prevent==1 prevents removal ... 1019 * Return of 0 -> success, 1020 * various SG_LIB_CAT_* positive values or -1 -> other errors */ 1021int 1022sg_ll_prevent_allow(int sg_fd, int prevent, bool noisy, int verbose) 1023{ 1024 static const char * const cdb_name_s = "prevent allow medium removal"; 1025 int k, res, ret, sense_cat; 1026 unsigned char p_cdb[PREVENT_ALLOW_CMDLEN] = 1027 {PREVENT_ALLOW_CMD, 0, 0, 0, 0, 0}; 1028 unsigned char sense_b[SENSE_BUFF_LEN]; 1029 struct sg_pt_base * ptvp; 1030 1031 if ((prevent < 0) || (prevent > 3)) { 1032 pr2ws("prevent argument should be 0, 1, 2 or 3\n"); 1033 return -1; 1034 } 1035 p_cdb[4] |= (prevent & 0x3); 1036 if (verbose) { 1037 pr2ws(" %s cdb: ", cdb_name_s); 1038 for (k = 0; k < PREVENT_ALLOW_CMDLEN; ++k) 1039 pr2ws("%02x ", p_cdb[k]); 1040 pr2ws("\n"); 1041 } 1042 1043 if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) 1044 return -1; 1045 set_scsi_pt_cdb(ptvp, p_cdb, sizeof(p_cdb)); 1046 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); 1047 res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose); 1048 ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, SG_NO_DATA_IN, sense_b, 1049 noisy, verbose, &sense_cat); 1050 if (-1 == ret) { 1051 int os_err = get_scsi_pt_os_err(ptvp); 1052 1053 if ((os_err > 0) && (os_err < 47)) 1054 ret = SG_LIB_OS_BASE_ERR + os_err; 1055 } else if (-2 == ret) { 1056 switch (sense_cat) { 1057 case SG_LIB_CAT_RECOVERED: 1058 case SG_LIB_CAT_NO_SENSE: 1059 ret = 0; 1060 break; 1061 default: 1062 ret = sense_cat; 1063 break; 1064 } 1065 } else 1066 ret = 0; 1067 destruct_scsi_pt_obj(ptvp); 1068 return ret; 1069} 1070