1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/scsi/scsi.h> 30 31 /* 32 * Utility SCSI routines 33 */ 34 35 /* 36 * Polling support routines 37 */ 38 39 extern uintptr_t scsi_callback_id; 40 41 /* 42 * Common buffer for scsi_log 43 */ 44 45 extern kmutex_t scsi_log_mutex; 46 static char scsi_log_buffer[MAXPATHLEN + 1]; 47 48 49 #define A_TO_TRAN(ap) (ap->a_hba_tran) 50 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran) 51 #define P_TO_ADDR(pkt) (&((pkt)->pkt_address)) 52 53 #define CSEC 10000 /* usecs */ 54 #define SEC_TO_CSEC (1000000/CSEC) 55 56 57 /*PRINTFLIKE4*/ 58 static void impl_scsi_log(dev_info_t *dev, char *label, uint_t level, 59 const char *fmt, ...) __KPRINTFLIKE(4); 60 /*PRINTFLIKE4*/ 61 static void v_scsi_log(dev_info_t *dev, char *label, uint_t level, 62 const char *fmt, va_list ap) __KVPRINTFLIKE(4); 63 64 int 65 scsi_poll(struct scsi_pkt *pkt) 66 { 67 register int busy_count, rval = -1, savef; 68 long savet; 69 void (*savec)(); 70 extern int do_polled_io; 71 72 /* 73 * save old flags.. 74 */ 75 savef = pkt->pkt_flags; 76 savec = pkt->pkt_comp; 77 savet = pkt->pkt_time; 78 79 pkt->pkt_flags |= FLAG_NOINTR; 80 81 /* 82 * XXX there is nothing in the SCSA spec that states that we should not 83 * do a callback for polled cmds; however, removing this will break sd 84 * and probably other target drivers 85 */ 86 pkt->pkt_comp = 0; 87 88 /* 89 * we don't like a polled command without timeout. 90 * 60 seconds seems long enough. 91 */ 92 if (pkt->pkt_time == 0) 93 pkt->pkt_time = SCSI_POLL_TIMEOUT; 94 95 /* 96 * Send polled cmd. 97 * 98 * We do some error recovery for various errors. Tran_busy, 99 * queue full, and non-dispatched commands are retried every 10 msec. 100 * as they are typically transient failures. Busy status is retried 101 * every second as this status takes a while to change. 102 */ 103 for (busy_count = 0; busy_count < (pkt->pkt_time * SEC_TO_CSEC); 104 busy_count++) { 105 int rc; 106 int poll_delay; 107 108 /* 109 * Initialize pkt status variables. 110 */ 111 *pkt->pkt_scbp = pkt->pkt_reason = pkt->pkt_state = 0; 112 113 if ((rc = scsi_transport(pkt)) != TRAN_ACCEPT) { 114 if (rc != TRAN_BUSY) { 115 /* Transport failed - give up. */ 116 break; 117 } else { 118 /* Transport busy - try again. */ 119 poll_delay = 1 *CSEC; /* 10 msec. */ 120 } 121 } else { 122 /* 123 * Transport accepted - check pkt status. 124 */ 125 rc = (*pkt->pkt_scbp) & STATUS_MASK; 126 127 if (pkt->pkt_reason == CMD_CMPLT && 128 rc == STATUS_GOOD) { 129 /* No error - we're done */ 130 rval = 0; 131 break; 132 133 } else if (pkt->pkt_reason == CMD_INCOMPLETE && 134 pkt->pkt_state == 0) { 135 /* Pkt not dispatched - try again. */ 136 poll_delay = 1 *CSEC; /* 10 msec. */ 137 138 } else if (pkt->pkt_reason == CMD_CMPLT && 139 rc == STATUS_QFULL) { 140 /* Queue full - try again. */ 141 poll_delay = 1 *CSEC; /* 10 msec. */ 142 143 } else if (pkt->pkt_reason == CMD_CMPLT && 144 rc == STATUS_BUSY) { 145 /* Busy - try again. */ 146 poll_delay = 100 *CSEC; /* 1 sec. */ 147 busy_count += (SEC_TO_CSEC - 1); 148 149 } else { 150 /* BAD status - give up. */ 151 break; 152 } 153 } 154 155 if ((curthread->t_flag & T_INTR_THREAD) == 0 && 156 !do_polled_io) { 157 delay(drv_usectohz(poll_delay)); 158 } else { 159 /* we busy wait during cpr_dump or interrupt threads */ 160 drv_usecwait(poll_delay); 161 } 162 } 163 164 pkt->pkt_flags = savef; 165 pkt->pkt_comp = savec; 166 pkt->pkt_time = savet; 167 return (rval); 168 } 169 170 /* 171 * Command packaging routines. 172 * 173 * makecom_g*() are original routines and scsi_setup_cdb() 174 * is the new and preferred routine. 175 */ 176 177 /* 178 * These routines put LUN information in CDB byte 1 bits 7-5. 179 * This was required in SCSI-1. SCSI-2 allowed it but it preferred 180 * sending LUN information as part of IDENTIFY message. 181 * This is not allowed in SCSI-3. 182 */ 183 184 void 185 makecom_g0(struct scsi_pkt *pkt, struct scsi_device *devp, 186 int flag, int cmd, int addr, int cnt) 187 { 188 MAKECOM_G0(pkt, devp, flag, cmd, addr, (uchar_t)cnt); 189 } 190 191 void 192 makecom_g0_s(struct scsi_pkt *pkt, struct scsi_device *devp, 193 int flag, int cmd, int cnt, int fixbit) 194 { 195 MAKECOM_G0_S(pkt, devp, flag, cmd, cnt, (uchar_t)fixbit); 196 } 197 198 void 199 makecom_g1(struct scsi_pkt *pkt, struct scsi_device *devp, 200 int flag, int cmd, int addr, int cnt) 201 { 202 MAKECOM_G1(pkt, devp, flag, cmd, addr, cnt); 203 } 204 205 void 206 makecom_g5(struct scsi_pkt *pkt, struct scsi_device *devp, 207 int flag, int cmd, int addr, int cnt) 208 { 209 MAKECOM_G5(pkt, devp, flag, cmd, addr, cnt); 210 } 211 212 /* 213 * Following routine does not put LUN information in CDB. 214 * This interface must be used for SCSI-2 targets having 215 * more than 8 LUNs or a SCSI-3 target. 216 */ 217 int 218 scsi_setup_cdb(union scsi_cdb *cdbp, uchar_t cmd, uint_t addr, uint_t cnt, 219 uint_t addtl_cdb_data) 220 { 221 uint_t addr_cnt; 222 223 cdbp->scc_cmd = cmd; 224 225 switch (CDB_GROUPID(cmd)) { 226 case CDB_GROUPID_0: 227 /* 228 * The following calculation is to take care of 229 * the fact that format of some 6 bytes tape 230 * command is different (compare 6 bytes disk and 231 * tape read commands). 232 */ 233 addr_cnt = (addr << 8) + cnt; 234 addr = (addr_cnt & 0x1fffff00) >> 8; 235 cnt = addr_cnt & 0xff; 236 FORMG0ADDR(cdbp, addr); 237 FORMG0COUNT(cdbp, cnt); 238 break; 239 240 case CDB_GROUPID_1: 241 case CDB_GROUPID_2: 242 FORMG1ADDR(cdbp, addr); 243 FORMG1COUNT(cdbp, cnt); 244 break; 245 246 case CDB_GROUPID_4: 247 FORMG4ADDR(cdbp, addr); 248 FORMG4COUNT(cdbp, cnt); 249 FORMG4ADDTL(cdbp, addtl_cdb_data); 250 break; 251 252 case CDB_GROUPID_5: 253 FORMG5ADDR(cdbp, addr); 254 FORMG5COUNT(cdbp, cnt); 255 break; 256 257 default: 258 return (0); 259 } 260 261 return (1); 262 } 263 264 265 /* 266 * Common iopbmap data area packet allocation routines 267 */ 268 269 struct scsi_pkt * 270 get_pktiopb(struct scsi_address *ap, caddr_t *datap, int cdblen, int statuslen, 271 int datalen, int readflag, int (*func)()) 272 { 273 scsi_hba_tran_t *tran = A_TO_TRAN(ap); 274 dev_info_t *pdip = tran->tran_hba_dip; 275 struct scsi_pkt *pkt = NULL; 276 struct buf local; 277 278 if (!datap) 279 return (pkt); 280 *datap = (caddr_t)0; 281 bzero((caddr_t)&local, sizeof (struct buf)); 282 if (ddi_iopb_alloc(pdip, (ddi_dma_lim_t *)0, 283 (uint_t)datalen, &local.b_un.b_addr)) { 284 return (pkt); 285 } 286 if (readflag) 287 local.b_flags = B_READ; 288 local.b_bcount = datalen; 289 pkt = (*tran->tran_init_pkt) (ap, NULL, &local, 290 cdblen, statuslen, 0, PKT_CONSISTENT, 291 (func == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC, 292 NULL); 293 if (!pkt) { 294 ddi_iopb_free(local.b_un.b_addr); 295 if (func != NULL_FUNC) { 296 ddi_set_callback(func, NULL, &scsi_callback_id); 297 } 298 } else { 299 *datap = local.b_un.b_addr; 300 } 301 return (pkt); 302 } 303 304 /* 305 * Equivalent deallocation wrapper 306 */ 307 308 void 309 free_pktiopb(struct scsi_pkt *pkt, caddr_t datap, int datalen) 310 { 311 register struct scsi_address *ap = P_TO_ADDR(pkt); 312 register scsi_hba_tran_t *tran = A_TO_TRAN(ap); 313 314 (*tran->tran_destroy_pkt)(ap, pkt); 315 if (datap && datalen) { 316 ddi_iopb_free(datap); 317 } 318 if (scsi_callback_id != 0) { 319 ddi_run_callback(&scsi_callback_id); 320 } 321 } 322 323 /* 324 * Common naming functions 325 */ 326 327 static char scsi_tmpname[64]; 328 329 char * 330 scsi_dname(int dtyp) 331 { 332 static char *dnames[] = { 333 "Direct Access", 334 "Sequential Access", 335 "Printer", 336 "Processor", 337 "Write-Once/Read-Many", 338 "Read-Only Direct Access", 339 "Scanner", 340 "Optical", 341 "Changer", 342 "Communications", 343 "Array Controller" 344 }; 345 346 if ((dtyp & DTYPE_MASK) <= DTYPE_COMM) { 347 return (dnames[dtyp&DTYPE_MASK]); 348 } else if (dtyp == DTYPE_NOTPRESENT) { 349 return ("Not Present"); 350 } 351 return ("<unknown device type>"); 352 353 } 354 355 char * 356 scsi_rname(uchar_t reason) 357 { 358 static char *rnames[] = { 359 "cmplt", 360 "incomplete", 361 "dma_derr", 362 "tran_err", 363 "reset", 364 "aborted", 365 "timeout", 366 "data_ovr", 367 "cmd_ovr", 368 "sts_ovr", 369 "badmsg", 370 "nomsgout", 371 "xid_fail", 372 "ide_fail", 373 "abort_fail", 374 "reject_fail", 375 "nop_fail", 376 "per_fail", 377 "bdr_fail", 378 "id_fail", 379 "unexpected_bus_free", 380 "tag reject", 381 "terminated" 382 }; 383 if (reason > CMD_TAG_REJECT) { 384 return ("<unknown reason>"); 385 } else { 386 return (rnames[reason]); 387 } 388 } 389 390 char * 391 scsi_mname(uchar_t msg) 392 { 393 static char *imsgs[23] = { 394 "COMMAND COMPLETE", 395 "EXTENDED", 396 "SAVE DATA POINTER", 397 "RESTORE POINTERS", 398 "DISCONNECT", 399 "INITIATOR DETECTED ERROR", 400 "ABORT", 401 "REJECT", 402 "NO-OP", 403 "MESSAGE PARITY", 404 "LINKED COMMAND COMPLETE", 405 "LINKED COMMAND COMPLETE (W/FLAG)", 406 "BUS DEVICE RESET", 407 "ABORT TAG", 408 "CLEAR QUEUE", 409 "INITIATE RECOVERY", 410 "RELEASE RECOVERY", 411 "TERMINATE PROCESS", 412 "CONTINUE TASK", 413 "TARGET TRANSFER DISABLE", 414 "RESERVED (0x14)", 415 "RESERVED (0x15)", 416 "CLEAR ACA" 417 }; 418 static char *imsgs_2[6] = { 419 "SIMPLE QUEUE TAG", 420 "HEAD OF QUEUE TAG", 421 "ORDERED QUEUE TAG", 422 "IGNORE WIDE RESIDUE", 423 "ACA", 424 "LOGICAL UNIT RESET" 425 }; 426 427 if (msg < 23) { 428 return (imsgs[msg]); 429 } else if (IS_IDENTIFY_MSG(msg)) { 430 return ("IDENTIFY"); 431 } else if (IS_2BYTE_MSG(msg) && 432 (int)((msg) & 0xF) < (sizeof (imsgs_2) / sizeof (char *))) { 433 return (imsgs_2[msg & 0xF]); 434 } else { 435 return ("<unknown msg>"); 436 } 437 438 } 439 440 char * 441 scsi_cname(uchar_t cmd, register char **cmdvec) 442 { 443 while (*cmdvec != (char *)0) { 444 if (cmd == **cmdvec) { 445 return ((char *)((long)(*cmdvec)+1)); 446 } 447 cmdvec++; 448 } 449 return (sprintf(scsi_tmpname, "<undecoded cmd 0x%x>", cmd)); 450 } 451 452 char * 453 scsi_cmd_name(uchar_t cmd, struct scsi_key_strings *cmdlist, char *tmpstr) 454 { 455 int i = 0; 456 457 while (cmdlist[i].key != -1) { 458 if (cmd == cmdlist[i].key) { 459 return ((char *)cmdlist[i].message); 460 } 461 i++; 462 } 463 return (sprintf(tmpstr, "<undecoded cmd 0x%x>", cmd)); 464 } 465 466 static struct scsi_asq_key_strings extended_sense_list[] = { 467 0x00, 0x00, "no additional sense info", 468 0x00, 0x01, "filemark detected", 469 0x00, 0x02, "end of partition/medium detected", 470 0x00, 0x03, "setmark detected", 471 0x00, 0x04, "begining of partition/medium detected", 472 0x00, 0x05, "end of data detected", 473 0x00, 0x06, "i/o process terminated", 474 0x00, 0x11, "audio play operation in progress", 475 0x00, 0x12, "audio play operation paused", 476 0x00, 0x13, "audio play operation successfully completed", 477 0x00, 0x14, "audio play operation stopped due to error", 478 0x00, 0x15, "no current audio status to return", 479 0x00, 0x16, "operation in progress", 480 0x00, 0x17, "cleaning requested", 481 0x00, 0x18, "erase operation in progress", 482 0x00, 0x19, "locate operation in progress", 483 0x00, 0x1A, "rewind operation in progress", 484 0x00, 0x1B, "set capacity operation in progress", 485 0x00, 0x1C, "verify operation in progress", 486 0x01, 0x00, "no index/sector signal", 487 0x02, 0x00, "no seek complete", 488 0x03, 0x00, "peripheral device write fault", 489 0x03, 0x01, "no write current", 490 0x03, 0x02, "excessive write errors", 491 0x04, 0x00, "LUN not ready", 492 0x04, 0x01, "LUN is becoming ready", 493 0x04, 0x02, "LUN initializing command required", 494 0x04, 0x03, "LUN not ready intervention required", 495 0x04, 0x04, "LUN not ready format in progress", 496 0x04, 0x05, "LUN not ready, rebuild in progress", 497 0x04, 0x06, "LUN not ready, recalculation in progress", 498 0x04, 0x07, "LUN not ready, operation in progress", 499 0x04, 0x08, "LUN not ready, long write in progress", 500 0x04, 0x09, "LUN not ready, self-test in progress", 501 0x04, 0x0A, "LUN not accessible, asymmetric access state transition", 502 0x04, 0x0B, "LUN not accessible, target port in standby state", 503 0x04, 0x0C, "LUN not accessible, target port in unavailable state", 504 0x04, 0x10, "LUN not ready, auxiliary memory not accessible", 505 0x05, 0x00, "LUN does not respond to selection", 506 0x06, 0x00, "reference position found", 507 0x07, 0x00, "multiple peripheral devices selected", 508 0x08, 0x00, "LUN communication failure", 509 0x08, 0x01, "LUN communication time-out", 510 0x08, 0x02, "LUN communication parity error", 511 0x08, 0x03, "LUN communication crc error (ultra-DMA/32)", 512 0x08, 0x04, "unreachable copy target", 513 0x09, 0x00, "track following error", 514 0x09, 0x01, "tracking servo failure", 515 0x09, 0x02, "focus servo failure", 516 0x09, 0x03, "spindle servo failure", 517 0x09, 0x04, "head select fault", 518 0x0a, 0x00, "error log overflow", 519 0x0b, 0x00, "warning", 520 0x0b, 0x01, "warning - specified temperature exceeded", 521 0x0b, 0x02, "warning - enclosure degraded", 522 0x0c, 0x00, "write error", 523 0x0c, 0x01, "write error - recovered with auto reallocation", 524 0x0c, 0x02, "write error - auto reallocation failed", 525 0x0c, 0x03, "write error - recommend reassignment", 526 0x0c, 0x04, "compression check miscompare error", 527 0x0c, 0x05, "data expansion occurred during compression", 528 0x0c, 0x06, "block not compressible", 529 0x0c, 0x07, "write error - recovery needed", 530 0x0c, 0x08, "write error - recovery failed", 531 0x0c, 0x09, "write error - loss of streaming", 532 0x0c, 0x0a, "write error - padding blocks added", 533 0x0c, 0x0b, "auxiliary memory write error", 534 0x0c, 0x0c, "write error - unexpected unsolicited data", 535 0x0c, 0x0d, "write error - not enough unsolicited data", 536 0x0d, 0x00, "error detected by third party temporary initiator", 537 0x0d, 0x01, "third party device failure", 538 0x0d, 0x02, "copy target device not reachable", 539 0x0d, 0x03, "incorrect copy target device type", 540 0x0d, 0x04, "copy target device data underrun", 541 0x0d, 0x05, "copy target device data overrun", 542 0x0e, 0x00, "invalid information unit", 543 0x0e, 0x01, "information unit too short", 544 0x0e, 0x02, "information unit too long", 545 0x10, 0x00, "ID CRC or ECC error", 546 0x11, 0x00, "unrecovered read error", 547 0x11, 0x01, "read retries exhausted", 548 0x11, 0x02, "error too long to correct", 549 0x11, 0x03, "multiple read errors", 550 0x11, 0x04, "unrecovered read error - auto reallocate failed", 551 0x11, 0x05, "L-EC uncorrectable error", 552 0x11, 0x06, "CIRC unrecovered error", 553 0x11, 0x07, "data re-synchronization error", 554 0x11, 0x08, "incomplete block read", 555 0x11, 0x09, "no gap found", 556 0x11, 0x0a, "miscorrected error", 557 0x11, 0x0b, "unrecovered read error - recommend reassignment", 558 0x11, 0x0c, "unrecovered read error - recommend rewrite the data", 559 0x11, 0x0d, "de-compression crc error", 560 0x11, 0x0e, "cannot decompress using declared algorithm", 561 0x11, 0x0f, "error reading UPC/EAN number", 562 0x11, 0x10, "error reading ISRC number", 563 0x11, 0x11, "read error - loss of streaming", 564 0x11, 0x12, "auxiliary memory read error", 565 0x11, 0x13, "read error - failed retransmission request", 566 0x12, 0x00, "address mark not found for ID field", 567 0x13, 0x00, "address mark not found for data field", 568 0x14, 0x00, "recorded entity not found", 569 0x14, 0x01, "record not found", 570 0x14, 0x02, "filemark or setmark not found", 571 0x14, 0x03, "end-of-data not found", 572 0x14, 0x04, "block sequence error", 573 0x14, 0x05, "record not found - recommend reassignment", 574 0x14, 0x06, "record not found - data auto-reallocated", 575 0x14, 0x07, "locate operation failure", 576 0x15, 0x00, "random positioning error", 577 0x15, 0x01, "mechanical positioning error", 578 0x15, 0x02, "positioning error detected by read of medium", 579 0x16, 0x00, "data sync mark error", 580 0x16, 0x01, "data sync error - data rewritten", 581 0x16, 0x02, "data sync error - recommend rewrite", 582 0x16, 0x03, "data sync error - data auto-reallocated", 583 0x16, 0x04, "data sync error - recommend reassignment", 584 0x17, 0x00, "recovered data with no error correction", 585 0x17, 0x01, "recovered data with retries", 586 0x17, 0x02, "recovered data with positive head offset", 587 0x17, 0x03, "recovered data with negative head offset", 588 0x17, 0x04, "recovered data with retries and/or CIRC applied", 589 0x17, 0x05, "recovered data using previous sector id", 590 0x17, 0x06, "recovered data without ECC - data auto-reallocated", 591 0x17, 0x07, "recovered data without ECC - recommend reassignment", 592 0x17, 0x08, "recovered data without ECC - recommend rewrite", 593 0x17, 0x09, "recovered data without ECC - data rewritten", 594 0x18, 0x00, "recovered data with error correction", 595 0x18, 0x01, "recovered data with error corr. & retries applied", 596 0x18, 0x02, "recovered data - data auto-reallocated", 597 0x18, 0x03, "recovered data with CIRC", 598 0x18, 0x04, "recovered data with L-EC", 599 0x18, 0x05, "recovered data - recommend reassignment", 600 0x18, 0x06, "recovered data - recommend rewrite", 601 0x18, 0x07, "recovered data with ECC - data rewritten", 602 0x18, 0x08, "recovered data with linking", 603 0x19, 0x00, "defect list error", 604 0x1a, 0x00, "parameter list length error", 605 0x1b, 0x00, "synchronous data xfer error", 606 0x1c, 0x00, "defect list not found", 607 0x1c, 0x01, "primary defect list not found", 608 0x1c, 0x02, "grown defect list not found", 609 0x1d, 0x00, "miscompare during verify", 610 0x1e, 0x00, "recovered ID with ECC", 611 0x1f, 0x00, "partial defect list transfer", 612 0x20, 0x00, "invalid command operation code", 613 0x20, 0x01, "access denied - initiator pending-enrolled", 614 0x20, 0x02, "access denied - no access rights", 615 0x20, 0x03, "access denied - invalid mgmt id key", 616 0x20, 0x04, "illegal command while in write capable state", 617 0x20, 0x06, "illegal command while in explicit address mode", 618 0x20, 0x07, "illegal command while in implicit address mode", 619 0x20, 0x08, "access denied - enrollment conflict", 620 0x20, 0x09, "access denied - invalid lu identifier", 621 0x20, 0x0a, "access denied - invalid proxy token", 622 0x20, 0x0b, "access denied - ACL LUN conflict", 623 0x21, 0x00, "logical block address out of range", 624 0x21, 0x01, "invalid element address", 625 0x21, 0x02, "invalid address for write", 626 0x22, 0x00, "illegal function", 627 0x24, 0x00, "invalid field in cdb", 628 0x24, 0x01, "cdb decryption error", 629 0x25, 0x00, "LUN not supported", 630 0x26, 0x00, "invalid field in param list", 631 0x26, 0x01, "parameter not supported", 632 0x26, 0x02, "parameter value invalid", 633 0x26, 0x03, "threshold parameters not supported", 634 0x26, 0x04, "invalid release of persistent reservation", 635 0x26, 0x05, "data decryption error", 636 0x26, 0x06, "too many target descriptors", 637 0x26, 0x07, "unsupported target descriptor type code", 638 0x26, 0x08, "too many segment descriptors", 639 0x26, 0x09, "unsupported segment descriptor type code", 640 0x26, 0x0a, "unexpected inexact segment", 641 0x26, 0x0b, "inline data length exceeded", 642 0x26, 0x0c, "invalid operation for copy source or destination", 643 0x26, 0x0d, "copy segment granularity violation", 644 0x27, 0x00, "write protected", 645 0x27, 0x01, "hardware write protected", 646 0x27, 0x02, "LUN software write protected", 647 0x27, 0x03, "associated write protect", 648 0x27, 0x04, "persistent write protect", 649 0x27, 0x05, "permanent write protect", 650 0x27, 0x06, "conditional write protect", 651 0x28, 0x00, "medium may have changed", 652 0x28, 0x01, "import or export element accessed", 653 0x29, 0x00, "power on, reset, or bus reset occurred", 654 0x29, 0x01, "power on occurred", 655 0x29, 0x02, "scsi bus reset occurred", 656 0x29, 0x03, "bus device reset message occurred", 657 0x29, 0x04, "device internal reset", 658 0x29, 0x05, "transceiver mode changed to single-ended", 659 0x29, 0x06, "transceiver mode changed to LVD", 660 0x29, 0x07, "i_t nexus loss occurred", 661 0x2a, 0x00, "parameters changed", 662 0x2a, 0x01, "mode parameters changed", 663 0x2a, 0x02, "log parameters changed", 664 0x2a, 0x03, "reservations preempted", 665 0x2a, 0x04, "reservations released", 666 0x2a, 0x05, "registrations preempted", 667 0x2a, 0x06, "asymmetric access state changed", 668 0x2a, 0x07, "implicit asymmetric access state transition failed", 669 0x2b, 0x00, "copy cannot execute since host cannot disconnect", 670 0x2c, 0x00, "command sequence error", 671 0x2c, 0x03, "current program area is not empty", 672 0x2c, 0x04, "current program area is empty", 673 0x2c, 0x06, "persistent prevent conflict", 674 0x2c, 0x07, "previous busy status", 675 0x2c, 0x08, "previous task set full status", 676 0x2c, 0x09, "previous reservation conflict status", 677 0x2d, 0x00, "overwrite error on update in place", 678 0x2e, 0x00, "insufficient time for operation", 679 0x2f, 0x00, "commands cleared by another initiator", 680 0x30, 0x00, "incompatible medium installed", 681 0x30, 0x01, "cannot read medium - unknown format", 682 0x30, 0x02, "cannot read medium - incompatible format", 683 0x30, 0x03, "cleaning cartridge installed", 684 0x30, 0x04, "cannot write medium - unknown format", 685 0x30, 0x05, "cannot write medium - incompatible format", 686 0x30, 0x06, "cannot format medium - incompatible medium", 687 0x30, 0x07, "cleaning failure", 688 0x30, 0x08, "cannot write - application code mismatch", 689 0x30, 0x09, "current session not fixated for append", 690 0x30, 0x10, "medium not formatted", 691 0x31, 0x00, "medium format corrupted", 692 0x31, 0x01, "format command failed", 693 0x31, 0x02, "zoned formatting failed due to spare linking", 694 0x32, 0x00, "no defect spare location available", 695 0x32, 0x01, "defect list update failure", 696 0x33, 0x00, "tape length error", 697 0x34, 0x00, "enclosure failure", 698 0x35, 0x00, "enclosure services failure", 699 0x35, 0x01, "unsupported enclosure function", 700 0x35, 0x02, "enclosure services unavailable", 701 0x35, 0x03, "enclosure services transfer failure", 702 0x35, 0x04, "enclosure services transfer refused", 703 0x36, 0x00, "ribbon, ink, or toner failure", 704 0x37, 0x00, "rounded parameter", 705 0x39, 0x00, "saving parameters not supported", 706 0x3a, 0x00, "medium not present", 707 0x3a, 0x01, "medium not present - tray closed", 708 0x3a, 0x02, "medium not present - tray open", 709 0x3a, 0x03, "medium not present - loadable", 710 0x3a, 0x04, "medium not present - medium auxiliary memory accessible", 711 0x3b, 0x00, "sequential positioning error", 712 0x3b, 0x01, "tape position error at beginning-of-medium", 713 0x3b, 0x02, "tape position error at end-of-medium", 714 0x3b, 0x08, "reposition error", 715 0x3b, 0x0c, "position past beginning of medium", 716 0x3b, 0x0d, "medium destination element full", 717 0x3b, 0x0e, "medium source element empty", 718 0x3b, 0x0f, "end of medium reached", 719 0x3b, 0x11, "medium magazine not accessible", 720 0x3b, 0x12, "medium magazine removed", 721 0x3b, 0x13, "medium magazine inserted", 722 0x3b, 0x14, "medium magazine locked", 723 0x3b, 0x15, "medium magazine unlocked", 724 0x3b, 0x16, "mechanical positioning or changer error", 725 0x3d, 0x00, "invalid bits in indentify message", 726 0x3e, 0x00, "LUN has not self-configured yet", 727 0x3e, 0x01, "LUN failure", 728 0x3e, 0x02, "timeout on LUN", 729 0x3e, 0x03, "LUN failed self-test", 730 0x3e, 0x04, "LUN unable to update self-test log", 731 0x3f, 0x00, "target operating conditions have changed", 732 0x3f, 0x01, "microcode has been changed", 733 0x3f, 0x02, "changed operating definition", 734 0x3f, 0x03, "inquiry data has changed", 735 0x3f, 0x04, "component device attached", 736 0x3f, 0x05, "device identifier changed", 737 0x3f, 0x06, "redundancy group created or modified", 738 0x3f, 0x07, "redundancy group deleted", 739 0x3f, 0x08, "spare created or modified", 740 0x3f, 0x09, "spare deleted", 741 0x3f, 0x0a, "volume set created or modified", 742 0x3f, 0x0b, "volume set deleted", 743 0x3f, 0x0c, "volume set deassigned", 744 0x3f, 0x0d, "volume set reassigned", 745 0x3f, 0x0e, "reported LUNs data has changed", 746 0x3f, 0x0f, "echo buffer overwritten", 747 0x3f, 0x10, "medium loadable", 748 0x3f, 0x11, "medium auxiliary memory accessible", 749 0x40, 0x00, "ram failure", 750 0x41, 0x00, "data path failure", 751 0x42, 0x00, "power-on or self-test failure", 752 0x43, 0x00, "message error", 753 0x44, 0x00, "internal target failure", 754 0x45, 0x00, "select or reselect failure", 755 0x46, 0x00, "unsuccessful soft reset", 756 0x47, 0x00, "scsi parity error", 757 0x47, 0x01, "data phase crc error detected", 758 0x47, 0x02, "scsi parity error detected during st data phase", 759 0x47, 0x03, "information unit iucrc error detected", 760 0x47, 0x04, "asynchronous information protection error detected", 761 0x47, 0x05, "protocol service crc error", 762 0x47, 0x7f, "some commands cleared by iscsi protocol event", 763 0x48, 0x00, "initiator detected error message received", 764 0x49, 0x00, "invalid message error", 765 0x4a, 0x00, "command phase error", 766 0x4b, 0x00, "data phase error", 767 0x4b, 0x01, "invalid target port transfer tag received", 768 0x4b, 0x02, "too much write data", 769 0x4b, 0x03, "ack/nak timeout", 770 0x4b, 0x04, "nak received", 771 0x4b, 0x05, "data offset error", 772 0x4c, 0x00, "logical unit failed self-configuration", 773 0x4d, 0x00, "tagged overlapped commands (ASCQ = queue tag)", 774 0x4e, 0x00, "overlapped commands attempted", 775 0x50, 0x00, "write append error", 776 0x51, 0x00, "erase failure", 777 0x52, 0x00, "cartridge fault", 778 0x53, 0x00, "media load or eject failed", 779 0x53, 0x01, "unload tape failure", 780 0x53, 0x02, "medium removal prevented", 781 0x54, 0x00, "scsi to host system interface failure", 782 0x55, 0x00, "system resource failure", 783 0x55, 0x01, "system buffer full", 784 0x55, 0x02, "insufficient reservation resources", 785 0x55, 0x03, "insufficient resources", 786 0x55, 0x04, "insufficient registration resources", 787 0x55, 0x05, "insufficient access control resources", 788 0x55, 0x06, "auxiliary memory out of space", 789 0x57, 0x00, "unable to recover TOC", 790 0x58, 0x00, "generation does not exist", 791 0x59, 0x00, "updated block read", 792 0x5a, 0x00, "operator request or state change input", 793 0x5a, 0x01, "operator medium removal request", 794 0x5a, 0x02, "operator selected write protect", 795 0x5a, 0x03, "operator selected write permit", 796 0x5b, 0x00, "log exception", 797 0x5b, 0x01, "threshold condition met", 798 0x5b, 0x02, "log counter at maximum", 799 0x5b, 0x03, "log list codes exhausted", 800 0x5c, 0x00, "RPL status change", 801 0x5c, 0x01, "spindles synchronized", 802 0x5c, 0x02, "spindles not synchronized", 803 0x5d, 0x00, "drive operation marginal, service immediately" 804 " (failure prediction threshold exceeded)", 805 0x5d, 0x01, "media failure prediction threshold exceeded", 806 0x5d, 0x02, "LUN failure prediction threshold exceeded", 807 0x5d, 0x03, "spare area exhaustion prediction threshold exceeded", 808 0x5d, 0x10, "hardware impending failure general hard drive failure", 809 0x5d, 0x11, "hardware impending failure drive error rate too high", 810 0x5d, 0x12, "hardware impending failure data error rate too high", 811 0x5d, 0x13, "hardware impending failure seek error rate too high", 812 0x5d, 0x14, "hardware impending failure too many block reassigns", 813 0x5d, 0x15, "hardware impending failure access times too high", 814 0x5d, 0x16, "hardware impending failure start unit times too high", 815 0x5d, 0x17, "hardware impending failure channel parametrics", 816 0x5d, 0x18, "hardware impending failure controller detected", 817 0x5d, 0x19, "hardware impending failure throughput performance", 818 0x5d, 0x1a, "hardware impending failure seek time performance", 819 0x5d, 0x1b, "hardware impending failure spin-up retry count", 820 0x5d, 0x1c, "hardware impending failure drive calibration retry count", 821 0x5d, 0x20, "controller impending failure general hard drive failure", 822 0x5d, 0x21, "controller impending failure drive error rate too high", 823 0x5d, 0x22, "controller impending failure data error rate too high", 824 0x5d, 0x23, "controller impending failure seek error rate too high", 825 0x5d, 0x24, "controller impending failure too many block reassigns", 826 0x5d, 0x25, "controller impending failure access times too high", 827 0x5d, 0x26, "controller impending failure start unit times too high", 828 0x5d, 0x27, "controller impending failure channel parametrics", 829 0x5d, 0x28, "controller impending failure controller detected", 830 0x5d, 0x29, "controller impending failure throughput performance", 831 0x5d, 0x2a, "controller impending failure seek time performance", 832 0x5d, 0x2b, "controller impending failure spin-up retry count", 833 0x5d, 0x2c, "controller impending failure drive calibration retry cnt", 834 0x5d, 0x30, "data channel impending failure general hard drive failure", 835 0x5d, 0x31, "data channel impending failure drive error rate too high", 836 0x5d, 0x32, "data channel impending failure data error rate too high", 837 0x5d, 0x33, "data channel impending failure seek error rate too high", 838 0x5d, 0x34, "data channel impending failure too many block reassigns", 839 0x5d, 0x35, "data channel impending failure access times too high", 840 0x5d, 0x36, "data channel impending failure start unit times too high", 841 0x5d, 0x37, "data channel impending failure channel parametrics", 842 0x5d, 0x38, "data channel impending failure controller detected", 843 0x5d, 0x39, "data channel impending failure throughput performance", 844 0x5d, 0x3a, "data channel impending failure seek time performance", 845 0x5d, 0x3b, "data channel impending failure spin-up retry count", 846 0x5d, 0x3c, "data channel impending failure drive calibrate retry cnt", 847 0x5d, 0x40, "servo impending failure general hard drive failure", 848 0x5d, 0x41, "servo impending failure drive error rate too high", 849 0x5d, 0x42, "servo impending failure data error rate too high", 850 0x5d, 0x43, "servo impending failure seek error rate too high", 851 0x5d, 0x44, "servo impending failure too many block reassigns", 852 0x5d, 0x45, "servo impending failure access times too high", 853 0x5d, 0x46, "servo impending failure start unit times too high", 854 0x5d, 0x47, "servo impending failure channel parametrics", 855 0x5d, 0x48, "servo impending failure controller detected", 856 0x5d, 0x49, "servo impending failure throughput performance", 857 0x5d, 0x4a, "servo impending failure seek time performance", 858 0x5d, 0x4b, "servo impending failure spin-up retry count", 859 0x5d, 0x4c, "servo impending failure drive calibration retry count", 860 0x5d, 0x50, "spindle impending failure general hard drive failure", 861 0x5d, 0x51, "spindle impending failure drive error rate too high", 862 0x5d, 0x52, "spindle impending failure data error rate too high", 863 0x5d, 0x53, "spindle impending failure seek error rate too high", 864 0x5d, 0x54, "spindle impending failure too many block reassigns", 865 0x5d, 0x55, "spindle impending failure access times too high", 866 0x5d, 0x56, "spindle impending failure start unit times too high", 867 0x5d, 0x57, "spindle impending failure channel parametrics", 868 0x5d, 0x58, "spindle impending failure controller detected", 869 0x5d, 0x59, "spindle impending failure throughput performance", 870 0x5d, 0x5a, "spindle impending failure seek time performance", 871 0x5d, 0x5b, "spindle impending failure spin-up retry count", 872 0x5d, 0x5c, "spindle impending failure drive calibration retry count", 873 0x5d, 0x60, "firmware impending failure general hard drive failure", 874 0x5d, 0x61, "firmware impending failure drive error rate too high", 875 0x5d, 0x62, "firmware impending failure data error rate too high", 876 0x5d, 0x63, "firmware impending failure seek error rate too high", 877 0x5d, 0x64, "firmware impending failure too many block reassigns", 878 0x5d, 0x65, "firmware impending failure access times too high", 879 0x5d, 0x66, "firmware impending failure start unit times too high", 880 0x5d, 0x67, "firmware impending failure channel parametrics", 881 0x5d, 0x68, "firmware impending failure controller detected", 882 0x5d, 0x69, "firmware impending failure throughput performance", 883 0x5d, 0x6a, "firmware impending failure seek time performance", 884 0x5d, 0x6b, "firmware impending failure spin-up retry count", 885 0x5d, 0x6c, "firmware impending failure drive calibration retry count", 886 0x5d, 0xff, "failure prediction threshold exceeded (false)", 887 0x5e, 0x00, "low power condition active", 888 0x5e, 0x01, "idle condition activated by timer", 889 0x5e, 0x02, "standby condition activated by timer", 890 0x5e, 0x03, "idle condition activated by command", 891 0x5e, 0x04, "standby condition activated by command", 892 0x60, 0x00, "lamp failure", 893 0x61, 0x00, "video aquisition error", 894 0x62, 0x00, "scan head positioning error", 895 0x63, 0x00, "end of user area encountered on this track", 896 0x63, 0x01, "packet does not fit in available space", 897 0x64, 0x00, "illegal mode for this track", 898 0x64, 0x01, "invalid packet size", 899 0x65, 0x00, "voltage fault", 900 0x66, 0x00, "automatic document feeder cover up", 901 0x67, 0x00, "configuration failure", 902 0x67, 0x01, "configuration of incapable LUNs failed", 903 0x67, 0x02, "add LUN failed", 904 0x67, 0x03, "modification of LUN failed", 905 0x67, 0x04, "exchange of LUN failed", 906 0x67, 0x05, "remove of LUN failed", 907 0x67, 0x06, "attachment of LUN failed", 908 0x67, 0x07, "creation of LUN failed", 909 0x67, 0x08, "assign failure occurred", 910 0x67, 0x09, "multiply assigned LUN", 911 0x67, 0x0a, "set target port groups command failed", 912 0x68, 0x00, "logical unit not configured", 913 0x69, 0x00, "data loss on logical unit", 914 0x69, 0x01, "multiple LUN failures", 915 0x69, 0x02, "parity/data mismatch", 916 0x6a, 0x00, "informational, refer to log", 917 0x6b, 0x00, "state change has occured", 918 0x6b, 0x01, "redundancy level got better", 919 0x6b, 0x02, "redundancy level got worse", 920 0x6c, 0x00, "rebuild failure occured", 921 0x6d, 0x00, "recalculate failure occured", 922 0x6e, 0x00, "command to logical unit failed", 923 0x6f, 0x00, "copy protect key exchange failure authentication failure", 924 0x6f, 0x01, "copy protect key exchange failure key not present", 925 0x6f, 0x02, "copy protect key exchange failure key not established", 926 0x6f, 0x03, "read of scrambled sector without authentication", 927 0x6f, 0x04, "media region code is mismatched to LUN region", 928 0x6f, 0x05, "drive region must be permanent/region reset count error", 929 0x70, 0xffff, "decompression exception short algorithm id of ASCQ", 930 0x71, 0x00, "decompression exception long algorithm id", 931 0x72, 0x00, "session fixation error", 932 0x72, 0x01, "session fixation error writing lead-in", 933 0x72, 0x02, "session fixation error writing lead-out", 934 0x72, 0x03, "session fixation error - incomplete track in session", 935 0x72, 0x04, "empty or partially written reserved track", 936 0x72, 0x05, "no more track reservations allowed", 937 0x73, 0x00, "cd control error", 938 0x73, 0x01, "power calibration area almost full", 939 0x73, 0x02, "power calibration area is full", 940 0x73, 0x03, "power calibration area error", 941 0x73, 0x04, "program memory area update failure", 942 0x73, 0x05, "program memory area is full", 943 0x73, 0x06, "rma/pma is almost full", 944 0xffff, 0xffff, NULL 945 }; 946 947 char * 948 scsi_esname(uint_t key, char *tmpstr) 949 { 950 int i = 0; 951 952 while (extended_sense_list[i].asc != 0xffff) { 953 if (key == extended_sense_list[i].asc) { 954 return ((char *)extended_sense_list[i].message); 955 } 956 i++; 957 } 958 return (sprintf(tmpstr, "<vendor unique code 0x%x>", key)); 959 } 960 961 char * 962 scsi_asc_name(uint_t asc, uint_t ascq, char *tmpstr) 963 { 964 int i = 0; 965 966 while (extended_sense_list[i].asc != 0xffff) { 967 if ((asc == extended_sense_list[i].asc) && 968 ((ascq == extended_sense_list[i].ascq) || 969 (extended_sense_list[i].ascq == 0xffff))) { 970 return ((char *)extended_sense_list[i].message); 971 } 972 i++; 973 } 974 return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc)); 975 } 976 977 char * 978 scsi_sname(uchar_t sense_key) 979 { 980 if (sense_key >= (uchar_t)(NUM_SENSE_KEYS+NUM_IMPL_SENSE_KEYS)) { 981 return ("<unknown sense key>"); 982 } else { 983 return (sense_keys[sense_key]); 984 } 985 } 986 987 988 /* 989 * Print a piece of inquiry data- cleaned up for non-printable characters. 990 */ 991 992 static void 993 inq_fill(char *p, int l, char *s) 994 { 995 register unsigned i = 0; 996 char c; 997 998 if (!p) 999 return; 1000 1001 while (i++ < l) { 1002 /* clean string of non-printing chars */ 1003 if ((c = *p++) < ' ' || c >= 0177) { 1004 c = ' '; 1005 } 1006 *s++ = c; 1007 } 1008 *s++ = 0; 1009 } 1010 1011 static char * 1012 scsi_asc_search(uint_t asc, uint_t ascq, 1013 struct scsi_asq_key_strings *list) 1014 { 1015 int i = 0; 1016 1017 while (list[i].asc != 0xffff) { 1018 if ((asc == list[i].asc) && 1019 ((ascq == list[i].ascq) || 1020 (list[i].ascq == 0xffff))) { 1021 return ((char *)list[i].message); 1022 } 1023 i++; 1024 } 1025 return (NULL); 1026 } 1027 1028 static char * 1029 scsi_asc_ascq_name(uint_t asc, uint_t ascq, char *tmpstr, 1030 struct scsi_asq_key_strings *list) 1031 { 1032 char *message; 1033 1034 if (list) { 1035 if (message = scsi_asc_search(asc, ascq, list)) { 1036 return (message); 1037 } 1038 } 1039 if (message = scsi_asc_search(asc, ascq, extended_sense_list)) { 1040 return (message); 1041 } 1042 1043 return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc)); 1044 } 1045 1046 /* 1047 * The first part/column of the error message will be at least this length. 1048 * This number has been calculated so that each line fits in 80 chars. 1049 */ 1050 #define SCSI_ERRMSG_COLUMN_LEN 42 1051 #define SCSI_ERRMSG_BUF_LEN 256 1052 1053 void 1054 scsi_vu_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label, 1055 int severity, daddr_t blkno, daddr_t err_blkno, 1056 struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep, 1057 struct scsi_asq_key_strings *asc_list, 1058 char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t)) 1059 { 1060 uchar_t com; 1061 static char buf[SCSI_ERRMSG_BUF_LEN]; 1062 static char buf1[SCSI_ERRMSG_BUF_LEN]; 1063 static char tmpbuf[64]; 1064 static char pad[SCSI_ERRMSG_COLUMN_LEN]; 1065 dev_info_t *dev = devp->sd_dev; 1066 static char *error_classes[] = { 1067 "All", "Unknown", "Informational", 1068 "Recovered", "Retryable", "Fatal" 1069 }; 1070 int i, buflen; 1071 1072 mutex_enter(&scsi_log_mutex); 1073 1074 /* 1075 * We need to put our space padding code because kernel version 1076 * of sprintf(9F) doesn't support %-<number>s type of left alignment. 1077 */ 1078 for (i = 0; i < SCSI_ERRMSG_COLUMN_LEN; i++) { 1079 pad[i] = ' '; 1080 } 1081 1082 bzero(buf, 256); 1083 com = ((union scsi_cdb *)pkt->pkt_cdbp)->scc_cmd; 1084 (void) sprintf(buf, "Error for Command: %s", 1085 scsi_cmd_name(com, cmdlist, tmpbuf)); 1086 buflen = strlen(buf); 1087 if (buflen < SCSI_ERRMSG_COLUMN_LEN) { 1088 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0'; 1089 (void) sprintf(&buf[buflen], "%s Error Level: %s", 1090 pad, error_classes[severity]); 1091 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' '; 1092 } else { 1093 (void) sprintf(&buf[buflen], " Error Level: %s", 1094 error_classes[severity]); 1095 } 1096 impl_scsi_log(dev, label, CE_WARN, buf); 1097 1098 if (blkno != -1 || err_blkno != -1 && 1099 ((com & 0xf) == SCMD_READ) || ((com & 0xf) == SCMD_WRITE)) { 1100 bzero(buf, 256); 1101 (void) sprintf(buf, "Requested Block: %ld", blkno); 1102 buflen = strlen(buf); 1103 if (buflen < SCSI_ERRMSG_COLUMN_LEN) { 1104 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0'; 1105 (void) sprintf(&buf[buflen], "%s Error Block: %ld\n", 1106 pad, err_blkno); 1107 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' '; 1108 } else { 1109 (void) sprintf(&buf[buflen], " Error Block: %ld\n", 1110 err_blkno); 1111 } 1112 impl_scsi_log(dev, label, CE_CONT, buf); 1113 } 1114 1115 bzero(buf, 256); 1116 (void) strcpy(buf, "Vendor: "); 1117 inq_fill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]); 1118 buflen = strlen(buf); 1119 if (buflen < SCSI_ERRMSG_COLUMN_LEN) { 1120 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0'; 1121 (void) sprintf(&buf[strlen(buf)], "%s Serial Number: ", pad); 1122 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' '; 1123 } else { 1124 (void) sprintf(&buf[strlen(buf)], " Serial Number: "); 1125 } 1126 inq_fill(devp->sd_inq->inq_serial, 12, &buf[strlen(buf)]); 1127 impl_scsi_log(dev, label, CE_CONT, "%s\n", buf); 1128 1129 if (sensep) { 1130 bzero(buf, 256); 1131 (void) sprintf(buf, "Sense Key: %s\n", 1132 sense_keys[sensep->es_key]); 1133 impl_scsi_log(dev, label, CE_CONT, buf); 1134 1135 bzero(buf, 256); 1136 if ((sensep->es_fru_code != 0) && 1137 (decode_fru != NULL)) { 1138 (*decode_fru)(devp, buf, SCSI_ERRMSG_BUF_LEN, 1139 sensep->es_fru_code); 1140 if (buf[0] != NULL) { 1141 bzero(buf1, 256); 1142 (void) sprintf(&buf1[strlen(buf1)], 1143 "ASC: 0x%x (%s)", sensep->es_add_code, 1144 scsi_asc_ascq_name(sensep->es_add_code, 1145 sensep->es_qual_code, tmpbuf, asc_list)); 1146 buflen = strlen(buf1); 1147 if (buflen < SCSI_ERRMSG_COLUMN_LEN) { 1148 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0'; 1149 (void) sprintf(&buf1[buflen], 1150 "%s ASCQ: 0x%x", pad, sensep->es_qual_code); 1151 } else { 1152 (void) sprintf(&buf1[buflen], " ASCQ: 0x%x", 1153 sensep->es_qual_code); 1154 } 1155 impl_scsi_log(dev, 1156 label, CE_CONT, "%s\n", buf1); 1157 impl_scsi_log(dev, label, CE_CONT, 1158 "FRU: 0x%x (%s)\n", 1159 sensep->es_fru_code, buf); 1160 mutex_exit(&scsi_log_mutex); 1161 return; 1162 } 1163 } 1164 (void) sprintf(&buf[strlen(buf)], 1165 "ASC: 0x%x (%s), ASCQ: 0x%x, FRU: 0x%x", 1166 sensep->es_add_code, 1167 scsi_asc_ascq_name(sensep->es_add_code, 1168 sensep->es_qual_code, tmpbuf, asc_list), 1169 sensep->es_qual_code, sensep->es_fru_code); 1170 impl_scsi_log(dev, label, CE_CONT, "%s\n", buf); 1171 } 1172 mutex_exit(&scsi_log_mutex); 1173 } 1174 1175 void 1176 scsi_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label, 1177 int severity, daddr_t blkno, daddr_t err_blkno, 1178 struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep) 1179 { 1180 scsi_vu_errmsg(devp, pkt, label, severity, blkno, 1181 err_blkno, cmdlist, sensep, NULL, NULL); 1182 } 1183 1184 /*PRINTFLIKE4*/ 1185 void 1186 scsi_log(dev_info_t *dev, char *label, uint_t level, 1187 const char *fmt, ...) 1188 { 1189 va_list ap; 1190 1191 va_start(ap, fmt); 1192 mutex_enter(&scsi_log_mutex); 1193 v_scsi_log(dev, label, level, fmt, ap); 1194 mutex_exit(&scsi_log_mutex); 1195 va_end(ap); 1196 } 1197 1198 /*PRINTFLIKE4*/ 1199 static void 1200 impl_scsi_log(dev_info_t *dev, char *label, uint_t level, 1201 const char *fmt, ...) 1202 { 1203 va_list ap; 1204 1205 ASSERT(mutex_owned(&scsi_log_mutex)); 1206 1207 va_start(ap, fmt); 1208 v_scsi_log(dev, label, level, fmt, ap); 1209 va_end(ap); 1210 } 1211 1212 1213 char *ddi_pathname(dev_info_t *dip, char *path); 1214 1215 /*PRINTFLIKE4*/ 1216 static void 1217 v_scsi_log(dev_info_t *dev, char *label, uint_t level, 1218 const char *fmt, va_list ap) 1219 { 1220 static char name[256]; 1221 int log_only = 0; 1222 int boot_only = 0; 1223 int console_only = 0; 1224 1225 ASSERT(mutex_owned(&scsi_log_mutex)); 1226 1227 if (dev) { 1228 if (level == CE_PANIC || level == CE_WARN || 1229 level == CE_NOTE) { 1230 (void) sprintf(name, "%s (%s%d):\n", 1231 ddi_pathname(dev, scsi_log_buffer), 1232 label, ddi_get_instance(dev)); 1233 } else if (level >= (uint_t)SCSI_DEBUG) { 1234 (void) sprintf(name, 1235 "%s%d:", label, ddi_get_instance(dev)); 1236 } else { 1237 name[0] = '\0'; 1238 } 1239 } else { 1240 (void) sprintf(name, "%s:", label); 1241 } 1242 1243 (void) vsprintf(scsi_log_buffer, fmt, ap); 1244 1245 switch (scsi_log_buffer[0]) { 1246 case '!': 1247 log_only = 1; 1248 break; 1249 case '?': 1250 boot_only = 1; 1251 break; 1252 case '^': 1253 console_only = 1; 1254 break; 1255 } 1256 1257 switch (level) { 1258 case CE_NOTE: 1259 level = CE_CONT; 1260 /* FALLTHROUGH */ 1261 case CE_CONT: 1262 case CE_WARN: 1263 case CE_PANIC: 1264 if (boot_only) { 1265 cmn_err(level, "?%s\t%s", name, 1266 &scsi_log_buffer[1]); 1267 } else if (console_only) { 1268 cmn_err(level, "^%s\t%s", name, 1269 &scsi_log_buffer[1]); 1270 } else if (log_only) { 1271 cmn_err(level, "!%s\t%s", name, 1272 &scsi_log_buffer[1]); 1273 } else { 1274 cmn_err(level, "%s\t%s", name, 1275 scsi_log_buffer); 1276 } 1277 break; 1278 case (uint_t)SCSI_DEBUG: 1279 default: 1280 cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, 1281 scsi_log_buffer); 1282 break; 1283 } 1284 } 1285 1286 int 1287 scsi_get_device_type_scsi_options(dev_info_t *dip, 1288 struct scsi_device *devp, int default_scsi_options) 1289 { 1290 1291 caddr_t config_list = NULL; 1292 int options = default_scsi_options; 1293 struct scsi_inquiry *inq = devp->sd_inq; 1294 caddr_t vidptr, datanameptr; 1295 int vidlen, dupletlen; 1296 int config_list_len, len; 1297 1298 /* 1299 * look up the device-type-scsi-options-list and walk thru 1300 * the list 1301 * compare the vendor ids of the earlier inquiry command and 1302 * with those vids in the list 1303 * if there is a match, lookup the scsi-options value 1304 */ 1305 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1306 "device-type-scsi-options-list", 1307 (caddr_t)&config_list, &config_list_len) == DDI_PROP_SUCCESS) { 1308 1309 /* 1310 * Compare vids in each duplet - if it matches, get value for 1311 * dataname and then lookup scsi_options 1312 * dupletlen is calculated later. 1313 */ 1314 for (len = config_list_len, vidptr = config_list; len > 0; 1315 vidptr += dupletlen, len -= dupletlen) { 1316 1317 vidlen = strlen(vidptr); 1318 datanameptr = vidptr + vidlen + 1; 1319 1320 if ((vidlen != 0) && 1321 bcmp(inq->inq_vid, vidptr, vidlen) == 0) { 1322 /* 1323 * get the data list 1324 */ 1325 options = ddi_prop_get_int(DDI_DEV_T_ANY, 1326 dip, 0, 1327 datanameptr, default_scsi_options); 1328 break; 1329 } 1330 dupletlen = vidlen + strlen(datanameptr) + 2; 1331 } 1332 kmem_free(config_list, config_list_len); 1333 } 1334 1335 return (options); 1336 } 1337