Print this page
NEX-16174 scsi error messages should go to system log only
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
1787 SATL fails to handle returned SMART sense data
Reviewed by: Richard Elling <richard.elling@richardelling.com>
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Robert Mustacchi <rm@joyent.com>


 454                 "ORDERED QUEUE TAG",
 455                 "IGNORE WIDE RESIDUE",
 456                 "ACA",
 457                 "LOGICAL UNIT RESET"
 458         };
 459 
 460         if (msg < 23) {
 461                 return (imsgs[msg]);
 462         } else if (IS_IDENTIFY_MSG(msg)) {
 463                 return ("IDENTIFY");
 464         } else if (IS_2BYTE_MSG(msg) &&
 465             (int)((msg) & 0xF) < (sizeof (imsgs_2) / sizeof (char *))) {
 466                 return (imsgs_2[msg & 0xF]);
 467         } else {
 468                 return ("<unknown msg>");
 469         }
 470 
 471 }
 472 
 473 char *
 474 scsi_cname(uchar_t cmd, register char **cmdvec)
 475 {
 476         while (*cmdvec != (char *)0) {
 477                 if (cmd == **cmdvec) {
 478                         return ((char *)((long)(*cmdvec)+1));
 479                 }
 480                 cmdvec++;
 481         }
 482         return (sprintf(scsi_tmpname, "<undecoded cmd 0x%x>", cmd));
 483 }
 484 
 485 char *
 486 scsi_cmd_name(uchar_t cmd, struct scsi_key_strings *cmdlist, char *tmpstr)
 487 {
 488         int i = 0;
 489 
 490         while (cmdlist[i].key !=  -1) {
 491                 if (cmd == cmdlist[i].key) {
 492                         return ((char *)cmdlist[i].message);
 493                 }
 494                 i++;
 495         }
 496         return (sprintf(tmpstr, "<undecoded cmd 0x%x>", cmd));
 497 }
 498 
 499 static struct scsi_asq_key_strings extended_sense_list[] = {


1008                 if ((asc == extended_sense_list[i].asc) &&
1009                     ((ascq == extended_sense_list[i].ascq) ||
1010                     (extended_sense_list[i].ascq == 0xffff))) {
1011                         return ((char *)extended_sense_list[i].message);
1012                 }
1013                 i++;
1014         }
1015         return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc));
1016 }
1017 
1018 char *
1019 scsi_sname(uchar_t sense_key)
1020 {
1021         if (sense_key >= (uchar_t)(NUM_SENSE_KEYS+NUM_IMPL_SENSE_KEYS)) {
1022                 return ("<unknown sense key>");
1023         } else {
1024                 return (sense_keys[sense_key]);
1025         }
1026 }
1027 
1028 
1029 /*
1030  * Print a piece of inquiry data- cleaned up for non-printable characters.
1031  */
1032 static void
1033 inq_fill(char *p, int l, char *s)
1034 {
1035         register unsigned i = 0;
1036         char c;
1037 
1038         if (!p)
1039                 return;
1040 
1041         while (i++ < l) {
1042                 /* clean string of non-printing chars */
1043                 if ((c = *p++) < ' ' || c >= 0177) {
1044                         c = ' ';
1045                 }
1046                 *s++ = c;
1047         }
1048         *s++ = 0;
1049 }
1050 
1051 static char *
1052 scsi_asc_search(uint_t asc, uint_t ascq,
1053     struct scsi_asq_key_strings *list)
1054 {
1055         int i = 0;
1056 
1057         while (list[i].asc != 0xffff) {
1058                 if ((asc == list[i].asc) &&
1059                     ((ascq == list[i].ascq) ||
1060                     (list[i].ascq == 0xffff))) {
1061                         return ((char *)list[i].message);
1062                 }
1063                 i++;
1064         }
1065         return (NULL);
1066 }
1067 
1068 static char *
1069 scsi_asc_ascq_name(uint_t asc, uint_t ascq, char *tmpstr,
1070         struct scsi_asq_key_strings *list)
1071 {
1072         char *message;
1073 
1074         if (list) {
1075                 if (message = scsi_asc_search(asc, ascq, list)) {
1076                         return (message);
1077                 }
1078         }
1079         if (message = scsi_asc_search(asc, ascq, extended_sense_list)) {
1080                 return (message);
1081         }
1082 
1083         return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc));
1084 }
1085 
1086 /*
1087  * The first part/column of the error message will be at least this length.
1088  * This number has been calculated so that each line fits in 80 chars.
1089  */
1090 #define SCSI_ERRMSG_COLUMN_LEN  42
1091 #define SCSI_ERRMSG_BUF_LEN     256
1092 
1093 void
1094 scsi_generic_errmsg(struct scsi_device *devp, char *label, int severity,
1095     daddr_t blkno, daddr_t err_blkno,
1096     uchar_t cmd_name, struct scsi_key_strings *cmdlist,
1097     uint8_t *sensep, struct scsi_asq_key_strings *asc_list,
1098     char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1099 {
1100         uchar_t com;
1101         static char buf[SCSI_ERRMSG_BUF_LEN];
1102         static char buf1[SCSI_ERRMSG_BUF_LEN];
1103         static char tmpbuf[64];
1104         static char pad[SCSI_ERRMSG_COLUMN_LEN];
1105         dev_info_t *dev = devp->sd_dev;
1106         static char *error_classes[] = {
1107                 "All", "Unknown", "Informational",
1108                 "Recovered", "Retryable", "Fatal"
1109         };
1110         uchar_t sense_key, asc, ascq, fru_code;
1111         uchar_t *fru_code_ptr;
1112         int i, buflen;
1113 
1114         mutex_enter(&scsi_log_mutex);
1115 
1116         /*
1117          * We need to put our space padding code because kernel version
1118          * of sprintf(9F) doesn't support %-<number>s type of left alignment.
1119          */
1120         for (i = 0; i < SCSI_ERRMSG_COLUMN_LEN; i++) {
1121                 pad[i] = ' ';
1122         }
1123 
1124         bzero(buf, SCSI_ERRMSG_BUF_LEN);
1125         com = cmd_name;
1126         (void) sprintf(buf, "Error for Command: %s",
1127             scsi_cmd_name(com, cmdlist, tmpbuf));
1128         buflen = strlen(buf);
1129         if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1130                 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1131                 (void) sprintf(&buf[buflen], "%s Error Level: %s",
1132                     pad, error_classes[severity]);
1133                 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1134         } else {
1135                 (void) sprintf(&buf[buflen], " Error Level: %s",
1136                     error_classes[severity]);
1137         }
1138         impl_scsi_log(dev, label, CE_WARN, buf);
1139 
1140         if (blkno != -1 || err_blkno != -1 &&
1141             ((com & 0xf) == SCMD_READ) || ((com & 0xf) == SCMD_WRITE)) {
1142                 bzero(buf, SCSI_ERRMSG_BUF_LEN);
1143                 (void) sprintf(buf, "Requested Block: %ld", blkno);
1144                 buflen = strlen(buf);
1145                 if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1146                         pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1147                         (void) sprintf(&buf[buflen], "%s Error Block: %ld\n",
1148                             pad, err_blkno);
1149                         pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1150                 } else {
1151                         (void) sprintf(&buf[buflen], " Error Block: %ld\n",
1152                             err_blkno);
1153                 }
1154                 impl_scsi_log(dev, label, CE_CONT, buf);
1155         }
1156 
1157         bzero(buf, SCSI_ERRMSG_BUF_LEN);
1158         (void) strcpy(buf, "Vendor: ");
1159         inq_fill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]);
1160         buflen = strlen(buf);
1161         if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1162                 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1163                 (void) sprintf(&buf[strlen(buf)], "%s Serial Number: ", pad);
1164                 pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1165         } else {
1166                 (void) sprintf(&buf[strlen(buf)], " Serial Number: ");
1167         }
1168         inq_fill(devp->sd_inq->inq_serial, 12, &buf[strlen(buf)]);
1169         impl_scsi_log(dev, label, CE_CONT, "%s\n", buf);
1170 
1171         if (sensep) {
1172                 sense_key = scsi_sense_key(sensep);
1173                 asc = scsi_sense_asc(sensep);
1174                 ascq = scsi_sense_ascq(sensep);
1175                 scsi_ext_sense_fields(sensep, SENSE_LENGTH,
1176                     NULL, NULL, &fru_code_ptr, NULL, NULL);
1177                 fru_code = (fru_code_ptr ? *fru_code_ptr : 0);
1178 
1179                 bzero(buf, SCSI_ERRMSG_BUF_LEN);
1180                 (void) sprintf(buf, "Sense Key: %s\n",
1181                     sense_keys[sense_key]);
1182                 impl_scsi_log(dev, label, CE_CONT, buf);
1183 
1184                 bzero(buf, SCSI_ERRMSG_BUF_LEN);
1185                 if ((fru_code != 0) &&
1186                     (decode_fru != NULL)) {
1187                         (*decode_fru)(devp, buf, SCSI_ERRMSG_BUF_LEN,
1188                             fru_code);
1189                         if (buf[0] != NULL) {
1190                                 bzero(buf1, SCSI_ERRMSG_BUF_LEN);
1191                                 (void) sprintf(&buf1[strlen(buf1)],
1192                                     "ASC: 0x%x (%s)", asc,
1193                                     scsi_asc_ascq_name(asc, ascq,
1194                                     tmpbuf, asc_list));
1195                                 buflen = strlen(buf1);
1196                                 if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1197                                         pad[SCSI_ERRMSG_COLUMN_LEN - buflen] =
1198                                             '\0';
1199                                         (void) sprintf(&buf1[buflen],
1200                                             "%s ASCQ: 0x%x", pad, ascq);
1201                                 } else {
1202                                         (void) sprintf(&buf1[buflen],
1203                                             " ASCQ: 0x%x", ascq);
1204                                 }
1205                                 impl_scsi_log(dev,
1206                                     label, CE_CONT, "%s\n", buf1);
1207                                 impl_scsi_log(dev,
1208                                     label, CE_CONT, "FRU: 0x%x (%s)\n",
1209                                     fru_code, buf);
1210                                 mutex_exit(&scsi_log_mutex);
1211                                 return;
1212                         }
1213                 }
1214                 (void) sprintf(&buf[strlen(buf)],
1215                     "ASC: 0x%x (%s), ASCQ: 0x%x, FRU: 0x%x",
1216                     asc, scsi_asc_ascq_name(asc, ascq, tmpbuf, asc_list),
1217                     ascq, fru_code);
1218                 impl_scsi_log(dev, label, CE_CONT, "%s\n", buf);
1219         }
1220         mutex_exit(&scsi_log_mutex);
1221 }
1222 
1223 void
1224 scsi_vu_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1225     int severity, daddr_t blkno, daddr_t err_blkno,
1226     struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep,
1227     struct scsi_asq_key_strings *asc_list,
1228     char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1229 {
1230         uchar_t com;
1231 
1232         com = ((union scsi_cdb *)pkt->pkt_cdbp)->scc_cmd;
1233 
1234         scsi_generic_errmsg(devp, label, severity, blkno, err_blkno,
1235             com, cmdlist, (uint8_t *)sensep, asc_list, decode_fru);
1236 
1237 
1238 }
1239 
1240 void
1241 scsi_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1242     int severity, daddr_t blkno, daddr_t err_blkno,
1243     struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep)
1244 {
1245         scsi_vu_errmsg(devp, pkt, label, severity, blkno,
1246             err_blkno, cmdlist, sensep, NULL, NULL);
1247 }
1248 
1249 /*PRINTFLIKE4*/
1250 void
1251 scsi_log(dev_info_t *dev, char *label, uint_t level,
1252     const char *fmt, ...)
1253 {
1254         va_list ap;
1255 
1256         va_start(ap, fmt);
1257         mutex_enter(&scsi_log_mutex);
1258         v_scsi_log(dev, label, level, fmt, ap);
1259         mutex_exit(&scsi_log_mutex);
1260         va_end(ap);
1261 }
1262 
1263 /*PRINTFLIKE4*/
1264 static void
1265 impl_scsi_log(dev_info_t *dev, char *label, uint_t level,
1266     const char *fmt, ...)
1267 {
1268         va_list ap;
1269 
1270         ASSERT(mutex_owned(&scsi_log_mutex));
1271 
1272         va_start(ap, fmt);
1273         v_scsi_log(dev, label, level, fmt, ap);
1274         va_end(ap);
1275 }
1276 
1277 
1278 char *ddi_pathname(dev_info_t *dip, char *path);
1279 
1280 /*PRINTFLIKE4*/
1281 static void
1282 v_scsi_log(dev_info_t *dev, char *label, uint_t level,
1283     const char *fmt, va_list ap)
1284 {
1285         static char name[256];
1286         int log_only = 0;
1287         int boot_only = 0;
1288         int console_only = 0;
1289 
1290         ASSERT(mutex_owned(&scsi_log_mutex));
1291 
1292         if (dev) {
1293                 if (level == CE_PANIC || level == CE_WARN ||
1294                     level == CE_NOTE) {
1295                         (void) sprintf(name, "%s (%s%d):\n",
1296                             ddi_pathname(dev, scsi_log_buffer),
1297                             label, ddi_get_instance(dev));
1298                 } else if (level >= (uint_t)SCSI_DEBUG) {
1299                         (void) sprintf(name,
1300                             "%s%d:", label, ddi_get_instance(dev));
1301                 } else {
1302                         name[0] = '\0';
1303                 }
1304         } else {
1305                 (void) sprintf(name, "%s:", label);
1306         }
1307 
1308         (void) vsprintf(scsi_log_buffer, fmt, ap);
1309 
1310         switch (scsi_log_buffer[0]) {
1311         case '!':
1312                 log_only = 1;
1313                 break;
1314         case '?':
1315                 boot_only = 1;
1316                 break;
1317         case '^':
1318                 console_only = 1;
1319                 break;
1320         }
1321 
1322         switch (level) {
1323         case CE_NOTE:
1324                 level = CE_CONT;
1325                 /* FALLTHROUGH */
1326         case CE_CONT:
1327         case CE_WARN:
1328         case CE_PANIC:
1329                 if (boot_only) {
1330                         cmn_err(level, "?%s\t%s", name, &scsi_log_buffer[1]);
1331                 } else if (console_only) {
1332                         cmn_err(level, "^%s\t%s", name, &scsi_log_buffer[1]);
1333                 } else if (log_only) {
1334                         cmn_err(level, "!%s\t%s", name, &scsi_log_buffer[1]);
1335                 } else {
1336                         cmn_err(level, "%s\t%s", name, scsi_log_buffer);
1337                 }
1338                 break;
1339         case (uint_t)SCSI_DEBUG:
1340         default:
1341                 cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, scsi_log_buffer);
1342                 break;
1343         }
1344 }
1345 
1346 /*
1347  * Lookup the 'prop_name' string array property and walk thru its list of
1348  * tuple values looking for a tuple who's VID/PID string (first part of tuple)
1349  * matches the inquiry VID/PID information for the scsi_device.  On a match,
1350  * return a duplicate of the second part of the tuple.  If no match is found,
1351  * return NULL. On non-NULL return, caller is responsible for freeing return
1352  * result via:
1353  *      kmem_free(string, strlen(string) + 1);
1354  *
1355  * This interface can either be used directly, or indirectly by
1356  * scsi_get_device_type_scsi_options.
1357  */
1358 char    *
1359 scsi_get_device_type_string(char *prop_name,
1360     dev_info_t *dip, struct scsi_device *devp)
1361 {




 454                 "ORDERED QUEUE TAG",
 455                 "IGNORE WIDE RESIDUE",
 456                 "ACA",
 457                 "LOGICAL UNIT RESET"
 458         };
 459 
 460         if (msg < 23) {
 461                 return (imsgs[msg]);
 462         } else if (IS_IDENTIFY_MSG(msg)) {
 463                 return ("IDENTIFY");
 464         } else if (IS_2BYTE_MSG(msg) &&
 465             (int)((msg) & 0xF) < (sizeof (imsgs_2) / sizeof (char *))) {
 466                 return (imsgs_2[msg & 0xF]);
 467         } else {
 468                 return ("<unknown msg>");
 469         }
 470 
 471 }
 472 
 473 char *
 474 scsi_cname(uchar_t cmd, char **cmdvec)
 475 {
 476         while (*cmdvec != NULL) {
 477                 if (cmd == **cmdvec)
 478                         return ((char *)(uintptr_t)(*cmdvec + 1));

 479                 cmdvec++;
 480         }
 481         return (sprintf(scsi_tmpname, "<undecoded cmd 0x%x>", cmd));
 482 }
 483 
 484 char *
 485 scsi_cmd_name(uchar_t cmd, struct scsi_key_strings *cmdlist, char *tmpstr)
 486 {
 487         int i = 0;
 488 
 489         while (cmdlist[i].key !=  -1) {
 490                 if (cmd == cmdlist[i].key) {
 491                         return ((char *)cmdlist[i].message);
 492                 }
 493                 i++;
 494         }
 495         return (sprintf(tmpstr, "<undecoded cmd 0x%x>", cmd));
 496 }
 497 
 498 static struct scsi_asq_key_strings extended_sense_list[] = {


1007                 if ((asc == extended_sense_list[i].asc) &&
1008                     ((ascq == extended_sense_list[i].ascq) ||
1009                     (extended_sense_list[i].ascq == 0xffff))) {
1010                         return ((char *)extended_sense_list[i].message);
1011                 }
1012                 i++;
1013         }
1014         return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc));
1015 }
1016 
1017 char *
1018 scsi_sname(uchar_t sense_key)
1019 {
1020         if (sense_key >= (uchar_t)(NUM_SENSE_KEYS+NUM_IMPL_SENSE_KEYS)) {
1021                 return ("<unknown sense key>");
1022         } else {
1023                 return (sense_keys[sense_key]);
1024         }
1025 }
1026 























1027 static char *
1028 scsi_asc_search(uint_t asc, uint_t ascq,
1029     struct scsi_asq_key_strings *list)
1030 {
1031         int i = 0;
1032 
1033         while (list[i].asc != 0xffff) {
1034                 if ((asc == list[i].asc) &&
1035                     ((ascq == list[i].ascq) ||
1036                     (list[i].ascq == 0xffff))) {
1037                         return ((char *)list[i].message);
1038                 }
1039                 i++;
1040         }
1041         return (NULL);
1042 }
1043 
1044 static char *
1045 scsi_asc_ascq_name(uint_t asc, uint_t ascq, char *tmpstr,
1046     struct scsi_asq_key_strings *list)
1047 {
1048         char *message;
1049 
1050         if (list) {
1051                 if (message = scsi_asc_search(asc, ascq, list)) {
1052                         return (message);
1053                 }
1054         }
1055         if (message = scsi_asc_search(asc, ascq, extended_sense_list)) {
1056                 return (message);
1057         }
1058 
1059         return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc));
1060 }
1061 
1062 #define SCSI_LOGBUF_LEN 512





1063 
1064 void
1065 scsi_generic_errmsg(struct scsi_device *devp, char *label, int severity,
1066     daddr_t blkno, daddr_t err_blkno,
1067     uchar_t cmd_name, struct scsi_key_strings *cmdlist,
1068     uint8_t *sensep, struct scsi_asq_key_strings *asc_list,
1069     char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1070 {
1071         char cmdbuf[SCSI_LOGBUF_LEN];
1072         char blkbuf[SCSI_LOGBUF_LEN];
1073         char sensebuf[SCSI_LOGBUF_LEN];
1074         char frubuf[SCSI_LOGBUF_LEN];
1075         char tmpbuf[SCSI_LOGBUF_LEN];

1076         static char *error_classes[] = {
1077                 "All", "Unknown", "Informational",
1078                 "Recovered", "Retryable", "Fatal"
1079         };



1080 
1081         mutex_enter(&scsi_log_mutex);
1082 
1083         (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s: cmd=%s",
1084             error_classes[severity], scsi_cmd_name(cmd_name, cmdlist, tmpbuf));





1085 
1086         blkbuf[0] = '\0';
1087         if ((blkno != -1 || err_blkno != -1) &&
1088             ((cmd_name & 0xf) == SCMD_READ || (cmd_name & 0xf) == SCMD_WRITE)) {
1089                 (void) snprintf(blkbuf, sizeof (blkbuf),
1090                     " (reqblk=%ld errblk=%ld)", blkno, err_blkno);








1091         }

1092 
1093         sensebuf[0] = '\0';
1094         frubuf[0] = '\0';
1095         if (sensep != NULL) {
1096                 uchar_t sense_key, asc, ascq, fru_code;
1097                 uchar_t *fru_code_ptr;











1098 















1099                 sense_key = scsi_sense_key(sensep);
1100                 asc = scsi_sense_asc(sensep);
1101                 ascq = scsi_sense_ascq(sensep);
1102                 scsi_ext_sense_fields(sensep, SENSE_LENGTH,
1103                     NULL, NULL, &fru_code_ptr, NULL, NULL);

1104 
1105                 (void) snprintf(sensebuf, sizeof (sensebuf),
1106                     " key=%s asc/ascq=0x%x/0x%x (\"%s\")",
1107                     sense_keys[sense_key], asc, ascq,
1108                     scsi_asc_ascq_name(asc, ascq, tmpbuf, asc_list));
1109 
1110                 fru_code = (fru_code_ptr != NULL ? *fru_code_ptr : 0);
1111                 if (fru_code != 0 &&
1112                     decode_fru != NULL) {
1113                         (*decode_fru)(devp, tmpbuf, sizeof (tmpbuf), fru_code);
1114                         if (tmpbuf[0] != '\0') {
1115                                 (void) snprintf(frubuf, sizeof (frubuf),
1116                                     " fru=0x%x (\"%s\")", fru_code, tmpbuf);













1117                         }







1118                 }
1119         }
1120 
1121         impl_scsi_log(devp->sd_dev, label, CE_WARN, "!%s%s%s%s",
1122             cmdbuf, blkbuf, sensebuf, frubuf);
1123 


1124         mutex_exit(&scsi_log_mutex);
1125 }
1126 
1127 void
1128 scsi_vu_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1129     int severity, daddr_t blkno, daddr_t err_blkno,
1130     struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep,
1131     struct scsi_asq_key_strings *asc_list,
1132     char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1133 {
1134         uchar_t com;
1135 
1136         com = ((union scsi_cdb *)pkt->pkt_cdbp)->scc_cmd;
1137 
1138         scsi_generic_errmsg(devp, label, severity, blkno, err_blkno,
1139             com, cmdlist, (uint8_t *)sensep, asc_list, decode_fru);


1140 }
1141 
1142 void
1143 scsi_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1144     int severity, daddr_t blkno, daddr_t err_blkno,
1145     struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep)
1146 {
1147         scsi_vu_errmsg(devp, pkt, label, severity, blkno,
1148             err_blkno, cmdlist, sensep, NULL, NULL);
1149 }
1150 
1151 /*PRINTFLIKE4*/
1152 void
1153 scsi_log(dev_info_t *dev, char *label, uint_t level,
1154     const char *fmt, ...)
1155 {
1156         va_list ap;
1157 
1158         va_start(ap, fmt);
1159         mutex_enter(&scsi_log_mutex);
1160         v_scsi_log(dev, label, level, fmt, ap);
1161         mutex_exit(&scsi_log_mutex);
1162         va_end(ap);
1163 }
1164 
1165 /*PRINTFLIKE4*/
1166 static void
1167 impl_scsi_log(dev_info_t *dev, char *label, uint_t level,
1168     const char *fmt, ...)
1169 {
1170         va_list ap;
1171 
1172         ASSERT(mutex_owned(&scsi_log_mutex));
1173 
1174         va_start(ap, fmt);
1175         v_scsi_log(dev, label, level, fmt, ap);
1176         va_end(ap);
1177 }
1178 



1179 /*PRINTFLIKE4*/
1180 static void
1181 v_scsi_log(dev_info_t *dev, char *label, uint_t level,
1182     const char *fmt, va_list ap)
1183 {
1184         static char name[256];
1185         int log_only = 0;
1186         int boot_only = 0;
1187         int console_only = 0;
1188 
1189         ASSERT(mutex_owned(&scsi_log_mutex));
1190 
1191         if (dev != NULL) {
1192                 if (level == CE_PANIC || level == CE_WARN ||
1193                     level == CE_NOTE || level >= (uint_t)SCSI_DEBUG) {
1194                         (void) snprintf(name, sizeof (name), "%s%d: ",
1195                             ddi_driver_name(dev), ddi_get_instance(dev));




1196                 } else {
1197                         name[0] = '\0';
1198                 }
1199         } else {
1200                 (void) sprintf(name, "%s: ", label);
1201         }
1202 
1203         (void) vsprintf(scsi_log_buffer, fmt, ap);
1204 
1205         switch (scsi_log_buffer[0]) {
1206         case '!':
1207                 log_only = 1;
1208                 break;
1209         case '?':
1210                 boot_only = 1;
1211                 break;
1212         case '^':
1213                 console_only = 1;
1214                 break;
1215         }
1216 
1217         switch (level) {
1218         case CE_NOTE:
1219                 level = CE_CONT;
1220                 /* FALLTHROUGH */
1221         case CE_CONT:
1222         case CE_WARN:
1223         case CE_PANIC:
1224                 if (boot_only) {
1225                         cmn_err(level, "?%s%s", name, &scsi_log_buffer[1]);
1226                 } else if (console_only) {
1227                         cmn_err(level, "^%s%s", name, &scsi_log_buffer[1]);
1228                 } else if (log_only) {
1229                         cmn_err(level, "!%s%s", name, &scsi_log_buffer[1]);
1230                 } else {
1231                         cmn_err(level, "%s%s", name, scsi_log_buffer);
1232                 }
1233                 break;
1234         case (uint_t)SCSI_DEBUG:
1235         default:
1236                 cmn_err(CE_CONT, "?DEBUG: %s%s", name, scsi_log_buffer);
1237                 break;
1238         }
1239 }
1240 
1241 /*
1242  * Lookup the 'prop_name' string array property and walk thru its list of
1243  * tuple values looking for a tuple who's VID/PID string (first part of tuple)
1244  * matches the inquiry VID/PID information for the scsi_device.  On a match,
1245  * return a duplicate of the second part of the tuple.  If no match is found,
1246  * return NULL. On non-NULL return, caller is responsible for freeing return
1247  * result via:
1248  *      kmem_free(string, strlen(string) + 1);
1249  *
1250  * This interface can either be used directly, or indirectly by
1251  * scsi_get_device_type_scsi_options.
1252  */
1253 char    *
1254 scsi_get_device_type_string(char *prop_name,
1255     dev_info_t *dip, struct scsi_device *devp)
1256 {