1 1.6 mlelstv /* $NetBSD: iscsic_driverif.c,v 1.6 2012/06/25 20:39:54 mlelstv Exp $ */ 2 1.1 agc 3 1.1 agc /*- 4 1.1 agc * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. 5 1.1 agc * All rights reserved. 6 1.1 agc * 7 1.1 agc * This code is derived from software contributed to The NetBSD Foundation 8 1.1 agc * by Wasabi Systems, Inc. 9 1.1 agc * 10 1.1 agc * Redistribution and use in source and binary forms, with or without 11 1.1 agc * modification, are permitted provided that the following conditions 12 1.1 agc * are met: 13 1.1 agc * 1. Redistributions of source code must retain the above copyright 14 1.1 agc * notice, this list of conditions and the following disclaimer. 15 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 agc * notice, this list of conditions and the following disclaimer in the 17 1.1 agc * documentation and/or other materials provided with the distribution. 18 1.1 agc * 19 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 agc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 agc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 agc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 agc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 agc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 agc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 agc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 agc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 agc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 agc * POSSIBILITY OF SUCH DAMAGE. 30 1.1 agc */ 31 1.1 agc 32 1.1 agc #include "iscsic_globals.h" 33 1.1 agc 34 1.1 agc #include <ctype.h> 35 1.1 agc #include <inttypes.h> 36 1.1 agc 37 1.1 agc typedef struct { 38 1.1 agc uint8_t asc; 39 1.1 agc uint8_t ascq; 40 1.1 agc const char *key; 41 1.1 agc } asc_tab_t; 42 1.1 agc 43 1.1 agc asc_tab_t asctab[] = { 44 1.1 agc {0x00, 0x01, "FILEMARK DETECTED"}, 45 1.1 agc {0x00, 0x02, "END-OF-PARTITION/MEDIUM DETECTED"}, 46 1.1 agc {0x00, 0x03, "SETMARK DETECTED"}, 47 1.1 agc {0x00, 0x04, "BEGINNING-OF-PARTITION/MEDIUM DETECTED"}, 48 1.1 agc {0x00, 0x05, "END-OF-DATA DETECTED"}, 49 1.1 agc {0x00, 0x06, "I/O PROCESS TERMINATED"}, 50 1.1 agc {0x00, 0x11, "AUDIO PLAY OPERATION IN PROGRESS"}, 51 1.1 agc {0x00, 0x12, "AUDIO PLAY OPERATION PAUSED"}, 52 1.1 agc {0x00, 0x13, "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"}, 53 1.1 agc {0x00, 0x14, "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"}, 54 1.1 agc {0x00, 0x15, "NO CURRENT AUDIO STATUS TO RETURN"}, 55 1.1 agc {0x01, 0x00, "NO INDEX/SECTOR SIGNAL"}, 56 1.1 agc {0x02, 0x00, "NO SEEK COMPLETE"}, 57 1.1 agc {0x03, 0x00, "PERIPHERAL DEVICE WRITE FAULT"}, 58 1.1 agc {0x03, 0x01, "NO WRITE CURRENT"}, 59 1.1 agc {0x03, 0x02, "EXCESSIVE WRITE ERRORS"}, 60 1.1 agc {0x04, 0x00, "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"}, 61 1.1 agc {0x04, 0x01, "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"}, 62 1.1 agc {0x04, 0x02, "LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED"}, 63 1.1 agc {0x04, 0x03, "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"}, 64 1.1 agc {0x04, 0x04, "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"}, 65 1.1 agc {0x05, 0x00, "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"}, 66 1.1 agc {0x06, 0x00, "NO REFERENCE POSITION FOUND"}, 67 1.1 agc {0x07, 0x00, "MULTIPLE PERIPHERAL DEVICES SELECTED"}, 68 1.1 agc {0x08, 0x00, "LOGICAL UNIT COMMUNICATION FAILURE"}, 69 1.1 agc {0x08, 0x01, "LOGICAL UNIT COMMUNICATION TIME-OUT"}, 70 1.1 agc {0x08, 0x02, "LOGICAL UNIT COMMUNICATION PARITY ERROR"}, 71 1.1 agc {0x09, 0x00, "TRACK FOLLOWING ERROR"}, 72 1.1 agc {0x09, 0x01, "TRACKING SERVO FAILURE"}, 73 1.1 agc {0x09, 0x02, "FOCUS SERVO FAILURE"}, 74 1.1 agc {0x09, 0x03, "SPINDLE SERVO FAILURE"}, 75 1.1 agc {0x0A, 0x00, "ERROR LOG OVERFLOW"}, 76 1.1 agc {0x0C, 0x00, "WRITE ERROR"}, 77 1.1 agc {0x0C, 0x01, "WRITE ERROR RECOVERED WITH AUTO REALLOCATION"}, 78 1.1 agc {0x0C, 0x02, "WRITE ERROR - AUTO REALLOCATION FAILED"}, 79 1.1 agc {0x10, 0x00, "ID CRC OR ECC ERROR"}, 80 1.1 agc {0x11, 0x00, "UNRECOVERED READ ERROR"}, 81 1.1 agc {0x11, 0x01, "READ RETRIES EXHAUSTED"}, 82 1.1 agc {0x11, 0x02, "ERROR TOO LONG TO CORRECT"}, 83 1.1 agc {0x11, 0x03, "MULTIPLE READ ERRORS"}, 84 1.1 agc {0x11, 0x04, "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"}, 85 1.1 agc {0x11, 0x05, "L-EC UNCORRECTABLE ERROR"}, 86 1.1 agc {0x11, 0x06, "CIRC UNRECOVERED ERROR"}, 87 1.1 agc {0x11, 0x07, "DATA RESYNCHRONIZATION ERROR"}, 88 1.1 agc {0x11, 0x08, "INCOMPLETE BLOCK READ"}, 89 1.1 agc {0x11, 0x09, "NO GAP FOUND"}, 90 1.1 agc {0x11, 0x0A, "MISCORRECTED ERROR"}, 91 1.1 agc {0x11, 0x0B, "UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT"}, 92 1.1 agc {0x11, 0x0C, "UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA"}, 93 1.1 agc {0x12, 0x00, "ADDRESS MARK NOT FOUND FOR ID FIELD"}, 94 1.1 agc {0x13, 0x00, "ADDRESS MARK NOT FOUND FOR DATA FIELD"}, 95 1.1 agc {0x14, 0x00, "RECORDED ENTITY NOT FOUND"}, 96 1.1 agc {0x14, 0x01, "RECORD NOT FOUND"}, 97 1.1 agc {0x14, 0x02, "FILEMARK OR SETMARK NOT FOUND"}, 98 1.1 agc {0x14, 0x03, "END-OF-DATA NOT FOUND"}, 99 1.1 agc {0x14, 0x04, "BLOCK SEQUENCE ERROR"}, 100 1.1 agc {0x15, 0x00, "RANDOM POSITIONING ERROR"}, 101 1.1 agc {0x15, 0x01, "MECHANICAL POSITIONING ERROR"}, 102 1.1 agc {0x15, 0x02, "POSITIONING ERROR DETECTED BY READ OF MEDIUM"}, 103 1.1 agc {0x16, 0x00, "DATA SYNCHRONIZATION MARK ERROR"}, 104 1.1 agc {0x17, 0x00, "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"}, 105 1.1 agc {0x17, 0x01, "RECOVERED DATA WITH RETRIES"}, 106 1.1 agc {0x17, 0x02, "RECOVERED DATA WITH POSITIVE HEAD OFFSET"}, 107 1.1 agc {0x17, 0x03, "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"}, 108 1.1 agc {0x17, 0x04, "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"}, 109 1.1 agc {0x17, 0x05, "RECOVERED DATA USING PREVIOUS SECTOR ID"}, 110 1.1 agc {0x17, 0x06, "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"}, 111 1.1 agc {0x17, 0x07, "RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT"}, 112 1.1 agc {0x17, 0x08, "RECOVERED DATA WITHOUT ECC - RECOMMEND REWRITE"}, 113 1.1 agc {0x18, 0x00, "RECOVERED DATA WITH ERROR CORRECTION APPLIED"}, 114 1.1 agc {0x18, 0x01, "RECOVERED DATA WITH ERROR CORRECTION & RETRIES APPLIED"}, 115 1.1 agc {0x18, 0x02, "RECOVERED DATA - DATA AUTO-REALLOCATED"}, 116 1.1 agc {0x18, 0x03, "RECOVERED DATA WITH CIRC"}, 117 1.1 agc {0x18, 0x04, "RECOVERED DATA WITH L-EC"}, 118 1.1 agc {0x18, 0x05, "RECOVERED DATA - RECOMMEND REASSIGNMENT"}, 119 1.1 agc {0x18, 0x06, "RECOVERED DATA - RECOMMEND REWRITE"}, 120 1.1 agc {0x19, 0x00, "DEFECT LIST ERROR"}, 121 1.1 agc {0x19, 0x01, "DEFECT LIST NOT AVAILABLE"}, 122 1.1 agc {0x19, 0x02, "DEFECT LIST ERROR IN PRIMARY LIST"}, 123 1.1 agc {0x19, 0x03, "DEFECT LIST ERROR IN GROWN LIST"}, 124 1.1 agc {0x1A, 0x00, "PARAMETER LIST LENGTH ERROR"}, 125 1.1 agc {0x1B, 0x00, "SYNCHRONOUS DATA TRANSFER ERROR"}, 126 1.1 agc {0x1C, 0x00, "DEFECT LIST NOT FOUND"}, 127 1.1 agc {0x1C, 0x01, "PRIMARY DEFECT LIST NOT FOUND"}, 128 1.1 agc {0x1C, 0x02, "GROWN DEFECT LIST NOT FOUND"}, 129 1.1 agc {0x1D, 0x00, "MISCOMPARE DURING VERIFY OPERATION"}, 130 1.1 agc {0x1E, 0x00, "RECOVERED ID WITH ECC CORRECTION"}, 131 1.1 agc {0x20, 0x00, "INVALID COMMAND OPERATION CODE"}, 132 1.1 agc {0x21, 0x00, "LOGICAL BLOCK ADDRESS OUT OF RANGE"}, 133 1.1 agc {0x21, 0x01, "INVALID ELEMENT ADDRESS"}, 134 1.1 agc {0x22, 0x00, "ILLEGAL FUNCTION"}, 135 1.1 agc {0x24, 0x00, "INVALID FIELD IN CDB"}, 136 1.1 agc {0x25, 0x00, "LOGICAL UNIT NOT SUPPORTED"}, 137 1.1 agc {0x26, 0x00, "INVALID FIELD IN PARAMETER LIST"}, 138 1.1 agc {0x26, 0x01, "PARAMETER NOT SUPPORTED"}, 139 1.1 agc {0x26, 0x02, "PARAMETER VALUE INVALID"}, 140 1.1 agc {0x26, 0x03, "THRESHOLD PARAMETERS NOT SUPPORTED"}, 141 1.1 agc {0x27, 0x00, "WRITE PROTECTED"}, 142 1.1 agc {0x28, 0x00, "NOT READY TO READY TRANSITION, MEDIUM MAY HAVE CHANGED"}, 143 1.1 agc {0x28, 0x01, "IMPORT OR EXPORT ELEMENT ACCESSED"}, 144 1.1 agc {0x29, 0x00, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"}, 145 1.1 agc {0x2A, 0x00, "PARAMETERS CHANGED"}, 146 1.1 agc {0x2A, 0x01, "MODE PARAMETERS CHANGED"}, 147 1.1 agc {0x2A, 0x02, "LOG PARAMETERS CHANGED"}, 148 1.1 agc {0x2B, 0x00, "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"}, 149 1.1 agc {0x2C, 0x00, "COMMAND SEQUENCE ERROR"}, 150 1.1 agc {0x2C, 0x01, "TOO MANY WINDOWS SPECIFIED"}, 151 1.1 agc {0x2C, 0x02, "INVALID COMBINATION OF WINDOWS SPECIFIED"}, 152 1.1 agc {0x2D, 0x00, "OVERWRITE ERROR ON UPDATE IN PLACE"}, 153 1.1 agc {0x2F, 0x00, "COMMANDS CLEARED BY ANOTHER INITIATOR"}, 154 1.1 agc {0x30, 0x00, "INCOMPATIBLE MEDIUM INSTALLED"}, 155 1.1 agc {0x30, 0x01, "CANNOT READ MEDIUM - UNKNOWN FORMAT"}, 156 1.1 agc {0x30, 0x02, "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"}, 157 1.1 agc {0x30, 0x03, "CLEANING CARTRIDGE INSTALLED"}, 158 1.1 agc {0x31, 0x00, "MEDIUM FORMAT CORRUPTED"}, 159 1.1 agc {0x31, 0x01, "FORMAT COMMAND FAILED"}, 160 1.1 agc {0x32, 0x00, "NO DEFECT SPARE LOCATION AVAILABLE"}, 161 1.1 agc {0x32, 0x01, "DEFECT LIST UPDATE FAILURE"}, 162 1.1 agc {0x33, 0x00, "TAPE LENGTH ERROR"}, 163 1.1 agc {0x36, 0x00, "RIBBON, INK, OR TONER FAILURE"}, 164 1.1 agc {0x37, 0x00, "ROUNDED PARAMETER"}, 165 1.1 agc {0x39, 0x00, "SAVING PARAMETERS NOT SUPPORTED"}, 166 1.1 agc {0x3A, 0x00, "MEDIUM NOT PRESENT"}, 167 1.1 agc {0x3B, 0x00, "SEQUENTIAL POSITIONING ERROR"}, 168 1.1 agc {0x3B, 0x01, "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"}, 169 1.1 agc {0x3B, 0x02, "TAPE POSITION ERROR AT END-OF-MEDIUM"}, 170 1.1 agc {0x3B, 0x03, "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"}, 171 1.1 agc {0x3B, 0x04, "SLEW FAILURE"}, 172 1.1 agc {0x3B, 0x05, "PAPER JAM"}, 173 1.1 agc {0x3B, 0x06, "FAILED TO SENSE TOP-OF-FORM"}, 174 1.1 agc {0x3B, 0x07, "FAILED TO SENSE BOTTOM-OF-FORM"}, 175 1.1 agc {0x3B, 0x08, "REPOSITION ERROR"}, 176 1.1 agc {0x3B, 0x09, "READ PAST END OF MEDIUM"}, 177 1.1 agc {0x3B, 0x0A, "READ PAST BEGINNING OF MEDIUM"}, 178 1.1 agc {0x3B, 0x0B, "POSITION PAST END OF MEDIUM"}, 179 1.1 agc {0x3B, 0x0C, "POSITION PAST BEGINNING OF MEDIUM"}, 180 1.1 agc {0x3B, 0x0D, "MEDIUM DESTINATION ELEMENT FULL"}, 181 1.1 agc {0x3B, 0x0E, "MEDIUM SOURCE ELEMENT EMPTY"}, 182 1.1 agc {0x3D, 0x00, "INVALID BITS IN IDENTIFY MESSAGE"}, 183 1.1 agc {0x3E, 0x00, "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"}, 184 1.1 agc {0x3F, 0x00, "TARGET OPERATING CONDITIONS HAVE CHANGED"}, 185 1.1 agc {0x3F, 0x01, "MICROCODE HAS BEEN CHANGED"}, 186 1.1 agc {0x3F, 0x02, "LPWRSOMC CHANGED OPERATING DEFINITION"}, 187 1.1 agc {0x3F, 0x03, "INQUIRY DATA HAS CHANGED"}, 188 1.1 agc {0x40, 0x00, "RAM FAILURE (SHOULD USE 40 NN)"}, 189 1.1 agc {0x41, 0x00, "DATA PATH FAILURE (SHOULD USE 40 NN)"}, 190 1.1 agc {0x42, 0x00, "POWER-ON OR SELF-TEST FAILURE (SHOULD USE 40 NN)"}, 191 1.1 agc {0x43, 0x00, "MESSAGE ERROR"}, 192 1.1 agc {0x44, 0x00, "INTERNAL TARGET FAILURE"}, 193 1.1 agc {0x45, 0x00, "SELECT OR RESELECT FAILURE"}, 194 1.1 agc {0x46, 0x00, "UNSUCCESSFUL SOFT RESET"}, 195 1.1 agc {0x47, 0x00, "SCSI PARITY ERROR"}, 196 1.1 agc {0x48, 0x00, "INITIATOR DETECTED ERROR MESSAGE RECEIVED"}, 197 1.1 agc {0x49, 0x00, "INVALID MESSAGE ERROR"}, 198 1.1 agc {0x4A, 0x00, "COMMAND PHASE ERROR"}, 199 1.1 agc {0x4B, 0x00, "DATA PHASE ERROR"}, 200 1.1 agc {0x4C, 0x00, "LOGICAL UNIT FAILED SELF-CONFIGURATION"}, 201 1.1 agc {0x4E, 0x00, "OVERLAPPED COMMANDS ATTEMPTED"}, 202 1.1 agc {0x50, 0x00, "WRITE APPEND ERROR"}, 203 1.1 agc {0x50, 0x01, "WRITE APPEND POSITION ERROR"}, 204 1.1 agc {0x50, 0x02, "POSITION ERROR RELATED TO TIMING"}, 205 1.1 agc {0x51, 0x00, "ERASE FAILURE"}, 206 1.1 agc {0x52, 0x00, "CARTRIDGE FAULT"}, 207 1.1 agc {0x53, 0x00, "MEDIA LOAD OR EJECT FAILED"}, 208 1.1 agc {0x53, 0x01, "UNLOAD TAPE FAILURE"}, 209 1.1 agc {0x53, 0x02, "MEDIUM REMOVAL PREVENTED"}, 210 1.1 agc {0x54, 0x00, "SCSI TO HOST SYSTEM INTERFACE FAILURE"}, 211 1.1 agc {0x55, 0x00, "SYSTEM RESOURCE FAILURE"}, 212 1.1 agc {0x57, 0x00, "UNABLE TO RECOVER TABLE-OF-CONTENTS"}, 213 1.1 agc {0x58, 0x00, "GENERATION DOES NOT EXIST"}, 214 1.1 agc {0x59, 0x00, "UPDATED BLOCK READ"}, 215 1.1 agc {0x5A, 0x00, "OPERATOR REQUEST OR STATE CHANGE INPUT (UNSPECIFIED)"}, 216 1.1 agc {0x5A, 0x01, "OPERATOR MEDIUM REMOVAL REQUEST"}, 217 1.1 agc {0x5A, 0x02, "OPERATOR SELECTED WRITE PROTECT"}, 218 1.1 agc {0x5A, 0x03, "OPERATOR SELECTED WRITE PERMIT"}, 219 1.1 agc {0x5B, 0x00, "LOG EXCEPTION"}, 220 1.1 agc {0x5B, 0x01, "THRESHOLD CONDITION MET"}, 221 1.1 agc {0x5B, 0x02, "LOG COUNTER AT MAXIMUM"}, 222 1.1 agc {0x5B, 0x03, "LOG LIST CODES EXHAUSTED"}, 223 1.1 agc {0x5C, 0x00, "RPL STATUS CHANGE"}, 224 1.1 agc {0x5C, 0x01, "SPINDLES SYNCHRONIZED"}, 225 1.1 agc {0x5C, 0x02, "SPINDLES NOT SYNCHRONIZED"}, 226 1.1 agc {0x60, 0x00, "LAMP FAILURE"}, 227 1.1 agc {0x61, 0x00, "VIDEO ACQUISITION ERROR"}, 228 1.1 agc {0x61, 0x01, "UNABLE TO ACQUIRE VIDEO"}, 229 1.1 agc {0x61, 0x02, "OUT OF FOCUS"}, 230 1.1 agc {0x62, 0x00, "SCAN HEAD POSITIONING ERROR"}, 231 1.1 agc {0x63, 0x00, "END OF USER AREA ENCOUNTERED ON THIS TRACK"}, 232 1.1 agc {0x64, 0x00, "ILLEGAL MODE FOR THIS TRACK"}, 233 1.1 agc {0x00, 0x00, NULL} 234 1.1 agc }; 235 1.1 agc 236 1.1 agc /* 237 1.1 agc * get_sessid: 238 1.1 agc * Get session ID. Queries Daemon for numeric ID if the user specifies 239 1.1 agc * a symbolic session name. 240 1.1 agc * 241 1.1 agc * Parameter: argc, argv (shifted) 242 1.1 agc * 243 1.1 agc * Returns: session ID if OK - else it doesn't return at all. 244 1.1 agc */ 245 1.1 agc 246 1.1 agc uint32_t 247 1.1 agc get_sessid(int argc, char **argv, int optional) 248 1.1 agc { 249 1.1 agc iscsid_sym_id_t sid; 250 1.1 agc iscsid_search_list_req_t srch; 251 1.1 agc iscsid_response_t *rsp; 252 1.1 agc 253 1.1 agc if (!cl_get_id('I', &sid, argc, argv)) { 254 1.1 agc if (!optional) { 255 1.1 agc arg_missing("Session ID"); 256 1.1 agc } 257 1.1 agc return 0; 258 1.1 agc } 259 1.1 agc 260 1.1 agc if (!sid.id) { 261 1.1 agc srch.list_kind = SESSION_LIST; 262 1.1 agc srch.search_kind = FIND_NAME; 263 1.1 agc strlcpy((char *)srch.strval, (char *)sid.name, sizeof(srch.strval)); 264 1.1 agc srch.intval = 0; 265 1.1 agc 266 1.1 agc send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch); 267 1.1 agc rsp = get_response(FALSE); 268 1.1 agc if (rsp->status) 269 1.1 agc status_error_slist(rsp->status); 270 1.1 agc 271 1.1 agc GET_SYM_ID(sid.id, rsp->parameter); 272 1.1 agc free_response(rsp); 273 1.1 agc } 274 1.1 agc return sid.id; 275 1.1 agc } 276 1.1 agc 277 1.1 agc 278 1.1 agc /* 279 1.1 agc * dump_data: 280 1.1 agc * Displays the returned data in hex and ASCII format. 281 1.1 agc * 282 1.1 agc * Parameter: 283 1.1 agc * title Title text for Dump. 284 1.1 agc * buf Buffer to dump. 285 1.1 agc * len Number of bytes in buffer. 286 1.1 agc */ 287 1.1 agc 288 1.1 agc void 289 1.2 christos dump_data(const char *title, const void *buffer, size_t len) 290 1.1 agc { 291 1.2 christos const uint8_t *bp = buffer; 292 1.2 christos size_t i, nelem; 293 1.1 agc 294 1.1 agc printf("%s\n", title); 295 1.1 agc 296 1.1 agc while (len > 0) { 297 1.1 agc nelem = min(16, len); 298 1.1 agc printf(" "); 299 1.1 agc 300 1.1 agc for (i = 0; i < nelem; i++) { 301 1.4 martin if (i >= len) 302 1.4 martin printf(" "); 303 1.4 martin else 304 1.4 martin printf("%02x ", bp[i]); 305 1.1 agc } 306 1.1 agc for (i = nelem; i < 16; i++) { 307 1.1 agc printf(" "); 308 1.1 agc } 309 1.1 agc printf(" '"); 310 1.1 agc for (i = 0; i < nelem; i++) { 311 1.3 martin if (i >= len) 312 1.3 martin break; 313 1.1 agc printf("%c", isprint(bp[i]) ? bp[i] : ' '); 314 1.1 agc } 315 1.1 agc printf("'\n"); 316 1.3 martin if (len < 16) 317 1.3 martin break; 318 1.1 agc len -= 16; 319 1.1 agc bp += 16; 320 1.1 agc } 321 1.1 agc } 322 1.1 agc 323 1.1 agc 324 1.1 agc /* 325 1.1 agc * add_asc_info: 326 1.1 agc * Examines additional sense code and qualifier, adds text to given string 327 1.1 agc * if it's in the table. 328 1.1 agc * 329 1.1 agc * Parameter: 330 1.1 agc * str The existing sense code string 331 1.1 agc * asc Additional sense code 332 1.1 agc * ascq Additional sense code qualifier 333 1.1 agc * 334 1.1 agc * Returns: the result string. 335 1.1 agc */ 336 1.1 agc 337 1.1 agc STATIC char * 338 1.1 agc add_asc_info(char *str, uint8_t asc, uint8_t ascq) 339 1.1 agc { 340 1.1 agc asc_tab_t *pt; 341 1.1 agc char *bp; 342 1.1 agc 343 1.1 agc for (pt = asctab; pt->key != NULL && asc >= pt->asc; pt++) { 344 1.1 agc if (asc == pt->asc && ascq == pt->ascq) { 345 1.1 agc bp = (char *)&buf[1024]; 346 1.1 agc snprintf(bp, sizeof(buf) - 1024, "%s: %s", 347 1.1 agc str, pt->key); 348 1.1 agc return bp; 349 1.1 agc } 350 1.1 agc } 351 1.1 agc return str; 352 1.1 agc } 353 1.1 agc 354 1.1 agc 355 1.1 agc /* 356 1.1 agc * do_ioctl: 357 1.1 agc * Executes the I/O command, evaluates the return code, and displays 358 1.1 agc * sense data if the command failed. 359 1.1 agc * 360 1.1 agc * Parameter: 361 1.1 agc * io The i/o command parameters. 362 1.1 agc * 363 1.1 agc * Returns: 0 if OK, else an error code. 364 1.1 agc */ 365 1.1 agc 366 1.1 agc int 367 1.1 agc do_ioctl(iscsi_iocommand_parameters_t * io, int rd) 368 1.1 agc { 369 1.1 agc char *esp; 370 1.1 agc char es[64]; 371 1.1 agc int rc; 372 1.1 agc 373 1.1 agc io->req.databuf = buf; 374 1.1 agc io->req.senselen = sizeof(io->req.sense); 375 1.1 agc io->req.senselen_used = 0; 376 1.1 agc io->req.flags = (rd) ? SCCMD_READ : SCCMD_WRITE; 377 1.1 agc 378 1.1 agc rc = ioctl(driver, ISCSI_IO_COMMAND, io); 379 1.1 agc 380 1.1 agc if (io->req.senselen_used) { 381 1.1 agc switch (io->req.sense[2] & 0x0f) { 382 1.1 agc case 0x01: 383 1.1 agc snprintf(esp = es, sizeof(es), "Recovered Error"); 384 1.1 agc break; 385 1.1 agc case 0x02: 386 1.1 agc snprintf(esp = es, sizeof(es), "Not Ready"); 387 1.1 agc break; 388 1.1 agc case 0x03: 389 1.1 agc snprintf(esp = es, sizeof(es), "Medium Error"); 390 1.1 agc break; 391 1.1 agc case 0x04: 392 1.1 agc snprintf(esp = es, sizeof(es), "Hardware Error"); 393 1.1 agc break; 394 1.1 agc case 0x05: 395 1.1 agc snprintf(esp = es, sizeof(es), "Illegal Request"); 396 1.1 agc break; 397 1.1 agc case 0x06: 398 1.1 agc snprintf(esp = es, sizeof(es), "Unit Attention"); 399 1.1 agc break; 400 1.1 agc case 0x07: 401 1.1 agc snprintf(esp = es, sizeof(es), "Data Protect"); 402 1.1 agc break; 403 1.1 agc case 0x08: 404 1.1 agc snprintf(esp = es, sizeof(es), "Blank Check"); 405 1.1 agc break; 406 1.1 agc default: 407 1.1 agc snprintf(esp = (char *)&buf[256], sizeof(buf) - 256, "Sense key 0x%x", 408 1.1 agc io->req.sense[2] & 0x0f); 409 1.1 agc break; 410 1.1 agc } 411 1.1 agc if (io->req.senselen_used >= 14) { 412 1.1 agc add_asc_info(esp, io->req.sense[12], io->req.sense[13]); 413 1.1 agc } 414 1.1 agc snprintf((char *)buf, sizeof(buf), "Sense Data (%s):", esp); 415 1.1 agc dump_data((char *)buf, io->req.sense, io->req.senselen_used); 416 1.1 agc return io->req.retsts; 417 1.1 agc } 418 1.1 agc 419 1.1 agc if (io->status) { 420 1.1 agc status_error(io->status); 421 1.1 agc } 422 1.1 agc if (rc) { 423 1.1 agc io_error("I/O command"); 424 1.1 agc } 425 1.1 agc return 0; 426 1.1 agc } 427 1.1 agc 428 1.1 agc 429 1.1 agc /* 430 1.1 agc * inquiry: 431 1.1 agc * Handle the inquiry command. 432 1.1 agc * 433 1.1 agc * Parameter: argc, argv (shifted) 434 1.1 agc * 435 1.1 agc * Returns: 0 if OK - else it doesn't return at all. 436 1.1 agc */ 437 1.1 agc 438 1.1 agc int 439 1.1 agc inquiry(int argc, char **argv) 440 1.1 agc { 441 1.1 agc iscsi_iocommand_parameters_t io; 442 1.1 agc char opt; 443 1.1 agc int pag, rc; 444 1.1 agc 445 1.1 agc (void) memset(&io, 0x0, sizeof(io)); 446 1.1 agc if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 447 1.1 agc return 1; 448 1.1 agc } 449 1.1 agc io.lun = cl_get_longlong('l', argc, argv); 450 1.1 agc 451 1.1 agc opt = cl_get_char('d', argc, argv); 452 1.1 agc switch (opt) { 453 1.1 agc case 0: 454 1.1 agc case '0': 455 1.1 agc opt = 0; 456 1.1 agc break; 457 1.1 agc 458 1.1 agc case 'p': 459 1.1 agc case 'P': 460 1.1 agc io.req.cmd[1] = 0x01; 461 1.1 agc opt = 1; 462 1.1 agc break; 463 1.1 agc 464 1.1 agc case 'c': 465 1.1 agc case 'C': 466 1.1 agc io.req.cmd[1] = 0x02; 467 1.1 agc opt = 2; 468 1.1 agc break; 469 1.1 agc 470 1.1 agc default: 471 1.1 agc gen_error("Invalid detail option '%c'\n", opt); 472 1.1 agc } 473 1.1 agc 474 1.1 agc pag = cl_get_int('p', argc, argv); 475 1.1 agc 476 1.1 agc check_extra_args(argc, argv); 477 1.1 agc 478 1.1 agc io.req.cmdlen = 6; 479 1.1 agc io.req.cmd[0] = 0x12; 480 1.1 agc io.req.cmd[2] = (uint8_t) pag; 481 1.1 agc io.req.cmd[4] = 0xff; 482 1.1 agc 483 1.1 agc io.req.datalen = 0xff; 484 1.1 agc 485 1.1 agc if ((rc = do_ioctl(&io, TRUE)) != 0) { 486 1.1 agc return rc; 487 1.1 agc } 488 1.1 agc if (!io.req.datalen_used) { 489 1.1 agc printf("No Data!\n"); 490 1.1 agc return 1; 491 1.1 agc } 492 1.1 agc dump_data("Inquiry Data:", buf, io.req.datalen_used); 493 1.1 agc return 0; 494 1.1 agc } 495 1.1 agc 496 1.1 agc 497 1.1 agc /* 498 1.1 agc * read_capacity: 499 1.1 agc * Handle the read_capacity command. 500 1.1 agc * 501 1.1 agc * Parameter: argc, argv (shifted) 502 1.1 agc * 503 1.1 agc * Returns: 0 if OK - else it doesn't return at all. 504 1.1 agc */ 505 1.1 agc 506 1.1 agc int 507 1.1 agc read_capacity(int argc, char **argv) 508 1.1 agc { 509 1.1 agc iscsi_iocommand_parameters_t io; 510 1.1 agc int rc; 511 1.1 agc uint32_t bsz; 512 1.1 agc uint64_t lbn, cap; 513 1.1 agc uint32_t n; 514 1.1 agc 515 1.1 agc (void) memset(&io, 0x0, sizeof(io)); 516 1.1 agc if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 517 1.1 agc return 1; 518 1.1 agc } 519 1.1 agc io.lun = cl_get_longlong('l', argc, argv); 520 1.1 agc check_extra_args(argc, argv); 521 1.1 agc 522 1.1 agc io.req.cmdlen = 10; 523 1.1 agc io.req.cmd[0] = 0x25; 524 1.1 agc 525 1.1 agc io.req.datalen = 8; 526 1.1 agc 527 1.1 agc if ((rc = do_ioctl(&io, TRUE)) != 0) { 528 1.1 agc return rc; 529 1.1 agc } 530 1.1 agc (void) memcpy(&n, buf, sizeof(n)); 531 1.1 agc lbn = (uint64_t)(n + 1); 532 1.1 agc (void) memcpy(&n, &buf[4], sizeof(n)); 533 1.1 agc bsz = ntohl(n); 534 1.1 agc cap = lbn * bsz; 535 1.1 agc printf("Total Blocks: %" PRIu64 ", Block Size: %u, Capacity: %" PRIu64 " Bytes\n", 536 1.1 agc lbn, bsz, cap); 537 1.1 agc 538 1.1 agc return 0; 539 1.1 agc } 540 1.1 agc 541 1.1 agc 542 1.1 agc /* 543 1.1 agc * test_unit_ready: 544 1.1 agc * Handle the test_unit_ready command. 545 1.1 agc * 546 1.1 agc * Parameter: argc, argv (shifted) 547 1.1 agc * 548 1.1 agc * Returns: 0 if OK - else it doesn't return at all. 549 1.1 agc */ 550 1.1 agc 551 1.1 agc int 552 1.1 agc test_unit_ready(int argc, char **argv) 553 1.1 agc { 554 1.1 agc iscsi_iocommand_parameters_t io; 555 1.1 agc int rc; 556 1.1 agc 557 1.1 agc (void) memset(&io, 0x0, sizeof(io)); 558 1.1 agc if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 559 1.1 agc return 1; 560 1.1 agc } 561 1.1 agc io.lun = cl_get_longlong('l', argc, argv); 562 1.1 agc check_extra_args(argc, argv); 563 1.1 agc 564 1.1 agc io.req.cmdlen = 6; 565 1.1 agc io.req.cmd[0] = 0x00; 566 1.1 agc 567 1.1 agc io.req.datalen = 0; 568 1.1 agc 569 1.1 agc if ((rc = do_ioctl(&io, TRUE)) != 0) { 570 1.1 agc return rc; 571 1.1 agc } 572 1.1 agc printf("Unit is ready\n"); 573 1.1 agc return 0; 574 1.1 agc } 575 1.1 agc 576 1.1 agc 577 1.1 agc /* 578 1.1 agc * report_luns: 579 1.1 agc * Handle the report_luns command. 580 1.1 agc * 581 1.1 agc * Parameter: argc, argv (shifted) 582 1.1 agc * 583 1.1 agc * Returns: 0 if OK - else it doesn't return at all. 584 1.1 agc */ 585 1.1 agc 586 1.1 agc int 587 1.1 agc report_luns(int argc, char **argv) 588 1.1 agc { 589 1.1 agc iscsi_iocommand_parameters_t io; 590 1.1 agc int rc; 591 1.2 christos size_t llen; 592 1.1 agc uint32_t n; 593 1.1 agc uint64_t *lp; 594 1.1 agc 595 1.1 agc (void) memset(&io, 0x0, sizeof(io)); 596 1.1 agc if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 597 1.1 agc return 1; 598 1.1 agc } 599 1.1 agc check_extra_args(argc, argv); 600 1.1 agc 601 1.1 agc io.req.cmdlen = 12; 602 1.1 agc io.req.cmd[0] = 0xa0; 603 1.1 agc n = htonl(sizeof(buf)); 604 1.1 agc (void) memcpy(&io.req.cmd[6], &n, sizeof(n)); 605 1.1 agc 606 1.1 agc io.req.datalen = sizeof(buf); 607 1.1 agc 608 1.1 agc if ((rc = do_ioctl(&io, TRUE)) != 0) { 609 1.1 agc return rc; 610 1.1 agc } 611 1.5 mlelstv (void) memcpy(&n, buf, sizeof(n)); 612 1.6 mlelstv llen = ntohl(n); 613 1.1 agc if (!llen) { 614 1.1 agc printf("No LUNs!\n"); 615 1.1 agc return 1; 616 1.1 agc } 617 1.1 agc if (llen + 8 > sizeof(buf)) 618 1.1 agc printf("Partial "); 619 1.1 agc printf("LUN List:\n"); 620 1.2 christos lp = (uint64_t *)(void *) &buf[8]; 621 1.1 agc 622 1.1 agc for (llen = min(llen, sizeof(buf) - 8) / 8; llen; llen--) { 623 1.1 agc printf(" 0x%" PRIx64 "\n", ntohq(*lp)); 624 1.1 agc lp++; 625 1.1 agc } 626 1.1 agc return 0; 627 1.1 agc } 628