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