Home | History | Annotate | Download | only in include
      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