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 2008 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/types.h>
30 #include <sys/scsi/generic/sense.h>
31 #include <sys/scsi/generic/status.h>
32
33 #include <stddef.h>
34 #include <stdio.h>
35
36 #include <scsi/libscsi.h>
37 #include "libscsi_impl.h"
38
39 typedef struct slist {
40 char *str;
41 int value;
42 } slist_t;
43
44 static slist_t sensekey_strings[] = {
45 { "No sense error", KEY_NO_SENSE },
46 { "Recoverable error", KEY_RECOVERABLE_ERROR },
47 { "Not ready error", KEY_NOT_READY },
48 { "Medium error", KEY_MEDIUM_ERROR },
49 { "Hardware error", KEY_HARDWARE_ERROR },
50 { "Illegal request", KEY_ILLEGAL_REQUEST },
51 { "Unit attention error", KEY_UNIT_ATTENTION },
52 { "Write protect error", KEY_WRITE_PROTECT },
53 { "Blank check error", KEY_BLANK_CHECK },
54 { "Vendor unique error", KEY_VENDOR_UNIQUE },
55 { "Copy aborted error", KEY_COPY_ABORTED },
56 { "Aborted command", KEY_ABORTED_COMMAND },
57 { "Equal error", KEY_EQUAL },
58 { "Volume overflow", KEY_VOLUME_OVERFLOW },
59 { "Miscompare error", KEY_MISCOMPARE },
60 { "Reserved error", KEY_RESERVED },
61 { NULL, 0 }
62 };
63
64 static struct asq_key_strings {
65 uint_t asc;
66 uint_t ascq;
67 const char *message;
68 } extended_sense_list[] = {
69 { 0x00, 0x00, "no additional sense info" },
70 { 0x00, 0x01, "filemark detected" },
71 { 0x00, 0x02, "end of partition/medium detected" },
72 { 0x00, 0x03, "setmark detected" },
73 { 0x00, 0x04, "begining of partition/medium detected" },
74 { 0x00, 0x05, "end of data detected" },
75 { 0x00, 0x06, "i/o process terminated" },
76 { 0x00, 0x11, "audio play operation in progress" },
77 { 0x00, 0x12, "audio play operation paused" },
78 { 0x00, 0x13, "audio play operation successfully completed" },
79 { 0x00, 0x14, "audio play operation stopped due to error" },
80 { 0x00, 0x15, "no current audio status to return" },
81 { 0x00, 0x16, "operation in progress" },
82 { 0x00, 0x17, "cleaning requested" },
83 { 0x00, 0x18, "erase operation in progress" },
84 { 0x00, 0x19, "locate operation in progress" },
85 { 0x00, 0x1A, "rewind operation in progress" },
86 { 0x00, 0x1B, "set capacity operation in progress" },
87 { 0x00, 0x1C, "verify operation in progress" },
88 { 0x01, 0x00, "no index/sector signal" },
89 { 0x02, 0x00, "no seek complete" },
90 { 0x03, 0x00, "peripheral device write fault" },
91 { 0x03, 0x01, "no write current" },
92 { 0x03, 0x02, "excessive write errors" },
93 { 0x04, 0x00, "LUN not ready" },
94 { 0x04, 0x01, "LUN is becoming ready" },
95 { 0x04, 0x02, "LUN initializing command required" },
96 { 0x04, 0x03, "LUN not ready intervention required" },
97 { 0x04, 0x04, "LUN not ready format in progress" },
98 { 0x04, 0x05, "LUN not ready, rebuild in progress" },
99 { 0x04, 0x06, "LUN not ready, recalculation in progress" },
100 { 0x04, 0x07, "LUN not ready, operation in progress" },
101 { 0x04, 0x08, "LUN not ready, long write in progress" },
102 { 0x04, 0x09, "LUN not ready, self-test in progress" },
103 { 0x04, 0x0A, "LUN not accessible, asymmetric access state "
104 "transition" },
105 { 0x04, 0x0B, "LUN not accessible, target port in standby state" },
106 { 0x04, 0x0C, "LUN not accessible, target port in unavailable state" },
107 { 0x04, 0x10, "LUN not ready, auxiliary memory not accessible" },
108 { 0x05, 0x00, "LUN does not respond to selection" },
109 { 0x06, 0x00, "reference position found" },
110 { 0x07, 0x00, "multiple peripheral devices selected" },
111 { 0x08, 0x00, "LUN communication failure" },
112 { 0x08, 0x01, "LUN communication time-out" },
113 { 0x08, 0x02, "LUN communication parity error" },
114 { 0x08, 0x03, "LUN communication crc error (ultra-DMA/32)" },
115 { 0x08, 0x04, "unreachable copy target" },
116 { 0x09, 0x00, "track following error" },
117 { 0x09, 0x01, "tracking servo failure" },
118 { 0x09, 0x02, "focus servo failure" },
119 { 0x09, 0x03, "spindle servo failure" },
120 { 0x09, 0x04, "head select fault" },
121 { 0x0a, 0x00, "error log overflow" },
122 { 0x0b, 0x00, "warning" },
123 { 0x0b, 0x01, "warning - specified temperature exceeded" },
124 { 0x0b, 0x02, "warning - enclosure degraded" },
125 { 0x0c, 0x00, "write error" },
126 { 0x0c, 0x01, "write error - recovered with auto reallocation" },
127 { 0x0c, 0x02, "write error - auto reallocation failed" },
128 { 0x0c, 0x03, "write error - recommend reassignment" },
129 { 0x0c, 0x04, "compression check miscompare error" },
130 { 0x0c, 0x05, "data expansion occurred during compression" },
131 { 0x0c, 0x06, "block not compressible" },
132 { 0x0c, 0x07, "write error - recovery needed" },
133 { 0x0c, 0x08, "write error - recovery failed" },
134 { 0x0c, 0x09, "write error - loss of streaming" },
135 { 0x0c, 0x0a, "write error - padding blocks added" },
136 { 0x0c, 0x0b, "auxiliary memory write error" },
137 { 0x0c, 0x0c, "write error - unexpected unsolicited data" },
138 { 0x0c, 0x0d, "write error - not enough unsolicited data" },
139 { 0x0d, 0x00, "error detected by third party temporary initiator" },
140 { 0x0d, 0x01, "third party device failure" },
141 { 0x0d, 0x02, "copy target device not reachable" },
142 { 0x0d, 0x03, "incorrect copy target device type" },
143 { 0x0d, 0x04, "copy target device data underrun" },
144 { 0x0d, 0x05, "copy target device data overrun" },
145 { 0x0e, 0x00, "invalid information unit" },
146 { 0x0e, 0x01, "information unit too short" },
147 { 0x0e, 0x02, "information unit too long" },
148 { 0x10, 0x00, "ID CRC or ECC error" },
149 { 0x11, 0x00, "unrecovered read error" },
150 { 0x11, 0x01, "read retries exhausted" },
151 { 0x11, 0x02, "error too long to correct" },
152 { 0x11, 0x03, "multiple read errors" },
153 { 0x11, 0x04, "unrecovered read error - auto reallocate failed" },
154 { 0x11, 0x05, "L-EC uncorrectable error" },
155 { 0x11, 0x06, "CIRC unrecovered error" },
156 { 0x11, 0x07, "data re-synchronization error" },
157 { 0x11, 0x08, "incomplete block read" },
158 { 0x11, 0x09, "no gap found" },
159 { 0x11, 0x0a, "miscorrected error" },
160 { 0x11, 0x0b, "unrecovered read error - recommend reassignment" },
161 { 0x11, 0x0c, "unrecovered read error - recommend rewrite the data" },
162 { 0x11, 0x0d, "de-compression crc error" },
163 { 0x11, 0x0e, "cannot decompress using declared algorithm" },
164 { 0x11, 0x0f, "error reading UPC/EAN number" },
165 { 0x11, 0x10, "error reading ISRC number" },
166 { 0x11, 0x11, "read error - loss of streaming" },
167 { 0x11, 0x12, "auxiliary memory read error" },
168 { 0x11, 0x13, "read error - failed retransmission request" },
169 { 0x12, 0x00, "address mark not found for ID field" },
170 { 0x13, 0x00, "address mark not found for data field" },
171 { 0x14, 0x00, "recorded entity not found" },
172 { 0x14, 0x01, "record not found" },
173 { 0x14, 0x02, "filemark or setmark not found" },
174 { 0x14, 0x03, "end-of-data not found" },
175 { 0x14, 0x04, "block sequence error" },
176 { 0x14, 0x05, "record not found - recommend reassignment" },
177 { 0x14, 0x06, "record not found - data auto-reallocated" },
178 { 0x14, 0x07, "locate operation failure" },
179 { 0x15, 0x00, "random positioning error" },
180 { 0x15, 0x01, "mechanical positioning error" },
181 { 0x15, 0x02, "positioning error detected by read of medium" },
182 { 0x16, 0x00, "data sync mark error" },
183 { 0x16, 0x01, "data sync error - data rewritten" },
184 { 0x16, 0x02, "data sync error - recommend rewrite" },
185 { 0x16, 0x03, "data sync error - data auto-reallocated" },
186 { 0x16, 0x04, "data sync error - recommend reassignment" },
187 { 0x17, 0x00, "recovered data with no error correction" },
188 { 0x17, 0x01, "recovered data with retries" },
189 { 0x17, 0x02, "recovered data with positive head offset" },
190 { 0x17, 0x03, "recovered data with negative head offset" },
191 { 0x17, 0x04, "recovered data with retries and/or CIRC applied" },
192 { 0x17, 0x05, "recovered data using previous sector id" },
193 { 0x17, 0x06, "recovered data without ECC - data auto-reallocated" },
194 { 0x17, 0x07, "recovered data without ECC - recommend reassignment" },
195 { 0x17, 0x08, "recovered data without ECC - recommend rewrite" },
196 { 0x17, 0x09, "recovered data without ECC - data rewritten" },
197 { 0x18, 0x00, "recovered data with error correction" },
198 { 0x18, 0x01, "recovered data with error corr. & retries applied" },
199 { 0x18, 0x02, "recovered data - data auto-reallocated" },
200 { 0x18, 0x03, "recovered data with CIRC" },
201 { 0x18, 0x04, "recovered data with L-EC" },
202 { 0x18, 0x05, "recovered data - recommend reassignment" },
203 { 0x18, 0x06, "recovered data - recommend rewrite" },
204 { 0x18, 0x07, "recovered data with ECC - data rewritten" },
205 { 0x18, 0x08, "recovered data with linking" },
206 { 0x19, 0x00, "defect list error" },
207 { 0x1a, 0x00, "parameter list length error" },
208 { 0x1b, 0x00, "synchronous data xfer error" },
209 { 0x1c, 0x00, "defect list not found" },
210 { 0x1c, 0x01, "primary defect list not found" },
211 { 0x1c, 0x02, "grown defect list not found" },
212 { 0x1d, 0x00, "miscompare during verify" },
213 { 0x1e, 0x00, "recovered ID with ECC" },
214 { 0x1f, 0x00, "partial defect list transfer" },
215 { 0x20, 0x00, "invalid command operation code" },
216 { 0x20, 0x01, "access denied - initiator pending-enrolled" },
217 { 0x20, 0x02, "access denied - no access rights" },
218 { 0x20, 0x03, "access denied - invalid mgmt id key" },
219 { 0x20, 0x04, "illegal command while in write capable state" },
220 { 0x20, 0x06, "illegal command while in explicit address mode" },
221 { 0x20, 0x07, "illegal command while in implicit address mode" },
222 { 0x20, 0x08, "access denied - enrollment conflict" },
223 { 0x20, 0x09, "access denied - invalid lu identifier" },
224 { 0x20, 0x0a, "access denied - invalid proxy token" },
225 { 0x20, 0x0b, "access denied - ACL LUN conflict" },
226 { 0x21, 0x00, "logical block address out of range" },
227 { 0x21, 0x01, "invalid element address" },
228 { 0x21, 0x02, "invalid address for write" },
229 { 0x22, 0x00, "illegal function" },
230 { 0x24, 0x00, "invalid field in cdb" },
231 { 0x24, 0x01, "cdb decryption error" },
232 { 0x25, 0x00, "LUN not supported" },
233 { 0x26, 0x00, "invalid field in param list" },
234 { 0x26, 0x01, "parameter not supported" },
235 { 0x26, 0x02, "parameter value invalid" },
236 { 0x26, 0x03, "threshold parameters not supported" },
237 { 0x26, 0x04, "invalid release of persistent reservation" },
238 { 0x26, 0x05, "data decryption error" },
239 { 0x26, 0x06, "too many target descriptors" },
240 { 0x26, 0x07, "unsupported target descriptor type code" },
241 { 0x26, 0x08, "too many segment descriptors" },
242 { 0x26, 0x09, "unsupported segment descriptor type code" },
243 { 0x26, 0x0a, "unexpected inexact segment" },
244 { 0x26, 0x0b, "inline data length exceeded" },
245 { 0x26, 0x0c, "invalid operation for copy source or destination" },
246 { 0x26, 0x0d, "copy segment granularity violation" },
247 { 0x27, 0x00, "write protected" },
248 { 0x27, 0x01, "hardware write protected" },
249 { 0x27, 0x02, "LUN software write protected" },
250 { 0x27, 0x03, "associated write protect" },
251 { 0x27, 0x04, "persistent write protect" },
252 { 0x27, 0x05, "permanent write protect" },
253 { 0x27, 0x06, "conditional write protect" },
254 { 0x28, 0x00, "medium may have changed" },
255 { 0x28, 0x01, "import or export element accessed" },
256 { 0x29, 0x00, "power on, reset, or bus reset occurred" },
257 { 0x29, 0x01, "power on occurred" },
258 { 0x29, 0x02, "scsi bus reset occurred" },
259 { 0x29, 0x03, "bus device reset message occurred" },
260 { 0x29, 0x04, "device internal reset" },
261 { 0x29, 0x05, "transceiver mode changed to single-ended" },
262 { 0x29, 0x06, "transceiver mode changed to LVD" },
263 { 0x29, 0x07, "i_t nexus loss occurred" },
264 { 0x2a, 0x00, "parameters changed" },
265 { 0x2a, 0x01, "mode parameters changed" },
266 { 0x2a, 0x02, "log parameters changed" },
267 { 0x2a, 0x03, "reservations preempted" },
268 { 0x2a, 0x04, "reservations released" },
269 { 0x2a, 0x05, "registrations preempted" },
270 { 0x2a, 0x06, "asymmetric access state changed" },
271 { 0x2a, 0x07, "implicit asymmetric access state transition failed" },
272 { 0x2b, 0x00, "copy cannot execute since host cannot disconnect" },
273 { 0x2c, 0x00, "command sequence error" },
274 { 0x2c, 0x03, "current program area is not empty" },
275 { 0x2c, 0x04, "current program area is empty" },
276 { 0x2c, 0x06, "persistent prevent conflict" },
277 { 0x2c, 0x07, "previous busy status" },
278 { 0x2c, 0x08, "previous task set full status" },
279 { 0x2c, 0x09, "previous reservation conflict status" },
280 { 0x2d, 0x00, "overwrite error on update in place" },
281 { 0x2e, 0x00, "insufficient time for operation" },
282 { 0x2f, 0x00, "commands cleared by another initiator" },
283 { 0x30, 0x00, "incompatible medium installed" },
284 { 0x30, 0x01, "cannot read medium - unknown format" },
285 { 0x30, 0x02, "cannot read medium - incompatible format" },
286 { 0x30, 0x03, "cleaning cartridge installed" },
287 { 0x30, 0x04, "cannot write medium - unknown format" },
288 { 0x30, 0x05, "cannot write medium - incompatible format" },
289 { 0x30, 0x06, "cannot format medium - incompatible medium" },
290 { 0x30, 0x07, "cleaning failure" },
291 { 0x30, 0x08, "cannot write - application code mismatch" },
292 { 0x30, 0x09, "current session not fixated for append" },
293 { 0x30, 0x10, "medium not formatted" },
294 { 0x31, 0x00, "medium format corrupted" },
295 { 0x31, 0x01, "format command failed" },
296 { 0x31, 0x02, "zoned formatting failed due to spare linking" },
297 { 0x32, 0x00, "no defect spare location available" },
298 { 0x32, 0x01, "defect list update failure" },
299 { 0x33, 0x00, "tape length error" },
300 { 0x34, 0x00, "enclosure failure" },
301 { 0x35, 0x00, "enclosure services failure" },
302 { 0x35, 0x01, "unsupported enclosure function" },
303 { 0x35, 0x02, "enclosure services unavailable" },
304 { 0x35, 0x03, "enclosure services transfer failure" },
305 { 0x35, 0x04, "enclosure services transfer refused" },
306 { 0x36, 0x00, "ribbon, ink, or toner failure" },
307 { 0x37, 0x00, "rounded parameter" },
308 { 0x39, 0x00, "saving parameters not supported" },
309 { 0x3a, 0x00, "medium not present" },
310 { 0x3a, 0x01, "medium not present - tray closed" },
311 { 0x3a, 0x02, "medium not present - tray open" },
312 { 0x3a, 0x03, "medium not present - loadable" },
313 { 0x3a, 0x04, "medium not present - medium auxiliary memory "
314 "accessible" },
315 { 0x3b, 0x00, "sequential positioning error" },
316 { 0x3b, 0x01, "tape position error at beginning-of-medium" },
317 { 0x3b, 0x02, "tape position error at end-of-medium" },
318 { 0x3b, 0x08, "reposition error" },
319 { 0x3b, 0x0c, "position past beginning of medium" },
320 { 0x3b, 0x0d, "medium destination element full" },
321 { 0x3b, 0x0e, "medium source element empty" },
322 { 0x3b, 0x0f, "end of medium reached" },
323 { 0x3b, 0x11, "medium magazine not accessible" },
324 { 0x3b, 0x12, "medium magazine removed" },
325 { 0x3b, 0x13, "medium magazine inserted" },
326 { 0x3b, 0x14, "medium magazine locked" },
327 { 0x3b, 0x15, "medium magazine unlocked" },
328 { 0x3b, 0x16, "mechanical positioning or changer error" },
329 { 0x3d, 0x00, "invalid bits in indentify message" },
330 { 0x3e, 0x00, "LUN has not self-configured yet" },
331 { 0x3e, 0x01, "LUN failure" },
332 { 0x3e, 0x02, "timeout on LUN" },
333 { 0x3e, 0x03, "LUN failed self-test" },
334 { 0x3e, 0x04, "LUN unable to update self-test log" },
335 { 0x3f, 0x00, "target operating conditions have changed" },
336 { 0x3f, 0x01, "microcode has been changed" },
337 { 0x3f, 0x02, "changed operating definition" },
338 { 0x3f, 0x03, "inquiry data has changed" },
339 { 0x3f, 0x04, "component device attached" },
340 { 0x3f, 0x05, "device identifier changed" },
341 { 0x3f, 0x06, "redundancy group created or modified" },
342 { 0x3f, 0x07, "redundancy group deleted" },
343 { 0x3f, 0x08, "spare created or modified" },
344 { 0x3f, 0x09, "spare deleted" },
345 { 0x3f, 0x0a, "volume set created or modified" },
346 { 0x3f, 0x0b, "volume set deleted" },
347 { 0x3f, 0x0c, "volume set deassigned" },
348 { 0x3f, 0x0d, "volume set reassigned" },
349 { 0x3f, 0x0e, "reported LUNs data has changed" },
350 { 0x3f, 0x0f, "echo buffer overwritten" },
351 { 0x3f, 0x10, "medium loadable" },
352 { 0x3f, 0x11, "medium auxiliary memory accessible" },
353 { 0x40, 0x00, "ram failure" },
354 { 0x41, 0x00, "data path failure" },
355 { 0x42, 0x00, "power-on or self-test failure" },
356 { 0x43, 0x00, "message error" },
357 { 0x44, 0x00, "internal target failure" },
358 { 0x45, 0x00, "select or reselect failure" },
359 { 0x46, 0x00, "unsuccessful soft reset" },
360 { 0x47, 0x00, "scsi parity error" },
361 { 0x47, 0x01, "data phase crc error detected" },
362 { 0x47, 0x02, "scsi parity error detected during st data phase" },
363 { 0x47, 0x03, "information unit iucrc error detected" },
364 { 0x47, 0x04, "asynchronous information protection error detected" },
365 { 0x47, 0x05, "protocol service crc error" },
366 { 0x47, 0x7f, "some commands cleared by iscsi protocol event" },
367 { 0x48, 0x00, "initiator detected error message received" },
368 { 0x49, 0x00, "invalid message error" },
369 { 0x4a, 0x00, "command phase error" },
370 { 0x4b, 0x00, "data phase error" },
371 { 0x4b, 0x01, "invalid target port transfer tag received" },
372 { 0x4b, 0x02, "too much write data" },
373 { 0x4b, 0x03, "ack/nak timeout" },
374 { 0x4b, 0x04, "nak received" },
375 { 0x4b, 0x05, "data offset error" },
376 { 0x4c, 0x00, "logical unit failed self-configuration" },
377 { 0x4d, 0x00, "tagged overlapped commands (ASCQ = queue tag)" },
378 { 0x4e, 0x00, "overlapped commands attempted" },
379 { 0x50, 0x00, "write append error" },
380 { 0x51, 0x00, "erase failure" },
381 { 0x52, 0x00, "cartridge fault" },
382 { 0x53, 0x00, "media load or eject failed" },
383 { 0x53, 0x01, "unload tape failure" },
384 { 0x53, 0x02, "medium removal prevented" },
385 { 0x54, 0x00, "scsi to host system interface failure" },
386 { 0x55, 0x00, "system resource failure" },
387 { 0x55, 0x01, "system buffer full" },
388 { 0x55, 0x02, "insufficient reservation resources" },
389 { 0x55, 0x03, "insufficient resources" },
390 { 0x55, 0x04, "insufficient registration resources" },
391 { 0x55, 0x05, "insufficient access control resources" },
392 { 0x55, 0x06, "auxiliary memory out of space" },
393 { 0x57, 0x00, "unable to recover TOC" },
394 { 0x58, 0x00, "generation does not exist" },
395 { 0x59, 0x00, "updated block read" },
396 { 0x5a, 0x00, "operator request or state change input" },
397 { 0x5a, 0x01, "operator medium removal request" },
398 { 0x5a, 0x02, "operator selected write protect" },
399 { 0x5a, 0x03, "operator selected write permit" },
400 { 0x5b, 0x00, "log exception" },
401 { 0x5b, 0x01, "threshold condition met" },
402 { 0x5b, 0x02, "log counter at maximum" },
403 { 0x5b, 0x03, "log list codes exhausted" },
404 { 0x5c, 0x00, "RPL status change" },
405 { 0x5c, 0x01, "spindles synchronized" },
406 { 0x5c, 0x02, "spindles not synchronized" },
407 { 0x5d, 0x00, "drive operation marginal, service immediately"
408 " (failure prediction threshold exceeded)" },
409 { 0x5d, 0x01, "media failure prediction threshold exceeded" },
410 { 0x5d, 0x02, "LUN failure prediction threshold exceeded" },
411 { 0x5d, 0x03, "spare area exhaustion prediction threshold exceeded" },
412 { 0x5d, 0x10, "hardware impending failure general hard drive failure" },
413 { 0x5d, 0x11, "hardware impending failure drive error rate too high" },
414 { 0x5d, 0x12, "hardware impending failure data error rate too high" },
415 { 0x5d, 0x13, "hardware impending failure seek error rate too high" },
416 { 0x5d, 0x14, "hardware impending failure too many block reassigns" },
417 { 0x5d, 0x15, "hardware impending failure access times too high" },
418 { 0x5d, 0x16, "hardware impending failure start unit times too high" },
419 { 0x5d, 0x17, "hardware impending failure channel parametrics" },
420 { 0x5d, 0x18, "hardware impending failure controller detected" },
421 { 0x5d, 0x19, "hardware impending failure throughput performance" },
422 { 0x5d, 0x1a, "hardware impending failure seek time performance" },
423 { 0x5d, 0x1b, "hardware impending failure spin-up retry count" },
424 { 0x5d, 0x1c, "hardware impending failure drive calibration retry "
425 "count" },
426 { 0x5d, 0x20, "controller impending failure general hard drive "
427 "failure" },
428 { 0x5d, 0x21, "controller impending failure drive error rate too "
429 "high" },
430 { 0x5d, 0x22, "controller impending failure data error rate too high" },
431 { 0x5d, 0x23, "controller impending failure seek error rate too high" },
432 { 0x5d, 0x24, "controller impending failure too many block reassigns" },
433 { 0x5d, 0x25, "controller impending failure access times too high" },
434 { 0x5d, 0x26, "controller impending failure start unit times too "
435 "high" },
436 { 0x5d, 0x27, "controller impending failure channel parametrics" },
437 { 0x5d, 0x28, "controller impending failure controller detected" },
438 { 0x5d, 0x29, "controller impending failure throughput performance" },
439 { 0x5d, 0x2a, "controller impending failure seek time performance" },
440 { 0x5d, 0x2b, "controller impending failure spin-up retry count" },
441 { 0x5d, 0x2c, "controller impending failure drive calibration retry "
442 "cnt" },
443 { 0x5d, 0x30, "data channel impending failure general hard drive "
444 "failure" },
445 { 0x5d, 0x31, "data channel impending failure drive error rate too "
446 "high" },
447 { 0x5d, 0x32, "data channel impending failure data error rate too "
448 "high" },
449 { 0x5d, 0x33, "data channel impending failure seek error rate too "
450 "high" },
451 { 0x5d, 0x34, "data channel impending failure too many block "
452 "reassigns" },
453 { 0x5d, 0x35, "data channel impending failure access times too high" },
454 { 0x5d, 0x36, "data channel impending failure start unit times too "
455 "high" },
456 { 0x5d, 0x37, "data channel impending failure channel parametrics" },
457 { 0x5d, 0x38, "data channel impending failure controller detected" },
458 { 0x5d, 0x39, "data channel impending failure throughput performance" },
459 { 0x5d, 0x3a, "data channel impending failure seek time performance" },
460 { 0x5d, 0x3b, "data channel impending failure spin-up retry count" },
461 { 0x5d, 0x3c, "data channel impending failure drive calibrate retry "
462 "cnt" },
463 { 0x5d, 0x40, "servo impending failure general hard drive failure" },
464 { 0x5d, 0x41, "servo impending failure drive error rate too high" },
465 { 0x5d, 0x42, "servo impending failure data error rate too high" },
466 { 0x5d, 0x43, "servo impending failure seek error rate too high" },
467 { 0x5d, 0x44, "servo impending failure too many block reassigns" },
468 { 0x5d, 0x45, "servo impending failure access times too high" },
469 { 0x5d, 0x46, "servo impending failure start unit times too high" },
470 { 0x5d, 0x47, "servo impending failure channel parametrics" },
471 { 0x5d, 0x48, "servo impending failure controller detected" },
472 { 0x5d, 0x49, "servo impending failure throughput performance" },
473 { 0x5d, 0x4a, "servo impending failure seek time performance" },
474 { 0x5d, 0x4b, "servo impending failure spin-up retry count" },
475 { 0x5d, 0x4c, "servo impending failure drive calibration retry count" },
476 { 0x5d, 0x50, "spindle impending failure general hard drive failure" },
477 { 0x5d, 0x51, "spindle impending failure drive error rate too high" },
478 { 0x5d, 0x52, "spindle impending failure data error rate too high" },
479 { 0x5d, 0x53, "spindle impending failure seek error rate too high" },
480 { 0x5d, 0x54, "spindle impending failure too many block reassigns" },
481 { 0x5d, 0x55, "spindle impending failure access times too high" },
482 { 0x5d, 0x56, "spindle impending failure start unit times too high" },
483 { 0x5d, 0x57, "spindle impending failure channel parametrics" },
484 { 0x5d, 0x58, "spindle impending failure controller detected" },
485 { 0x5d, 0x59, "spindle impending failure throughput performance" },
486 { 0x5d, 0x5a, "spindle impending failure seek time performance" },
487 { 0x5d, 0x5b, "spindle impending failure spin-up retry count" },
488 { 0x5d, 0x5c, "spindle impending failure drive calibration retry "
489 "count" },
490 { 0x5d, 0x60, "firmware impending failure general hard drive failure" },
491 { 0x5d, 0x61, "firmware impending failure drive error rate too high" },
492 { 0x5d, 0x62, "firmware impending failure data error rate too high" },
493 { 0x5d, 0x63, "firmware impending failure seek error rate too high" },
494 { 0x5d, 0x64, "firmware impending failure too many block reassigns" },
495 { 0x5d, 0x65, "firmware impending failure access times too high" },
496 { 0x5d, 0x66, "firmware impending failure start unit times too high" },
497 { 0x5d, 0x67, "firmware impending failure channel parametrics" },
498 { 0x5d, 0x68, "firmware impending failure controller detected" },
499 { 0x5d, 0x69, "firmware impending failure throughput performance" },
500 { 0x5d, 0x6a, "firmware impending failure seek time performance" },
501 { 0x5d, 0x6b, "firmware impending failure spin-up retry count" },
502 { 0x5d, 0x6c, "firmware impending failure drive calibration retry "
503 "count" },
504 { 0x5d, 0xff, "failure prediction threshold exceeded (false)" },
505 { 0x5e, 0x00, "low power condition active" },
506 { 0x5e, 0x01, "idle condition activated by timer" },
507 { 0x5e, 0x02, "standby condition activated by timer" },
508 { 0x5e, 0x03, "idle condition activated by command" },
509 { 0x5e, 0x04, "standby condition activated by command" },
510 { 0x60, 0x00, "lamp failure" },
511 { 0x61, 0x00, "video aquisition error" },
512 { 0x62, 0x00, "scan head positioning error" },
513 { 0x63, 0x00, "end of user area encountered on this track" },
514 { 0x63, 0x01, "packet does not fit in available space" },
515 { 0x64, 0x00, "illegal mode for this track" },
516 { 0x64, 0x01, "invalid packet size" },
517 { 0x65, 0x00, "voltage fault" },
518 { 0x66, 0x00, "automatic document feeder cover up" },
519 { 0x67, 0x00, "configuration failure" },
520 { 0x67, 0x01, "configuration of incapable LUNs failed" },
521 { 0x67, 0x02, "add LUN failed" },
522 { 0x67, 0x03, "modification of LUN failed" },
523 { 0x67, 0x04, "exchange of LUN failed" },
524 { 0x67, 0x05, "remove of LUN failed" },
525 { 0x67, 0x06, "attachment of LUN failed" },
526 { 0x67, 0x07, "creation of LUN failed" },
527 { 0x67, 0x08, "assign failure occurred" },
528 { 0x67, 0x09, "multiply assigned LUN" },
529 { 0x67, 0x0a, "set target port groups command failed" },
530 { 0x68, 0x00, "logical unit not configured" },
531 { 0x69, 0x00, "data loss on logical unit" },
532 { 0x69, 0x01, "multiple LUN failures" },
533 { 0x69, 0x02, "parity/data mismatch" },
534 { 0x6a, 0x00, "informational, refer to log" },
535 { 0x6b, 0x00, "state change has occured" },
536 { 0x6b, 0x01, "redundancy level got better" },
537 { 0x6b, 0x02, "redundancy level got worse" },
538 { 0x6c, 0x00, "rebuild failure occured" },
539 { 0x6d, 0x00, "recalculate failure occured" },
540 { 0x6e, 0x00, "command to logical unit failed" },
541 { 0x6f, 0x00, "copy protect key exchange failure authentication "
542 "failure" },
543 { 0x6f, 0x01, "copy protect key exchange failure key not present" },
544 { 0x6f, 0x02, "copy protect key exchange failure key not established" },
545 { 0x6f, 0x03, "read of scrambled sector without authentication" },
546 { 0x6f, 0x04, "media region code is mismatched to LUN region" },
547 { 0x6f, 0x05, "drive region must be permanent/region reset count "
548 "error" },
549 { 0x70, 0xffff, "decompression exception short algorithm id of ASCQ" },
550 { 0x71, 0x00, "decompression exception long algorithm id" },
551 { 0x72, 0x00, "session fixation error" },
552 { 0x72, 0x01, "session fixation error writing lead-in" },
553 { 0x72, 0x02, "session fixation error writing lead-out" },
554 { 0x72, 0x03, "session fixation error - incomplete track in session" },
555 { 0x72, 0x04, "empty or partially written reserved track" },
556 { 0x72, 0x05, "no more track reservations allowed" },
557 { 0x73, 0x00, "cd control error" },
558 { 0x73, 0x01, "power calibration area almost full" },
559 { 0x73, 0x02, "power calibration area is full" },
560 { 0x73, 0x03, "power calibration area error" },
561 { 0x73, 0x04, "program memory area update failure" },
562 { 0x73, 0x05, "program memory area is full" },
563 { 0x73, 0x06, "rma/pma is almost full" },
564 { 0xffff, 0xffff, NULL }
565 };
566
567 static const char *
find_string(slist_t * slist,int match_value)568 find_string(slist_t *slist, int match_value)
569 {
570 for (; slist->str != NULL; slist++) {
571 if (slist->value == match_value) {
572 return (slist->str);
573 }
574 }
575
576 return (NULL);
577 }
578
579 const char *
libscsi_sense_key_name(uint64_t key)580 libscsi_sense_key_name(uint64_t key)
581 {
582 return (find_string(sensekey_strings, (int)key));
583 }
584
585 /*
586 * Given an asc (Additional Sense Code) and ascq (Additional Sense Code
587 * Qualifier), return a string describing the error information.
588 */
589 const char *
libscsi_sense_code_name(uint64_t asc,uint64_t ascq)590 libscsi_sense_code_name(uint64_t asc, uint64_t ascq)
591 {
592 int i = 0;
593
594 while (extended_sense_list[i].asc != 0xffff) {
595 if ((asc == extended_sense_list[i].asc) &&
596 ((ascq == extended_sense_list[i].ascq) ||
597 (extended_sense_list[i].ascq == 0xffff))) {
598 return ((char *)extended_sense_list[i].message);
599 }
600 i++;
601 }
602
603 return (NULL);
604 }
605
606 /*
607 * Retrieve "information" field from descriptor format sense data. Iterates
608 * through each sense descriptor looking for the information descriptor and
609 * returns the information field from that descriptor.
610 */
611 static diskaddr_t
scsi_extract_sense_info_descr(struct scsi_descr_sense_hdr * sdsp,size_t len)612 scsi_extract_sense_info_descr(struct scsi_descr_sense_hdr *sdsp, size_t len)
613 {
614 diskaddr_t result;
615 uint8_t *descr_offset;
616 size_t valid_sense_length;
617 struct scsi_information_sense_descr *isd;
618
619 /*
620 * Initialize result to -1 indicating there is no information
621 * descriptor
622 */
623 result = (diskaddr_t)-1;
624
625 /*
626 * The first descriptor will immediately follow the header
627 */
628 descr_offset = (uint8_t *)(sdsp+1);
629
630 /*
631 * Calculate the amount of valid sense data
632 */
633 valid_sense_length =
634 MIN((sizeof (struct scsi_descr_sense_hdr) +
635 sdsp->ds_addl_sense_length), len);
636
637 /*
638 * Iterate through the list of descriptors, stopping when we run out of
639 * sense data
640 */
641 while ((descr_offset + sizeof (struct scsi_information_sense_descr)) <=
642 (uint8_t *)sdsp + valid_sense_length) {
643 /*
644 * Check if this is an information descriptor. We can use the
645 * scsi_information_sense_descr structure as a template since
646 * the first two fields are always the same
647 */
648 isd = (struct scsi_information_sense_descr *)descr_offset;
649 if (isd->isd_descr_type == DESCR_INFORMATION) {
650 /*
651 * Found an information descriptor. Copy the
652 * information field. There will only be one
653 * information descriptor so we can stop looking.
654 */
655 result =
656 (((diskaddr_t)isd->isd_information[0] << 56) |
657 ((diskaddr_t)isd->isd_information[1] << 48) |
658 ((diskaddr_t)isd->isd_information[2] << 40) |
659 ((diskaddr_t)isd->isd_information[3] << 32) |
660 ((diskaddr_t)isd->isd_information[4] << 24) |
661 ((diskaddr_t)isd->isd_information[5] << 16) |
662 ((diskaddr_t)isd->isd_information[6] << 8) |
663 ((diskaddr_t)isd->isd_information[7]));
664 break;
665 }
666
667 /*
668 * Get pointer to the next descriptor. The "additional length"
669 * field holds the length of the descriptor except for the
670 * "type" and "additional length" fields, so we need to add 2 to
671 * get the total length.
672 */
673 descr_offset += (isd->isd_addl_length + 2);
674 }
675
676 return (result);
677 }
678
679 int
libscsi_action_parse_sense(const libscsi_action_t * ap,uint64_t * keyp,uint64_t * ascp,uint64_t * ascqp,diskaddr_t * blkp)680 libscsi_action_parse_sense(const libscsi_action_t *ap, uint64_t *keyp,
681 uint64_t *ascp, uint64_t *ascqp, diskaddr_t *blkp)
682 {
683 struct scsi_extended_sense *xsp;
684 struct scsi_descr_sense_hdr *sdsp;
685 size_t len;
686
687 if (libscsi_action_get_sense(ap, (uint8_t **)&xsp, NULL, &len) != 0)
688 return (-1);
689
690 sdsp = (struct scsi_descr_sense_hdr *)xsp;
691
692 if (keyp != NULL)
693 *keyp = (uint64_t)xsp->es_key;
694
695 switch (xsp->es_code) {
696 case CODE_FMT_DESCR_CURRENT:
697 case CODE_FMT_DESCR_DEFERRED:
698 if (blkp != NULL)
699 *blkp = (diskaddr_t)
700 scsi_extract_sense_info_descr(sdsp, len);
701 if (ascp != NULL)
702 *ascp = (uint64_t)sdsp->ds_add_code;
703 if (ascqp != NULL)
704 *ascqp = (uint64_t)sdsp->ds_qual_code;
705 break;
706 case CODE_FMT_FIXED_CURRENT:
707 case CODE_FMT_FIXED_DEFERRED:
708 default:
709 if (xsp->es_valid && blkp != NULL)
710 *blkp = (diskaddr_t)
711 ((xsp->es_info_1 << 24) | (xsp->es_info_2 << 16) |
712 (xsp->es_info_3 << 8) | xsp->es_info_4);
713 if (xsp->es_add_len >= 6) {
714 if (ascp != NULL)
715 *ascp = (uint64_t)xsp->es_add_code;
716 if (ascqp != NULL)
717 *ascqp = (uint64_t)xsp->es_qual_code;
718 }
719 break;
720 }
721
722 return (0);
723 }
724