Home | History | Annotate | Download | only in include
      1 #ifndef SG_PT_H
      2 #define SG_PT_H
      3 
      4 /*
      5  * Copyright (c) 2005-2018 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 #include <stdint.h>
     12 #include <stdbool.h>
     13 
     14 #ifdef __cplusplus
     15 extern "C" {
     16 #endif
     17 
     18 /* This declaration hides the fact that each implementation has its own
     19  * structure "derived" (using a C++ term) from this one. It compiles
     20  * because 'struct sg_pt_base' is only referenced (by pointer: 'objp')
     21  * in this interface. An instance of this structure represents the
     22  * context of one SCSI command. */
     23 struct sg_pt_base;
     24 
     25 
     26 /* The format of the version string is like this: "2.01 20090201".
     27  * The leading digit will be incremented if this interface changes
     28  * in a way that may impact backward compatibility. */
     29 const char * scsi_pt_version();
     30 
     31 
     32 /* Returns >= 0 if successful. If error in Unix returns negated errno. */
     33 int scsi_pt_open_device(const char * device_name, bool read_only, int verbose);
     34 
     35 /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed
     36  * together. Returns valid file descriptor( >= 0 ) if successful, otherwise
     37  * returns -1 or a negated errno.
     38  * In Win32 O_EXCL translated to equivalent. */
     39 int scsi_pt_open_flags(const char * device_name, int flags, int verbose);
     40 
     41 /* Returns 0 if successful. If error in Unix returns negated errno. */
     42 int scsi_pt_close_device(int device_fd);
     43 
     44 /* Assumes dev_fd is an "open" file handle associated with device_name. If
     45  * the implementation (possibly for one OS) cannot determine from dev_fd if
     46  * a SCSI or NVMe pass-through is referenced, then it might guess based on
     47  * device_name. Returns 1 if SCSI generic pass-though device, returns 2 if
     48  * secondary SCSI pass-through device (in Linux a bsg device); returns 3 is
     49  * char NVMe device (i.e. no NSID); returns 4 if block NVMe device (includes
     50  * NSID), or 0 if something else (e.g. ATA block device) or dev_fd < 0.
     51  * If error, returns negated errno (operating system) value. */
     52 int check_pt_file_handle(int dev_fd, const char * device_name, int verbose);
     53 
     54 
     55 /* Creates an object that can be used to issue one or more SCSI commands
     56  * (or task management functions). Returns NULL if problem.
     57  * Once this object has been created it should be destroyed with
     58  * destruct_scsi_pt_obj() when it is no longer needed. */
     59 struct sg_pt_base * construct_scsi_pt_obj(void);
     60 
     61 /* An alternate way to create an object that can be used to issue one or
     62  * more SCSI commands (or task management functions). This variant
     63  * associate a device file descriptor (handle) with the object and a
     64  * verbose argument that causes error messages if errors occur. The
     65  * reason for this is to optionally allow the detection of NVMe devices
     66  * that will cause pt_device_is_nvme() to return true. Set dev_fd to
     67  * -1 if no open device file descriptor is available. Caller should
     68  *  additionally call get_scsi_pt_os_err() after this call. */
     69 struct sg_pt_base *
     70         construct_scsi_pt_obj_with_fd(int dev_fd, int verbose);
     71 
     72 /* Forget any previous dev_fd and install the one given. May attempt to
     73  * find file type (e.g. if pass-though) from OS so there could be an error.
     74  * Returns 0 for success or the same value as get_scsi_pt_os_err()
     75  * will return. dev_fd should be >= 0 for a valid file handle or -1 . */
     76 int set_pt_file_handle(struct sg_pt_base * objp, int dev_fd, int verbose);
     77 
     78 /* Valid file handles (which is the return value) are >= 0 . Returns -1
     79  * if there is no valid file handle. */
     80 int get_pt_file_handle(const struct sg_pt_base * objp);
     81 
     82 /* Clear state information held in *objp . This allows this object to be
     83  * used to issue more than one SCSI command. The dev_fd is remembered.
     84  * Use set_pt_file_handle() to change dev_fd. */
     85 void clear_scsi_pt_obj(struct sg_pt_base * objp);
     86 
     87 /* Set the CDB (command descriptor block) */
     88 void set_scsi_pt_cdb(struct sg_pt_base * objp, const unsigned char * cdb,
     89                      int cdb_len);
     90 /* Set the sense buffer and the maximum length that it can handle */
     91 void set_scsi_pt_sense(struct sg_pt_base * objp, unsigned char * sense,
     92                        int max_sense_len);
     93 /* Set a pointer and length to be used for data transferred from device */
     94 void set_scsi_pt_data_in(struct sg_pt_base * objp,   /* from device */
     95                          unsigned char * dxferp, int dxfer_ilen);
     96 /* Set a pointer and length to be used for data transferred to device */
     97 void set_scsi_pt_data_out(struct sg_pt_base * objp,    /* to device */
     98                           const unsigned char * dxferp, int dxfer_olen);
     99 /* Set a pointer and length to be used for metadata transferred to
    100  * (out_true=true) or from (out_true-false) device */
    101 void set_pt_metadata_xfer(struct sg_pt_base * objp, unsigned char * mdxferp,
    102                           uint32_t mdxfer_len, bool out_true);
    103 /* The following "set_"s implementations may be dummies */
    104 void set_scsi_pt_packet_id(struct sg_pt_base * objp, int pack_id);
    105 void set_scsi_pt_tag(struct sg_pt_base * objp, uint64_t tag);
    106 void set_scsi_pt_task_management(struct sg_pt_base * objp, int tmf_code);
    107 void set_scsi_pt_task_attr(struct sg_pt_base * objp, int attribute,
    108                            int priority);
    109 
    110 /* Following is a guard which is defined when set_scsi_pt_flags() is
    111  * present. Older versions of this library may not have this function. */
    112 #define SCSI_PT_FLAGS_FUNCTION 1
    113 /* If neither QUEUE_AT_HEAD nor QUEUE_AT_TAIL are given, or both
    114  * are given, use the pass-through default. */
    115 #define SCSI_PT_FLAGS_QUEUE_AT_TAIL 0x10
    116 #define SCSI_PT_FLAGS_QUEUE_AT_HEAD 0x20
    117 /* Set (potentially OS dependent) flags for pass-through mechanism.
    118  * Apart from contradictions, flags can be OR-ed together. */
    119 void set_scsi_pt_flags(struct sg_pt_base * objp, int flags);
    120 
    121 #define SCSI_PT_DO_START_OK 0
    122 #define SCSI_PT_DO_BAD_PARAMS 1
    123 #define SCSI_PT_DO_TIMEOUT 2
    124 #define SCSI_PT_DO_NVME_STATUS 48       /* == SG_LIB_NVME_STATUS */
    125 /* If OS error prior to or during command submission then returns negated
    126  * error value (e.g. Unix '-errno'). This includes interrupted system calls
    127  * (e.g. by a signal) in which case -EINTR would be returned. Note that
    128  * system call errors also can be fetched with get_scsi_pt_os_err().
    129  * Return 0 if okay (i.e. at the very least: command sent). Positive
    130  * return values are errors (see SCSI_PT_DO_* defines). If a file descriptor
    131  * has already been provided by construct_scsi_pt_obj_with_fd() then the
    132  * given 'fd' can be -1 or the same value as given to the constructor. */
    133 int do_scsi_pt(struct sg_pt_base * objp, int fd, int timeout_secs,
    134                int verbose);
    135 
    136 #define SCSI_PT_RESULT_GOOD 0
    137 #define SCSI_PT_RESULT_STATUS 1 /* other than GOOD and CHECK CONDITION */
    138 #define SCSI_PT_RESULT_SENSE 2
    139 #define SCSI_PT_RESULT_TRANSPORT_ERR 3
    140 #define SCSI_PT_RESULT_OS_ERR 4
    141 /* highest numbered applicable category returned */
    142 int get_scsi_pt_result_category(const struct sg_pt_base * objp);
    143 
    144 /* If not available return 0 which implies there is no residual
    145  * value. If supported the number of bytes actually sent back by
    146  * the device is 'dxfer_ilen - get_scsi_pt_len()' bytes.  */
    147 int get_scsi_pt_resid(const struct sg_pt_base * objp);
    148 
    149 /* Returns SCSI status value (from device that received the command). If an
    150  * NVMe command was issued directly (i.e. through do_scsi_pt() then return
    151  * NVMe status (i.e. ((SCT << 8) | SC)) */
    152 int get_scsi_pt_status_response(const struct sg_pt_base * objp);
    153 
    154 /* Returns SCSI status value or, if NVMe command given to do_scsi_pt(),
    155  * then returns NVMe result (i.e. DWord(0) from completion queue). If
    156  * 'objp' is NULL then returns 0xffffffff. */
    157 uint32_t get_pt_result(const struct sg_pt_base * objp);
    158 
    159 /* Actual sense length returned. If sense data is present but
    160    actual sense length is not known, return 'max_sense_len' */
    161 int get_scsi_pt_sense_len(const struct sg_pt_base * objp);
    162 
    163 /* If not available return 0 (for success). */
    164 int get_scsi_pt_os_err(const struct sg_pt_base * objp);
    165 char * get_scsi_pt_os_err_str(const struct sg_pt_base * objp, int max_b_len,
    166                               char * b);
    167 
    168 /* If not available return 0 (for success) */
    169 int get_scsi_pt_transport_err(const struct sg_pt_base * objp);
    170 void set_scsi_pt_transport_err(struct sg_pt_base * objp, int err);
    171 char * get_scsi_pt_transport_err_str(const struct sg_pt_base * objp,
    172                                      int max_b_len, char * b);
    173 
    174 /* If not available return -1 */
    175 int get_scsi_pt_duration_ms(const struct sg_pt_base * objp);
    176 
    177 /* Return true if device associated with 'objp' uses NVMe command set. To
    178  * be useful (in modifying the type of command sent (SCSI or NVMe) then
    179  * construct_scsi_pt_obj_with_fd() should be used followed by an invocation
    180  * of this function. */
    181 bool pt_device_is_nvme(const struct sg_pt_base * objp);
    182 
    183 /* If a NVMe block device (which includes the NSID) handle is associated
    184  * with 'objp', then its NSID is returned (values range from 0x1 to
    185  * 0xffffffe). Otherwise 0 is returned. */
    186 uint32_t get_pt_nvme_nsid(const struct sg_pt_base * objp);
    187 
    188 
    189 /* Should be invoked once per objp after other processing is complete in
    190  * order to clean up resources. For ever successful construct_scsi_pt_obj()
    191  * call there should be one destruct_scsi_pt_obj(). If the
    192  * construct_scsi_pt_obj_with_fd() function was used to create this object
    193  * then the dev_fd provided to that constructor is not altered by this
    194  * destructor. So the user should still close dev_fd (perhaps with
    195  * scsi_pt_close_device() ).  */
    196 void destruct_scsi_pt_obj(struct sg_pt_base * objp);
    197 
    198 #ifdef SG_LIB_WIN32
    199 #define SG_LIB_WIN32_DIRECT 1
    200 
    201 /* Request SPT direct interface when state_direct is 1, state_direct set
    202  * to 0 for the SPT indirect interface. Default setting selected by build
    203  * (i.e. library compile time) and is usually indirect. */
    204 void scsi_pt_win32_direct(int state_direct);
    205 
    206 /* Returns current SPT interface state, 1 for direct, 0 for indirect */
    207 int scsi_pt_win32_spt_state(void);
    208 
    209 #endif
    210 
    211 #ifdef __cplusplus
    212 }
    213 #endif
    214 
    215 #endif
    216