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