1 #ifndef SG_CMDS_BASIC_H 2 #define SG_CMDS_BASIC_H 3 4 /* 5 * Copyright (c) 2004-2017 Douglas Gilbert. 6 * All rights reserved. 7 * Use of this source code is governed by a BSD-style 8 * license that can be found in the BSD_LICENSE file. 9 */ 10 11 /* 12 * Error, warning and verbose output is sent to the file pointed to by 13 * sg_warnings_strm which is declared in sg_lib.h and can be set with 14 * the sg_set_warnings_strm() function. If not given sg_warnings_strm 15 * defaults to stderr. 16 * If 'noisy' is false and 'verbose' is zero then following functions should 17 * not output anything to sg_warnings_strm. If 'noisy' is true and 18 * 'verbose' is zero then Unit Attention, Recovered, Medium and Hardware 19 * errors (sense keys) send output to sg_warnings_strm. Increasing values 20 * of 'verbose' send increasing amounts of (debug) output to 21 * sg_warnings_strm. 22 */ 23 24 #include <stdint.h> 25 #include <stdbool.h> 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 32 /* Invokes a SCSI INQUIRY command and yields the response 33 * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, 34 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 35 * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other errors */ 36 int sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp, 37 int mx_resp_len, bool noisy, int verbose); 38 39 /* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when 40 * successful, various SG_LIB_CAT_* positive values or -1 -> other errors. 41 * The CMDDT field is obsolete in the INQUIRY cdb (since spc3r16 in 2003) so 42 * an argument to set it has been removed (use the REPORT SUPPORTED OPERATION 43 * CODES command instead). Adds the ability to set the command abort timeout 44 * and the ability to report the residual count. If timeout_secs is zero 45 * or less the default command abort timeout (60 seconds) is used. 46 * If residp is non-NULL then the residual value is written where residp 47 * points. A residual value of 0 implies mx_resp_len bytes have be written 48 * where resp points. If the residual value equals mx_resp_len then no 49 * bytes have been written. */ 50 int 51 sg_ll_inquiry_v2(int sg_fd, bool evpd, int pg_op, void * resp, 52 int mx_resp_len, int timeout_secs, int * residp, 53 bool noisy, int verbose); 54 55 /* Invokes a SCSI LOG SELECT command. Return of 0 -> success, 56 * SG_LIB_CAT_INVALID_OP -> Log Select not supported, 57 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 58 * SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, 59 * -1 -> other failure */ 60 int sg_ll_log_select(int sg_fd, bool pcr, bool sp, int pc, int pg_code, 61 int subpg_code, unsigned char * paramp, int param_len, 62 bool noisy, int verbose); 63 64 /* Invokes a SCSI LOG SENSE command. Return of 0 -> success, 65 * SG_LIB_CAT_INVALID_OP -> Log Sense not supported, 66 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 67 * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 68 * -1 -> other failure */ 69 int sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code, 70 int subpg_code, int paramp, unsigned char * resp, 71 int mx_resp_len, bool noisy, int verbose); 72 73 /* Same as sg_ll_log_sense() apart from timeout_secs and residp. See 74 * sg_ll_inquiry_v2() for their description */ 75 int sg_ll_log_sense_v2(int sg_fd, bool ppc, bool sp, int pc, int pg_code, 76 int subpg_code, int paramp, unsigned char * resp, 77 int mx_resp_len, int timeout_secs, int * residp, 78 bool noisy, int verbose); 79 80 /* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success, 81 * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 82 * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 83 * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 84 * -1 -> other failure */ 85 int sg_ll_mode_select6(int sg_fd, bool pf, bool sp, void * paramp, 86 int param_len, bool noisy, int verbose); 87 88 /* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success, 89 * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 90 * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 91 * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 92 * -1 -> other failure */ 93 int sg_ll_mode_select10(int sg_fd, bool pf, bool sp, void * paramp, 94 int param_len, bool noisy, int verbose); 95 96 /* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success, 97 * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 98 * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 99 * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 100 * -1 -> other failure */ 101 int sg_ll_mode_sense6(int sg_fd, bool dbd, int pc, int pg_code, 102 int sub_pg_code, void * resp, int mx_resp_len, 103 bool noisy, int verbose); 104 105 /* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, 106 * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 107 * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 108 * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 109 * -1 -> other failure */ 110 int sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code, 111 int sub_pg_code, void * resp, int mx_resp_len, 112 bool noisy, int verbose); 113 114 /* Same as sg_ll_mode_sense10() apart from timeout_secs and residp. See 115 * sg_ll_inquiry_v2() for their description */ 116 int sg_ll_mode_sense10_v2(int sg_fd, bool llbaa, bool dbd, int pc, 117 int pg_code, int sub_pg_code, void * resp, 118 int mx_resp_len, int timeout_secs, int * residp, 119 bool noisy, int verbose); 120 121 /* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command (SPC-3) 122 * prevent==0 allows removal, prevent==1 prevents removal ... 123 * Return of 0 -> success, 124 * SG_LIB_CAT_INVALID_OP -> command not supported 125 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 126 * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 127 * -1 -> other failure */ 128 int sg_ll_prevent_allow(int sg_fd, int prevent, bool noisy, int verbose); 129 130 /* Invokes a SCSI READ CAPACITY (10) command. Return of 0 -> success, 131 * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION 132 * -> perhaps media changed, SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 133 * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 134 * -1 -> other failure */ 135 int sg_ll_readcap_10(int sg_fd, bool pmi, unsigned int lba, void * resp, 136 int mx_resp_len, bool noisy, int verbose); 137 138 /* Invokes a SCSI READ CAPACITY (16) command. Returns 0 -> success, 139 * SG_LIB_CAT_UNIT_ATTENTION -> media changed??, SG_LIB_CAT_INVALID_OP 140 * -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb 141 * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 142 * -1 -> other failure */ 143 int sg_ll_readcap_16(int sg_fd, bool pmi, uint64_t llba, void * resp, 144 int mx_resp_len, bool noisy, int verbose); 145 146 /* Invokes a SCSI REPORT LUNS command. Return of 0 -> success, 147 * SG_LIB_CAT_INVALID_OP -> Report Luns not supported, 148 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 149 * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ 150 int sg_ll_report_luns(int sg_fd, int select_report, void * resp, 151 int mx_resp_len, bool noisy, int verbose); 152 153 /* Invokes a SCSI REQUEST SENSE command. Return of 0 -> success, 154 * SG_LIB_CAT_INVALID_OP -> Request Sense not supported??, 155 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 156 * -1 -> other failure */ 157 int sg_ll_request_sense(int sg_fd, bool desc, void * resp, int mx_resp_len, 158 bool noisy, int verbose); 159 160 /* Invokes a SCSI START STOP UNIT command (SBC + MMC). 161 * Return of 0 -> success, 162 * SG_LIB_CAT_INVALID_OP -> Start stop unit not supported, 163 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 164 * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 165 * -1 -> other failure 166 * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and 167 * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) 168 * and fl(mmc) one bit field. This is the cause of the awkardly named 169 * pc_mod__fl_num and noflush__fl arguments to this function. */ 170 int sg_ll_start_stop_unit(int sg_fd, bool immed, int pc_mod__fl_num, 171 int power_cond, bool noflush__fl, bool loej, 172 bool start, bool noisy, int verbose); 173 174 /* Invokes a SCSI SYNCHRONIZE CACHE (10) command. Return of 0 -> success, 175 * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 176 * SG_LIB_CAT_INVALID_OP -> cdb not supported, 177 * SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb 178 * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ 179 int sg_ll_sync_cache_10(int sg_fd, bool sync_nv, bool immed, int group, 180 unsigned int lba, unsigned int count, bool noisy, 181 int verbose); 182 183 /* Invokes a SCSI TEST UNIT READY command. 184 * 'pack_id' is just for diagnostics, safe to set to 0. 185 * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, 186 * SG_LIB_CAT_NOT_READY -> device not ready, 187 * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ 188 int sg_ll_test_unit_ready(int sg_fd, int pack_id, bool noisy, int verbose); 189 190 /* Invokes a SCSI TEST UNIT READY command. 191 * 'pack_id' is just for diagnostics, safe to set to 0. 192 * Looks for progress indicator if 'progress' non-NULL; 193 * if found writes value [0..65535] else write -1. 194 * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, 195 * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> 196 * device not ready, -1 -> other failure */ 197 int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress, 198 bool noisy, int verbose); 199 200 201 struct sg_simple_inquiry_resp { 202 unsigned char peripheral_qualifier; 203 unsigned char peripheral_type; 204 unsigned char byte_1; /* was 'rmb' prior to version 1.39 */ 205 /* now rmb == !!(0x80 & byte_1) */ 206 unsigned char version; /* as per recent drafts: whole of byte 2 */ 207 unsigned char byte_3; 208 unsigned char byte_5; 209 unsigned char byte_6; 210 unsigned char byte_7; 211 char vendor[9]; /* T10 field is 8 bytes, NUL char appended */ 212 char product[17]; 213 char revision[5]; 214 }; 215 216 /* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response. 217 * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, 218 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 219 * -1 -> other errors */ 220 int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data, 221 bool noisy, int verbose); 222 223 /* MODE SENSE commands yield a response that has header then zero or more 224 * block descriptors followed by mode pages. In most cases users are 225 * interested in the first mode page. This function returns the (byte) 226 * offset of the start of the first mode page. Set mode_sense_6 to true for 227 * MODE SENSE (6) and false for MODE SENSE (10). Returns >= 0 is successful 228 * or -1 if failure. If there is a failure a message is written to err_buff 229 * if it is non-NULL and err_buff_len > 0. */ 230 int sg_mode_page_offset(const unsigned char * resp, int resp_len, 231 bool mode_sense_6, char * err_buff, int err_buff_len); 232 233 /* MODE SENSE commands yield a response that has header then zero or more 234 * block descriptors followed by mode pages. This functions returns the 235 * length (in bytes) of those three components. Note that the return value 236 * can exceed resp_len in which case the MODE SENSE command should be 237 * re-issued with a larger response buffer. If bd_lenp is non-NULL and if 238 * successful the block descriptor length (in bytes) is written to *bd_lenp. 239 * Set mode_sense_6 to true for MODE SENSE (6) and false for MODE SENSE (10) 240 * responses. Returns -1 if there is an error (e.g. response too short). */ 241 int sg_msense_calc_length(const unsigned char * resp, int resp_len, 242 bool mode_sense_6, int * bd_lenp); 243 244 /* Fetches current, changeable, default and/or saveable modes pages as 245 * indicated by pcontrol_arr for given pg_code and sub_pg_code. If 246 * mode6==0 then use MODE SENSE (10) else use MODE SENSE (6). If 247 * flexible set and mode data length seems wrong then try and 248 * fix (compensating hack for bad device or driver). pcontrol_arr 249 * should have 4 elements for output of current, changeable, default 250 * and saved values respectively. Each element should be NULL or 251 * at least mx_mpage_len bytes long. 252 * Return of 0 -> overall success, SG_LIB_CAT_INVALID_OP -> invalid opcode, 253 * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 254 * SG_LIB_CAT_NOT_READY -> device not ready, 255 * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other failure. 256 * If success_mask pointer is not NULL then first zeros it. Then set bits 257 * 0, 1, 2 and/or 3 if the current, changeable, default and saved values 258 * respectively have been fetched. If error on current page 259 * then stops and returns that error; otherwise continues if an error is 260 * detected but returns the first error encountered. */ 261 int sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, 262 int sub_pg_code, bool dbd, bool flexible, 263 int mx_mpage_len, int * success_mask, 264 void * pcontrol_arr[], int * reported_lenp, 265 int verbose); 266 267 /* Returns file descriptor >= 0 if successful. If error in Unix returns 268 negated errno. Implementation calls scsi_pt_open_device(). */ 269 int sg_cmds_open_device(const char * device_name, bool read_only, int verbose); 270 271 /* Returns file descriptor >= 0 if successful. If error in Unix returns 272 negated errno. Implementation calls scsi_pt_open_flags(). */ 273 int sg_cmds_open_flags(const char * device_name, int flags, int verbose); 274 275 /* Returns 0 if successful. If error in Unix returns negated errno. 276 Implementation calls scsi_pt_close_device(). */ 277 int sg_cmds_close_device(int device_fd); 278 279 const char * sg_cmds_version(); 280 281 #define SG_NO_DATA_IN 0 282 283 struct sg_pt_base; 284 285 /* This is a helper function used by sg_cmds_* implementations after the 286 * call to the pass-through. pt_res is returned from do_scsi_pt(). If valid 287 * sense data is found it is decoded and output to sg_warnings_strm (def: 288 * stderr); depending on the 'noisy' and 'verbose' settings. Returns -2 for 289 * sense data (may not be fatal), -1 for failed, 0, or a positive number. If 290 * 'mx_di_len > 0' then asks pass-through for resid and returns 291 * (mx_di_len - resid); otherwise returns 0. So for data-in it should return 292 * the actual number of bytes received. For data-out (to device) or no data 293 * call with 'mx_di_len' set to 0 or less. If -2 returned then sense category 294 * output via 'o_sense_cat' pointer (if not NULL). Note that several sense 295 * categories also have data in bytes received; -2 is still returned. */ 296 int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, 297 int pt_res, int mx_di_len, 298 const unsigned char * sense_b, bool noisy, 299 int verbose, int * o_sense_cat); 300 301 /* NVMe devices use a different command set. This function will return true 302 * if the device associated with 'pvtp' is a NVME device, else it will 303 * return false (e.g. for SCSI devices). */ 304 bool sg_cmds_is_nvme(const struct sg_pt_base * ptvp); 305 306 #ifdef __cplusplus 307 } 308 #endif 309 310 #endif 311