├── Makefile ├── README.md ├── include ├── sg_cmds.h ├── sg_cmds_basic.h ├── sg_cmds_extra.h ├── sg_cmds_mmc.h ├── sg_io_linux.h ├── sg_lib.h ├── sg_lib_data.h ├── sg_linux_inc.h ├── sg_pt.h └── sg_pt_win32.h ├── lib32 ├── sg_io_linux.o ├── sg_lib.o └── sg_lib_data.o ├── lib64 ├── sg_io_linux.o ├── sg_lib.o └── sg_lib_data.o ├── lto-cm.1.gz ├── lto-cm.c └── lto-cm.h /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | ARCH = $(shell arch) 3 | DESTDIR ?= $RPM_BUILD_ROOT 4 | CC = gcc 5 | EXECS = install 6 | LARGE_FILE_FLAGS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 7 | 8 | install: lto-cm.o $(LIBFILES) 9 | $(CC) -o lto-cm $(LDFLAGS) $^ 10 | @mkdir -p $(DESTDIR)/usr/bin 11 | @cp lto-cm $(DESTDIR)/usr/bin 12 | @mkdir -p $(DESTDIR)/usr/lib64 13 | @mkdir -p $(DESTDIR)/usr/lib 14 | @mkdir -p $(DESTDIR)/usr/include 15 | @mkdir -p $(DESTDIR)/usr/share/man/ 16 | @mkdir -p $(DESTDIR)/usr/share/man/en 17 | @mkdir -p $(DESTDIR)/usr/share/man/en/man1 18 | @cp ./lto-cm.1.gz $(DESTDIR)/usr/share/man/en/man1 19 | @cp ./include/sg_cmds.h $(DESTDIR)/usr/include 20 | @cp ./include/sg_cmds_basic.h $(DESTDIR)/usr/include 21 | @cp ./include/sg_cmds_extra.h $(DESTDIR)/usr/include 22 | @cp ./include/sg_cmds_mmc.h $(DESTDIR)/usr/include 23 | @cp ./include/sg_io_linux.h $(DESTDIR)/usr/include 24 | @cp ./include/sg_lib.h $(DESTDIR)/usr/include 25 | @cp ./include/sg_lib_data.h $(DESTDIR)/usr/include 26 | @cp ./include/sg_linux_inc.h $(DESTDIR)/usr/include 27 | @cp ./include/sg_pt.h $(DESTDIR)/usr/include 28 | @cp ./include/sg_pt_win32.h $(DESTDIR)/usr/include 29 | @cp ./lib32/sg_lib.o $(DESTDIR)/usr/lib 30 | @cp ./lib32/sg_io_linux.o $(DESTDIR)/usr/lib 31 | @cp ./lib32/sg_lib_data.o $(DESTDIR)/usr/lib 32 | @cp ./lib64/sg_lib.o $(DESTDIR)/usr/lib64 33 | @cp ./lib64/sg_io_linux.o $(DESTDIR)/usr/lib64 34 | @cp ./lib64/sg_lib_data.o $(DESTDIR)/usr/lib64 35 | 36 | uninstall: 37 | @rm -rf $(DESTDIR)/usr/bin/lto-cm 38 | 39 | reinstall: uninstall install 40 | 41 | clean: 42 | @rm -f *.o *~ ./$(EXECS) 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lto-cm 2 | ======= 3 | 4 | Read and write the text attribute of a Linear Tape Open (LTO) cartridge memory chip, also called Medium Access Memory (MAM). 5 | 6 | 7 | How to Generate Binaries 8 | ======================== 9 | 10 | **Requires gcc 11 | 12 | - Download root directory of lto-cm 13 | - Open a terminal 14 | - Replace Makefile on root folder with binaries/Makefile 15 | - Open location in terminal 16 | - Type make 17 | 18 | This should provide binaries for lto-cm. 19 | -------------------------------------------------------------------------------- /include/sg_cmds.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_CMDS_H 2 | #define SG_CMDS_H 3 | 4 | /******************************************************************** 5 | * This header did contain wrapper declarations for many SCSI commands 6 | * up until sg3_utils version 1.22 . In that version, the command 7 | * wrappers were broken into two groups, the 'basic' ones found in the 8 | * "sg_cmds_basic.h" header and the 'extra' ones found in the 9 | * "sg_cmds_extra.h" header. This header now simply includes those two 10 | * headers. 11 | * In sg3_utils version 1.26 the sg_cmds_mmc.h header was added and 12 | * contains some MMC specific commands. 13 | * The corresponding function definitions are found in the sg_cmds_basic.c, 14 | * sg_cmds_extra.c and sg_cmds_mmc.c files. 15 | ********************************************************************/ 16 | 17 | #include "sg_cmds_basic.h" 18 | #include "sg_cmds_extra.h" 19 | #include "sg_cmds_mmc.h" 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/sg_cmds_basic.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_CMDS_BASIC_H 2 | #define SG_CMDS_BASIC_H 3 | 4 | /* 5 | * Copyright (c) 2004-2010 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 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | /* Invokes a SCSI INQUIRY command and yields the response 17 | * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, 18 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 19 | * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other errors */ 20 | extern int sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, 21 | void * resp, int mx_resp_len, int noisy, 22 | int verbose); 23 | 24 | /* Invokes a SCSI LOG SELECT command. Return of 0 -> success, 25 | * SG_LIB_CAT_INVALID_OP -> Log Select not supported, 26 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 27 | * SG_LIB_CAT_ABORTED_COMMAND, * SG_LIB_CAT_NOT_READY -> device not ready, 28 | * -1 -> other failure */ 29 | extern int sg_ll_log_select(int sg_fd, int pcr, int sp, int pc, 30 | int pg_code, int subpg_code, 31 | unsigned char * paramp, int param_len, 32 | int noisy, int verbose); 33 | 34 | /* Invokes a SCSI LOG SENSE command. Return of 0 -> success, 35 | * SG_LIB_CAT_INVALID_OP -> Log Sense not supported, 36 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 37 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 38 | * -1 -> other failure */ 39 | extern int sg_ll_log_sense(int sg_fd, int ppc, int sp, int pc, int pg_code, 40 | int subpg_code, int paramp, unsigned char * resp, 41 | int mx_resp_len, int noisy, int verbose); 42 | 43 | /* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success, 44 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 45 | * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 46 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 47 | * -1 -> other failure */ 48 | extern int sg_ll_mode_select6(int sg_fd, int pf, int sp, void * paramp, 49 | int param_len, int noisy, int verbose); 50 | 51 | /* Invokes a SCSI MODE SELECT (10) command. Return of 0 -> success, 52 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 53 | * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 54 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 55 | * -1 -> other failure */ 56 | extern int sg_ll_mode_select10(int sg_fd, int pf, int sp, void * paramp, 57 | int param_len, int noisy, int verbose); 58 | 59 | /* Invokes a SCSI MODE SENSE (6) command. Return of 0 -> success, 60 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 61 | * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 62 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 63 | * -1 -> other failure */ 64 | extern int sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, 65 | int sub_pg_code, void * resp, int mx_resp_len, 66 | int noisy, int verbose); 67 | 68 | /* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success, 69 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ -> 70 | * bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready, 71 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 72 | * -1 -> other failure */ 73 | extern int sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, 74 | int pg_code, int sub_pg_code, void * resp, 75 | int mx_resp_len, int noisy, int verbose); 76 | 77 | /* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command (SPC-3) 78 | * prevent==0 allows removal, prevent==1 prevents removal ... 79 | * Return of 0 -> success, 80 | * SG_LIB_CAT_INVALID_OP -> command not supported 81 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 82 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 83 | * -1 -> other failure */ 84 | extern int sg_ll_prevent_allow(int sg_fd, int prevent, int noisy, 85 | int verbose); 86 | 87 | /* Invokes a SCSI READ CAPACITY (10) command. Return of 0 -> success, 88 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION 89 | * -> perhaps media changed, SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 90 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 91 | * -1 -> other failure */ 92 | extern int sg_ll_readcap_10(int sg_fd, int pmi, unsigned int lba, 93 | void * resp, int mx_resp_len, int noisy, 94 | int verbose); 95 | 96 | /* Invokes a SCSI READ CAPACITY (16) command. Returns 0 -> success, 97 | * SG_LIB_CAT_UNIT_ATTENTION -> media changed??, SG_LIB_CAT_INVALID_OP 98 | * -> cdb not supported, SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb 99 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 100 | * -1 -> other failure */ 101 | extern int sg_ll_readcap_16(int sg_fd, int pmi, uint64_t llba, void * resp, 102 | int mx_resp_len, int noisy, int verbose); 103 | 104 | /* Invokes a SCSI REPORT LUNS command. Return of 0 -> success, 105 | * SG_LIB_CAT_INVALID_OP -> Report Luns not supported, 106 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 107 | * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ 108 | extern int sg_ll_report_luns(int sg_fd, int select_report, void * resp, 109 | int mx_resp_len, int noisy, int verbose); 110 | 111 | /* Invokes a SCSI REQUEST SENSE command. Return of 0 -> success, 112 | * SG_LIB_CAT_INVALID_OP -> Request Sense not supported??, 113 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 114 | * -1 -> other failure */ 115 | extern int sg_ll_request_sense(int sg_fd, int desc, void * resp, 116 | int mx_resp_len, int noisy, int verbose); 117 | 118 | /* Invokes a SCSI START STOP UNIT command (SBC + MMC). 119 | * Return of 0 -> success, 120 | * SG_LIB_CAT_INVALID_OP -> Start stop unit not supported, 121 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 122 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 123 | * -1 -> other failure 124 | * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and 125 | * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) 126 | * and fl(mmc) one bit field. This is the cause of the awkardly named 127 | * pc_mod__fl_num and noflush__fl arguments to this function. */ 128 | extern int sg_ll_start_stop_unit(int sg_fd, int immed, int pc_mod__fl_num, 129 | int power_cond, int noflush__fl, int loej, 130 | int start, int noisy, int verbose); 131 | 132 | /* Invokes a SCSI SYNCHRONIZE CACHE (10) command. Return of 0 -> success, 133 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, 134 | * SG_LIB_CAT_INVALID_OP -> cdb not supported, 135 | * SG_LIB_CAT_IlLEGAL_REQ -> bad field in cdb 136 | * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ 137 | extern int sg_ll_sync_cache_10(int sg_fd, int sync_nv, int immed, int group, 138 | unsigned int lba, unsigned int count, 139 | int noisy, int verbose); 140 | 141 | /* Invokes a SCSI TEST UNIT READY command. 142 | * 'pack_id' is just for diagnostics, safe to set to 0. 143 | * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, 144 | * SG_LIB_CAT_NOT_READY -> device not ready, 145 | * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other failure */ 146 | extern int sg_ll_test_unit_ready(int sg_fd, int pack_id, int noisy, 147 | int verbose); 148 | 149 | /* Invokes a SCSI TEST UNIT READY command. 150 | * 'pack_id' is just for diagnostics, safe to set to 0. 151 | * Looks for progress indicator if 'progress' non-NULL; 152 | * if found writes value [0..65535] else write -1. 153 | * Return of 0 -> success, SG_LIB_CAT_UNIT_ATTENTION, 154 | * SG_LIB_CAT_ABORTED_COMMAND, SG_LIB_CAT_NOT_READY -> 155 | * device not ready, -1 -> other failure */ 156 | extern int sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, 157 | int * progress, int noisy, 158 | int verbose); 159 | 160 | 161 | struct sg_simple_inquiry_resp { 162 | unsigned char peripheral_qualifier; 163 | unsigned char peripheral_type; 164 | unsigned char rmb; 165 | unsigned char version; /* as per recent drafts: whole of byte 2 */ 166 | unsigned char byte_3; 167 | unsigned char byte_5; 168 | unsigned char byte_6; 169 | unsigned char byte_7; 170 | char vendor[9]; 171 | char product[17]; 172 | char revision[5]; 173 | }; 174 | 175 | /* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response. 176 | * Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported, 177 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 178 | * -1 -> other errors */ 179 | extern int sg_simple_inquiry(int sg_fd, 180 | struct sg_simple_inquiry_resp * inq_data, 181 | int noisy, int verbose); 182 | 183 | /* MODE SENSE commands yield a response that has block descriptors followed 184 | * by mode pages. In most cases users are interested in the first mode page. 185 | * This function returns the (byte) offset of the start of the first mode 186 | * page. Set mode_sense_6 to 1 for MODE SENSE (6) and 0 for MODE SENSE (10). 187 | * Returns >= 0 is successful or -1 if failure. If there is a failure 188 | * a message is written to err_buff. */ 189 | extern int sg_mode_page_offset(const unsigned char * resp, int resp_len, 190 | int mode_sense_6, char * err_buff, 191 | int err_buff_len); 192 | 193 | /* Fetches current, changeable, default and/or saveable modes pages as 194 | * indicated by pcontrol_arr for given pg_code and sub_pg_code. If 195 | * mode6==0 then use MODE SENSE (10) else use MODE SENSE (6). If 196 | * flexible set and mode data length seems wrong then try and 197 | * fix (compensating hack for bad device or driver). pcontrol_arr 198 | * should have 4 elements for output of current, changeable, default 199 | * and saved values respectively. Each element should be NULL or 200 | * at least mx_mpage_len bytes long. 201 | * Return of 0 -> overall success, SG_LIB_CAT_INVALID_OP -> invalid opcode, 202 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 203 | * SG_LIB_CAT_NOT_READY -> device not ready, 204 | * SG_LIB_CAT_MALFORMED -> bad response, -1 -> other failure. 205 | * If success_mask pointer is not NULL then first zeros it. Then set bits 206 | * 0, 1, 2 and/or 3 if the current, changeable, default and saved values 207 | * respectively have been fetched. If error on current page 208 | * then stops and returns that error; otherwise continues if an error is 209 | * detected but returns the first error encountered. */ 210 | extern int sg_get_mode_page_controls(int sg_fd, int mode6, int pg_code, 211 | int sub_pg_code, int dbd, int flexible, 212 | int mx_mpage_len, int * success_mask, 213 | void * pcontrol_arr[], int * reported_len, 214 | int verbose); 215 | 216 | /* Returns file descriptor >= 0 if successful. If error in Unix returns 217 | negated errno. Implementation calls scsi_pt_open_device(). */ 218 | extern int sg_cmds_open_device(const char * device_name, int read_only, 219 | int verbose); 220 | 221 | /* Returns file descriptor >= 0 if successful. If error in Unix returns 222 | negated errno. Implementation calls scsi_pt_open_flags(). */ 223 | extern int sg_cmds_open_flags(const char * device_name, int flags, 224 | int verbose); 225 | 226 | /* Returns 0 if successful. If error in Unix returns negated errno. 227 | Implementation calls scsi_pt_close_device(). */ 228 | extern int sg_cmds_close_device(int device_fd); 229 | 230 | extern const char * sg_cmds_version(); 231 | 232 | 233 | struct sg_pt_base; 234 | 235 | /* This is a helper function used by sg_cmds_* implementations after 236 | * the call to the pass-through. pt_res is returned from do_scsi_pt(). 237 | * If valid sense data is found it is decoded and output to sg_warnings_strm 238 | * (def: stderr); depending on the 'noisy' and 'verbose' settings. 239 | * Returns -2 for sense data (may not be fatal), -1 for failed or the 240 | * number of data in bytes received. For data out (to device) or no data, 241 | * set 'mx_di_len' to 0 or less. If -2 returned then sense category 242 | * output via 'o_sense_cat' pointer (if not NULL). Note that several sense 243 | * categories also have data in bytes received; -2 is still returned. */ 244 | extern int sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin, 245 | int pt_res, int mx_di_len, 246 | const unsigned char * sense_b, int noisy, 247 | int verbose, int * o_sense_cat); 248 | 249 | #ifdef __cplusplus 250 | } 251 | #endif 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /include/sg_cmds_extra.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_CMDS_EXTRA_H 2 | #define SG_CMDS_EXTRA_H 3 | 4 | /* 5 | * Copyright (c) 2004-2012 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 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | /* Invokes a ATA PASS-THROUGH (12 or 16) SCSI command (SAT). If cdb_len 17 | * is 12 then a ATA PASS-THROUGH (12) command is called. If cdb_len is 16 18 | * then a ATA PASS-THROUGH (16) command is called. If cdb_len is any other 19 | * value -1 is returned. After copying from cdbp to an internal buffer, 20 | * the first byte (i.e. offset 0) is set to 0xa1 if cdb_len is 12; or is 21 | * set to 0x85 if cdb_len is 16. The last byte (offset 11 or offset 15) is 22 | * set to 0x0 in the internal buffer. If timeout_secs <= 0 then the timeout 23 | * is set to 60 seconds. For data in or out transfers set dinp or doutp, 24 | * and dlen to the number of bytes to transfer. If dlen is zero then no data 25 | * transfer is assumed. If sense buffer obtained then it is written to 26 | * sensep, else sensep[0] is set to 0x0. If ATA return descriptor is obtained 27 | * then written to ata_return_dp, else ata_return_dp[0] is set to 0x0. Either 28 | * sensep or ata_return_dp (or both) may be NULL pointers. Returns SCSI 29 | * status value (>= 0) or -1 if other error. Users are expected to check the 30 | * sense buffer themselves. If available the data in resid is written to 31 | * residp. Note in SAT-2 and later, fixed format sense data may be placed in 32 | * *sensep in which case sensep[0]==0x70 . 33 | */ 34 | extern int sg_ll_ata_pt(int sg_fd, const unsigned char * cdbp, int cdb_len, 35 | int timeout_secs, void * dinp, void * doutp, 36 | int dlen, unsigned char * sensep, 37 | int max_sense_len, unsigned char * ata_return_dp, 38 | int max_ata_return_len, int * residp, int verbose); 39 | 40 | /* Invokes a FORMAT UNIT (SBC-3) command. Return of 0 -> success, 41 | * SG_LIB_CAT_INVALID_OP -> Format unit not supported, 42 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 43 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 44 | * -1 -> other failure */ 45 | extern int sg_ll_format_unit(int sg_fd, int fmtpinfo, int longlist, 46 | int fmtdata, int cmplist, int dlist_format, 47 | int timeout_secs, void * paramp, int param_len, 48 | int noisy, int verbose); 49 | 50 | /* Invokes a SCSI GET LBA STATUS command (SBC). Returns 0 -> success, 51 | * SG_LIB_CAT_INVALID_OP -> GET LBA STATUS not supported, 52 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 53 | * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ 54 | extern int sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp, 55 | int alloc_len, int noisy, int verbose); 56 | 57 | /* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0 58 | * when successful, SG_LIB_CAT_INVALID_OP if command not supported, 59 | * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, 60 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ 61 | extern int sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, 62 | void * resp, int mx_resp_len, 63 | int noisy, int verbose); 64 | 65 | /* Invokes a SCSI PERSISTENT RESERVE OUT command (SPC). Returns 0 66 | * when successful, SG_LIB_CAT_INVALID_OP if command not supported, 67 | * SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, 68 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ 69 | extern int sg_ll_persistent_reserve_out(int sg_fd, int rq_servact, 70 | int rq_scope, unsigned int rq_type, 71 | void * paramp, int param_len, 72 | int noisy, int verbose); 73 | 74 | /* Invokes a SCSI READ BLOCK LIMITS command. Return of 0 -> success, 75 | * SG_LIB_CAT_INVALID_OP -> READ BLOCK LIMITS not supported, 76 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 77 | * SG_LIB_NOT_READY (shouldn't happen), -1 -> other failure */ 78 | extern int sg_ll_read_block_limits(int sg_fd, void * resp, 79 | int mx_resp_len, int noisy, int verbose); 80 | 81 | /* Invokes a SCSI READ BUFFER command (SPC). Return of 0 -> 82 | * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, 83 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 84 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 85 | * -1 -> other failure */ 86 | extern int sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, 87 | int buffer_offset, void * resp, 88 | int mx_resp_len, int noisy, int verbose); 89 | 90 | /* Invokes a SCSI READ DEFECT DATA (10) command (SBC). Return of 0 -> 91 | * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, 92 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 93 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 94 | * -1 -> other failure */ 95 | extern int sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, 96 | int dl_format, void * resp, int mx_resp_len, 97 | int noisy, int verbose); 98 | 99 | /* Invokes a SCSI READ LONG (10) command (SBC). Note that 'xfer_len' 100 | * is in bytes. Returns 0 -> success, 101 | * SG_LIB_CAT_INVALID_OP -> READ LONG(10) not supported, 102 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 103 | * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info 104 | * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, 105 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 106 | * -1 -> other failure */ 107 | extern int sg_ll_read_long10(int sg_fd, int pblock, int correct, 108 | unsigned int lba, void * resp, int xfer_len, 109 | int * offsetp, int noisy, int verbose); 110 | 111 | /* Invokes a SCSI READ LONG (16) command (SBC). Note that 'xfer_len' 112 | * is in bytes. Returns 0 -> success, 113 | * SG_LIB_CAT_INVALID_OP -> READ LONG(16) not supported, 114 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 115 | * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info 116 | * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, 117 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 118 | * -1 -> other failure */ 119 | extern int sg_ll_read_long16(int sg_fd, int pblock, int correct, 120 | uint64_t llba, void * resp, int xfer_len, 121 | int * offsetp, int noisy, int verbose); 122 | 123 | /* Invokes a SCSI READ MEDIA SERIAL NUMBER command. Return of 0 -> success, 124 | * SG_LIB_CAT_INVALID_OP -> Read media serial number 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 | extern int sg_ll_read_media_serial_num(int sg_fd, void * resp, 129 | int mx_resp_len, int noisy, 130 | int verbose); 131 | 132 | /* Invokes a SCSI REASSIGN BLOCKS command. Return of 0 -> success, 133 | * SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_UNIT_ATTENTION, 134 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 135 | * SG_LIB_CAT_NOT_READY -> device not ready, -1 -> other failure */ 136 | extern int sg_ll_reassign_blocks(int sg_fd, int longlba, int longlist, 137 | void * paramp, int param_len, int noisy, 138 | int verbose); 139 | 140 | /* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success, 141 | * SG_LIB_CAT_INVALID_OP -> Receive diagnostic results not supported, 142 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 143 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 144 | * -1 -> other failure */ 145 | extern int sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp, 146 | int mx_resp_len, int noisy, int verbose); 147 | 148 | /* Invokes a SCSI REPORT IDENTIFYING INFORMATION command. This command was 149 | * called REPORT DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, 150 | * SG_LIB_CAT_INVALID_OP -> Report identifying information not supported, 151 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 152 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 153 | * -1 -> other failure */ 154 | extern int sg_ll_report_id_info(int sg_fd, int itype, void * resp, 155 | int max_resp_len, int noisy, int verbose); 156 | 157 | /* Invokes a SCSI REPORT TARGET PORT GROUPS command. Return of 0 -> success, 158 | * SG_LIB_CAT_INVALID_OP -> Report Target Port Groups not supported, 159 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 160 | * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ 161 | extern int sg_ll_report_tgt_prt_grp(int sg_fd, void * resp, 162 | int mx_resp_len, int noisy, int verbose); 163 | extern int sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len, 164 | int extended, int noisy, int verbose); 165 | 166 | /* Invokes a SCSI SET TARGET PORT GROUPS command. Return of 0 -> success, 167 | * SG_LIB_CAT_INVALID_OP -> Report Target Port Groups not supported, 168 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 169 | * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ 170 | extern int sg_ll_set_tgt_prt_grp(int sg_fd, void * paramp, 171 | int param_len, int noisy, int verbose); 172 | 173 | /* Invokes a SCSI REPORT REFERRALS command. Return of 0 -> success, 174 | * SG_LIB_CAT_INVALID_OP -> Report Referrals not supported, 175 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 176 | * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ 177 | extern int sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg, 178 | void * resp,int mx_resp_len, int noisy, 179 | int verbose); 180 | 181 | /* Invokes a SCSI SEND DIAGNOSTIC command. Foreground, extended self tests can 182 | * take a long time, if so set long_duration flag. Return of 0 -> success, 183 | * SG_LIB_CAT_INVALID_OP -> Send diagnostic not supported, 184 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 185 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 186 | * -1 -> other failure */ 187 | extern int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit, 188 | int devofl_bit, int unitofl_bit, int long_duration, 189 | void * paramp, int param_len, int noisy, 190 | int verbose); 191 | 192 | /* Invokes a SCSI SET IDENTIFYING INFORMATION command. This command was 193 | * called SET DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success, 194 | * SG_LIB_CAT_INVALID_OP -> Set identifying information not supported, 195 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 196 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 197 | * -1 -> other failure */ 198 | extern int sg_ll_set_id_info(int sg_fd, int itype, void * paramp, 199 | int param_len, int noisy, int verbose); 200 | 201 | /* Invokes a SCSI UNMAP (SBC-3) command. Return of 0 -> success, 202 | * SG_LIB_CAT_INVALID_OP -> command not supported, 203 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 204 | * SG_LIB_CAT_UNIT_ATTENTION, -1 -> other failure */ 205 | extern int sg_ll_unmap(int sg_fd, int group_num, int timeout_secs, 206 | void * paramp, int param_len, int noisy, int verbose); 207 | /* Invokes a SCSI UNMAP (SBC-3) command. Version 2 adds anchor field 208 | * (sbc3r22). Otherwise same as sg_ll_unmap() . */ 209 | extern int sg_ll_unmap_v2(int sg_fd, int anchor, int group_num, 210 | int timeout_secs, void * paramp, int param_len, 211 | int noisy, int verbose); 212 | 213 | /* Invokes a SCSI VERIFY (10) command (SBC and MMC). 214 | * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. 215 | * Returns of 0 -> success, 216 | * SG_LIB_CAT_INVALID_OP -> Verify(10) not supported, 217 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 218 | * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, 219 | * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, 220 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 221 | * -1 -> other failure */ 222 | extern int sg_ll_verify10(int sg_fd, int vrprotect, int dpo, int bytechk, 223 | unsigned int lba, int veri_len, void * data_out, 224 | int data_out_len, unsigned int * infop, int noisy, 225 | int verbose); 226 | 227 | /* Invokes a SCSI VERIFY (16) command (SBC). 228 | * Note that 'veri_len' is in blocks while 'data_out_len' is in bytes. 229 | * Returns of 0 -> success, 230 | * SG_LIB_CAT_INVALID_OP -> Verify(16) not supported, 231 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 232 | * SG_LIB_CAT_MEDIUM_HARD -> medium or hardware error, no valid info, 233 | * SG_LIB_CAT_MEDIUM_HARD_WITH_INFO -> as previous, with valid info, 234 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 235 | * -1 -> other failure */ 236 | extern int sg_ll_verify16(int sg_fd, int vrprotect, int dpo, int bytechk, 237 | uint64_t llba, int veri_len, int group_num, 238 | void * data_out, int data_out_len, 239 | uint64_t * infop, int noisy, int verbose); 240 | 241 | /* Invokes a SCSI WRITE BUFFER command (SPC). Return of 0 -> 242 | * success, SG_LIB_CAT_INVALID_OP -> invalid opcode, 243 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 244 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 245 | * -1 -> other failure */ 246 | extern int sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, 247 | int buffer_offset, void * paramp, 248 | int param_len, int noisy, int verbose); 249 | /* Need a sg_ll_write_buffer_v2() function because SPC-4 rev32 has added 250 | * a "mode specific" field. Wait for next rev change of this library */ 251 | 252 | /* Invokes a SCSI WRITE LONG (10) command (SBC). Note that 'xfer_len' 253 | * is in bytes. Returns 0 -> success, 254 | * SG_LIB_CAT_INVALID_OP -> WRITE LONG(10) not supported, 255 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 256 | * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info 257 | * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, 258 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 259 | * -1 -> other failure */ 260 | extern int sg_ll_write_long10(int sg_fd, int cor_dis, int wr_uncor, int pblock, 261 | unsigned int lba, void * data_out, 262 | int xfer_len, int * offsetp, int noisy, 263 | int verbose); 264 | 265 | /* Invokes a SCSI WRITE LONG (16) command (SBC). Note that 'xfer_len' 266 | * is in bytes. Returns 0 -> success, 267 | * SG_LIB_CAT_INVALID_OP -> WRITE LONG(16) not supported, 268 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, 269 | * SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO -> bad field in cdb, with info 270 | * field written to 'offsetp', SG_LIB_CAT_UNIT_ATTENTION, 271 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 272 | * -1 -> other failure */ 273 | extern int sg_ll_write_long16(int sg_fd, int cor_dis, int wr_uncor, int pblock, 274 | uint64_t llba, void * data_out, int xfer_len, 275 | int * offsetp, int noisy, int verbose); 276 | 277 | /* Invokes a SCSI RECEIVE COPY RESULTS command. Return of 0 -> success, 278 | * SG_LIB_CAT_INVALID_OP -> Receive copy results not supported, 279 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 280 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 281 | * -1 -> other failure */ 282 | extern int sg_ll_receive_copy_results(int sg_fd, int sa, int list_id, 283 | void * resp, int mx_resp_len, 284 | int noisy, int verbose); 285 | 286 | /* Invokes a SCSI EXTENDEd COPY command. Return of 0 -> success, 287 | * SG_LIB_CAT_INVALID_OP -> Extended copy not supported, 288 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 289 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 290 | * -1 -> other failure */ 291 | extern int sg_ll_extended_copy(int sg_fd, void * resp, int mx_resp_len, 292 | int noisy, int verbose); 293 | 294 | #ifdef __cplusplus 295 | } 296 | #endif 297 | 298 | #endif 299 | -------------------------------------------------------------------------------- /include/sg_cmds_mmc.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_CMDS_MMC_H 2 | #define SG_CMDS_MMC_H 3 | 4 | /* 5 | * Copyright (c) 2008-2010 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 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | /* Invokes a SCSI GET CONFIGURATION command (MMC-3...6). 17 | * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not 18 | * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, 19 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ 20 | extern int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp, 21 | int mx_resp_len, int noisy, int verbose); 22 | 23 | /* Invokes a SCSI GET PERFORMANCE command (MMC-3...6). 24 | * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not 25 | * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported, 26 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */ 27 | extern int sg_ll_get_performance(int sg_fd, int data_type, 28 | unsigned int starting_lba, int max_num_desc, 29 | int type, void * resp, int mx_resp_len, 30 | int noisy, int verbose); 31 | 32 | /* Invokes a SCSI SET CD SPEED command (MMC). 33 | * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported, 34 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION, 35 | * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND, 36 | * -1 -> other failure */ 37 | extern int sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed, 38 | int drv_write_speed, int noisy, int verbose); 39 | 40 | /* Invokes a SCSI SET STREAMING command (MMC). Return of 0 -> success, 41 | * SG_LIB_CAT_INVALID_OP -> Set Streaming not supported, 42 | * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND, 43 | * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_NOT_READY -> device not ready, 44 | * -1 -> other failure */ 45 | extern int sg_ll_set_streaming(int sg_fd, int type, void * paramp, 46 | int param_len, int noisy, int verbose); 47 | 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/sg_io_linux.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_IO_LINUX_H 2 | #define SG_IO_LINUX_H 3 | 4 | /* 5 | * Copyright (c) 2004-2012 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 | * Version 1.03 [20120914] 13 | */ 14 | 15 | /* 16 | * This header file contains linux specific information related to the SCSI 17 | * command pass through in the SCSI generic (sg) driver and the linux 18 | * block layer. 19 | */ 20 | 21 | #include "sg_lib.h" 22 | #include "sg_linux_inc.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* The following are 'host_status' codes */ 29 | #ifndef DID_OK 30 | #define DID_OK 0x00 31 | #endif 32 | #ifndef DID_NO_CONNECT 33 | #define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ 34 | #define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ 35 | #define DID_TIME_OUT 0x03 /* Timed out for some other reason */ 36 | #define DID_BAD_TARGET 0x04 /* Bad target (id?) */ 37 | #define DID_ABORT 0x05 /* Told to abort for some other reason */ 38 | #define DID_PARITY 0x06 /* Parity error (on SCSI bus) */ 39 | #define DID_ERROR 0x07 /* Internal error */ 40 | #define DID_RESET 0x08 /* Reset by somebody */ 41 | #define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */ 42 | #define DID_PASSTHROUGH 0x0a /* Force command past mid-level */ 43 | #define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */ 44 | #endif 45 | #ifndef DID_IMM_RETRY 46 | #define DID_IMM_RETRY 0x0c /* Retry without decrementing retry count */ 47 | #endif 48 | #ifndef DID_REQUEUE 49 | #define DID_REQUEUE 0x0d /* Requeue command (no immediate retry) also 50 | * without decrementing the retry count */ 51 | #endif 52 | #ifndef DID_TRANSPORT_DISRUPTED 53 | #define DID_TRANSPORT_DISRUPTED 0xe 54 | #endif 55 | #ifndef DID_TRANSPORT_FAILFAST 56 | #define DID_TRANSPORT_FAILFAST 0xf 57 | #endif 58 | #ifndef DID_TARGET_FAILURE 59 | #define DID_TARGET_FAILURE 0x10 60 | #endif 61 | #ifndef DID_NEXUS_FAILURE 62 | #define DID_NEXUS_FAILURE 0x11 63 | #endif 64 | 65 | /* These defines are to isolate applications from kernel define changes */ 66 | #define SG_LIB_DID_OK DID_OK 67 | #define SG_LIB_DID_NO_CONNECT DID_NO_CONNECT 68 | #define SG_LIB_DID_BUS_BUSY DID_BUS_BUSY 69 | #define SG_LIB_DID_TIME_OUT DID_TIME_OUT 70 | #define SG_LIB_DID_BAD_TARGET DID_BAD_TARGET 71 | #define SG_LIB_DID_ABORT DID_ABORT 72 | #define SG_LIB_DID_PARITY DID_PARITY 73 | #define SG_LIB_DID_ERROR DID_ERROR 74 | #define SG_LIB_DID_RESET DID_RESET 75 | #define SG_LIB_DID_BAD_INTR DID_BAD_INTR 76 | #define SG_LIB_DID_PASSTHROUGH DID_PASSTHROUGH 77 | #define SG_LIB_DID_SOFT_ERROR DID_SOFT_ERROR 78 | #define SG_LIB_DID_IMM_RETRY DID_IMM_RETRY 79 | #define SG_LIB_DID_REQUEUE DID_REQUEUE 80 | #define SG_LIB_TRANSPORT_DISRUPTED DID_TRANSPORT_DISRUPTED 81 | #define SG_LIB_DID_TRANSPORT_FAILFAST DID_TRANSPORT_FAILFAST 82 | #define SG_LIB_DID_TARGET_FAILURE DID_TARGET_FAILURE 83 | #define SG_LIB_DID_NEXUS_FAILURE DID_NEXUS_FAILURE 84 | 85 | /* The following are 'driver_status' codes */ 86 | #ifndef DRIVER_OK 87 | #define DRIVER_OK 0x00 88 | #endif 89 | #ifndef DRIVER_BUSY 90 | #define DRIVER_BUSY 0x01 91 | #define DRIVER_SOFT 0x02 92 | #define DRIVER_MEDIA 0x03 93 | #define DRIVER_ERROR 0x04 94 | #define DRIVER_INVALID 0x05 95 | #define DRIVER_TIMEOUT 0x06 96 | #define DRIVER_HARD 0x07 97 | #define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ 98 | 99 | /* Following "suggests" are "or-ed" with one of previous 8 entries */ 100 | #define SUGGEST_RETRY 0x10 101 | #define SUGGEST_ABORT 0x20 102 | #define SUGGEST_REMAP 0x30 103 | #define SUGGEST_DIE 0x40 104 | #define SUGGEST_SENSE 0x80 105 | #define SUGGEST_IS_OK 0xff 106 | #endif 107 | #ifndef DRIVER_MASK 108 | #define DRIVER_MASK 0x0f 109 | #endif 110 | #ifndef SUGGEST_MASK 111 | #define SUGGEST_MASK 0xf0 112 | #endif 113 | 114 | /* These defines are to isolate applications from kernel define changes */ 115 | #define SG_LIB_DRIVER_OK DRIVER_OK 116 | #define SG_LIB_DRIVER_BUSY DRIVER_BUSY 117 | #define SG_LIB_DRIVER_SOFT DRIVER_SOFT 118 | #define SG_LIB_DRIVER_MEDIA DRIVER_MEDIA 119 | #define SG_LIB_DRIVER_ERROR DRIVER_ERROR 120 | #define SG_LIB_DRIVER_INVALID DRIVER_INVALID 121 | #define SG_LIB_DRIVER_TIMEOUT DRIVER_TIMEOUT 122 | #define SG_LIB_DRIVER_HARD DRIVER_HARD 123 | #define SG_LIB_DRIVER_SENSE DRIVER_SENSE 124 | #define SG_LIB_SUGGEST_RETRY SUGGEST_RETRY 125 | #define SG_LIB_SUGGEST_ABORT SUGGEST_ABORT 126 | #define SG_LIB_SUGGEST_REMAP SUGGEST_REMAP 127 | #define SG_LIB_SUGGEST_DIE SUGGEST_DIE 128 | #define SG_LIB_SUGGEST_SENSE SUGGEST_SENSE 129 | #define SG_LIB_SUGGEST_IS_OK SUGGEST_IS_OK 130 | #define SG_LIB_DRIVER_MASK DRIVER_MASK 131 | #define SG_LIB_SUGGEST_MASK SUGGEST_MASK 132 | 133 | extern void sg_print_masked_status(int masked_status); 134 | extern void sg_print_host_status(int host_status); 135 | extern void sg_print_driver_status(int driver_status); 136 | 137 | /* sg_chk_n_print() returns 1 quietly if there are no errors/warnings 138 | else it prints errors/warnings (prefixed by 'leadin') to 139 | 'sg_warnings_fd' and returns 0. raw_sinfo indicates whether the 140 | raw sense buffer (in ASCII hex) should be printed. */ 141 | extern int sg_chk_n_print(const char * leadin, int masked_status, 142 | int host_status, int driver_status, 143 | const unsigned char * sense_buffer, int sb_len, 144 | int raw_sinfo); 145 | 146 | /* The following function declaration is for the sg version 3 driver. */ 147 | struct sg_io_hdr; 148 | /* sg_chk_n_print3() returns 1 quietly if there are no errors/warnings; 149 | else it prints errors/warnings (prefixed by 'leadin') to 150 | 'sg_warnings_fd' and returns 0. */ 151 | extern int sg_chk_n_print3(const char * leadin, struct sg_io_hdr * hp, 152 | int raw_sinfo); 153 | 154 | /* Calls sg_scsi_normalize_sense() after obtaining the sense buffer and 155 | its length from the struct sg_io_hdr pointer. If these cannot be 156 | obtained, 0 is returned. */ 157 | extern int sg_normalize_sense(const struct sg_io_hdr * hp, 158 | struct sg_scsi_sense_hdr * sshp); 159 | 160 | extern int sg_err_category(int masked_status, int host_status, 161 | int driver_status, const unsigned char * sense_buffer, 162 | int sb_len); 163 | 164 | extern int sg_err_category_new(int scsi_status, int host_status, 165 | int driver_status, const unsigned char * sense_buffer, 166 | int sb_len); 167 | 168 | /* The following function declaration is for the sg version 3 driver. */ 169 | extern int sg_err_category3(struct sg_io_hdr * hp); 170 | 171 | 172 | /* Note about SCSI status codes found in older versions of Linux. 173 | Linux has traditionally used a 1 bit right shifted and masked 174 | version of SCSI standard status codes. Now CHECK_CONDITION 175 | and friends (in ) are deprecated. */ 176 | 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /include/sg_lib.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_LIB_H 2 | #define SG_LIB_H 3 | 4 | /* 5 | * Copyright (c) 2004-2012 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 | * 13 | * On 5th October 2004 a FreeBSD license was added to this file. 14 | * The intention is to keep this file and the related sg_lib.c file 15 | * as open source and encourage their unencumbered use. 16 | * 17 | * Current version number is in the sg_lib.c file and can be accessed 18 | * with the sg_lib_version() function. 19 | */ 20 | 21 | 22 | /* 23 | * This header file contains defines and function declarations that may 24 | * be useful to applications that communicate with devices that use a 25 | * SCSI command set. These command sets have names like SPC-4, SBC-3, 26 | * SSC-3, SES-2 and draft standards defining them can be found at 27 | * http://www.t10.org . Virtually all devices in the Linux SCSI subsystem 28 | * utilize SCSI command sets. Many devices in other Linux device subsystems 29 | * utilize SCSI command sets either natively or via emulation (e.g. a 30 | * parallel ATA disk in a USB enclosure). 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /* SCSI Peripheral Device Types (PDT) [5 bit field] */ 41 | #define PDT_DISK 0x0 /* direct access block device (disk) */ 42 | #define PDT_TAPE 0x1 /* sequential access device (magnetic tape) */ 43 | #define PDT_PRINTER 0x2 /* printer device (see SSC-1) */ 44 | #define PDT_PROCESSOR 0x3 /* processor device (e.g. SAFTE device) */ 45 | #define PDT_WO 0x4 /* write once device (some optical disks) */ 46 | #define PDT_MMC 0x5 /* CD/DVD/BD (multi-media) */ 47 | #define PDT_SCANNER 0x6 /* obsolete */ 48 | #define PDT_OPTICAL 0x7 /* optical memory device (some optical disks) */ 49 | #define PDT_MCHANGER 0x8 /* media changer device (e.g. tape robot) */ 50 | #define PDT_COMMS 0x9 /* communications device (obsolete) */ 51 | #define PDT_SAC 0xc /* storage array controller device */ 52 | #define PDT_SES 0xd /* SCSI Enclosure Services (SES) device */ 53 | #define PDT_RBC 0xe /* Reduced Block Commands (simplified PDT_DISK) */ 54 | #define PDT_OCRW 0xf /* optical card read/write device */ 55 | #define PDT_BCC 0x10 /* bridge controller commands */ 56 | #define PDT_OSD 0x11 /* Object Storage Device (OSD) */ 57 | #define PDT_ADC 0x12 /* Automation/drive commands (ADC) */ 58 | #define PDT_SMD 0x13 /* Security Manager Device (SMD) */ 59 | #define PDT_WLUN 0x1e /* Well known logical unit (WLUN) */ 60 | #define PDT_UNKNOWN 0x1f /* Unknown or no device type */ 61 | 62 | #ifndef SAM_STAT_GOOD 63 | /* The SCSI status codes as found in SAM-4 at www.t10.org */ 64 | #define SAM_STAT_GOOD 0x0 65 | #define SAM_STAT_CHECK_CONDITION 0x2 66 | #define SAM_STAT_CONDITION_MET 0x4 67 | #define SAM_STAT_BUSY 0x8 68 | #define SAM_STAT_INTERMEDIATE 0x10 /* obsolete in SAM-4 */ 69 | #define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 /* obsolete in SAM-4 */ 70 | #define SAM_STAT_RESERVATION_CONFLICT 0x18 71 | #define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */ 72 | #define SAM_STAT_TASK_SET_FULL 0x28 73 | #define SAM_STAT_ACA_ACTIVE 0x30 74 | #define SAM_STAT_TASK_ABORTED 0x40 75 | #endif 76 | 77 | /* The SCSI sense key codes as found in SPC-4 at www.t10.org */ 78 | #define SPC_SK_NO_SENSE 0x0 79 | #define SPC_SK_RECOVERED_ERROR 0x1 80 | #define SPC_SK_NOT_READY 0x2 81 | #define SPC_SK_MEDIUM_ERROR 0x3 82 | #define SPC_SK_HARDWARE_ERROR 0x4 83 | #define SPC_SK_ILLEGAL_REQUEST 0x5 84 | #define SPC_SK_UNIT_ATTENTION 0x6 85 | #define SPC_SK_DATA_PROTECT 0x7 86 | #define SPC_SK_BLANK_CHECK 0x8 87 | #define SPC_SK_COPY_ABORTED 0xa 88 | #define SPC_SK_ABORTED_COMMAND 0xb 89 | #define SPC_SK_VOLUME_OVERFLOW 0xd 90 | #define SPC_SK_MISCOMPARE 0xe 91 | #define SPC_SK_COMPLETED 0xf 92 | 93 | /* Transport protocol identifiers or just Protocol identifiers */ 94 | #define TPROTO_FCP 0 95 | #define TPROTO_SPI 1 96 | #define TPROTO_SSA 2 97 | #define TPROTO_1394 3 98 | #define TPROTO_SRP 4 99 | #define TPROTO_ISCSI 5 100 | #define TPROTO_SAS 6 101 | #define TPROTO_ADT 7 102 | #define TPROTO_ATA 8 103 | #define TPROTO_UAS 9 104 | #define TPROTO_SOP 0xa 105 | #define TPROTO_NONE 0xf 106 | 107 | 108 | /* The format of the version string is like this: "1.47 20090201" */ 109 | extern const char * sg_lib_version(); 110 | 111 | /* Returns length of SCSI command given the opcode (first byte). 112 | * Yields the wrong answer for variable length commands (opcode=0x7f) 113 | * and potentially some vendor specific commands. */ 114 | extern int sg_get_command_size(unsigned char cdb_byte0); 115 | 116 | /* Command name given pointer to the cdb. Certain command names 117 | * depend on peripheral type (give 0 if unknown). Places command 118 | * name into buff and will write no more than buff_len bytes. */ 119 | extern void sg_get_command_name(const unsigned char * cdbp, int peri_type, 120 | int buff_len, char * buff); 121 | 122 | /* Command name given only the first byte (byte 0) of a cdb and 123 | * peripheral type. */ 124 | extern void sg_get_opcode_name(unsigned char cdb_byte0, int peri_type, 125 | int buff_len, char * buff); 126 | 127 | /* Command name given opcode (byte 0), service action and peripheral type. 128 | * If no service action give 0, if unknown peripheral type give 0. */ 129 | extern void sg_get_opcode_sa_name(unsigned char cdb_byte0, int service_action, 130 | int peri_type, int buff_len, char * buff); 131 | 132 | /* Fetch scsi status string. */ 133 | extern void sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff); 134 | 135 | /* This is a slightly stretched SCSI sense "descriptor" format header. 136 | * The addition is to allow the 0x70 and 0x71 response codes. The idea 137 | * is to place the salient data of both "fixed" and "descriptor" sense 138 | * format into one structure to ease application processing. 139 | * The original sense buffer should be kept around for those cases 140 | * in which more information is required (e.g. the LBA of a MEDIUM ERROR). */ 141 | struct sg_scsi_sense_hdr { 142 | unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */ 143 | unsigned char sense_key; 144 | unsigned char asc; 145 | unsigned char ascq; 146 | unsigned char byte4; 147 | unsigned char byte5; 148 | unsigned char byte6; 149 | unsigned char additional_length; 150 | }; 151 | 152 | /* Maps the salient data from a sense buffer which is in either fixed or 153 | * descriptor format into a structure mimicking a descriptor format 154 | * header (i.e. the first 8 bytes of sense descriptor format). 155 | * If zero response code returns 0. Otherwise returns 1 and if 'sshp' is 156 | * non-NULL then zero all fields and then set the appropriate fields in 157 | * that structure. sshp::additional_length is always 0 for response 158 | * codes 0x70 and 0x71 (fixed format). */ 159 | extern int sg_scsi_normalize_sense(const unsigned char * sensep, 160 | int sense_len, 161 | struct sg_scsi_sense_hdr * sshp); 162 | 163 | /* Attempt to find the first SCSI sense data descriptor that matches the 164 | * given 'desc_type'. If found return pointer to start of sense data 165 | * descriptor; otherwise (including fixed format sense data) returns NULL. */ 166 | extern const unsigned char * sg_scsi_sense_desc_find( 167 | const unsigned char * sensep, int sense_len, int desc_type); 168 | 169 | /* Yield string associated with sense_key value. Returns 'buff'. */ 170 | extern char * sg_get_sense_key_str(int sense_key, int buff_len, char * buff); 171 | 172 | /* Yield string associated with ASC/ASCQ values. Returns 'buff'. */ 173 | extern char * sg_get_asc_ascq_str(int asc, int ascq, int buff_len, 174 | char * buff); 175 | 176 | /* Returns 1 if valid bit set, 0 if valid bit clear. Irrespective the 177 | * information field is written out via 'info_outp' (except when it is 178 | * NULL). Handles both fixed and descriptor sense formats. */ 179 | extern int sg_get_sense_info_fld(const unsigned char * sensep, int sb_len, 180 | uint64_t * info_outp); 181 | 182 | /* Returns 1 if any of the 3 bits (i.e. FILEMARK, EOM or ILI) are set. 183 | * In descriptor format if the stream commands descriptor not found 184 | * then returns 0. Writes 1 or 0 corresponding to these bits to the 185 | * last three arguments if they are non-NULL. */ 186 | extern int sg_get_sense_filemark_eom_ili(const unsigned char * sensep, 187 | int sb_len, int * filemark_p, 188 | int * eom_p, int * ili_p); 189 | 190 | /* Returns 1 if SKSV is set and sense key is NO_SENSE or NOT_READY. Also 191 | * returns 1 if progress indication sense data descriptor found. Places 192 | * progress field from sense data where progress_outp points. If progress 193 | * field is not available returns 0. Handles both fixed and descriptor 194 | * sense formats. N.B. App should multiply by 100 and divide by 65536 195 | * to get percentage completion from given value. */ 196 | extern int sg_get_sense_progress_fld(const unsigned char * sensep, 197 | int sb_len, int * progress_outp); 198 | 199 | /* Closely related to sg_print_sense(). Puts decode sense data in 'buff'. 200 | * Usually multiline with multiple '\n' including one trailing. If 201 | * 'raw_sinfo' set appends sense buffer in hex. */ 202 | extern void sg_get_sense_str(const char * leadin, 203 | const unsigned char * sense_buffer, int sb_len, 204 | int raw_sinfo, int buff_len, char * buff); 205 | 206 | /* Yield string associated with peripheral device type (pdt). Returns 207 | * 'buff'. If 'pdt' out of range yields "bad pdt" string. */ 208 | extern char * sg_get_pdt_str(int pdt, int buff_len, char * buff); 209 | 210 | /* Yield string associated with transport protocol identifier (tpi). Returns 211 | * 'buff'. If 'tpi' out of range yields "bad tpi" string. */ 212 | extern char * sg_get_trans_proto_str(int tpi, int buff_len, char * buff); 213 | 214 | extern FILE * sg_warnings_strm; 215 | 216 | extern void sg_set_warnings_strm(FILE * warnings_strm); 217 | 218 | /* The following "print" functions send ACSII to 'sg_warnings_strm' file 219 | * descriptor (default value is stderr) */ 220 | extern void sg_print_command(const unsigned char * command); 221 | extern void sg_print_sense(const char * leadin, 222 | const unsigned char * sense_buffer, int sb_len, 223 | int raw_info); 224 | extern void sg_print_scsi_status(int scsi_status); 225 | 226 | /* Utilities can use these process status values for syntax errors and 227 | * file (device node) problems (e.g. not found or permissions). */ 228 | #define SG_LIB_SYNTAX_ERROR 1 229 | #define SG_LIB_FILE_ERROR 15 230 | 231 | /* The sg_err_category_sense() function returns one of the following. 232 | * These may be used as process status values (on exit). Notice that 233 | * some of the lower values correspond to SCSI sense key values. */ 234 | #define SG_LIB_CAT_CLEAN 0 /* No errors or other information */ 235 | /* Value 1 left unused for utilities to use SG_LIB_SYNTAX_ERROR */ 236 | #define SG_LIB_CAT_NOT_READY 2 /* interpreted from sense buffer */ 237 | /* [sk,asc,ascq: 0x2,*,*] */ 238 | #define SG_LIB_CAT_MEDIUM_HARD 3 /* medium or hardware error, blank check */ 239 | /* [sk,asc,ascq: 0x3/0x4/0x8,*,*] */ 240 | #define SG_LIB_CAT_ILLEGAL_REQ 5 /* Illegal request (other than invalid */ 241 | /* opcode): [sk,asc,ascq: 0x5,*,*] */ 242 | #define SG_LIB_CAT_UNIT_ATTENTION 6 /* interpreted from sense buffer */ 243 | /* [sk,asc,ascq: 0x6,*,*] */ 244 | /* was SG_LIB_CAT_MEDIA_CHANGED earlier [sk,asc,ascq: 0x6,0x28,*] */ 245 | #define SG_LIB_CAT_INVALID_OP 9 /* (Illegal request,) Invalid opcode: */ 246 | /* [sk,asc,ascq: 0x5,0x20,0x0] */ 247 | #define SG_LIB_CAT_ABORTED_COMMAND 11 /* interpreted from sense buffer */ 248 | /* [sk,asc,ascq: 0xb,*,*] */ 249 | #define SG_LIB_CAT_NO_SENSE 20 /* sense data with key of "no sense" */ 250 | /* [sk,asc,ascq: 0x0,*,*] */ 251 | #define SG_LIB_CAT_RECOVERED 21 /* Successful command after recovered err */ 252 | /* [sk,asc,ascq: 0x1,*,*] */ 253 | #define SG_LIB_CAT_MALFORMED 97 /* Response to SCSI command malformed */ 254 | #define SG_LIB_CAT_SENSE 98 /* Something else is in the sense buffer */ 255 | #define SG_LIB_CAT_OTHER 99 /* Some other error/warning has occurred */ 256 | /* (e.g. a transport or driver error) */ 257 | 258 | /* Returns a SG_LIB_CAT_* value. If cannot decode sense_buffer or a less 259 | * common sense key then return SG_LIB_CAT_SENSE .*/ 260 | extern int sg_err_category_sense(const unsigned char * sense_buffer, 261 | int sb_len); 262 | 263 | /* Here are some additional sense data categories that are not returned 264 | * by sg_err_category_sense() but are returned by some related functions. */ 265 | #define SG_LIB_CAT_ILLEGAL_REQ_WITH_INFO 17 /* Illegal request (other than */ 266 | /* invalid opcode) plus 'info' field: */ 267 | /* [sk,asc,ascq: 0x5,*,*] */ 268 | #define SG_LIB_CAT_MEDIUM_HARD_WITH_INFO 18 /* medium or hardware error */ 269 | /* sense key plus 'info' field: */ 270 | /* [sk,asc,ascq: 0x3/0x4,*,*] */ 271 | #define SG_LIB_CAT_TIMEOUT 33 272 | 273 | 274 | /* Iterates to next designation descriptor in the device identification 275 | * VPD page. The 'initial_desig_desc' should point to start of first 276 | * descriptor with 'page_len' being the number of valid bytes in that 277 | * and following descriptors. To start, 'off' should point to a negative 278 | * value, thereafter it should point to the value yielded by the previous 279 | * call. If 0 returned then 'initial_desig_desc + *off' should be a valid 280 | * descriptor; returns -1 if normal end condition and -2 for an abnormal 281 | * termination. Matches association, designator_type and/or code_set when 282 | * any of those values are greater than or equal to zero. */ 283 | extern int sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc, 284 | int page_len, int * off, int m_assoc, 285 | int m_desig_type, int m_code_set); 286 | 287 | 288 | /* <<< General purpose (i.e. not SCSI specific) utility functions >>> */ 289 | 290 | /* Always returns valid string even if errnum is wild (or library problem). 291 | * If errnum is negative, flip its sign. */ 292 | extern char * safe_strerror(int errnum); 293 | 294 | 295 | /* Print (to stdout) 'str' of bytes in hex, 16 bytes per line optionally 296 | * followed at the right hand side of the line with an ASCII interpretation. 297 | * Each line is prefixed with an address, starting at 0 for str[0]..str[15]. 298 | * All output numbers are in hex. 'no_ascii' allows for 3 output types: 299 | * > 0 each line has address then up to 16 ASCII-hex bytes 300 | * = 0 in addition, the bytes are listed in ASCII to the right 301 | * < 0 only the ASCII-hex bytes are listed (i.e. without address) 302 | */ 303 | extern void dStrHex(const char* str, int len, int no_ascii); 304 | 305 | /* Returns 1 when executed on big endian machine; else returns 0. 306 | * Useful for displaying ATA identify words (which need swapping on a 307 | * big endian machine). 308 | */ 309 | extern int sg_is_big_endian(); 310 | 311 | /* Extract character sequence from ATA words as in the model string 312 | * in a IDENTIFY DEVICE response. Returns number of characters 313 | * written to 'ochars' before 0 character is found or 'num' words 314 | * are processed. */ 315 | extern int sg_ata_get_chars(const unsigned short * word_arr, int start_word, 316 | int num_words, int is_big_endian, char * ochars); 317 | 318 | /* Print (to stdout) 16 bit 'words' in hex, 8 words per line optionally 319 | * followed at the right hand side of the line with an ASCII interpretation 320 | * (pairs of ASCII characters in big endian order (upper first)). 321 | * Each line is prefixed with an address, starting at 0. 322 | * All output numbers are in hex. 'no_ascii' allows for 3 output types: 323 | * > 0 each line has address then up to 8 ASCII-hex words 324 | * = 0 in addition, the words are listed in ASCII pairs to the right 325 | * = -1 only the ASCII-hex words are listed (i.e. without address) 326 | * = -2 only the ASCII-hex words, formatted for "hdparm --Istdin" 327 | * < -2 same as -1 328 | * If 'swapb' non-zero then bytes in each word swapped. Needs to be set 329 | * for ATA IDENTIFY DEVICE response on big-endian machines. 330 | */ 331 | extern void dWordHex(const unsigned short* words, int num, int no_ascii, 332 | int swapb); 333 | 334 | /* If the number in 'buf' can not be decoded or the multiplier is unknown 335 | * then -1 is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H') 336 | * suffix. Otherwise a decimal multiplier suffix may be given. Recognised 337 | * multipliers: c C *1; w W *2; b B *512; k K KiB *1,024; 338 | * KB *1,000; m M MiB *1,048,576; MB *1,000,000; g G GiB *1,073,741,824; 339 | * GB *1,000,000,000 and x which multiplies by . */ 340 | extern int sg_get_num(const char * buf); 341 | 342 | /* If the number in 'buf' can not be decoded then -1 is returned. Accepts a 343 | * hex prefix (0x or 0X) or a 'h' (or 'H') suffix; otherwise decimal is 344 | * assumed. Does not accept multipliers. Accept a comma (","), a whitespace 345 | * or newline as terminator. */ 346 | extern int sg_get_num_nomult(const char * buf); 347 | 348 | /* If the number in 'buf' can not be decoded or the multiplier is unknown 349 | * then -1LL is returned. Accepts a hex prefix (0x or 0X) or a 'h' (or 'H') 350 | * suffix. Otherwise a decimal multiplier suffix may be given. In addition 351 | * to supporting the multipliers of sg_get_num(), this function supports: 352 | * t T TiB *(2**40); TB *(10**12); p P PiB *(2**50); PB *(10**15) . */ 353 | extern int64_t sg_get_llnum(const char * buf); 354 | 355 | 356 | /* <<< Architectural support functions [is there a better place?] >>> */ 357 | 358 | /* Non Unix OSes distinguish between text and binary files. 359 | * Set text mode on fd. Does nothing in Unix. Returns negative number on 360 | * failure. */ 361 | extern int sg_set_text_mode(int fd); 362 | 363 | /* Set binary mode on fd. Does nothing in Unix. Returns negative number on 364 | * failure. */ 365 | extern int sg_set_binary_mode(int fd); 366 | 367 | #ifdef __cplusplus 368 | } 369 | #endif 370 | 371 | #endif 372 | -------------------------------------------------------------------------------- /include/sg_lib_data.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_LIB_DATA_H 2 | #define SG_LIB_DATA_H 3 | 4 | /* 5 | * Copyright (c) 2007-2012 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 | * This header file contains some structure declarations and array name 13 | * declarations which are defined in the sg_lib_data.c . 14 | * Typically this header does not need to be exposed to users of the 15 | * sg_lib interface declared in sg_libs.h . 16 | */ 17 | 18 | #include 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /* Commands with service actions that change the command name */ 25 | #define SG_MAINTENANCE_IN 0xa3 26 | #define SG_MAINTENANCE_OUT 0xa4 27 | #define SG_PERSISTENT_RESERVE_IN 0x5e 28 | #define SG_PERSISTENT_RESERVE_OUT 0x5f 29 | #define SG_EXTENDED_COPY 0x83 30 | #define SG_RECEIVE_COPY 0x84 31 | #define SG_SERVICE_ACTION_IN_12 0xab 32 | #define SG_SERVICE_ACTION_OUT_12 0xa9 33 | #define SG_SERVICE_ACTION_BIDI 0x9d 34 | #define SG_SERVICE_ACTION_IN_16 0x9e 35 | #define SG_SERVICE_ACTION_OUT_16 0x9f 36 | #define SG_READ_BUFFER 0x3c 37 | #define SG_WRITE_BUFFER 0x3b 38 | #define SG_VARIABLE_LENGTH_CMD 0x7f 39 | 40 | 41 | 42 | struct sg_lib_value_name_t { 43 | int value; 44 | int peri_dev_type; /* 0 -> SPC and/or PDT_DISK, >0 -> PDT */ 45 | const char * name; 46 | }; 47 | 48 | struct sg_lib_asc_ascq_t { 49 | unsigned char asc; /* additional sense code */ 50 | unsigned char ascq; /* additional sense code qualifier */ 51 | const char * text; 52 | }; 53 | 54 | struct sg_lib_asc_ascq_range_t { 55 | unsigned char asc; /* additional sense code (ASC) */ 56 | unsigned char ascq_min; /* ASCQ minimum in range */ 57 | unsigned char ascq_max; /* ASCQ maximum in range */ 58 | const char * text; 59 | }; 60 | 61 | 62 | extern const char * sg_lib_version_str; 63 | 64 | extern struct sg_lib_value_name_t sg_lib_normal_opcodes[]; 65 | extern struct sg_lib_value_name_t sg_lib_read_buff_arr[]; 66 | extern struct sg_lib_value_name_t sg_lib_write_buff_arr[]; 67 | extern struct sg_lib_value_name_t sg_lib_maint_in_arr[]; 68 | extern struct sg_lib_value_name_t sg_lib_maint_out_arr[]; 69 | extern struct sg_lib_value_name_t sg_lib_pr_in_arr[]; 70 | extern struct sg_lib_value_name_t sg_lib_pr_out_arr[]; 71 | extern struct sg_lib_value_name_t sg_lib_serv_in12_arr[]; 72 | extern struct sg_lib_value_name_t sg_lib_serv_out12_arr[]; 73 | extern struct sg_lib_value_name_t sg_lib_serv_in16_arr[]; 74 | extern struct sg_lib_value_name_t sg_lib_serv_out16_arr[]; 75 | extern struct sg_lib_value_name_t sg_lib_serv_bidi_arr[]; 76 | extern struct sg_lib_value_name_t sg_lib_xcopy_sa_arr[]; 77 | extern struct sg_lib_value_name_t sg_lib_rec_copy_sa_arr[]; 78 | extern struct sg_lib_value_name_t sg_lib_variable_length_arr[]; 79 | extern struct sg_lib_asc_ascq_range_t sg_lib_asc_ascq_range[]; 80 | extern struct sg_lib_asc_ascq_t sg_lib_asc_ascq[]; 81 | extern const char * sg_lib_sense_key_desc[]; 82 | extern const char * sg_lib_pdt_strs[]; 83 | extern const char * sg_lib_transport_proto_strs[]; 84 | 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /include/sg_linux_inc.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_LINUX_INC_H 2 | #define SG_LINUX_INC_H 3 | 4 | #ifdef SG_KERNEL_INCLUDES 5 | #define __user 6 | typedef unsigned char u8; 7 | #include "/usr/src/linux/include/scsi/sg.h" 8 | #include "/usr/src/linux/include/scsi/scsi.h" 9 | #else 10 | #ifdef SG_TRICK_GNU_INCLUDES 11 | #include 12 | #include 13 | #else 14 | #include 15 | #include 16 | #endif 17 | #endif 18 | 19 | #ifdef BLKGETSIZE64 20 | #ifndef u64 21 | #include /* C99 header for exact integer types */ 22 | typedef uint64_t u64; /* problems with BLKGETSIZE64 ioctl in lk 2.4 */ 23 | #endif 24 | #endif 25 | 26 | /* 27 | Getting the correct include files for the sg interface can be an ordeal. 28 | In a perfect world, one would just write: 29 | #include 30 | #include 31 | This would include the files found in the /usr/include/scsi directory. 32 | Those files are maintained with the GNU library which may or may not 33 | agree with the kernel and version of sg driver that is running. Any 34 | many cases this will not matter. However in some it might, for example 35 | glibc 2.1's include files match the sg driver found in the lk 2.2 36 | series. Hence if glibc 2.1 is used with lk 2.4 then the additional 37 | sg v3 interface will not be visible. 38 | If this is a problem then defining SG_KERNEL_INCLUDES will access the 39 | kernel supplied header files (assuming they are in the normal place). 40 | The GNU library maintainers and various kernel people don't like 41 | this approach (but it does work). 42 | The technique selected by defining SG_TRICK_GNU_INCLUDES worked (and 43 | was used) prior to glibc 2.2 . Prior to that version /usr/include/linux 44 | was a symbolic link to /usr/src/linux/include/linux . 45 | 46 | There are other approaches if this include "mixup" causes pain. These 47 | would involve include files being copied or symbolic links being 48 | introduced. 49 | 50 | Sorry about the inconvenience. Typically neither SG_KERNEL_INCLUDES 51 | nor SG_TRICK_GNU_INCLUDES is defined. 52 | 53 | dpg 20010415, 20030522 54 | */ 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/sg_pt.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_PT_H 2 | #define SG_PT_H 3 | 4 | /* 5 | * Copyright (c) 2005-2011 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 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /* This declaration hides the fact that each implementation has its own 18 | * structure "derived" (using a C++ term) from this one. It compiles 19 | * because 'struct sg_pt_base' is only referenced (by pointer: 'objp') 20 | * in this interface. An instance of this structure represents the 21 | * context of one SCSI command. */ 22 | struct sg_pt_base; 23 | 24 | 25 | /* The format of the version string is like this: "2.01 20090201". 26 | * The leading digit will be incremented if this interface changes 27 | * in a way that may impact backward compatibility. */ 28 | extern const char * scsi_pt_version(); 29 | 30 | 31 | /* Returns >= 0 if successful. If error in Unix returns negated errno. */ 32 | extern int scsi_pt_open_device(const char * device_name, int read_only, 33 | 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 | extern int scsi_pt_open_flags(const char * device_name, int flags, 39 | int verbose); 40 | 41 | /* Returns 0 if successful. If error in Unix returns negated errno. */ 42 | extern int scsi_pt_close_device(int device_fd); 43 | 44 | 45 | /* Creates an object that can be used to issue one or more SCSI commands 46 | * (or task management functions). Returns NULL if problem. 47 | * Once this object has been created it should be destroyed with 48 | * destruct_scsi_pt_obj() when it is no longer needed. */ 49 | extern struct sg_pt_base * construct_scsi_pt_obj(void); 50 | 51 | /* Clear state information held in *objp . This allows this object to be 52 | * used to issue more than one SCSI command. */ 53 | extern void clear_scsi_pt_obj(struct sg_pt_base * objp); 54 | 55 | /* Set the CDB (command descriptor block) */ 56 | extern void set_scsi_pt_cdb(struct sg_pt_base * objp, 57 | const unsigned char * cdb, int cdb_len); 58 | /* Set the sense buffer and the maximum length that it can handle */ 59 | extern void set_scsi_pt_sense(struct sg_pt_base * objp, unsigned char * sense, 60 | int max_sense_len); 61 | /* Set a pointer and length to be used for data transferred from device */ 62 | extern void set_scsi_pt_data_in(struct sg_pt_base * objp, /* from device */ 63 | unsigned char * dxferp, int dxfer_len); 64 | /* Set a pointer and length to be used for data transferred to device */ 65 | extern void set_scsi_pt_data_out(struct sg_pt_base * objp, /* to device */ 66 | const unsigned char * dxferp, int dxfer_len); 67 | /* The following "set_"s implementations may be dummies */ 68 | extern void set_scsi_pt_packet_id(struct sg_pt_base * objp, int pack_id); 69 | extern void set_scsi_pt_tag(struct sg_pt_base * objp, uint64_t tag); 70 | extern void set_scsi_pt_task_management(struct sg_pt_base * objp, 71 | int tmf_code); 72 | extern void set_scsi_pt_task_attr(struct sg_pt_base * objp, int attribute, 73 | int priority); 74 | 75 | /* Following is a guard which is defined when set_scsi_pt_flags() is 76 | * present. Older versions of this library may not have this function. */ 77 | #define SCSI_PT_FLAGS_FUNCTION 1 78 | /* If neither QUEUE_AT_HEAD nor QUEUE_AT_TAIL are given, or both 79 | * are given, use the pass-through default. */ 80 | #define SCSI_PT_FLAGS_QUEUE_AT_TAIL 0x10 81 | #define SCSI_PT_FLAGS_QUEUE_AT_HEAD 0x20 82 | /* Set (potentially OS dependant) flags for pass-through mechanism. 83 | * Apart from contradictions, flags can be OR-ed together. */ 84 | extern void set_scsi_pt_flags(struct sg_pt_base * objp, int flags); 85 | 86 | #define SCSI_PT_DO_START_OK 0 87 | #define SCSI_PT_DO_BAD_PARAMS 1 88 | #define SCSI_PT_DO_TIMEOUT 2 89 | /* If OS error prior to or during command submission then returns negated 90 | * error value (e.g. Unix '-errno'). This includes interrupted system calls 91 | * (e.g. by a signal) in which case -EINTR would be returned. Note that 92 | * system call errors also can be fetched with get_scsi_pt_os_err(). 93 | * Return 0 if okay (i.e. at the very least: command sent). Positive 94 | * return values are errors (see SCSI_PT_DO_* defines). */ 95 | extern int do_scsi_pt(struct sg_pt_base * objp, int fd, int timeout_secs, 96 | int verbose); 97 | 98 | #define SCSI_PT_RESULT_GOOD 0 99 | #define SCSI_PT_RESULT_STATUS 1 /* other than GOOD and CHECK CONDITION */ 100 | #define SCSI_PT_RESULT_SENSE 2 101 | #define SCSI_PT_RESULT_TRANSPORT_ERR 3 102 | #define SCSI_PT_RESULT_OS_ERR 4 103 | /* highest numbered applicable category returned */ 104 | extern int get_scsi_pt_result_category(const struct sg_pt_base * objp); 105 | 106 | /* If not available return 0 */ 107 | extern int get_scsi_pt_resid(const struct sg_pt_base * objp); 108 | /* Returns SCSI status value (from device that received the 109 | command). */ 110 | extern int get_scsi_pt_status_response(const struct sg_pt_base * objp); 111 | /* Actual sense length returned. If sense data is present but 112 | actual sense length is not known, return 'max_sense_len' */ 113 | extern int get_scsi_pt_sense_len(const struct sg_pt_base * objp); 114 | /* If not available return 0 */ 115 | extern int get_scsi_pt_os_err(const struct sg_pt_base * objp); 116 | extern char * get_scsi_pt_os_err_str(const struct sg_pt_base * objp, 117 | int max_b_len, char * b); 118 | /* If not available return 0 */ 119 | extern int get_scsi_pt_transport_err(const struct sg_pt_base * objp); 120 | extern char * get_scsi_pt_transport_err_str(const struct sg_pt_base * objp, 121 | int max_b_len, char * b); 122 | 123 | /* If not available return -1 */ 124 | extern int get_scsi_pt_duration_ms(const struct sg_pt_base * objp); 125 | 126 | 127 | /* Should be invoked once per objp after other processing is complete in 128 | * order to clean up resources. For ever successful construct_scsi_pt_obj() 129 | * call there should be one destruct_scsi_pt_obj(). */ 130 | extern void destruct_scsi_pt_obj(struct sg_pt_base * objp); 131 | 132 | #ifdef SG_LIB_WIN32 133 | #define SG_LIB_WIN32_DIRECT 1 134 | 135 | /* Request SPT direct interface when state_direct is 1, state_direct set 136 | * to 0 for the SPT indirect interface. Default setting selected by build 137 | * (i.e. library compile time) and is usually indirect. */ 138 | extern void scsi_pt_win32_direct(int state_direct); 139 | 140 | /* Returns current SPT interface state, 1 for direct, 0 for indirect */ 141 | extern int scsi_pt_win32_spt_state(void); 142 | 143 | #endif 144 | 145 | #ifdef __cplusplus 146 | } 147 | #endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /include/sg_pt_win32.h: -------------------------------------------------------------------------------- 1 | #ifndef SG_PT_WIN32_H 2 | #define SG_PT_WIN32_H 3 | /* 4 | * The information in this file was obtained from scsi-wnt.h by 5 | * Richard Stemmer, rs@epost.de . He in turn gives credit to 6 | * Jay A. Key (for scsipt.c). 7 | * The plscsi program (by Pat LaVarre ) has 8 | * also been used as a reference. 9 | * Much of the information in this header can also be obtained 10 | * from msdn.microsoft.com . 11 | */ 12 | 13 | #include 14 | 15 | #define SCSI_MAX_SENSE_LEN 64 16 | #define SCSI_MAX_CDB_LEN 16 17 | #define SCSI_MAX_INDIRECT_DATA 16384 18 | 19 | typedef struct { 20 | USHORT Length; 21 | UCHAR ScsiStatus; 22 | UCHAR PathId; 23 | UCHAR TargetId; 24 | UCHAR Lun; 25 | UCHAR CdbLength; 26 | UCHAR SenseInfoLength; 27 | UCHAR DataIn; 28 | ULONG DataTransferLength; 29 | ULONG TimeOutValue; 30 | ULONG_PTR DataBufferOffset; /* was ULONG; problem in 64 bit */ 31 | ULONG SenseInfoOffset; 32 | UCHAR Cdb[SCSI_MAX_CDB_LEN]; 33 | } SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; 34 | 35 | 36 | typedef struct { 37 | USHORT Length; 38 | UCHAR ScsiStatus; 39 | UCHAR PathId; 40 | UCHAR TargetId; 41 | UCHAR Lun; 42 | UCHAR CdbLength; 43 | UCHAR SenseInfoLength; 44 | UCHAR DataIn; 45 | ULONG DataTransferLength; 46 | ULONG TimeOutValue; 47 | PVOID DataBuffer; 48 | ULONG SenseInfoOffset; 49 | UCHAR Cdb[SCSI_MAX_CDB_LEN]; 50 | } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; 51 | 52 | 53 | typedef struct { 54 | SCSI_PASS_THROUGH spt; 55 | /* plscsi shows a follow on 16 bytes allowing 32 byte cdb */ 56 | ULONG Filler; 57 | UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; 58 | UCHAR ucDataBuf[SCSI_MAX_INDIRECT_DATA]; 59 | } SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; 60 | 61 | 62 | typedef struct { 63 | SCSI_PASS_THROUGH_DIRECT spt; 64 | ULONG Filler; 65 | UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; 66 | } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; 67 | 68 | 69 | 70 | typedef struct { 71 | UCHAR NumberOfLogicalUnits; 72 | UCHAR InitiatorBusId; 73 | ULONG InquiryDataOffset; 74 | } SCSI_BUS_DATA, *PSCSI_BUS_DATA; 75 | 76 | 77 | typedef struct { 78 | UCHAR NumberOfBusses; 79 | SCSI_BUS_DATA BusData[1]; 80 | } SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; 81 | 82 | 83 | typedef struct { 84 | UCHAR PathId; 85 | UCHAR TargetId; 86 | UCHAR Lun; 87 | BOOLEAN DeviceClaimed; 88 | ULONG InquiryDataLength; 89 | ULONG NextInquiryDataOffset; 90 | UCHAR InquiryData[1]; 91 | } SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; 92 | 93 | 94 | typedef struct { 95 | ULONG Length; 96 | UCHAR PortNumber; 97 | UCHAR PathId; 98 | UCHAR TargetId; 99 | UCHAR Lun; 100 | } SCSI_ADDRESS, *PSCSI_ADDRESS; 101 | 102 | 103 | /* 104 | * method codes 105 | */ 106 | #define METHOD_BUFFERED 0 107 | #define METHOD_IN_DIRECT 1 108 | #define METHOD_OUT_DIRECT 2 109 | #define METHOD_NEITHER 3 110 | 111 | /* 112 | * file access values 113 | */ 114 | #define FILE_ANY_ACCESS 0 115 | #define FILE_READ_ACCESS 0x0001 116 | #define FILE_WRITE_ACCESS 0x0002 117 | 118 | 119 | #define IOCTL_SCSI_BASE 0x00000004 120 | 121 | /* 122 | * constants for DataIn member of SCSI_PASS_THROUGH* structures 123 | */ 124 | #define SCSI_IOCTL_DATA_OUT 0 125 | #define SCSI_IOCTL_DATA_IN 1 126 | #define SCSI_IOCTL_DATA_UNSPECIFIED 2 127 | 128 | /* 129 | * Standard IOCTL define 130 | */ 131 | #define CTL_CODE(DevType, Function, Method, Access) \ 132 | (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) 133 | 134 | #define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 135 | #define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 136 | #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) 137 | #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) 138 | #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 139 | #define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /lib32/sg_io_linux.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib32/sg_io_linux.o -------------------------------------------------------------------------------- /lib32/sg_lib.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib32/sg_lib.o -------------------------------------------------------------------------------- /lib32/sg_lib_data.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib32/sg_lib_data.o -------------------------------------------------------------------------------- /lib64/sg_io_linux.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib64/sg_io_linux.o -------------------------------------------------------------------------------- /lib64/sg_lib.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib64/sg_lib.o -------------------------------------------------------------------------------- /lib64/sg_lib_data.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lib64/sg_lib_data.o -------------------------------------------------------------------------------- /lto-cm.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scangeo/lto-cm/3bd60db16639e843c269ce2e2b32d94b54477fcf/lto-cm.1.gz -------------------------------------------------------------------------------- /lto-cm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "sg_lib.h" 11 | #include "sg_io_linux.h" 12 | #include "lto-cm.h" 13 | 14 | struct globalArgs_t { 15 | int verbose; 16 | const char* device_name; 17 | int readopt; 18 | int writeopt; 19 | char* msg; 20 | } globalArgs; 21 | 22 | //---------------Usage-------------- 23 | static void usage() 24 | { 25 | fprintf(stderr, 26 | "LTO-3/LTO-4 Medium Access Memory tool for User Medium Text Label\n" 27 | "Usage: \n" 28 | "lto-cm -f device -r/w [\"message\"] [-v]\n" 29 | " where:\n" 30 | " -f device is a sg device \n" 31 | " -r/w read OR write\n" 32 | " if \'w\': \"message to write\" (160 bytes)\n" 33 | " -v increase verbosity \n" 34 | " -h/? display usage\n" 35 | ); 36 | } 37 | 38 | //------------------------------WRITE 0803 FUNCTION--------------------------------- 39 | int att_0803_write(int fd, char* data){ 40 | int ok; 41 | sg_io_hdr_t io_hdr; 42 | unsigned char WrAttCmdBlk [WRITE_ATT_CMD_LEN] = {0x8D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0}; 43 | unsigned char sense_buffer[32]; 44 | unsigned char Wr_Att[169] = {0,0,0,165,0x08,0x03,2,0,160}; 45 | 46 | // if(att_0805_write(fd)==-1){ if(globalArgs.verbose)printf("SG_WRITE_ATT_0803: Error on SG_WRITE_ATT_0805\n");return -1;} 47 | 48 | if(strlen (data) > 160 ){ printf("ERROR : String must not Exceed 160 Bytes\n"); return -1;} 49 | else{strcpy( (char*)&Wr_Att[9], data );} 50 | 51 | 52 | memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 53 | io_hdr.interface_id = 'S'; 54 | io_hdr.cmd_len = sizeof(WrAttCmdBlk); 55 | io_hdr.mx_sb_len = sizeof(sense_buffer); 56 | io_hdr.dxfer_direction = SG_DXFER_TO_DEV; 57 | io_hdr.dxfer_len = 169; 58 | io_hdr.dxferp = Wr_Att; 59 | io_hdr.cmdp = WrAttCmdBlk; 60 | io_hdr.sbp = sense_buffer; 61 | io_hdr.timeout = 20000; 62 | 63 | 64 | if (ioctl(fd, SG_IO, &io_hdr) < 0) { 65 | if(globalArgs.verbose)perror("SG_WRITE_ATT_0803: Inquiry SG_IO ioctl error"); 66 | close(fd); 67 | return -1; 68 | } 69 | 70 | ok = 0; 71 | switch (sg_err_category3(&io_hdr)) { 72 | case SG_LIB_CAT_CLEAN: 73 | ok = 1; 74 | break; 75 | case SG_LIB_CAT_RECOVERED: 76 | if(globalArgs.verbose)printf("Recovered error on SG_WRITE_ATT_0803, continuing\n"); 77 | ok = 1; 78 | break; 79 | default: /* won't bother decoding other categories */ 80 | if(globalArgs.verbose)sg_chk_n_print3("SG_WRITE_ATT_0803 command error", &io_hdr, 1); 81 | return -1; 82 | } 83 | 84 | if (ok) { /* output result if it is available */ 85 | if(globalArgs.verbose)printf("SG_WRITE_ATT_0803 duration=%u millisecs, resid=%d, msg_status=%d\n", 86 | io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status); 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | 93 | //-----------------------------READ 0803 FUNCTION--------------------------------- 94 | int att_0803_read(int fd, char* data){ 95 | int ok; 96 | unsigned char rAttCmdBlk[READ_ATT_CMD_LEN] = {0x8C, 0x00, 0, 0, 0, 0, 0, 0, 0x08, 0x03, 0, 0, 159,0, 0, 0}; 97 | unsigned char inBuff[READ_ATT_REPLY_LEN]; 98 | unsigned char sense_buffer[32]; 99 | sg_io_hdr_t io_hdr; 100 | 101 | 102 | memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 103 | io_hdr.interface_id = 'S'; 104 | io_hdr.cmd_len = sizeof(rAttCmdBlk); 105 | io_hdr.mx_sb_len = sizeof(sense_buffer); 106 | io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; 107 | io_hdr.dxfer_len = READ_ATT_REPLY_LEN; 108 | io_hdr.dxferp = inBuff; 109 | io_hdr.cmdp = rAttCmdBlk; 110 | io_hdr.sbp = sense_buffer; 111 | io_hdr.timeout = 20000; 112 | 113 | if (ioctl(fd, SG_IO, &io_hdr) < 0) { 114 | if(globalArgs.verbose)perror("SG_READ_ATT_0803: Inquiry SG_IO ioctl error"); 115 | close(fd); 116 | return -1; 117 | } 118 | 119 | ok = 0; 120 | switch (sg_err_category3(&io_hdr)) { 121 | case SG_LIB_CAT_CLEAN: 122 | ok = 1; 123 | break; 124 | case SG_LIB_CAT_RECOVERED: 125 | if(globalArgs.verbose)printf("Recovered error on SG_READ_ATT_0803, continuing\n"); 126 | ok = 1; 127 | break; 128 | default: /* won't bother decoding other categories */ 129 | printf("ERROR : Attribute 0803h doesn't exist yet, perform a write first\n"); 130 | if(globalArgs.verbose)sg_chk_n_print3("SG_READ_ATT_0803 command error", &io_hdr, 1); 131 | return -1; 132 | } 133 | 134 | if (ok) { /* output result if it is available */ 135 | 136 | if(globalArgs.verbose)printf("SG_READ_ATT_0803 duration=%u millisecs, resid=%d, msg_status=%d\n", 137 | io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status); 138 | 139 | strncpy( data, (char*)&inBuff[9],160 ); 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | 146 | //----------------------------- MAIN FUNCTION--------------------------------- 147 | int main(int argc, char * argv[]) 148 | { 149 | int sg_fd; 150 | int k,i,l; 151 | char * file_name = 0; 152 | char ebuff[EBUFF_SZ]; 153 | char messageout[160] ; 154 | int c=0; 155 | 156 | globalArgs.verbose=0; 157 | globalArgs.device_name=NULL; 158 | globalArgs.readopt=0; 159 | globalArgs.writeopt=0; 160 | globalArgs.msg=NULL; 161 | 162 | while (1) { 163 | 164 | c = getopt(argc, argv, "f:rw:h?v"); 165 | 166 | if (c == -1) 167 | break; 168 | 169 | switch (c) { 170 | case 'f': 171 | if ((globalArgs.device_name=(char*)optarg)==NULL) { 172 | fprintf(stderr, "ERROR : Specify a device\n"); 173 | usage(); 174 | return SG_LIB_SYNTAX_ERROR; 175 | } 176 | break; 177 | case 'r': 178 | globalArgs.readopt =1; 179 | break; 180 | 181 | case 'w': 182 | globalArgs.writeopt =1; 183 | if ((globalArgs.msg=(char*)optarg)==NULL) { 184 | fprintf(stderr, "ERROR : Specify a message\n"); 185 | usage(); 186 | return SG_LIB_SYNTAX_ERROR; 187 | } 188 | break; 189 | 190 | case 'h': 191 | case '?': 192 | usage(); 193 | return 0; 194 | /* case 'm': 195 | if ((globalArgs.msg=(char*)optarg)==NULL) { 196 | fprintf(stderr, "ERROR : Specify a message\n"); 197 | usage(); 198 | return SG_LIB_SYNTAX_ERROR; 199 | } 200 | break;*/ 201 | case 'v': 202 | ++globalArgs.verbose; 203 | break; 204 | default: 205 | fprintf(stderr, "ERROR : Unrecognised option code 0x%x ??\n", c); 206 | usage(); 207 | return SG_LIB_SYNTAX_ERROR; 208 | } 209 | 210 | } 211 | 212 | if (argc == 1) { 213 | usage(); 214 | return 1; 215 | } 216 | 217 | if (optind < argc) { 218 | for (; optind < argc; ++optind) 219 | fprintf(stderr, "ERROR : Unexpected extra argument: %s\n", 220 | argv[optind]); 221 | usage(); 222 | return SG_LIB_SYNTAX_ERROR; 223 | } 224 | 225 | if(!(globalArgs.device_name)){ 226 | usage(); 227 | return SG_LIB_SYNTAX_ERROR; 228 | } 229 | 230 | if((globalArgs.readopt)&&(globalArgs.writeopt)){ 231 | fprintf(stderr, "ERROR : Can't read AND write\n"); 232 | usage(); 233 | return SG_LIB_SYNTAX_ERROR; 234 | } 235 | 236 | if(!((globalArgs.readopt)||(globalArgs.writeopt))){ 237 | fprintf(stderr, "ERROR : Specify read OR Write operation\n"); 238 | usage(); 239 | return SG_LIB_SYNTAX_ERROR; 240 | } 241 | if((globalArgs.writeopt)&&(globalArgs.msg==NULL)){ 242 | fprintf(stderr, "ERROR : Message is missing\n"); 243 | usage(); 244 | return SG_LIB_SYNTAX_ERROR; 245 | } 246 | 247 | if((globalArgs.readopt)&&(globalArgs.msg!=NULL)){ 248 | fprintf(stderr, "ERROR : Unexpected extra argument\n"); 249 | usage(); 250 | return SG_LIB_SYNTAX_ERROR; 251 | } 252 | 253 | if ((sg_fd = open(globalArgs.device_name, O_RDWR)) < 0) { 254 | snprintf(ebuff, EBUFF_SZ, 255 | "ERROR : opening file: %s", file_name); 256 | perror(ebuff); 257 | return -1; 258 | } 259 | /* Just to be safe, check we have a new sg device by trying an ioctl */ 260 | if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { 261 | printf("ERROR : %s doesn't seem to be an new sg device\n", 262 | globalArgs.device_name); 263 | close(sg_fd); 264 | return -1; 265 | } 266 | 267 | 268 | if (globalArgs.readopt){ 269 | if(att_0803_read(sg_fd,messageout)==-1){ 270 | printf("ERROR : Read failed (try verbose opt)\n"); 271 | close(sg_fd);return -1;} 272 | l=strlen (messageout); 273 | for ( i = 0; i < l; ++i ){printf("%c", messageout[i]);} 274 | printf("\n"); 275 | } 276 | else if(globalArgs.writeopt){ 277 | if(att_0803_write(sg_fd,globalArgs.msg)==-1){ 278 | printf("ERROR : Write failed (try verbose opt)\n"); 279 | close(sg_fd);return -1;} 280 | } 281 | 282 | else { 283 | fprintf(stderr, "ERROR : Unavailable Attribute, retry tomorrow\n"); 284 | return SG_LIB_SYNTAX_ERROR; 285 | } 286 | 287 | close(sg_fd); 288 | return 0; 289 | } 290 | 291 | -------------------------------------------------------------------------------- /lto-cm.h: -------------------------------------------------------------------------------- 1 | #define USER_MEDIUM_TEXT_LABEL_SIZE 160 2 | #define TEXT_LOCALIZATION_IDENTIFIER_SIZE 1 3 | #define BARCODE_SIZE 32 4 | #define APPLICATON_FORMAT_VERSION_SIZE 32 5 | 6 | 7 | #define USER_MEDIUM_TEXT_LABEL 0x0803 8 | 9 | 10 | #define READ_ATT_REPLY_LEN 512 11 | #define WRITE_ATT_REPLY_LEN 512 12 | #define READ_ATT_CMD_LEN 16 13 | #define WRITE_ATT_CMD_LEN 16 14 | 15 | #define EBUFF_SZ 256 16 | 17 | static void usage(); 18 | 19 | int att_0803_write(int ,char* ); 20 | int att_0803_read(int ,char* ); 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------