1 /* $NetBSD: iscsic_driverif.c,v 1.2 2011/10/30 18:40:06 christos 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 printf("%02x ", bp[i]); 302 } 303 for (i = nelem; i < 16; i++) { 304 printf(" "); 305 } 306 printf(" '"); 307 for (i = 0; i < nelem; i++) { 308 printf("%c", isprint(bp[i]) ? bp[i] : ' '); 309 } 310 printf("'\n"); 311 len -= 16; 312 bp += 16; 313 } 314 } 315 316 317 /* 318 * add_asc_info: 319 * Examines additional sense code and qualifier, adds text to given string 320 * if it's in the table. 321 * 322 * Parameter: 323 * str The existing sense code string 324 * asc Additional sense code 325 * ascq Additional sense code qualifier 326 * 327 * Returns: the result string. 328 */ 329 330 STATIC char * 331 add_asc_info(char *str, uint8_t asc, uint8_t ascq) 332 { 333 asc_tab_t *pt; 334 char *bp; 335 336 for (pt = asctab; pt->key != NULL && asc >= pt->asc; pt++) { 337 if (asc == pt->asc && ascq == pt->ascq) { 338 bp = (char *)&buf[1024]; 339 snprintf(bp, sizeof(buf) - 1024, "%s: %s", 340 str, pt->key); 341 return bp; 342 } 343 } 344 return str; 345 } 346 347 348 /* 349 * do_ioctl: 350 * Executes the I/O command, evaluates the return code, and displays 351 * sense data if the command failed. 352 * 353 * Parameter: 354 * io The i/o command parameters. 355 * 356 * Returns: 0 if OK, else an error code. 357 */ 358 359 int 360 do_ioctl(iscsi_iocommand_parameters_t * io, int rd) 361 { 362 char *esp; 363 char es[64]; 364 int rc; 365 366 io->req.databuf = buf; 367 io->req.senselen = sizeof(io->req.sense); 368 io->req.senselen_used = 0; 369 io->req.flags = (rd) ? SCCMD_READ : SCCMD_WRITE; 370 371 rc = ioctl(driver, ISCSI_IO_COMMAND, io); 372 373 if (io->req.senselen_used) { 374 switch (io->req.sense[2] & 0x0f) { 375 case 0x01: 376 snprintf(esp = es, sizeof(es), "Recovered Error"); 377 break; 378 case 0x02: 379 snprintf(esp = es, sizeof(es), "Not Ready"); 380 break; 381 case 0x03: 382 snprintf(esp = es, sizeof(es), "Medium Error"); 383 break; 384 case 0x04: 385 snprintf(esp = es, sizeof(es), "Hardware Error"); 386 break; 387 case 0x05: 388 snprintf(esp = es, sizeof(es), "Illegal Request"); 389 break; 390 case 0x06: 391 snprintf(esp = es, sizeof(es), "Unit Attention"); 392 break; 393 case 0x07: 394 snprintf(esp = es, sizeof(es), "Data Protect"); 395 break; 396 case 0x08: 397 snprintf(esp = es, sizeof(es), "Blank Check"); 398 break; 399 default: 400 snprintf(esp = (char *)&buf[256], sizeof(buf) - 256, "Sense key 0x%x", 401 io->req.sense[2] & 0x0f); 402 break; 403 } 404 if (io->req.senselen_used >= 14) { 405 add_asc_info(esp, io->req.sense[12], io->req.sense[13]); 406 } 407 snprintf((char *)buf, sizeof(buf), "Sense Data (%s):", esp); 408 dump_data((char *)buf, io->req.sense, io->req.senselen_used); 409 return io->req.retsts; 410 } 411 412 if (io->status) { 413 status_error(io->status); 414 } 415 if (rc) { 416 io_error("I/O command"); 417 } 418 return 0; 419 } 420 421 422 /* 423 * inquiry: 424 * Handle the inquiry command. 425 * 426 * Parameter: argc, argv (shifted) 427 * 428 * Returns: 0 if OK - else it doesn't return at all. 429 */ 430 431 int 432 inquiry(int argc, char **argv) 433 { 434 iscsi_iocommand_parameters_t io; 435 char opt; 436 int pag, rc; 437 438 (void) memset(&io, 0x0, sizeof(io)); 439 if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 440 return 1; 441 } 442 io.lun = cl_get_longlong('l', argc, argv); 443 444 opt = cl_get_char('d', argc, argv); 445 switch (opt) { 446 case 0: 447 case '0': 448 opt = 0; 449 break; 450 451 case 'p': 452 case 'P': 453 io.req.cmd[1] = 0x01; 454 opt = 1; 455 break; 456 457 case 'c': 458 case 'C': 459 io.req.cmd[1] = 0x02; 460 opt = 2; 461 break; 462 463 default: 464 gen_error("Invalid detail option '%c'\n", opt); 465 } 466 467 pag = cl_get_int('p', argc, argv); 468 469 check_extra_args(argc, argv); 470 471 io.req.cmdlen = 6; 472 io.req.cmd[0] = 0x12; 473 io.req.cmd[2] = (uint8_t) pag; 474 io.req.cmd[4] = 0xff; 475 476 io.req.datalen = 0xff; 477 478 if ((rc = do_ioctl(&io, TRUE)) != 0) { 479 return rc; 480 } 481 if (!io.req.datalen_used) { 482 printf("No Data!\n"); 483 return 1; 484 } 485 dump_data("Inquiry Data:", buf, io.req.datalen_used); 486 return 0; 487 } 488 489 490 /* 491 * read_capacity: 492 * Handle the read_capacity command. 493 * 494 * Parameter: argc, argv (shifted) 495 * 496 * Returns: 0 if OK - else it doesn't return at all. 497 */ 498 499 int 500 read_capacity(int argc, char **argv) 501 { 502 iscsi_iocommand_parameters_t io; 503 int rc; 504 uint32_t bsz; 505 uint64_t lbn, cap; 506 uint32_t n; 507 508 (void) memset(&io, 0x0, sizeof(io)); 509 if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 510 return 1; 511 } 512 io.lun = cl_get_longlong('l', argc, argv); 513 check_extra_args(argc, argv); 514 515 io.req.cmdlen = 10; 516 io.req.cmd[0] = 0x25; 517 518 io.req.datalen = 8; 519 520 if ((rc = do_ioctl(&io, TRUE)) != 0) { 521 return rc; 522 } 523 (void) memcpy(&n, buf, sizeof(n)); 524 lbn = (uint64_t)(n + 1); 525 (void) memcpy(&n, &buf[4], sizeof(n)); 526 bsz = ntohl(n); 527 cap = lbn * bsz; 528 printf("Total Blocks: %" PRIu64 ", Block Size: %u, Capacity: %" PRIu64 " Bytes\n", 529 lbn, bsz, cap); 530 531 return 0; 532 } 533 534 535 /* 536 * test_unit_ready: 537 * Handle the test_unit_ready command. 538 * 539 * Parameter: argc, argv (shifted) 540 * 541 * Returns: 0 if OK - else it doesn't return at all. 542 */ 543 544 int 545 test_unit_ready(int argc, char **argv) 546 { 547 iscsi_iocommand_parameters_t io; 548 int rc; 549 550 (void) memset(&io, 0x0, sizeof(io)); 551 if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 552 return 1; 553 } 554 io.lun = cl_get_longlong('l', argc, argv); 555 check_extra_args(argc, argv); 556 557 io.req.cmdlen = 6; 558 io.req.cmd[0] = 0x00; 559 560 io.req.datalen = 0; 561 562 if ((rc = do_ioctl(&io, TRUE)) != 0) { 563 return rc; 564 } 565 printf("Unit is ready\n"); 566 return 0; 567 } 568 569 570 /* 571 * report_luns: 572 * Handle the report_luns command. 573 * 574 * Parameter: argc, argv (shifted) 575 * 576 * Returns: 0 if OK - else it doesn't return at all. 577 */ 578 579 int 580 report_luns(int argc, char **argv) 581 { 582 iscsi_iocommand_parameters_t io; 583 int rc; 584 size_t llen; 585 uint32_t n; 586 uint16_t n2; 587 uint64_t *lp; 588 589 (void) memset(&io, 0x0, sizeof(io)); 590 if ((io.session_id = get_sessid(argc, argv, FALSE)) == 0) { 591 return 1; 592 } 593 check_extra_args(argc, argv); 594 595 io.req.cmdlen = 12; 596 io.req.cmd[0] = 0xa0; 597 n = htonl(sizeof(buf)); 598 (void) memcpy(&io.req.cmd[6], &n, sizeof(n)); 599 600 io.req.datalen = sizeof(buf); 601 602 if ((rc = do_ioctl(&io, TRUE)) != 0) { 603 return rc; 604 } 605 (void) memcpy(&n2, buf, sizeof(n2)); 606 llen = ntohs(n2); 607 if (!llen) { 608 printf("No LUNs!\n"); 609 return 1; 610 } 611 if (llen + 8 > sizeof(buf)) 612 printf("Partial "); 613 printf("LUN List:\n"); 614 lp = (uint64_t *)(void *) &buf[8]; 615 616 for (llen = min(llen, sizeof(buf) - 8) / 8; llen; llen--) { 617 printf(" 0x%" PRIx64 "\n", ntohq(*lp)); 618 lp++; 619 } 620 return 0; 621 } 622