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