scsi_all.c revision 323987
1/*- 2 * Implementation of Utility functions for all SCSI device types. 3 * 4 * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. 5 * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: stable/10/sys/cam/scsi/scsi_all.c 323987 2017-09-25 18:26:31Z jkim $"); 32 33#include <sys/param.h> 34#include <sys/types.h> 35#include <sys/stdint.h> 36 37#ifdef _KERNEL 38#include <opt_scsi.h> 39 40#include <sys/systm.h> 41#include <sys/libkern.h> 42#include <sys/kernel.h> 43#include <sys/lock.h> 44#include <sys/malloc.h> 45#include <sys/mutex.h> 46#include <sys/sysctl.h> 47#include <sys/ctype.h> 48#else 49#include <errno.h> 50#include <stdio.h> 51#include <stdlib.h> 52#include <string.h> 53#include <ctype.h> 54#endif 55 56#include <cam/cam.h> 57#include <cam/cam_ccb.h> 58#include <cam/cam_queue.h> 59#include <cam/cam_xpt.h> 60#include <cam/scsi/scsi_all.h> 61#include <sys/ata.h> 62#include <sys/sbuf.h> 63 64#ifdef _KERNEL 65#include <cam/cam_periph.h> 66#include <cam/cam_xpt_sim.h> 67#include <cam/cam_xpt_periph.h> 68#include <cam/cam_xpt_internal.h> 69#else 70#include <camlib.h> 71#include <stddef.h> 72 73#ifndef FALSE 74#define FALSE 0 75#endif /* FALSE */ 76#ifndef TRUE 77#define TRUE 1 78#endif /* TRUE */ 79#define ERESTART -1 /* restart syscall */ 80#define EJUSTRETURN -2 /* don't modify regs, just return */ 81#endif /* !_KERNEL */ 82 83/* 84 * This is the default number of milliseconds we wait for devices to settle 85 * after a SCSI bus reset. 86 */ 87#ifndef SCSI_DELAY 88#define SCSI_DELAY 2000 89#endif 90/* 91 * All devices need _some_ sort of bus settle delay, so we'll set it to 92 * a minimum value of 100ms. Note that this is pertinent only for SPI- 93 * not transport like Fibre Channel or iSCSI where 'delay' is completely 94 * meaningless. 95 */ 96#ifndef SCSI_MIN_DELAY 97#define SCSI_MIN_DELAY 100 98#endif 99/* 100 * Make sure the user isn't using seconds instead of milliseconds. 101 */ 102#if (SCSI_DELAY < SCSI_MIN_DELAY && SCSI_DELAY != 0) 103#error "SCSI_DELAY is in milliseconds, not seconds! Please use a larger value" 104#endif 105 106int scsi_delay; 107 108static int ascentrycomp(const void *key, const void *member); 109static int senseentrycomp(const void *key, const void *member); 110static void fetchtableentries(int sense_key, int asc, int ascq, 111 struct scsi_inquiry_data *, 112 const struct sense_key_table_entry **, 113 const struct asc_table_entry **); 114#ifdef _KERNEL 115static void init_scsi_delay(void); 116static int sysctl_scsi_delay(SYSCTL_HANDLER_ARGS); 117static int set_scsi_delay(int delay); 118#endif 119 120#if !defined(SCSI_NO_OP_STRINGS) 121 122#define D (1 << T_DIRECT) 123#define T (1 << T_SEQUENTIAL) 124#define L (1 << T_PRINTER) 125#define P (1 << T_PROCESSOR) 126#define W (1 << T_WORM) 127#define R (1 << T_CDROM) 128#define O (1 << T_OPTICAL) 129#define M (1 << T_CHANGER) 130#define A (1 << T_STORARRAY) 131#define E (1 << T_ENCLOSURE) 132#define B (1 << T_RBC) 133#define K (1 << T_OCRW) 134#define V (1 << T_ADC) 135#define F (1 << T_OSD) 136#define S (1 << T_SCANNER) 137#define C (1 << T_COMM) 138 139#define ALL (D | T | L | P | W | R | O | M | A | E | B | K | V | F | S | C) 140 141static struct op_table_entry plextor_cd_ops[] = { 142 { 0xD8, R, "CD-DA READ" } 143}; 144 145static struct scsi_op_quirk_entry scsi_op_quirk_table[] = { 146 { 147 /* 148 * I believe that 0xD8 is the Plextor proprietary command 149 * to read CD-DA data. I'm not sure which Plextor CDROM 150 * models support the command, though. I know for sure 151 * that the 4X, 8X, and 12X models do, and presumably the 152 * 12-20X does. I don't know about any earlier models, 153 * though. If anyone has any more complete information, 154 * feel free to change this quirk entry. 155 */ 156 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"}, 157 sizeof(plextor_cd_ops)/sizeof(struct op_table_entry), 158 plextor_cd_ops 159 } 160}; 161 162static struct op_table_entry scsi_op_codes[] = { 163 /* 164 * From: http://www.t10.org/lists/op-num.txt 165 * Modifications by Kenneth Merry (ken@FreeBSD.ORG) 166 * and Jung-uk Kim (jkim@FreeBSD.org) 167 * 168 * Note: order is important in this table, scsi_op_desc() currently 169 * depends on the opcodes in the table being in order to save 170 * search time. 171 * Note: scanner and comm. devices are carried over from the previous 172 * version because they were removed in the latest spec. 173 */ 174 /* File: OP-NUM.TXT 175 * 176 * SCSI Operation Codes 177 * Numeric Sorted Listing 178 * as of 5/26/15 179 * 180 * D - DIRECT ACCESS DEVICE (SBC-2) device column key 181 * .T - SEQUENTIAL ACCESS DEVICE (SSC-2) ----------------- 182 * . L - PRINTER DEVICE (SSC) M = Mandatory 183 * . P - PROCESSOR DEVICE (SPC) O = Optional 184 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2) V = Vendor spec. 185 * . . R - CD/DVE DEVICE (MMC-3) Z = Obsolete 186 * . . O - OPTICAL MEMORY DEVICE (SBC-2) 187 * . . .M - MEDIA CHANGER DEVICE (SMC-2) 188 * . . . A - STORAGE ARRAY DEVICE (SCC-2) 189 * . . . .E - ENCLOSURE SERVICES DEVICE (SES) 190 * . . . .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC) 191 * . . . . K - OPTICAL CARD READER/WRITER DEVICE (OCRW) 192 * . . . . V - AUTOMATION/DRIVE INTERFACE (ADC) 193 * . . . . .F - OBJECT-BASED STORAGE (OSD) 194 * OP DTLPWROMAEBKVF Description 195 * -- -------------- ---------------------------------------------- */ 196 /* 00 MMMMMMMMMMMMMM TEST UNIT READY */ 197 { 0x00, ALL, "TEST UNIT READY" }, 198 /* 01 M REWIND */ 199 { 0x01, T, "REWIND" }, 200 /* 01 Z V ZZZZ REZERO UNIT */ 201 { 0x01, D | W | R | O | M, "REZERO UNIT" }, 202 /* 02 VVVVVV V */ 203 /* 03 MMMMMMMMMMOMMM REQUEST SENSE */ 204 { 0x03, ALL, "REQUEST SENSE" }, 205 /* 04 M OO FORMAT UNIT */ 206 { 0x04, D | R | O, "FORMAT UNIT" }, 207 /* 04 O FORMAT MEDIUM */ 208 { 0x04, T, "FORMAT MEDIUM" }, 209 /* 04 O FORMAT */ 210 { 0x04, L, "FORMAT" }, 211 /* 05 VMVVVV V READ BLOCK LIMITS */ 212 { 0x05, T, "READ BLOCK LIMITS" }, 213 /* 06 VVVVVV V */ 214 /* 07 OVV O OV REASSIGN BLOCKS */ 215 { 0x07, D | W | O, "REASSIGN BLOCKS" }, 216 /* 07 O INITIALIZE ELEMENT STATUS */ 217 { 0x07, M, "INITIALIZE ELEMENT STATUS" }, 218 /* 08 MOV O OV READ(6) */ 219 { 0x08, D | T | W | O, "READ(6)" }, 220 /* 08 O RECEIVE */ 221 { 0x08, P, "RECEIVE" }, 222 /* 08 GET MESSAGE(6) */ 223 { 0x08, C, "GET MESSAGE(6)" }, 224 /* 09 VVVVVV V */ 225 /* 0A OO O OV WRITE(6) */ 226 { 0x0A, D | T | W | O, "WRITE(6)" }, 227 /* 0A M SEND(6) */ 228 { 0x0A, P, "SEND(6)" }, 229 /* 0A SEND MESSAGE(6) */ 230 { 0x0A, C, "SEND MESSAGE(6)" }, 231 /* 0A M PRINT */ 232 { 0x0A, L, "PRINT" }, 233 /* 0B Z ZOZV SEEK(6) */ 234 { 0x0B, D | W | R | O, "SEEK(6)" }, 235 /* 0B O SET CAPACITY */ 236 { 0x0B, T, "SET CAPACITY" }, 237 /* 0B O SLEW AND PRINT */ 238 { 0x0B, L, "SLEW AND PRINT" }, 239 /* 0C VVVVVV V */ 240 /* 0D VVVVVV V */ 241 /* 0E VVVVVV V */ 242 /* 0F VOVVVV V READ REVERSE(6) */ 243 { 0x0F, T, "READ REVERSE(6)" }, 244 /* 10 VM VVV WRITE FILEMARKS(6) */ 245 { 0x10, T, "WRITE FILEMARKS(6)" }, 246 /* 10 O SYNCHRONIZE BUFFER */ 247 { 0x10, L, "SYNCHRONIZE BUFFER" }, 248 /* 11 VMVVVV SPACE(6) */ 249 { 0x11, T, "SPACE(6)" }, 250 /* 12 MMMMMMMMMMMMMM INQUIRY */ 251 { 0x12, ALL, "INQUIRY" }, 252 /* 13 V VVVV */ 253 /* 13 O VERIFY(6) */ 254 { 0x13, T, "VERIFY(6)" }, 255 /* 14 VOOVVV RECOVER BUFFERED DATA */ 256 { 0x14, T | L, "RECOVER BUFFERED DATA" }, 257 /* 15 OMO O OOOO OO MODE SELECT(6) */ 258 { 0x15, ALL & ~(P | R | B | F), "MODE SELECT(6)" }, 259 /* 16 ZZMZO OOOZ O RESERVE(6) */ 260 { 0x16, ALL & ~(R | B | V | F | C), "RESERVE(6)" }, 261 /* 16 Z RESERVE ELEMENT(6) */ 262 { 0x16, M, "RESERVE ELEMENT(6)" }, 263 /* 17 ZZMZO OOOZ O RELEASE(6) */ 264 { 0x17, ALL & ~(R | B | V | F | C), "RELEASE(6)" }, 265 /* 17 Z RELEASE ELEMENT(6) */ 266 { 0x17, M, "RELEASE ELEMENT(6)" }, 267 /* 18 ZZZZOZO Z COPY */ 268 { 0x18, D | T | L | P | W | R | O | K | S, "COPY" }, 269 /* 19 VMVVVV ERASE(6) */ 270 { 0x19, T, "ERASE(6)" }, 271 /* 1A OMO O OOOO OO MODE SENSE(6) */ 272 { 0x1A, ALL & ~(P | R | B | F), "MODE SENSE(6)" }, 273 /* 1B O OOO O MO O START STOP UNIT */ 274 { 0x1B, D | W | R | O | A | B | K | F, "START STOP UNIT" }, 275 /* 1B O M LOAD UNLOAD */ 276 { 0x1B, T | V, "LOAD UNLOAD" }, 277 /* 1B SCAN */ 278 { 0x1B, S, "SCAN" }, 279 /* 1B O STOP PRINT */ 280 { 0x1B, L, "STOP PRINT" }, 281 /* 1B O OPEN/CLOSE IMPORT/EXPORT ELEMENT */ 282 { 0x1B, M, "OPEN/CLOSE IMPORT/EXPORT ELEMENT" }, 283 /* 1C OOOOO OOOM OOO RECEIVE DIAGNOSTIC RESULTS */ 284 { 0x1C, ALL & ~(R | B), "RECEIVE DIAGNOSTIC RESULTS" }, 285 /* 1D MMMMM MMOM MMM SEND DIAGNOSTIC */ 286 { 0x1D, ALL & ~(R | B), "SEND DIAGNOSTIC" }, 287 /* 1E OO OOOO O O PREVENT ALLOW MEDIUM REMOVAL */ 288 { 0x1E, D | T | W | R | O | M | K | F, "PREVENT ALLOW MEDIUM REMOVAL" }, 289 /* 1F */ 290 /* 20 V VVV V */ 291 /* 21 V VVV V */ 292 /* 22 V VVV V */ 293 /* 23 V V V V */ 294 /* 23 O READ FORMAT CAPACITIES */ 295 { 0x23, R, "READ FORMAT CAPACITIES" }, 296 /* 24 V VV SET WINDOW */ 297 { 0x24, S, "SET WINDOW" }, 298 /* 25 M M M M READ CAPACITY(10) */ 299 { 0x25, D | W | O | B, "READ CAPACITY(10)" }, 300 /* 25 O READ CAPACITY */ 301 { 0x25, R, "READ CAPACITY" }, 302 /* 25 M READ CARD CAPACITY */ 303 { 0x25, K, "READ CARD CAPACITY" }, 304 /* 25 GET WINDOW */ 305 { 0x25, S, "GET WINDOW" }, 306 /* 26 V VV */ 307 /* 27 V VV */ 308 /* 28 M MOM MM READ(10) */ 309 { 0x28, D | W | R | O | B | K | S, "READ(10)" }, 310 /* 28 GET MESSAGE(10) */ 311 { 0x28, C, "GET MESSAGE(10)" }, 312 /* 29 V VVO READ GENERATION */ 313 { 0x29, O, "READ GENERATION" }, 314 /* 2A O MOM MO WRITE(10) */ 315 { 0x2A, D | W | R | O | B | K, "WRITE(10)" }, 316 /* 2A SEND(10) */ 317 { 0x2A, S, "SEND(10)" }, 318 /* 2A SEND MESSAGE(10) */ 319 { 0x2A, C, "SEND MESSAGE(10)" }, 320 /* 2B Z OOO O SEEK(10) */ 321 { 0x2B, D | W | R | O | K, "SEEK(10)" }, 322 /* 2B O LOCATE(10) */ 323 { 0x2B, T, "LOCATE(10)" }, 324 /* 2B O POSITION TO ELEMENT */ 325 { 0x2B, M, "POSITION TO ELEMENT" }, 326 /* 2C V OO ERASE(10) */ 327 { 0x2C, R | O, "ERASE(10)" }, 328 /* 2D O READ UPDATED BLOCK */ 329 { 0x2D, O, "READ UPDATED BLOCK" }, 330 /* 2D V */ 331 /* 2E O OOO MO WRITE AND VERIFY(10) */ 332 { 0x2E, D | W | R | O | B | K, "WRITE AND VERIFY(10)" }, 333 /* 2F O OOO VERIFY(10) */ 334 { 0x2F, D | W | R | O, "VERIFY(10)" }, 335 /* 30 Z ZZZ SEARCH DATA HIGH(10) */ 336 { 0x30, D | W | R | O, "SEARCH DATA HIGH(10)" }, 337 /* 31 Z ZZZ SEARCH DATA EQUAL(10) */ 338 { 0x31, D | W | R | O, "SEARCH DATA EQUAL(10)" }, 339 /* 31 OBJECT POSITION */ 340 { 0x31, S, "OBJECT POSITION" }, 341 /* 32 Z ZZZ SEARCH DATA LOW(10) */ 342 { 0x32, D | W | R | O, "SEARCH DATA LOW(10)" }, 343 /* 33 Z OZO SET LIMITS(10) */ 344 { 0x33, D | W | R | O, "SET LIMITS(10)" }, 345 /* 34 O O O O PRE-FETCH(10) */ 346 { 0x34, D | W | O | K, "PRE-FETCH(10)" }, 347 /* 34 M READ POSITION */ 348 { 0x34, T, "READ POSITION" }, 349 /* 34 GET DATA BUFFER STATUS */ 350 { 0x34, S, "GET DATA BUFFER STATUS" }, 351 /* 35 O OOO MO SYNCHRONIZE CACHE(10) */ 352 { 0x35, D | W | R | O | B | K, "SYNCHRONIZE CACHE(10)" }, 353 /* 36 Z O O O LOCK UNLOCK CACHE(10) */ 354 { 0x36, D | W | O | K, "LOCK UNLOCK CACHE(10)" }, 355 /* 37 O O READ DEFECT DATA(10) */ 356 { 0x37, D | O, "READ DEFECT DATA(10)" }, 357 /* 37 O INITIALIZE ELEMENT STATUS WITH RANGE */ 358 { 0x37, M, "INITIALIZE ELEMENT STATUS WITH RANGE" }, 359 /* 38 O O O MEDIUM SCAN */ 360 { 0x38, W | O | K, "MEDIUM SCAN" }, 361 /* 39 ZZZZOZO Z COMPARE */ 362 { 0x39, D | T | L | P | W | R | O | K | S, "COMPARE" }, 363 /* 3A ZZZZOZO Z COPY AND VERIFY */ 364 { 0x3A, D | T | L | P | W | R | O | K | S, "COPY AND VERIFY" }, 365 /* 3B OOOOOOOOOOMOOO WRITE BUFFER */ 366 { 0x3B, ALL, "WRITE BUFFER" }, 367 /* 3C OOOOOOOOOO OOO READ BUFFER */ 368 { 0x3C, ALL & ~(B), "READ BUFFER" }, 369 /* 3D O UPDATE BLOCK */ 370 { 0x3D, O, "UPDATE BLOCK" }, 371 /* 3E O O O READ LONG(10) */ 372 { 0x3E, D | W | O, "READ LONG(10)" }, 373 /* 3F O O O WRITE LONG(10) */ 374 { 0x3F, D | W | O, "WRITE LONG(10)" }, 375 /* 40 ZZZZOZOZ CHANGE DEFINITION */ 376 { 0x40, D | T | L | P | W | R | O | M | S | C, "CHANGE DEFINITION" }, 377 /* 41 O WRITE SAME(10) */ 378 { 0x41, D, "WRITE SAME(10)" }, 379 /* 42 O UNMAP */ 380 { 0x42, D, "UNMAP" }, 381 /* 42 O READ SUB-CHANNEL */ 382 { 0x42, R, "READ SUB-CHANNEL" }, 383 /* 43 O READ TOC/PMA/ATIP */ 384 { 0x43, R, "READ TOC/PMA/ATIP" }, 385 /* 44 M M REPORT DENSITY SUPPORT */ 386 { 0x44, T | V, "REPORT DENSITY SUPPORT" }, 387 /* 44 READ HEADER */ 388 /* 45 O PLAY AUDIO(10) */ 389 { 0x45, R, "PLAY AUDIO(10)" }, 390 /* 46 M GET CONFIGURATION */ 391 { 0x46, R, "GET CONFIGURATION" }, 392 /* 47 O PLAY AUDIO MSF */ 393 { 0x47, R, "PLAY AUDIO MSF" }, 394 /* 48 */ 395 /* 49 */ 396 /* 4A M GET EVENT STATUS NOTIFICATION */ 397 { 0x4A, R, "GET EVENT STATUS NOTIFICATION" }, 398 /* 4B O PAUSE/RESUME */ 399 { 0x4B, R, "PAUSE/RESUME" }, 400 /* 4C OOOOO OOOO OOO LOG SELECT */ 401 { 0x4C, ALL & ~(R | B), "LOG SELECT" }, 402 /* 4D OOOOO OOOO OMO LOG SENSE */ 403 { 0x4D, ALL & ~(R | B), "LOG SENSE" }, 404 /* 4E O STOP PLAY/SCAN */ 405 { 0x4E, R, "STOP PLAY/SCAN" }, 406 /* 4F */ 407 /* 50 O XDWRITE(10) */ 408 { 0x50, D, "XDWRITE(10)" }, 409 /* 51 O XPWRITE(10) */ 410 { 0x51, D, "XPWRITE(10)" }, 411 /* 51 O READ DISC INFORMATION */ 412 { 0x51, R, "READ DISC INFORMATION" }, 413 /* 52 O XDREAD(10) */ 414 { 0x52, D, "XDREAD(10)" }, 415 /* 52 O READ TRACK INFORMATION */ 416 { 0x52, R, "READ TRACK INFORMATION" }, 417 /* 53 O RESERVE TRACK */ 418 { 0x53, R, "RESERVE TRACK" }, 419 /* 54 O SEND OPC INFORMATION */ 420 { 0x54, R, "SEND OPC INFORMATION" }, 421 /* 55 OOO OMOOOOMOMO MODE SELECT(10) */ 422 { 0x55, ALL & ~(P), "MODE SELECT(10)" }, 423 /* 56 ZZMZO OOOZ RESERVE(10) */ 424 { 0x56, ALL & ~(R | B | K | V | F | C), "RESERVE(10)" }, 425 /* 56 Z RESERVE ELEMENT(10) */ 426 { 0x56, M, "RESERVE ELEMENT(10)" }, 427 /* 57 ZZMZO OOOZ RELEASE(10) */ 428 { 0x57, ALL & ~(R | B | K | V | F | C), "RELEASE(10)" }, 429 /* 57 Z RELEASE ELEMENT(10) */ 430 { 0x57, M, "RELEASE ELEMENT(10)" }, 431 /* 58 O REPAIR TRACK */ 432 { 0x58, R, "REPAIR TRACK" }, 433 /* 59 */ 434 /* 5A OOO OMOOOOMOMO MODE SENSE(10) */ 435 { 0x5A, ALL & ~(P), "MODE SENSE(10)" }, 436 /* 5B O CLOSE TRACK/SESSION */ 437 { 0x5B, R, "CLOSE TRACK/SESSION" }, 438 /* 5C O READ BUFFER CAPACITY */ 439 { 0x5C, R, "READ BUFFER CAPACITY" }, 440 /* 5D O SEND CUE SHEET */ 441 { 0x5D, R, "SEND CUE SHEET" }, 442 /* 5E OOOOO OOOO M PERSISTENT RESERVE IN */ 443 { 0x5E, ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE IN" }, 444 /* 5F OOOOO OOOO M PERSISTENT RESERVE OUT */ 445 { 0x5F, ALL & ~(R | B | K | V | C), "PERSISTENT RESERVE OUT" }, 446 /* 7E OO O OOOO O extended CDB */ 447 { 0x7E, D | T | R | M | A | E | B | V, "extended CDB" }, 448 /* 7F O M variable length CDB (more than 16 bytes) */ 449 { 0x7F, D | F, "variable length CDB (more than 16 bytes)" }, 450 /* 80 Z XDWRITE EXTENDED(16) */ 451 { 0x80, D, "XDWRITE EXTENDED(16)" }, 452 /* 80 M WRITE FILEMARKS(16) */ 453 { 0x80, T, "WRITE FILEMARKS(16)" }, 454 /* 81 Z REBUILD(16) */ 455 { 0x81, D, "REBUILD(16)" }, 456 /* 81 O READ REVERSE(16) */ 457 { 0x81, T, "READ REVERSE(16)" }, 458 /* 82 Z REGENERATE(16) */ 459 { 0x82, D, "REGENERATE(16)" }, 460 /* 83 OOOOO O OO EXTENDED COPY */ 461 { 0x83, D | T | L | P | W | O | K | V, "EXTENDED COPY" }, 462 /* 84 OOOOO O OO RECEIVE COPY RESULTS */ 463 { 0x84, D | T | L | P | W | O | K | V, "RECEIVE COPY RESULTS" }, 464 /* 85 O O O ATA COMMAND PASS THROUGH(16) */ 465 { 0x85, D | R | B, "ATA COMMAND PASS THROUGH(16)" }, 466 /* 86 OO OO OOOOOOO ACCESS CONTROL IN */ 467 { 0x86, ALL & ~(L | R | F), "ACCESS CONTROL IN" }, 468 /* 87 OO OO OOOOOOO ACCESS CONTROL OUT */ 469 { 0x87, ALL & ~(L | R | F), "ACCESS CONTROL OUT" }, 470 /* 88 MM O O O READ(16) */ 471 { 0x88, D | T | W | O | B, "READ(16)" }, 472 /* 89 O COMPARE AND WRITE*/ 473 { 0x89, D, "COMPARE AND WRITE" }, 474 /* 8A OM O O O WRITE(16) */ 475 { 0x8A, D | T | W | O | B, "WRITE(16)" }, 476 /* 8B O ORWRITE */ 477 { 0x8B, D, "ORWRITE" }, 478 /* 8C OO O OO O M READ ATTRIBUTE */ 479 { 0x8C, D | T | W | O | M | B | V, "READ ATTRIBUTE" }, 480 /* 8D OO O OO O O WRITE ATTRIBUTE */ 481 { 0x8D, D | T | W | O | M | B | V, "WRITE ATTRIBUTE" }, 482 /* 8E O O O O WRITE AND VERIFY(16) */ 483 { 0x8E, D | W | O | B, "WRITE AND VERIFY(16)" }, 484 /* 8F OO O O O VERIFY(16) */ 485 { 0x8F, D | T | W | O | B, "VERIFY(16)" }, 486 /* 90 O O O O PRE-FETCH(16) */ 487 { 0x90, D | W | O | B, "PRE-FETCH(16)" }, 488 /* 91 O O O O SYNCHRONIZE CACHE(16) */ 489 { 0x91, D | W | O | B, "SYNCHRONIZE CACHE(16)" }, 490 /* 91 O SPACE(16) */ 491 { 0x91, T, "SPACE(16)" }, 492 /* 92 Z O O LOCK UNLOCK CACHE(16) */ 493 { 0x92, D | W | O, "LOCK UNLOCK CACHE(16)" }, 494 /* 92 O LOCATE(16) */ 495 { 0x92, T, "LOCATE(16)" }, 496 /* 93 O WRITE SAME(16) */ 497 { 0x93, D, "WRITE SAME(16)" }, 498 /* 93 M ERASE(16) */ 499 { 0x93, T, "ERASE(16)" }, 500 /* 94 O ZBC OUT */ 501 { 0x94, D, "ZBC OUT" }, 502 /* 95 O ZBC OUT */ 503 { 0x95, D, "ZBC OUT" }, 504 /* 96 */ 505 /* 97 */ 506 /* 98 */ 507 /* 99 */ 508 /* 9A O WRITE STREAM(16) */ 509 { 0x9A, D, "WRITE STREAM(16)" }, 510 /* 9B OOOOOOOOOO OOO READ BUFFER(16) */ 511 { 0x9B, ALL & ~(B) , "READ BUFFER(16)" }, 512 /* 9C O WRITE ATOMIC(16) */ 513 { 0x9C, D, "WRITE ATOMIC(16)" }, 514 /* 9D SERVICE ACTION BIDIRECTIONAL */ 515 { 0x9D, ALL, "SERVICE ACTION BIDIRECTIONAL" }, 516 /* XXX KDM ALL for this? op-num.txt defines it for none.. */ 517 /* 9E SERVICE ACTION IN(16) */ 518 { 0x9E, ALL, "SERVICE ACTION IN(16)" }, 519 /* XXX KDM ALL for this? op-num.txt defines it for ADC.. */ 520 /* 9F M SERVICE ACTION OUT(16) */ 521 { 0x9F, ALL, "SERVICE ACTION OUT(16)" }, 522 /* A0 MMOOO OMMM OMO REPORT LUNS */ 523 { 0xA0, ALL & ~(R | B), "REPORT LUNS" }, 524 /* A1 O BLANK */ 525 { 0xA1, R, "BLANK" }, 526 /* A1 O O ATA COMMAND PASS THROUGH(12) */ 527 { 0xA1, D | B, "ATA COMMAND PASS THROUGH(12)" }, 528 /* A2 OO O O SECURITY PROTOCOL IN */ 529 { 0xA2, D | T | R | V, "SECURITY PROTOCOL IN" }, 530 /* A3 OOO O OOMOOOM MAINTENANCE (IN) */ 531 { 0xA3, ALL & ~(P | R | F), "MAINTENANCE (IN)" }, 532 /* A3 O SEND KEY */ 533 { 0xA3, R, "SEND KEY" }, 534 /* A4 OOO O OOOOOOO MAINTENANCE (OUT) */ 535 { 0xA4, ALL & ~(P | R | F), "MAINTENANCE (OUT)" }, 536 /* A4 O REPORT KEY */ 537 { 0xA4, R, "REPORT KEY" }, 538 /* A5 O O OM MOVE MEDIUM */ 539 { 0xA5, T | W | O | M, "MOVE MEDIUM" }, 540 /* A5 O PLAY AUDIO(12) */ 541 { 0xA5, R, "PLAY AUDIO(12)" }, 542 /* A6 O EXCHANGE MEDIUM */ 543 { 0xA6, M, "EXCHANGE MEDIUM" }, 544 /* A6 O LOAD/UNLOAD C/DVD */ 545 { 0xA6, R, "LOAD/UNLOAD C/DVD" }, 546 /* A7 ZZ O O MOVE MEDIUM ATTACHED */ 547 { 0xA7, D | T | W | O, "MOVE MEDIUM ATTACHED" }, 548 /* A7 O SET READ AHEAD */ 549 { 0xA7, R, "SET READ AHEAD" }, 550 /* A8 O OOO READ(12) */ 551 { 0xA8, D | W | R | O, "READ(12)" }, 552 /* A8 GET MESSAGE(12) */ 553 { 0xA8, C, "GET MESSAGE(12)" }, 554 /* A9 O SERVICE ACTION OUT(12) */ 555 { 0xA9, V, "SERVICE ACTION OUT(12)" }, 556 /* AA O OOO WRITE(12) */ 557 { 0xAA, D | W | R | O, "WRITE(12)" }, 558 /* AA SEND MESSAGE(12) */ 559 { 0xAA, C, "SEND MESSAGE(12)" }, 560 /* AB O O SERVICE ACTION IN(12) */ 561 { 0xAB, R | V, "SERVICE ACTION IN(12)" }, 562 /* AC O ERASE(12) */ 563 { 0xAC, O, "ERASE(12)" }, 564 /* AC O GET PERFORMANCE */ 565 { 0xAC, R, "GET PERFORMANCE" }, 566 /* AD O READ DVD STRUCTURE */ 567 { 0xAD, R, "READ DVD STRUCTURE" }, 568 /* AE O O O WRITE AND VERIFY(12) */ 569 { 0xAE, D | W | O, "WRITE AND VERIFY(12)" }, 570 /* AF O OZO VERIFY(12) */ 571 { 0xAF, D | W | R | O, "VERIFY(12)" }, 572 /* B0 ZZZ SEARCH DATA HIGH(12) */ 573 { 0xB0, W | R | O, "SEARCH DATA HIGH(12)" }, 574 /* B1 ZZZ SEARCH DATA EQUAL(12) */ 575 { 0xB1, W | R | O, "SEARCH DATA EQUAL(12)" }, 576 /* B2 ZZZ SEARCH DATA LOW(12) */ 577 { 0xB2, W | R | O, "SEARCH DATA LOW(12)" }, 578 /* B3 Z OZO SET LIMITS(12) */ 579 { 0xB3, D | W | R | O, "SET LIMITS(12)" }, 580 /* B4 ZZ OZO READ ELEMENT STATUS ATTACHED */ 581 { 0xB4, D | T | W | R | O, "READ ELEMENT STATUS ATTACHED" }, 582 /* B5 OO O O SECURITY PROTOCOL OUT */ 583 { 0xB5, D | T | R | V, "SECURITY PROTOCOL OUT" }, 584 /* B5 O REQUEST VOLUME ELEMENT ADDRESS */ 585 { 0xB5, M, "REQUEST VOLUME ELEMENT ADDRESS" }, 586 /* B6 O SEND VOLUME TAG */ 587 { 0xB6, M, "SEND VOLUME TAG" }, 588 /* B6 O SET STREAMING */ 589 { 0xB6, R, "SET STREAMING" }, 590 /* B7 O O READ DEFECT DATA(12) */ 591 { 0xB7, D | O, "READ DEFECT DATA(12)" }, 592 /* B8 O OZOM READ ELEMENT STATUS */ 593 { 0xB8, T | W | R | O | M, "READ ELEMENT STATUS" }, 594 /* B9 O READ CD MSF */ 595 { 0xB9, R, "READ CD MSF" }, 596 /* BA O O OOMO REDUNDANCY GROUP (IN) */ 597 { 0xBA, D | W | O | M | A | E, "REDUNDANCY GROUP (IN)" }, 598 /* BA O SCAN */ 599 { 0xBA, R, "SCAN" }, 600 /* BB O O OOOO REDUNDANCY GROUP (OUT) */ 601 { 0xBB, D | W | O | M | A | E, "REDUNDANCY GROUP (OUT)" }, 602 /* BB O SET CD SPEED */ 603 { 0xBB, R, "SET CD SPEED" }, 604 /* BC O O OOMO SPARE (IN) */ 605 { 0xBC, D | W | O | M | A | E, "SPARE (IN)" }, 606 /* BD O O OOOO SPARE (OUT) */ 607 { 0xBD, D | W | O | M | A | E, "SPARE (OUT)" }, 608 /* BD O MECHANISM STATUS */ 609 { 0xBD, R, "MECHANISM STATUS" }, 610 /* BE O O OOMO VOLUME SET (IN) */ 611 { 0xBE, D | W | O | M | A | E, "VOLUME SET (IN)" }, 612 /* BE O READ CD */ 613 { 0xBE, R, "READ CD" }, 614 /* BF O O OOOO VOLUME SET (OUT) */ 615 { 0xBF, D | W | O | M | A | E, "VOLUME SET (OUT)" }, 616 /* BF O SEND DVD STRUCTURE */ 617 { 0xBF, R, "SEND DVD STRUCTURE" } 618}; 619 620const char * 621scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data) 622{ 623 caddr_t match; 624 int i, j; 625 u_int32_t opmask; 626 u_int16_t pd_type; 627 int num_ops[2]; 628 struct op_table_entry *table[2]; 629 int num_tables; 630 631 /* 632 * If we've got inquiry data, use it to determine what type of 633 * device we're dealing with here. Otherwise, assume direct 634 * access. 635 */ 636 if (inq_data == NULL) { 637 pd_type = T_DIRECT; 638 match = NULL; 639 } else { 640 pd_type = SID_TYPE(inq_data); 641 642 match = cam_quirkmatch((caddr_t)inq_data, 643 (caddr_t)scsi_op_quirk_table, 644 sizeof(scsi_op_quirk_table)/ 645 sizeof(*scsi_op_quirk_table), 646 sizeof(*scsi_op_quirk_table), 647 scsi_inquiry_match); 648 } 649 650 if (match != NULL) { 651 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table; 652 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops; 653 table[1] = scsi_op_codes; 654 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]); 655 num_tables = 2; 656 } else { 657 /* 658 * If this is true, we have a vendor specific opcode that 659 * wasn't covered in the quirk table. 660 */ 661 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80))) 662 return("Vendor Specific Command"); 663 664 table[0] = scsi_op_codes; 665 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]); 666 num_tables = 1; 667 } 668 669 /* RBC is 'Simplified' Direct Access Device */ 670 if (pd_type == T_RBC) 671 pd_type = T_DIRECT; 672 673 /* Map NODEVICE to Direct Access Device to handle REPORT LUNS, etc. */ 674 if (pd_type == T_NODEVICE) 675 pd_type = T_DIRECT; 676 677 opmask = 1 << pd_type; 678 679 for (j = 0; j < num_tables; j++) { 680 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){ 681 if ((table[j][i].opcode == opcode) 682 && ((table[j][i].opmask & opmask) != 0)) 683 return(table[j][i].desc); 684 } 685 } 686 687 /* 688 * If we can't find a match for the command in the table, we just 689 * assume it's a vendor specifc command. 690 */ 691 return("Vendor Specific Command"); 692 693} 694 695#else /* SCSI_NO_OP_STRINGS */ 696 697const char * 698scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data) 699{ 700 return(""); 701} 702 703#endif 704 705 706#if !defined(SCSI_NO_SENSE_STRINGS) 707#define SST(asc, ascq, action, desc) \ 708 asc, ascq, action, desc 709#else 710const char empty_string[] = ""; 711 712#define SST(asc, ascq, action, desc) \ 713 asc, ascq, action, empty_string 714#endif 715 716const struct sense_key_table_entry sense_key_table[] = 717{ 718 { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" }, 719 { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" }, 720 { SSD_KEY_NOT_READY, SS_RDEF, "NOT READY" }, 721 { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" }, 722 { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" }, 723 { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" }, 724 { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" }, 725 { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" }, 726 { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" }, 727 { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" }, 728 { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" }, 729 { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" }, 730 { SSD_KEY_EQUAL, SS_NOP, "EQUAL" }, 731 { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" }, 732 { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" }, 733 { SSD_KEY_COMPLETED, SS_NOP, "COMPLETED" } 734}; 735 736const int sense_key_table_size = 737 sizeof(sense_key_table)/sizeof(sense_key_table[0]); 738 739static struct asc_table_entry quantum_fireball_entries[] = { 740 { SST(0x04, 0x0b, SS_START | SSQ_DECREMENT_COUNT | ENXIO, 741 "Logical unit not ready, initializing cmd. required") } 742}; 743 744static struct asc_table_entry sony_mo_entries[] = { 745 { SST(0x04, 0x00, SS_START | SSQ_DECREMENT_COUNT | ENXIO, 746 "Logical unit not ready, cause not reportable") } 747}; 748 749static struct asc_table_entry hgst_entries[] = { 750 { SST(0x04, 0xF0, SS_RDEF, 751 "Vendor Unique - Logical Unit Not Ready") }, 752 { SST(0x0A, 0x01, SS_RDEF, 753 "Unrecovered Super Certification Log Write Error") }, 754 { SST(0x0A, 0x02, SS_RDEF, 755 "Unrecovered Super Certification Log Read Error") }, 756 { SST(0x15, 0x03, SS_RDEF, 757 "Unrecovered Sector Error") }, 758 { SST(0x3E, 0x04, SS_RDEF, 759 "Unrecovered Self-Test Hard-Cache Test Fail") }, 760 { SST(0x3E, 0x05, SS_RDEF, 761 "Unrecovered Self-Test OTF-Cache Fail") }, 762 { SST(0x40, 0x00, SS_RDEF, 763 "Unrecovered SAT No Buffer Overflow Error") }, 764 { SST(0x40, 0x01, SS_RDEF, 765 "Unrecovered SAT Buffer Overflow Error") }, 766 { SST(0x40, 0x02, SS_RDEF, 767 "Unrecovered SAT No Buffer Overflow With ECS Fault") }, 768 { SST(0x40, 0x03, SS_RDEF, 769 "Unrecovered SAT Buffer Overflow With ECS Fault") }, 770 { SST(0x40, 0x81, SS_RDEF, 771 "DRAM Failure") }, 772 { SST(0x44, 0x0B, SS_RDEF, 773 "Vendor Unique - Internal Target Failure") }, 774 { SST(0x44, 0xF2, SS_RDEF, 775 "Vendor Unique - Internal Target Failure") }, 776 { SST(0x44, 0xF6, SS_RDEF, 777 "Vendor Unique - Internal Target Failure") }, 778 { SST(0x44, 0xF9, SS_RDEF, 779 "Vendor Unique - Internal Target Failure") }, 780 { SST(0x44, 0xFA, SS_RDEF, 781 "Vendor Unique - Internal Target Failure") }, 782 { SST(0x5D, 0x22, SS_RDEF, 783 "Extreme Over-Temperature Warning") }, 784 { SST(0x5D, 0x50, SS_RDEF, 785 "Load/Unload cycle Count Warning") }, 786 { SST(0x81, 0x00, SS_RDEF, 787 "Vendor Unique - Internal Logic Error") }, 788 { SST(0x85, 0x00, SS_RDEF, 789 "Vendor Unique - Internal Key Seed Error") }, 790}; 791 792static struct asc_table_entry seagate_entries[] = { 793 { SST(0x04, 0xF0, SS_RDEF, 794 "Logical Unit Not Ready, super certify in Progress") }, 795 { SST(0x08, 0x86, SS_RDEF, 796 "Write Fault Data Corruption") }, 797 { SST(0x09, 0x0D, SS_RDEF, 798 "Tracking Failure") }, 799 { SST(0x09, 0x0E, SS_RDEF, 800 "ETF Failure") }, 801 { SST(0x0B, 0x5D, SS_RDEF, 802 "Pre-SMART Warning") }, 803 { SST(0x0B, 0x85, SS_RDEF, 804 "5V Voltage Warning") }, 805 { SST(0x0B, 0x8C, SS_RDEF, 806 "12V Voltage Warning") }, 807 { SST(0x0C, 0xFF, SS_RDEF, 808 "Write Error - Too many error recovery revs") }, 809 { SST(0x11, 0xFF, SS_RDEF, 810 "Unrecovered Read Error - Too many error recovery revs") }, 811 { SST(0x19, 0x0E, SS_RDEF, 812 "Fewer than 1/2 defect list copies") }, 813 { SST(0x20, 0xF3, SS_RDEF, 814 "Illegal CDB linked to skip mask cmd") }, 815 { SST(0x24, 0xF0, SS_RDEF, 816 "Illegal byte in CDB, LBA not matching") }, 817 { SST(0x24, 0xF1, SS_RDEF, 818 "Illegal byte in CDB, LEN not matching") }, 819 { SST(0x24, 0xF2, SS_RDEF, 820 "Mask not matching transfer length") }, 821 { SST(0x24, 0xF3, SS_RDEF, 822 "Drive formatted without plist") }, 823 { SST(0x26, 0x95, SS_RDEF, 824 "Invalid Field Parameter - CAP File") }, 825 { SST(0x26, 0x96, SS_RDEF, 826 "Invalid Field Parameter - RAP File") }, 827 { SST(0x26, 0x97, SS_RDEF, 828 "Invalid Field Parameter - TMS Firmware Tag") }, 829 { SST(0x26, 0x98, SS_RDEF, 830 "Invalid Field Parameter - Check Sum") }, 831 { SST(0x26, 0x99, SS_RDEF, 832 "Invalid Field Parameter - Firmware Tag") }, 833 { SST(0x29, 0x08, SS_RDEF, 834 "Write Log Dump data") }, 835 { SST(0x29, 0x09, SS_RDEF, 836 "Write Log Dump data") }, 837 { SST(0x29, 0x0A, SS_RDEF, 838 "Reserved disk space") }, 839 { SST(0x29, 0x0B, SS_RDEF, 840 "SDBP") }, 841 { SST(0x29, 0x0C, SS_RDEF, 842 "SDBP") }, 843 { SST(0x31, 0x91, SS_RDEF, 844 "Format Corrupted World Wide Name (WWN) is Invalid") }, 845 { SST(0x32, 0x03, SS_RDEF, 846 "Defect List - Length exceeds Command Allocated Length") }, 847 { SST(0x33, 0x00, SS_RDEF, 848 "Flash not ready for access") }, 849 { SST(0x3F, 0x70, SS_RDEF, 850 "Invalid RAP block") }, 851 { SST(0x3F, 0x71, SS_RDEF, 852 "RAP/ETF mismatch") }, 853 { SST(0x3F, 0x90, SS_RDEF, 854 "Invalid CAP block") }, 855 { SST(0x3F, 0x91, SS_RDEF, 856 "World Wide Name (WWN) Mismatch") }, 857 { SST(0x40, 0x01, SS_RDEF, 858 "DRAM Parity Error") }, 859 { SST(0x40, 0x02, SS_RDEF, 860 "DRAM Parity Error") }, 861 { SST(0x42, 0x0A, SS_RDEF, 862 "Loopback Test") }, 863 { SST(0x42, 0x0B, SS_RDEF, 864 "Loopback Test") }, 865 { SST(0x44, 0xF2, SS_RDEF, 866 "Compare error during data integrity check") }, 867 { SST(0x44, 0xF6, SS_RDEF, 868 "Unrecoverable error during data integrity check") }, 869 { SST(0x47, 0x80, SS_RDEF, 870 "Fibre Channel Sequence Error") }, 871 { SST(0x4E, 0x01, SS_RDEF, 872 "Information Unit Too Short") }, 873 { SST(0x80, 0x00, SS_RDEF, 874 "General Firmware Error / Command Timeout") }, 875 { SST(0x80, 0x01, SS_RDEF, 876 "Command Timeout") }, 877 { SST(0x80, 0x02, SS_RDEF, 878 "Command Timeout") }, 879 { SST(0x80, 0x80, SS_RDEF, 880 "FC FIFO Error During Read Transfer") }, 881 { SST(0x80, 0x81, SS_RDEF, 882 "FC FIFO Error During Write Transfer") }, 883 { SST(0x80, 0x82, SS_RDEF, 884 "DISC FIFO Error During Read Transfer") }, 885 { SST(0x80, 0x83, SS_RDEF, 886 "DISC FIFO Error During Write Transfer") }, 887 { SST(0x80, 0x84, SS_RDEF, 888 "LBA Seeded LRC Error on Read") }, 889 { SST(0x80, 0x85, SS_RDEF, 890 "LBA Seeded LRC Error on Write") }, 891 { SST(0x80, 0x86, SS_RDEF, 892 "IOEDC Error on Read") }, 893 { SST(0x80, 0x87, SS_RDEF, 894 "IOEDC Error on Write") }, 895 { SST(0x80, 0x88, SS_RDEF, 896 "Host Parity Check Failed") }, 897 { SST(0x80, 0x89, SS_RDEF, 898 "IOEDC error on read detected by formatter") }, 899 { SST(0x80, 0x8A, SS_RDEF, 900 "Host Parity Errors / Host FIFO Initialization Failed") }, 901 { SST(0x80, 0x8B, SS_RDEF, 902 "Host Parity Errors") }, 903 { SST(0x80, 0x8C, SS_RDEF, 904 "Host Parity Errors") }, 905 { SST(0x80, 0x8D, SS_RDEF, 906 "Host Parity Errors") }, 907 { SST(0x81, 0x00, SS_RDEF, 908 "LA Check Failed") }, 909 { SST(0x82, 0x00, SS_RDEF, 910 "Internal client detected insufficient buffer") }, 911 { SST(0x84, 0x00, SS_RDEF, 912 "Scheduled Diagnostic And Repair") }, 913}; 914 915static struct scsi_sense_quirk_entry sense_quirk_table[] = { 916 { 917 /* 918 * XXX The Quantum Fireball ST and SE like to return 0x04 0x0b 919 * when they really should return 0x04 0x02. 920 */ 921 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"}, 922 /*num_sense_keys*/0, 923 sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry), 924 /*sense key entries*/NULL, 925 quantum_fireball_entries 926 }, 927 { 928 /* 929 * This Sony MO drive likes to return 0x04, 0x00 when it 930 * isn't spun up. 931 */ 932 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"}, 933 /*num_sense_keys*/0, 934 sizeof(sony_mo_entries)/sizeof(struct asc_table_entry), 935 /*sense key entries*/NULL, 936 sony_mo_entries 937 }, 938 { 939 /* 940 * HGST vendor-specific error codes 941 */ 942 {T_DIRECT, SIP_MEDIA_FIXED, "HGST", "*", "*"}, 943 /*num_sense_keys*/0, 944 sizeof(hgst_entries)/sizeof(struct asc_table_entry), 945 /*sense key entries*/NULL, 946 hgst_entries 947 }, 948 { 949 /* 950 * SEAGATE vendor-specific error codes 951 */ 952 {T_DIRECT, SIP_MEDIA_FIXED, "SEAGATE", "*", "*"}, 953 /*num_sense_keys*/0, 954 sizeof(seagate_entries)/sizeof(struct asc_table_entry), 955 /*sense key entries*/NULL, 956 seagate_entries 957 } 958}; 959 960const int sense_quirk_table_size = 961 sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]); 962 963static struct asc_table_entry asc_table[] = { 964 /* 965 * From: http://www.t10.org/lists/asc-num.txt 966 * Modifications by Jung-uk Kim (jkim@FreeBSD.org) 967 */ 968 /* 969 * File: ASC-NUM.TXT 970 * 971 * SCSI ASC/ASCQ Assignments 972 * Numeric Sorted Listing 973 * as of 8/12/15 974 * 975 * D - DIRECT ACCESS DEVICE (SBC-2) device column key 976 * .T - SEQUENTIAL ACCESS DEVICE (SSC) ------------------- 977 * . L - PRINTER DEVICE (SSC) blank = reserved 978 * . P - PROCESSOR DEVICE (SPC) not blank = allowed 979 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC-2) 980 * . . R - CD DEVICE (MMC) 981 * . . O - OPTICAL MEMORY DEVICE (SBC-2) 982 * . . .M - MEDIA CHANGER DEVICE (SMC) 983 * . . . A - STORAGE ARRAY DEVICE (SCC) 984 * . . . E - ENCLOSURE SERVICES DEVICE (SES) 985 * . . . .B - SIMPLIFIED DIRECT-ACCESS DEVICE (RBC) 986 * . . . . K - OPTICAL CARD READER/WRITER DEVICE (OCRW) 987 * . . . . V - AUTOMATION/DRIVE INTERFACE (ADC) 988 * . . . . .F - OBJECT-BASED STORAGE (OSD) 989 * DTLPWROMAEBKVF 990 * ASC ASCQ Action 991 * Description 992 */ 993 /* DTLPWROMAEBKVF */ 994 { SST(0x00, 0x00, SS_NOP, 995 "No additional sense information") }, 996 /* T */ 997 { SST(0x00, 0x01, SS_RDEF, 998 "Filemark detected") }, 999 /* T */ 1000 { SST(0x00, 0x02, SS_RDEF, 1001 "End-of-partition/medium detected") }, 1002 /* T */ 1003 { SST(0x00, 0x03, SS_RDEF, 1004 "Setmark detected") }, 1005 /* T */ 1006 { SST(0x00, 0x04, SS_RDEF, 1007 "Beginning-of-partition/medium detected") }, 1008 /* TL */ 1009 { SST(0x00, 0x05, SS_RDEF, 1010 "End-of-data detected") }, 1011 /* DTLPWROMAEBKVF */ 1012 { SST(0x00, 0x06, SS_RDEF, 1013 "I/O process terminated") }, 1014 /* T */ 1015 { SST(0x00, 0x07, SS_RDEF, /* XXX TBD */ 1016 "Programmable early warning detected") }, 1017 /* R */ 1018 { SST(0x00, 0x11, SS_FATAL | EBUSY, 1019 "Audio play operation in progress") }, 1020 /* R */ 1021 { SST(0x00, 0x12, SS_NOP, 1022 "Audio play operation paused") }, 1023 /* R */ 1024 { SST(0x00, 0x13, SS_NOP, 1025 "Audio play operation successfully completed") }, 1026 /* R */ 1027 { SST(0x00, 0x14, SS_RDEF, 1028 "Audio play operation stopped due to error") }, 1029 /* R */ 1030 { SST(0x00, 0x15, SS_NOP, 1031 "No current audio status to return") }, 1032 /* DTLPWROMAEBKVF */ 1033 { SST(0x00, 0x16, SS_FATAL | EBUSY, 1034 "Operation in progress") }, 1035 /* DTL WROMAEBKVF */ 1036 { SST(0x00, 0x17, SS_RDEF, 1037 "Cleaning requested") }, 1038 /* T */ 1039 { SST(0x00, 0x18, SS_RDEF, /* XXX TBD */ 1040 "Erase operation in progress") }, 1041 /* T */ 1042 { SST(0x00, 0x19, SS_RDEF, /* XXX TBD */ 1043 "Locate operation in progress") }, 1044 /* T */ 1045 { SST(0x00, 0x1A, SS_RDEF, /* XXX TBD */ 1046 "Rewind operation in progress") }, 1047 /* T */ 1048 { SST(0x00, 0x1B, SS_RDEF, /* XXX TBD */ 1049 "Set capacity operation in progress") }, 1050 /* T */ 1051 { SST(0x00, 0x1C, SS_RDEF, /* XXX TBD */ 1052 "Verify operation in progress") }, 1053 /* DT B */ 1054 { SST(0x00, 0x1D, SS_NOP, 1055 "ATA pass through information available") }, 1056 /* DT R MAEBKV */ 1057 { SST(0x00, 0x1E, SS_RDEF, /* XXX TBD */ 1058 "Conflicting SA creation request") }, 1059 /* DT B */ 1060 { SST(0x00, 0x1F, SS_RDEF, /* XXX TBD */ 1061 "Logical unit transitioning to another power condition") }, 1062 /* DT P B */ 1063 { SST(0x00, 0x20, SS_NOP, 1064 "Extended copy information available") }, 1065 /* D */ 1066 { SST(0x00, 0x21, SS_RDEF, /* XXX TBD */ 1067 "Atomic command aborted due to ACA") }, 1068 /* D W O BK */ 1069 { SST(0x01, 0x00, SS_RDEF, 1070 "No index/sector signal") }, 1071 /* D WRO BK */ 1072 { SST(0x02, 0x00, SS_RDEF, 1073 "No seek complete") }, 1074 /* DTL W O BK */ 1075 { SST(0x03, 0x00, SS_RDEF, 1076 "Peripheral device write fault") }, 1077 /* T */ 1078 { SST(0x03, 0x01, SS_RDEF, 1079 "No write current") }, 1080 /* T */ 1081 { SST(0x03, 0x02, SS_RDEF, 1082 "Excessive write errors") }, 1083 /* DTLPWROMAEBKVF */ 1084 { SST(0x04, 0x00, SS_RDEF, 1085 "Logical unit not ready, cause not reportable") }, 1086 /* DTLPWROMAEBKVF */ 1087 { SST(0x04, 0x01, SS_WAIT | EBUSY, 1088 "Logical unit is in process of becoming ready") }, 1089 /* DTLPWROMAEBKVF */ 1090 { SST(0x04, 0x02, SS_START | SSQ_DECREMENT_COUNT | ENXIO, 1091 "Logical unit not ready, initializing command required") }, 1092 /* DTLPWROMAEBKVF */ 1093 { SST(0x04, 0x03, SS_FATAL | ENXIO, 1094 "Logical unit not ready, manual intervention required") }, 1095 /* DTL RO B */ 1096 { SST(0x04, 0x04, SS_FATAL | EBUSY, 1097 "Logical unit not ready, format in progress") }, 1098 /* DT W O A BK F */ 1099 { SST(0x04, 0x05, SS_FATAL | EBUSY, 1100 "Logical unit not ready, rebuild in progress") }, 1101 /* DT W O A BK */ 1102 { SST(0x04, 0x06, SS_FATAL | EBUSY, 1103 "Logical unit not ready, recalculation in progress") }, 1104 /* DTLPWROMAEBKVF */ 1105 { SST(0x04, 0x07, SS_FATAL | EBUSY, 1106 "Logical unit not ready, operation in progress") }, 1107 /* R */ 1108 { SST(0x04, 0x08, SS_FATAL | EBUSY, 1109 "Logical unit not ready, long write in progress") }, 1110 /* DTLPWROMAEBKVF */ 1111 { SST(0x04, 0x09, SS_RDEF, /* XXX TBD */ 1112 "Logical unit not ready, self-test in progress") }, 1113 /* DTLPWROMAEBKVF */ 1114 { SST(0x04, 0x0A, SS_WAIT | ENXIO, 1115 "Logical unit not accessible, asymmetric access state transition")}, 1116 /* DTLPWROMAEBKVF */ 1117 { SST(0x04, 0x0B, SS_FATAL | ENXIO, 1118 "Logical unit not accessible, target port in standby state") }, 1119 /* DTLPWROMAEBKVF */ 1120 { SST(0x04, 0x0C, SS_FATAL | ENXIO, 1121 "Logical unit not accessible, target port in unavailable state") }, 1122 /* F */ 1123 { SST(0x04, 0x0D, SS_RDEF, /* XXX TBD */ 1124 "Logical unit not ready, structure check required") }, 1125 /* DTL WR MAEBKVF */ 1126 { SST(0x04, 0x0E, SS_RDEF, /* XXX TBD */ 1127 "Logical unit not ready, security session in progress") }, 1128 /* DT WROM B */ 1129 { SST(0x04, 0x10, SS_RDEF, /* XXX TBD */ 1130 "Logical unit not ready, auxiliary memory not accessible") }, 1131 /* DT WRO AEB VF */ 1132 { SST(0x04, 0x11, SS_WAIT | EBUSY, 1133 "Logical unit not ready, notify (enable spinup) required") }, 1134 /* M V */ 1135 { SST(0x04, 0x12, SS_RDEF, /* XXX TBD */ 1136 "Logical unit not ready, offline") }, 1137 /* DT R MAEBKV */ 1138 { SST(0x04, 0x13, SS_RDEF, /* XXX TBD */ 1139 "Logical unit not ready, SA creation in progress") }, 1140 /* D B */ 1141 { SST(0x04, 0x14, SS_RDEF, /* XXX TBD */ 1142 "Logical unit not ready, space allocation in progress") }, 1143 /* M */ 1144 { SST(0x04, 0x15, SS_RDEF, /* XXX TBD */ 1145 "Logical unit not ready, robotics disabled") }, 1146 /* M */ 1147 { SST(0x04, 0x16, SS_RDEF, /* XXX TBD */ 1148 "Logical unit not ready, configuration required") }, 1149 /* M */ 1150 { SST(0x04, 0x17, SS_RDEF, /* XXX TBD */ 1151 "Logical unit not ready, calibration required") }, 1152 /* M */ 1153 { SST(0x04, 0x18, SS_RDEF, /* XXX TBD */ 1154 "Logical unit not ready, a door is open") }, 1155 /* M */ 1156 { SST(0x04, 0x19, SS_RDEF, /* XXX TBD */ 1157 "Logical unit not ready, operating in sequential mode") }, 1158 /* DT B */ 1159 { SST(0x04, 0x1A, SS_RDEF, /* XXX TBD */ 1160 "Logical unit not ready, START/STOP UNIT command in progress") }, 1161 /* D B */ 1162 { SST(0x04, 0x1B, SS_RDEF, /* XXX TBD */ 1163 "Logical unit not ready, sanitize in progress") }, 1164 /* DT MAEB */ 1165 { SST(0x04, 0x1C, SS_RDEF, /* XXX TBD */ 1166 "Logical unit not ready, additional power use not yet granted") }, 1167 /* D */ 1168 { SST(0x04, 0x1D, SS_RDEF, /* XXX TBD */ 1169 "Logical unit not ready, configuration in progress") }, 1170 /* D */ 1171 { SST(0x04, 0x1E, SS_FATAL | ENXIO, 1172 "Logical unit not ready, microcode activation required") }, 1173 /* DTLPWROMAEBKVF */ 1174 { SST(0x04, 0x1F, SS_FATAL | ENXIO, 1175 "Logical unit not ready, microcode download required") }, 1176 /* DTLPWROMAEBKVF */ 1177 { SST(0x04, 0x20, SS_RDEF, /* XXX TBD */ 1178 "Logical unit not ready, logical unit reset required") }, 1179 /* DTLPWROMAEBKVF */ 1180 { SST(0x04, 0x21, SS_RDEF, /* XXX TBD */ 1181 "Logical unit not ready, hard reset required") }, 1182 /* DTLPWROMAEBKVF */ 1183 { SST(0x04, 0x22, SS_RDEF, /* XXX TBD */ 1184 "Logical unit not ready, power cycle required") }, 1185 /* DTL WROMAEBKVF */ 1186 { SST(0x05, 0x00, SS_RDEF, 1187 "Logical unit does not respond to selection") }, 1188 /* D WROM BK */ 1189 { SST(0x06, 0x00, SS_RDEF, 1190 "No reference position found") }, 1191 /* DTL WROM BK */ 1192 { SST(0x07, 0x00, SS_RDEF, 1193 "Multiple peripheral devices selected") }, 1194 /* DTL WROMAEBKVF */ 1195 { SST(0x08, 0x00, SS_RDEF, 1196 "Logical unit communication failure") }, 1197 /* DTL WROMAEBKVF */ 1198 { SST(0x08, 0x01, SS_RDEF, 1199 "Logical unit communication time-out") }, 1200 /* DTL WROMAEBKVF */ 1201 { SST(0x08, 0x02, SS_RDEF, 1202 "Logical unit communication parity error") }, 1203 /* DT ROM BK */ 1204 { SST(0x08, 0x03, SS_RDEF, 1205 "Logical unit communication CRC error (Ultra-DMA/32)") }, 1206 /* DTLPWRO K */ 1207 { SST(0x08, 0x04, SS_RDEF, /* XXX TBD */ 1208 "Unreachable copy target") }, 1209 /* DT WRO B */ 1210 { SST(0x09, 0x00, SS_RDEF, 1211 "Track following error") }, 1212 /* WRO K */ 1213 { SST(0x09, 0x01, SS_RDEF, 1214 "Tracking servo failure") }, 1215 /* WRO K */ 1216 { SST(0x09, 0x02, SS_RDEF, 1217 "Focus servo failure") }, 1218 /* WRO */ 1219 { SST(0x09, 0x03, SS_RDEF, 1220 "Spindle servo failure") }, 1221 /* DT WRO B */ 1222 { SST(0x09, 0x04, SS_RDEF, 1223 "Head select fault") }, 1224 /* DT RO B */ 1225 { SST(0x09, 0x05, SS_RDEF, 1226 "Vibration induced tracking error") }, 1227 /* DTLPWROMAEBKVF */ 1228 { SST(0x0A, 0x00, SS_FATAL | ENOSPC, 1229 "Error log overflow") }, 1230 /* DTLPWROMAEBKVF */ 1231 { SST(0x0B, 0x00, SS_NOP | SSQ_PRINT_SENSE, 1232 "Warning") }, 1233 /* DTLPWROMAEBKVF */ 1234 { SST(0x0B, 0x01, SS_NOP | SSQ_PRINT_SENSE, 1235 "Warning - specified temperature exceeded") }, 1236 /* DTLPWROMAEBKVF */ 1237 { SST(0x0B, 0x02, SS_NOP | SSQ_PRINT_SENSE, 1238 "Warning - enclosure degraded") }, 1239 /* DTLPWROMAEBKVF */ 1240 { SST(0x0B, 0x03, SS_NOP | SSQ_PRINT_SENSE, 1241 "Warning - background self-test failed") }, 1242 /* DTLPWRO AEBKVF */ 1243 { SST(0x0B, 0x04, SS_NOP | SSQ_PRINT_SENSE, 1244 "Warning - background pre-scan detected medium error") }, 1245 /* DTLPWRO AEBKVF */ 1246 { SST(0x0B, 0x05, SS_NOP | SSQ_PRINT_SENSE, 1247 "Warning - background medium scan detected medium error") }, 1248 /* DTLPWROMAEBKVF */ 1249 { SST(0x0B, 0x06, SS_NOP | SSQ_PRINT_SENSE, 1250 "Warning - non-volatile cache now volatile") }, 1251 /* DTLPWROMAEBKVF */ 1252 { SST(0x0B, 0x07, SS_NOP | SSQ_PRINT_SENSE, 1253 "Warning - degraded power to non-volatile cache") }, 1254 /* DTLPWROMAEBKVF */ 1255 { SST(0x0B, 0x08, SS_NOP | SSQ_PRINT_SENSE, 1256 "Warning - power loss expected") }, 1257 /* D */ 1258 { SST(0x0B, 0x09, SS_NOP | SSQ_PRINT_SENSE, 1259 "Warning - device statistics notification available") }, 1260 /* DTLPWROMAEBKVF */ 1261 { SST(0x0B, 0x0A, SS_NOP | SSQ_PRINT_SENSE, 1262 "Warning - High critical temperature limit exceeded") }, 1263 /* DTLPWROMAEBKVF */ 1264 { SST(0x0B, 0x0B, SS_NOP | SSQ_PRINT_SENSE, 1265 "Warning - Low critical temperature limit exceeded") }, 1266 /* DTLPWROMAEBKVF */ 1267 { SST(0x0B, 0x0C, SS_NOP | SSQ_PRINT_SENSE, 1268 "Warning - High operating temperature limit exceeded") }, 1269 /* DTLPWROMAEBKVF */ 1270 { SST(0x0B, 0x0D, SS_NOP | SSQ_PRINT_SENSE, 1271 "Warning - Low operating temperature limit exceeded") }, 1272 /* DTLPWROMAEBKVF */ 1273 { SST(0x0B, 0x0E, SS_NOP | SSQ_PRINT_SENSE, 1274 "Warning - High citical humidity limit exceeded") }, 1275 /* DTLPWROMAEBKVF */ 1276 { SST(0x0B, 0x0F, SS_NOP | SSQ_PRINT_SENSE, 1277 "Warning - Low citical humidity limit exceeded") }, 1278 /* DTLPWROMAEBKVF */ 1279 { SST(0x0B, 0x10, SS_NOP | SSQ_PRINT_SENSE, 1280 "Warning - High operating humidity limit exceeded") }, 1281 /* DTLPWROMAEBKVF */ 1282 { SST(0x0B, 0x11, SS_NOP | SSQ_PRINT_SENSE, 1283 "Warning - Low operating humidity limit exceeded") }, 1284 /* T R */ 1285 { SST(0x0C, 0x00, SS_RDEF, 1286 "Write error") }, 1287 /* K */ 1288 { SST(0x0C, 0x01, SS_NOP | SSQ_PRINT_SENSE, 1289 "Write error - recovered with auto reallocation") }, 1290 /* D W O BK */ 1291 { SST(0x0C, 0x02, SS_RDEF, 1292 "Write error - auto reallocation failed") }, 1293 /* D W O BK */ 1294 { SST(0x0C, 0x03, SS_RDEF, 1295 "Write error - recommend reassignment") }, 1296 /* DT W O B */ 1297 { SST(0x0C, 0x04, SS_RDEF, 1298 "Compression check miscompare error") }, 1299 /* DT W O B */ 1300 { SST(0x0C, 0x05, SS_RDEF, 1301 "Data expansion occurred during compression") }, 1302 /* DT W O B */ 1303 { SST(0x0C, 0x06, SS_RDEF, 1304 "Block not compressible") }, 1305 /* R */ 1306 { SST(0x0C, 0x07, SS_RDEF, 1307 "Write error - recovery needed") }, 1308 /* R */ 1309 { SST(0x0C, 0x08, SS_RDEF, 1310 "Write error - recovery failed") }, 1311 /* R */ 1312 { SST(0x0C, 0x09, SS_RDEF, 1313 "Write error - loss of streaming") }, 1314 /* R */ 1315 { SST(0x0C, 0x0A, SS_RDEF, 1316 "Write error - padding blocks added") }, 1317 /* DT WROM B */ 1318 { SST(0x0C, 0x0B, SS_RDEF, /* XXX TBD */ 1319 "Auxiliary memory write error") }, 1320 /* DTLPWRO AEBKVF */ 1321 { SST(0x0C, 0x0C, SS_RDEF, /* XXX TBD */ 1322 "Write error - unexpected unsolicited data") }, 1323 /* DTLPWRO AEBKVF */ 1324 { SST(0x0C, 0x0D, SS_RDEF, /* XXX TBD */ 1325 "Write error - not enough unsolicited data") }, 1326 /* DT W O BK */ 1327 { SST(0x0C, 0x0E, SS_RDEF, /* XXX TBD */ 1328 "Multiple write errors") }, 1329 /* R */ 1330 { SST(0x0C, 0x0F, SS_RDEF, /* XXX TBD */ 1331 "Defects in error window") }, 1332 /* D */ 1333 { SST(0x0C, 0x10, SS_RDEF, /* XXX TBD */ 1334 "Incomplete multiple atomic write operations") }, 1335 /* D */ 1336 { SST(0x0C, 0x11, SS_RDEF, /* XXX TBD */ 1337 "Write error - recovery scan needed") }, 1338 /* D */ 1339 { SST(0x0C, 0x12, SS_RDEF, /* XXX TBD */ 1340 "Write error - insufficient zone resources") }, 1341 /* DTLPWRO A K */ 1342 { SST(0x0D, 0x00, SS_RDEF, /* XXX TBD */ 1343 "Error detected by third party temporary initiator") }, 1344 /* DTLPWRO A K */ 1345 { SST(0x0D, 0x01, SS_RDEF, /* XXX TBD */ 1346 "Third party device failure") }, 1347 /* DTLPWRO A K */ 1348 { SST(0x0D, 0x02, SS_RDEF, /* XXX TBD */ 1349 "Copy target device not reachable") }, 1350 /* DTLPWRO A K */ 1351 { SST(0x0D, 0x03, SS_RDEF, /* XXX TBD */ 1352 "Incorrect copy target device type") }, 1353 /* DTLPWRO A K */ 1354 { SST(0x0D, 0x04, SS_RDEF, /* XXX TBD */ 1355 "Copy target device data underrun") }, 1356 /* DTLPWRO A K */ 1357 { SST(0x0D, 0x05, SS_RDEF, /* XXX TBD */ 1358 "Copy target device data overrun") }, 1359 /* DT PWROMAEBK F */ 1360 { SST(0x0E, 0x00, SS_RDEF, /* XXX TBD */ 1361 "Invalid information unit") }, 1362 /* DT PWROMAEBK F */ 1363 { SST(0x0E, 0x01, SS_RDEF, /* XXX TBD */ 1364 "Information unit too short") }, 1365 /* DT PWROMAEBK F */ 1366 { SST(0x0E, 0x02, SS_RDEF, /* XXX TBD */ 1367 "Information unit too long") }, 1368 /* DT P R MAEBK F */ 1369 { SST(0x0E, 0x03, SS_FATAL | EINVAL, 1370 "Invalid field in command information unit") }, 1371 /* D W O BK */ 1372 { SST(0x10, 0x00, SS_RDEF, 1373 "ID CRC or ECC error") }, 1374 /* DT W O */ 1375 { SST(0x10, 0x01, SS_RDEF, /* XXX TBD */ 1376 "Logical block guard check failed") }, 1377 /* DT W O */ 1378 { SST(0x10, 0x02, SS_RDEF, /* XXX TBD */ 1379 "Logical block application tag check failed") }, 1380 /* DT W O */ 1381 { SST(0x10, 0x03, SS_RDEF, /* XXX TBD */ 1382 "Logical block reference tag check failed") }, 1383 /* T */ 1384 { SST(0x10, 0x04, SS_RDEF, /* XXX TBD */ 1385 "Logical block protection error on recovered buffer data") }, 1386 /* T */ 1387 { SST(0x10, 0x05, SS_RDEF, /* XXX TBD */ 1388 "Logical block protection method error") }, 1389 /* DT WRO BK */ 1390 { SST(0x11, 0x00, SS_FATAL|EIO, 1391 "Unrecovered read error") }, 1392 /* DT WRO BK */ 1393 { SST(0x11, 0x01, SS_FATAL|EIO, 1394 "Read retries exhausted") }, 1395 /* DT WRO BK */ 1396 { SST(0x11, 0x02, SS_FATAL|EIO, 1397 "Error too long to correct") }, 1398 /* DT W O BK */ 1399 { SST(0x11, 0x03, SS_FATAL|EIO, 1400 "Multiple read errors") }, 1401 /* D W O BK */ 1402 { SST(0x11, 0x04, SS_FATAL|EIO, 1403 "Unrecovered read error - auto reallocate failed") }, 1404 /* WRO B */ 1405 { SST(0x11, 0x05, SS_FATAL|EIO, 1406 "L-EC uncorrectable error") }, 1407 /* WRO B */ 1408 { SST(0x11, 0x06, SS_FATAL|EIO, 1409 "CIRC unrecovered error") }, 1410 /* W O B */ 1411 { SST(0x11, 0x07, SS_RDEF, 1412 "Data re-synchronization error") }, 1413 /* T */ 1414 { SST(0x11, 0x08, SS_RDEF, 1415 "Incomplete block read") }, 1416 /* T */ 1417 { SST(0x11, 0x09, SS_RDEF, 1418 "No gap found") }, 1419 /* DT O BK */ 1420 { SST(0x11, 0x0A, SS_RDEF, 1421 "Miscorrected error") }, 1422 /* D W O BK */ 1423 { SST(0x11, 0x0B, SS_FATAL|EIO, 1424 "Unrecovered read error - recommend reassignment") }, 1425 /* D W O BK */ 1426 { SST(0x11, 0x0C, SS_FATAL|EIO, 1427 "Unrecovered read error - recommend rewrite the data") }, 1428 /* DT WRO B */ 1429 { SST(0x11, 0x0D, SS_RDEF, 1430 "De-compression CRC error") }, 1431 /* DT WRO B */ 1432 { SST(0x11, 0x0E, SS_RDEF, 1433 "Cannot decompress using declared algorithm") }, 1434 /* R */ 1435 { SST(0x11, 0x0F, SS_RDEF, 1436 "Error reading UPC/EAN number") }, 1437 /* R */ 1438 { SST(0x11, 0x10, SS_RDEF, 1439 "Error reading ISRC number") }, 1440 /* R */ 1441 { SST(0x11, 0x11, SS_RDEF, 1442 "Read error - loss of streaming") }, 1443 /* DT WROM B */ 1444 { SST(0x11, 0x12, SS_RDEF, /* XXX TBD */ 1445 "Auxiliary memory read error") }, 1446 /* DTLPWRO AEBKVF */ 1447 { SST(0x11, 0x13, SS_RDEF, /* XXX TBD */ 1448 "Read error - failed retransmission request") }, 1449 /* D */ 1450 { SST(0x11, 0x14, SS_RDEF, /* XXX TBD */ 1451 "Read error - LBA marked bad by application client") }, 1452 /* D */ 1453 { SST(0x11, 0x15, SS_RDEF, /* XXX TBD */ 1454 "Write after sanitize required") }, 1455 /* D W O BK */ 1456 { SST(0x12, 0x00, SS_RDEF, 1457 "Address mark not found for ID field") }, 1458 /* D W O BK */ 1459 { SST(0x13, 0x00, SS_RDEF, 1460 "Address mark not found for data field") }, 1461 /* DTL WRO BK */ 1462 { SST(0x14, 0x00, SS_RDEF, 1463 "Recorded entity not found") }, 1464 /* DT WRO BK */ 1465 { SST(0x14, 0x01, SS_RDEF, 1466 "Record not found") }, 1467 /* T */ 1468 { SST(0x14, 0x02, SS_RDEF, 1469 "Filemark or setmark not found") }, 1470 /* T */ 1471 { SST(0x14, 0x03, SS_RDEF, 1472 "End-of-data not found") }, 1473 /* T */ 1474 { SST(0x14, 0x04, SS_RDEF, 1475 "Block sequence error") }, 1476 /* DT W O BK */ 1477 { SST(0x14, 0x05, SS_RDEF, 1478 "Record not found - recommend reassignment") }, 1479 /* DT W O BK */ 1480 { SST(0x14, 0x06, SS_RDEF, 1481 "Record not found - data auto-reallocated") }, 1482 /* T */ 1483 { SST(0x14, 0x07, SS_RDEF, /* XXX TBD */ 1484 "Locate operation failure") }, 1485 /* DTL WROM BK */ 1486 { SST(0x15, 0x00, SS_RDEF, 1487 "Random positioning error") }, 1488 /* DTL WROM BK */ 1489 { SST(0x15, 0x01, SS_RDEF, 1490 "Mechanical positioning error") }, 1491 /* DT WRO BK */ 1492 { SST(0x15, 0x02, SS_RDEF, 1493 "Positioning error detected by read of medium") }, 1494 /* D W O BK */ 1495 { SST(0x16, 0x00, SS_RDEF, 1496 "Data synchronization mark error") }, 1497 /* D W O BK */ 1498 { SST(0x16, 0x01, SS_RDEF, 1499 "Data sync error - data rewritten") }, 1500 /* D W O BK */ 1501 { SST(0x16, 0x02, SS_RDEF, 1502 "Data sync error - recommend rewrite") }, 1503 /* D W O BK */ 1504 { SST(0x16, 0x03, SS_NOP | SSQ_PRINT_SENSE, 1505 "Data sync error - data auto-reallocated") }, 1506 /* D W O BK */ 1507 { SST(0x16, 0x04, SS_RDEF, 1508 "Data sync error - recommend reassignment") }, 1509 /* DT WRO BK */ 1510 { SST(0x17, 0x00, SS_NOP | SSQ_PRINT_SENSE, 1511 "Recovered data with no error correction applied") }, 1512 /* DT WRO BK */ 1513 { SST(0x17, 0x01, SS_NOP | SSQ_PRINT_SENSE, 1514 "Recovered data with retries") }, 1515 /* DT WRO BK */ 1516 { SST(0x17, 0x02, SS_NOP | SSQ_PRINT_SENSE, 1517 "Recovered data with positive head offset") }, 1518 /* DT WRO BK */ 1519 { SST(0x17, 0x03, SS_NOP | SSQ_PRINT_SENSE, 1520 "Recovered data with negative head offset") }, 1521 /* WRO B */ 1522 { SST(0x17, 0x04, SS_NOP | SSQ_PRINT_SENSE, 1523 "Recovered data with retries and/or CIRC applied") }, 1524 /* D WRO BK */ 1525 { SST(0x17, 0x05, SS_NOP | SSQ_PRINT_SENSE, 1526 "Recovered data using previous sector ID") }, 1527 /* D W O BK */ 1528 { SST(0x17, 0x06, SS_NOP | SSQ_PRINT_SENSE, 1529 "Recovered data without ECC - data auto-reallocated") }, 1530 /* D WRO BK */ 1531 { SST(0x17, 0x07, SS_NOP | SSQ_PRINT_SENSE, 1532 "Recovered data without ECC - recommend reassignment") }, 1533 /* D WRO BK */ 1534 { SST(0x17, 0x08, SS_NOP | SSQ_PRINT_SENSE, 1535 "Recovered data without ECC - recommend rewrite") }, 1536 /* D WRO BK */ 1537 { SST(0x17, 0x09, SS_NOP | SSQ_PRINT_SENSE, 1538 "Recovered data without ECC - data rewritten") }, 1539 /* DT WRO BK */ 1540 { SST(0x18, 0x00, SS_NOP | SSQ_PRINT_SENSE, 1541 "Recovered data with error correction applied") }, 1542 /* D WRO BK */ 1543 { SST(0x18, 0x01, SS_NOP | SSQ_PRINT_SENSE, 1544 "Recovered data with error corr. & retries applied") }, 1545 /* D WRO BK */ 1546 { SST(0x18, 0x02, SS_NOP | SSQ_PRINT_SENSE, 1547 "Recovered data - data auto-reallocated") }, 1548 /* R */ 1549 { SST(0x18, 0x03, SS_NOP | SSQ_PRINT_SENSE, 1550 "Recovered data with CIRC") }, 1551 /* R */ 1552 { SST(0x18, 0x04, SS_NOP | SSQ_PRINT_SENSE, 1553 "Recovered data with L-EC") }, 1554 /* D WRO BK */ 1555 { SST(0x18, 0x05, SS_NOP | SSQ_PRINT_SENSE, 1556 "Recovered data - recommend reassignment") }, 1557 /* D WRO BK */ 1558 { SST(0x18, 0x06, SS_NOP | SSQ_PRINT_SENSE, 1559 "Recovered data - recommend rewrite") }, 1560 /* D W O BK */ 1561 { SST(0x18, 0x07, SS_NOP | SSQ_PRINT_SENSE, 1562 "Recovered data with ECC - data rewritten") }, 1563 /* R */ 1564 { SST(0x18, 0x08, SS_RDEF, /* XXX TBD */ 1565 "Recovered data with linking") }, 1566 /* D O K */ 1567 { SST(0x19, 0x00, SS_RDEF, 1568 "Defect list error") }, 1569 /* D O K */ 1570 { SST(0x19, 0x01, SS_RDEF, 1571 "Defect list not available") }, 1572 /* D O K */ 1573 { SST(0x19, 0x02, SS_RDEF, 1574 "Defect list error in primary list") }, 1575 /* D O K */ 1576 { SST(0x19, 0x03, SS_RDEF, 1577 "Defect list error in grown list") }, 1578 /* DTLPWROMAEBKVF */ 1579 { SST(0x1A, 0x00, SS_RDEF, 1580 "Parameter list length error") }, 1581 /* DTLPWROMAEBKVF */ 1582 { SST(0x1B, 0x00, SS_RDEF, 1583 "Synchronous data transfer error") }, 1584 /* D O BK */ 1585 { SST(0x1C, 0x00, SS_RDEF, 1586 "Defect list not found") }, 1587 /* D O BK */ 1588 { SST(0x1C, 0x01, SS_RDEF, 1589 "Primary defect list not found") }, 1590 /* D O BK */ 1591 { SST(0x1C, 0x02, SS_RDEF, 1592 "Grown defect list not found") }, 1593 /* DT WRO BK */ 1594 { SST(0x1D, 0x00, SS_FATAL, 1595 "Miscompare during verify operation") }, 1596 /* D B */ 1597 { SST(0x1D, 0x01, SS_RDEF, /* XXX TBD */ 1598 "Miscomparable verify of unmapped LBA") }, 1599 /* D W O BK */ 1600 { SST(0x1E, 0x00, SS_NOP | SSQ_PRINT_SENSE, 1601 "Recovered ID with ECC correction") }, 1602 /* D O K */ 1603 { SST(0x1F, 0x00, SS_RDEF, 1604 "Partial defect list transfer") }, 1605 /* DTLPWROMAEBKVF */ 1606 { SST(0x20, 0x00, SS_FATAL | EINVAL, 1607 "Invalid command operation code") }, 1608 /* DT PWROMAEBK */ 1609 { SST(0x20, 0x01, SS_RDEF, /* XXX TBD */ 1610 "Access denied - initiator pending-enrolled") }, 1611 /* DT PWROMAEBK */ 1612 { SST(0x20, 0x02, SS_FATAL | EPERM, 1613 "Access denied - no access rights") }, 1614 /* DT PWROMAEBK */ 1615 { SST(0x20, 0x03, SS_RDEF, /* XXX TBD */ 1616 "Access denied - invalid mgmt ID key") }, 1617 /* T */ 1618 { SST(0x20, 0x04, SS_RDEF, /* XXX TBD */ 1619 "Illegal command while in write capable state") }, 1620 /* T */ 1621 { SST(0x20, 0x05, SS_RDEF, /* XXX TBD */ 1622 "Obsolete") }, 1623 /* T */ 1624 { SST(0x20, 0x06, SS_RDEF, /* XXX TBD */ 1625 "Illegal command while in explicit address mode") }, 1626 /* T */ 1627 { SST(0x20, 0x07, SS_RDEF, /* XXX TBD */ 1628 "Illegal command while in implicit address mode") }, 1629 /* DT PWROMAEBK */ 1630 { SST(0x20, 0x08, SS_RDEF, /* XXX TBD */ 1631 "Access denied - enrollment conflict") }, 1632 /* DT PWROMAEBK */ 1633 { SST(0x20, 0x09, SS_RDEF, /* XXX TBD */ 1634 "Access denied - invalid LU identifier") }, 1635 /* DT PWROMAEBK */ 1636 { SST(0x20, 0x0A, SS_RDEF, /* XXX TBD */ 1637 "Access denied - invalid proxy token") }, 1638 /* DT PWROMAEBK */ 1639 { SST(0x20, 0x0B, SS_RDEF, /* XXX TBD */ 1640 "Access denied - ACL LUN conflict") }, 1641 /* T */ 1642 { SST(0x20, 0x0C, SS_FATAL | EINVAL, 1643 "Illegal command when not in append-only mode") }, 1644 /* DT WRO BK */ 1645 { SST(0x21, 0x00, SS_FATAL | EINVAL, 1646 "Logical block address out of range") }, 1647 /* DT WROM BK */ 1648 { SST(0x21, 0x01, SS_FATAL | EINVAL, 1649 "Invalid element address") }, 1650 /* R */ 1651 { SST(0x21, 0x02, SS_RDEF, /* XXX TBD */ 1652 "Invalid address for write") }, 1653 /* R */ 1654 { SST(0x21, 0x03, SS_RDEF, /* XXX TBD */ 1655 "Invalid write crossing layer jump") }, 1656 /* D */ 1657 { SST(0x21, 0x04, SS_RDEF, /* XXX TBD */ 1658 "Unaligned write command") }, 1659 /* D */ 1660 { SST(0x21, 0x05, SS_RDEF, /* XXX TBD */ 1661 "Write boundary violation") }, 1662 /* D */ 1663 { SST(0x21, 0x06, SS_RDEF, /* XXX TBD */ 1664 "Attempt to read invalid data") }, 1665 /* D */ 1666 { SST(0x21, 0x07, SS_RDEF, /* XXX TBD */ 1667 "Read boundary violation") }, 1668 /* D */ 1669 { SST(0x22, 0x00, SS_FATAL | EINVAL, 1670 "Illegal function (use 20 00, 24 00, or 26 00)") }, 1671 /* DT P B */ 1672 { SST(0x23, 0x00, SS_FATAL | EINVAL, 1673 "Invalid token operation, cause not reportable") }, 1674 /* DT P B */ 1675 { SST(0x23, 0x01, SS_FATAL | EINVAL, 1676 "Invalid token operation, unsupported token type") }, 1677 /* DT P B */ 1678 { SST(0x23, 0x02, SS_FATAL | EINVAL, 1679 "Invalid token operation, remote token usage not supported") }, 1680 /* DT P B */ 1681 { SST(0x23, 0x03, SS_FATAL | EINVAL, 1682 "Invalid token operation, remote ROD token creation not supported") }, 1683 /* DT P B */ 1684 { SST(0x23, 0x04, SS_FATAL | EINVAL, 1685 "Invalid token operation, token unknown") }, 1686 /* DT P B */ 1687 { SST(0x23, 0x05, SS_FATAL | EINVAL, 1688 "Invalid token operation, token corrupt") }, 1689 /* DT P B */ 1690 { SST(0x23, 0x06, SS_FATAL | EINVAL, 1691 "Invalid token operation, token revoked") }, 1692 /* DT P B */ 1693 { SST(0x23, 0x07, SS_FATAL | EINVAL, 1694 "Invalid token operation, token expired") }, 1695 /* DT P B */ 1696 { SST(0x23, 0x08, SS_FATAL | EINVAL, 1697 "Invalid token operation, token cancelled") }, 1698 /* DT P B */ 1699 { SST(0x23, 0x09, SS_FATAL | EINVAL, 1700 "Invalid token operation, token deleted") }, 1701 /* DT P B */ 1702 { SST(0x23, 0x0A, SS_FATAL | EINVAL, 1703 "Invalid token operation, invalid token length") }, 1704 /* DTLPWROMAEBKVF */ 1705 { SST(0x24, 0x00, SS_FATAL | EINVAL, 1706 "Invalid field in CDB") }, 1707 /* DTLPWRO AEBKVF */ 1708 { SST(0x24, 0x01, SS_RDEF, /* XXX TBD */ 1709 "CDB decryption error") }, 1710 /* T */ 1711 { SST(0x24, 0x02, SS_RDEF, /* XXX TBD */ 1712 "Obsolete") }, 1713 /* T */ 1714 { SST(0x24, 0x03, SS_RDEF, /* XXX TBD */ 1715 "Obsolete") }, 1716 /* F */ 1717 { SST(0x24, 0x04, SS_RDEF, /* XXX TBD */ 1718 "Security audit value frozen") }, 1719 /* F */ 1720 { SST(0x24, 0x05, SS_RDEF, /* XXX TBD */ 1721 "Security working key frozen") }, 1722 /* F */ 1723 { SST(0x24, 0x06, SS_RDEF, /* XXX TBD */ 1724 "NONCE not unique") }, 1725 /* F */ 1726 { SST(0x24, 0x07, SS_RDEF, /* XXX TBD */ 1727 "NONCE timestamp out of range") }, 1728 /* DT R MAEBKV */ 1729 { SST(0x24, 0x08, SS_RDEF, /* XXX TBD */ 1730 "Invalid XCDB") }, 1731 /* DTLPWROMAEBKVF */ 1732 { SST(0x25, 0x00, SS_FATAL | ENXIO | SSQ_LOST, 1733 "Logical unit not supported") }, 1734 /* DTLPWROMAEBKVF */ 1735 { SST(0x26, 0x00, SS_FATAL | EINVAL, 1736 "Invalid field in parameter list") }, 1737 /* DTLPWROMAEBKVF */ 1738 { SST(0x26, 0x01, SS_FATAL | EINVAL, 1739 "Parameter not supported") }, 1740 /* DTLPWROMAEBKVF */ 1741 { SST(0x26, 0x02, SS_FATAL | EINVAL, 1742 "Parameter value invalid") }, 1743 /* DTLPWROMAE K */ 1744 { SST(0x26, 0x03, SS_FATAL | EINVAL, 1745 "Threshold parameters not supported") }, 1746 /* DTLPWROMAEBKVF */ 1747 { SST(0x26, 0x04, SS_FATAL | EINVAL, 1748 "Invalid release of persistent reservation") }, 1749 /* DTLPWRO A BK */ 1750 { SST(0x26, 0x05, SS_RDEF, /* XXX TBD */ 1751 "Data decryption error") }, 1752 /* DTLPWRO K */ 1753 { SST(0x26, 0x06, SS_FATAL | EINVAL, 1754 "Too many target descriptors") }, 1755 /* DTLPWRO K */ 1756 { SST(0x26, 0x07, SS_FATAL | EINVAL, 1757 "Unsupported target descriptor type code") }, 1758 /* DTLPWRO K */ 1759 { SST(0x26, 0x08, SS_FATAL | EINVAL, 1760 "Too many segment descriptors") }, 1761 /* DTLPWRO K */ 1762 { SST(0x26, 0x09, SS_FATAL | EINVAL, 1763 "Unsupported segment descriptor type code") }, 1764 /* DTLPWRO K */ 1765 { SST(0x26, 0x0A, SS_FATAL | EINVAL, 1766 "Unexpected inexact segment") }, 1767 /* DTLPWRO K */ 1768 { SST(0x26, 0x0B, SS_FATAL | EINVAL, 1769 "Inline data length exceeded") }, 1770 /* DTLPWRO K */ 1771 { SST(0x26, 0x0C, SS_FATAL | EINVAL, 1772 "Invalid operation for copy source or destination") }, 1773 /* DTLPWRO K */ 1774 { SST(0x26, 0x0D, SS_FATAL | EINVAL, 1775 "Copy segment granularity violation") }, 1776 /* DT PWROMAEBK */ 1777 { SST(0x26, 0x0E, SS_RDEF, /* XXX TBD */ 1778 "Invalid parameter while port is enabled") }, 1779 /* F */ 1780 { SST(0x26, 0x0F, SS_RDEF, /* XXX TBD */ 1781 "Invalid data-out buffer integrity check value") }, 1782 /* T */ 1783 { SST(0x26, 0x10, SS_RDEF, /* XXX TBD */ 1784 "Data decryption key fail limit reached") }, 1785 /* T */ 1786 { SST(0x26, 0x11, SS_RDEF, /* XXX TBD */ 1787 "Incomplete key-associated data set") }, 1788 /* T */ 1789 { SST(0x26, 0x12, SS_RDEF, /* XXX TBD */ 1790 "Vendor specific key reference not found") }, 1791 /* D */ 1792 { SST(0x26, 0x13, SS_RDEF, /* XXX TBD */ 1793 "Application tag mode page is invalid") }, 1794 /* DT WRO BK */ 1795 { SST(0x27, 0x00, SS_FATAL | EACCES, 1796 "Write protected") }, 1797 /* DT WRO BK */ 1798 { SST(0x27, 0x01, SS_FATAL | EACCES, 1799 "Hardware write protected") }, 1800 /* DT WRO BK */ 1801 { SST(0x27, 0x02, SS_FATAL | EACCES, 1802 "Logical unit software write protected") }, 1803 /* T R */ 1804 { SST(0x27, 0x03, SS_FATAL | EACCES, 1805 "Associated write protect") }, 1806 /* T R */ 1807 { SST(0x27, 0x04, SS_FATAL | EACCES, 1808 "Persistent write protect") }, 1809 /* T R */ 1810 { SST(0x27, 0x05, SS_FATAL | EACCES, 1811 "Permanent write protect") }, 1812 /* R F */ 1813 { SST(0x27, 0x06, SS_RDEF, /* XXX TBD */ 1814 "Conditional write protect") }, 1815 /* D B */ 1816 { SST(0x27, 0x07, SS_FATAL | ENOSPC, 1817 "Space allocation failed write protect") }, 1818 /* D */ 1819 { SST(0x27, 0x08, SS_FATAL | EACCES, 1820 "Zone is read only") }, 1821 /* DTLPWROMAEBKVF */ 1822 { SST(0x28, 0x00, SS_FATAL | ENXIO, 1823 "Not ready to ready change, medium may have changed") }, 1824 /* DT WROM B */ 1825 { SST(0x28, 0x01, SS_FATAL | ENXIO, 1826 "Import or export element accessed") }, 1827 /* R */ 1828 { SST(0x28, 0x02, SS_RDEF, /* XXX TBD */ 1829 "Format-layer may have changed") }, 1830 /* M */ 1831 { SST(0x28, 0x03, SS_RDEF, /* XXX TBD */ 1832 "Import/export element accessed, medium changed") }, 1833 /* 1834 * XXX JGibbs - All of these should use the same errno, but I don't 1835 * think ENXIO is the correct choice. Should we borrow from 1836 * the networking errnos? ECONNRESET anyone? 1837 */ 1838 /* DTLPWROMAEBKVF */ 1839 { SST(0x29, 0x00, SS_FATAL | ENXIO, 1840 "Power on, reset, or bus device reset occurred") }, 1841 /* DTLPWROMAEBKVF */ 1842 { SST(0x29, 0x01, SS_RDEF, 1843 "Power on occurred") }, 1844 /* DTLPWROMAEBKVF */ 1845 { SST(0x29, 0x02, SS_RDEF, 1846 "SCSI bus reset occurred") }, 1847 /* DTLPWROMAEBKVF */ 1848 { SST(0x29, 0x03, SS_RDEF, 1849 "Bus device reset function occurred") }, 1850 /* DTLPWROMAEBKVF */ 1851 { SST(0x29, 0x04, SS_RDEF, 1852 "Device internal reset") }, 1853 /* DTLPWROMAEBKVF */ 1854 { SST(0x29, 0x05, SS_RDEF, 1855 "Transceiver mode changed to single-ended") }, 1856 /* DTLPWROMAEBKVF */ 1857 { SST(0x29, 0x06, SS_RDEF, 1858 "Transceiver mode changed to LVD") }, 1859 /* DTLPWROMAEBKVF */ 1860 { SST(0x29, 0x07, SS_RDEF, /* XXX TBD */ 1861 "I_T nexus loss occurred") }, 1862 /* DTL WROMAEBKVF */ 1863 { SST(0x2A, 0x00, SS_RDEF, 1864 "Parameters changed") }, 1865 /* DTL WROMAEBKVF */ 1866 { SST(0x2A, 0x01, SS_RDEF, 1867 "Mode parameters changed") }, 1868 /* DTL WROMAE K */ 1869 { SST(0x2A, 0x02, SS_RDEF, 1870 "Log parameters changed") }, 1871 /* DTLPWROMAE K */ 1872 { SST(0x2A, 0x03, SS_RDEF, 1873 "Reservations preempted") }, 1874 /* DTLPWROMAE */ 1875 { SST(0x2A, 0x04, SS_RDEF, /* XXX TBD */ 1876 "Reservations released") }, 1877 /* DTLPWROMAE */ 1878 { SST(0x2A, 0x05, SS_RDEF, /* XXX TBD */ 1879 "Registrations preempted") }, 1880 /* DTLPWROMAEBKVF */ 1881 { SST(0x2A, 0x06, SS_RDEF, /* XXX TBD */ 1882 "Asymmetric access state changed") }, 1883 /* DTLPWROMAEBKVF */ 1884 { SST(0x2A, 0x07, SS_RDEF, /* XXX TBD */ 1885 "Implicit asymmetric access state transition failed") }, 1886 /* DT WROMAEBKVF */ 1887 { SST(0x2A, 0x08, SS_RDEF, /* XXX TBD */ 1888 "Priority changed") }, 1889 /* D */ 1890 { SST(0x2A, 0x09, SS_RDEF, /* XXX TBD */ 1891 "Capacity data has changed") }, 1892 /* DT */ 1893 { SST(0x2A, 0x0A, SS_RDEF, /* XXX TBD */ 1894 "Error history I_T nexus cleared") }, 1895 /* DT */ 1896 { SST(0x2A, 0x0B, SS_RDEF, /* XXX TBD */ 1897 "Error history snapshot released") }, 1898 /* F */ 1899 { SST(0x2A, 0x0C, SS_RDEF, /* XXX TBD */ 1900 "Error recovery attributes have changed") }, 1901 /* T */ 1902 { SST(0x2A, 0x0D, SS_RDEF, /* XXX TBD */ 1903 "Data encryption capabilities changed") }, 1904 /* DT M E V */ 1905 { SST(0x2A, 0x10, SS_RDEF, /* XXX TBD */ 1906 "Timestamp changed") }, 1907 /* T */ 1908 { SST(0x2A, 0x11, SS_RDEF, /* XXX TBD */ 1909 "Data encryption parameters changed by another I_T nexus") }, 1910 /* T */ 1911 { SST(0x2A, 0x12, SS_RDEF, /* XXX TBD */ 1912 "Data encryption parameters changed by vendor specific event") }, 1913 /* T */ 1914 { SST(0x2A, 0x13, SS_RDEF, /* XXX TBD */ 1915 "Data encryption key instance counter has changed") }, 1916 /* DT R MAEBKV */ 1917 { SST(0x2A, 0x14, SS_RDEF, /* XXX TBD */ 1918 "SA creation capabilities data has changed") }, 1919 /* T M V */ 1920 { SST(0x2A, 0x15, SS_RDEF, /* XXX TBD */ 1921 "Medium removal prevention preempted") }, 1922 /* DTLPWRO K */ 1923 { SST(0x2B, 0x00, SS_RDEF, 1924 "Copy cannot execute since host cannot disconnect") }, 1925 /* DTLPWROMAEBKVF */ 1926 { SST(0x2C, 0x00, SS_RDEF, 1927 "Command sequence error") }, 1928 /* */ 1929 { SST(0x2C, 0x01, SS_RDEF, 1930 "Too many windows specified") }, 1931 /* */ 1932 { SST(0x2C, 0x02, SS_RDEF, 1933 "Invalid combination of windows specified") }, 1934 /* R */ 1935 { SST(0x2C, 0x03, SS_RDEF, 1936 "Current program area is not empty") }, 1937 /* R */ 1938 { SST(0x2C, 0x04, SS_RDEF, 1939 "Current program area is empty") }, 1940 /* B */ 1941 { SST(0x2C, 0x05, SS_RDEF, /* XXX TBD */ 1942 "Illegal power condition request") }, 1943 /* R */ 1944 { SST(0x2C, 0x06, SS_RDEF, /* XXX TBD */ 1945 "Persistent prevent conflict") }, 1946 /* DTLPWROMAEBKVF */ 1947 { SST(0x2C, 0x07, SS_RDEF, /* XXX TBD */ 1948 "Previous busy status") }, 1949 /* DTLPWROMAEBKVF */ 1950 { SST(0x2C, 0x08, SS_RDEF, /* XXX TBD */ 1951 "Previous task set full status") }, 1952 /* DTLPWROM EBKVF */ 1953 { SST(0x2C, 0x09, SS_RDEF, /* XXX TBD */ 1954 "Previous reservation conflict status") }, 1955 /* F */ 1956 { SST(0x2C, 0x0A, SS_RDEF, /* XXX TBD */ 1957 "Partition or collection contains user objects") }, 1958 /* T */ 1959 { SST(0x2C, 0x0B, SS_RDEF, /* XXX TBD */ 1960 "Not reserved") }, 1961 /* D */ 1962 { SST(0x2C, 0x0C, SS_RDEF, /* XXX TBD */ 1963 "ORWRITE generation does not match") }, 1964 /* D */ 1965 { SST(0x2C, 0x0D, SS_RDEF, /* XXX TBD */ 1966 "Reset write pointer not allowed") }, 1967 /* D */ 1968 { SST(0x2C, 0x0E, SS_RDEF, /* XXX TBD */ 1969 "Zone is offline") }, 1970 /* D */ 1971 { SST(0x2C, 0x0F, SS_RDEF, /* XXX TBD */ 1972 "Stream not open") }, 1973 /* D */ 1974 { SST(0x2C, 0x10, SS_RDEF, /* XXX TBD */ 1975 "Unwritten data in zone") }, 1976 /* T */ 1977 { SST(0x2D, 0x00, SS_RDEF, 1978 "Overwrite error on update in place") }, 1979 /* R */ 1980 { SST(0x2E, 0x00, SS_RDEF, /* XXX TBD */ 1981 "Insufficient time for operation") }, 1982 /* D */ 1983 { SST(0x2E, 0x01, SS_RDEF, /* XXX TBD */ 1984 "Command timeout before processing") }, 1985 /* D */ 1986 { SST(0x2E, 0x02, SS_RDEF, /* XXX TBD */ 1987 "Command timeout during processing") }, 1988 /* D */ 1989 { SST(0x2E, 0x03, SS_RDEF, /* XXX TBD */ 1990 "Command timeout during processing due to error recovery") }, 1991 /* DTLPWROMAEBKVF */ 1992 { SST(0x2F, 0x00, SS_RDEF, 1993 "Commands cleared by another initiator") }, 1994 /* D */ 1995 { SST(0x2F, 0x01, SS_RDEF, /* XXX TBD */ 1996 "Commands cleared by power loss notification") }, 1997 /* DTLPWROMAEBKVF */ 1998 { SST(0x2F, 0x02, SS_RDEF, /* XXX TBD */ 1999 "Commands cleared by device server") }, 2000 /* DTLPWROMAEBKVF */ 2001 { SST(0x2F, 0x03, SS_RDEF, /* XXX TBD */ 2002 "Some commands cleared by queuing layer event") }, 2003 /* DT WROM BK */ 2004 { SST(0x30, 0x00, SS_RDEF, 2005 "Incompatible medium installed") }, 2006 /* DT WRO BK */ 2007 { SST(0x30, 0x01, SS_RDEF, 2008 "Cannot read medium - unknown format") }, 2009 /* DT WRO BK */ 2010 { SST(0x30, 0x02, SS_RDEF, 2011 "Cannot read medium - incompatible format") }, 2012 /* DT R K */ 2013 { SST(0x30, 0x03, SS_RDEF, 2014 "Cleaning cartridge installed") }, 2015 /* DT WRO BK */ 2016 { SST(0x30, 0x04, SS_RDEF, 2017 "Cannot write medium - unknown format") }, 2018 /* DT WRO BK */ 2019 { SST(0x30, 0x05, SS_RDEF, 2020 "Cannot write medium - incompatible format") }, 2021 /* DT WRO B */ 2022 { SST(0x30, 0x06, SS_RDEF, 2023 "Cannot format medium - incompatible medium") }, 2024 /* DTL WROMAEBKVF */ 2025 { SST(0x30, 0x07, SS_RDEF, 2026 "Cleaning failure") }, 2027 /* R */ 2028 { SST(0x30, 0x08, SS_RDEF, 2029 "Cannot write - application code mismatch") }, 2030 /* R */ 2031 { SST(0x30, 0x09, SS_RDEF, 2032 "Current session not fixated for append") }, 2033 /* DT WRO AEBK */ 2034 { SST(0x30, 0x0A, SS_RDEF, /* XXX TBD */ 2035 "Cleaning request rejected") }, 2036 /* T */ 2037 { SST(0x30, 0x0C, SS_RDEF, /* XXX TBD */ 2038 "WORM medium - overwrite attempted") }, 2039 /* T */ 2040 { SST(0x30, 0x0D, SS_RDEF, /* XXX TBD */ 2041 "WORM medium - integrity check") }, 2042 /* R */ 2043 { SST(0x30, 0x10, SS_RDEF, /* XXX TBD */ 2044 "Medium not formatted") }, 2045 /* M */ 2046 { SST(0x30, 0x11, SS_RDEF, /* XXX TBD */ 2047 "Incompatible volume type") }, 2048 /* M */ 2049 { SST(0x30, 0x12, SS_RDEF, /* XXX TBD */ 2050 "Incompatible volume qualifier") }, 2051 /* M */ 2052 { SST(0x30, 0x13, SS_RDEF, /* XXX TBD */ 2053 "Cleaning volume expired") }, 2054 /* DT WRO BK */ 2055 { SST(0x31, 0x00, SS_RDEF, 2056 "Medium format corrupted") }, 2057 /* D L RO B */ 2058 { SST(0x31, 0x01, SS_RDEF, 2059 "Format command failed") }, 2060 /* R */ 2061 { SST(0x31, 0x02, SS_RDEF, /* XXX TBD */ 2062 "Zoned formatting failed due to spare linking") }, 2063 /* D B */ 2064 { SST(0x31, 0x03, SS_RDEF, /* XXX TBD */ 2065 "SANITIZE command failed") }, 2066 /* D W O BK */ 2067 { SST(0x32, 0x00, SS_RDEF, 2068 "No defect spare location available") }, 2069 /* D W O BK */ 2070 { SST(0x32, 0x01, SS_RDEF, 2071 "Defect list update failure") }, 2072 /* T */ 2073 { SST(0x33, 0x00, SS_RDEF, 2074 "Tape length error") }, 2075 /* DTLPWROMAEBKVF */ 2076 { SST(0x34, 0x00, SS_RDEF, 2077 "Enclosure failure") }, 2078 /* DTLPWROMAEBKVF */ 2079 { SST(0x35, 0x00, SS_RDEF, 2080 "Enclosure services failure") }, 2081 /* DTLPWROMAEBKVF */ 2082 { SST(0x35, 0x01, SS_RDEF, 2083 "Unsupported enclosure function") }, 2084 /* DTLPWROMAEBKVF */ 2085 { SST(0x35, 0x02, SS_RDEF, 2086 "Enclosure services unavailable") }, 2087 /* DTLPWROMAEBKVF */ 2088 { SST(0x35, 0x03, SS_RDEF, 2089 "Enclosure services transfer failure") }, 2090 /* DTLPWROMAEBKVF */ 2091 { SST(0x35, 0x04, SS_RDEF, 2092 "Enclosure services transfer refused") }, 2093 /* DTL WROMAEBKVF */ 2094 { SST(0x35, 0x05, SS_RDEF, /* XXX TBD */ 2095 "Enclosure services checksum error") }, 2096 /* L */ 2097 { SST(0x36, 0x00, SS_RDEF, 2098 "Ribbon, ink, or toner failure") }, 2099 /* DTL WROMAEBKVF */ 2100 { SST(0x37, 0x00, SS_RDEF, 2101 "Rounded parameter") }, 2102 /* B */ 2103 { SST(0x38, 0x00, SS_RDEF, /* XXX TBD */ 2104 "Event status notification") }, 2105 /* B */ 2106 { SST(0x38, 0x02, SS_RDEF, /* XXX TBD */ 2107 "ESN - power management class event") }, 2108 /* B */ 2109 { SST(0x38, 0x04, SS_RDEF, /* XXX TBD */ 2110 "ESN - media class event") }, 2111 /* B */ 2112 { SST(0x38, 0x06, SS_RDEF, /* XXX TBD */ 2113 "ESN - device busy class event") }, 2114 /* D */ 2115 { SST(0x38, 0x07, SS_RDEF, /* XXX TBD */ 2116 "Thin provisioning soft threshold reached") }, 2117 /* DTL WROMAE K */ 2118 { SST(0x39, 0x00, SS_RDEF, 2119 "Saving parameters not supported") }, 2120 /* DTL WROM BK */ 2121 { SST(0x3A, 0x00, SS_FATAL | ENXIO, 2122 "Medium not present") }, 2123 /* DT WROM BK */ 2124 { SST(0x3A, 0x01, SS_FATAL | ENXIO, 2125 "Medium not present - tray closed") }, 2126 /* DT WROM BK */ 2127 { SST(0x3A, 0x02, SS_FATAL | ENXIO, 2128 "Medium not present - tray open") }, 2129 /* DT WROM B */ 2130 { SST(0x3A, 0x03, SS_RDEF, /* XXX TBD */ 2131 "Medium not present - loadable") }, 2132 /* DT WRO B */ 2133 { SST(0x3A, 0x04, SS_RDEF, /* XXX TBD */ 2134 "Medium not present - medium auxiliary memory accessible") }, 2135 /* TL */ 2136 { SST(0x3B, 0x00, SS_RDEF, 2137 "Sequential positioning error") }, 2138 /* T */ 2139 { SST(0x3B, 0x01, SS_RDEF, 2140 "Tape position error at beginning-of-medium") }, 2141 /* T */ 2142 { SST(0x3B, 0x02, SS_RDEF, 2143 "Tape position error at end-of-medium") }, 2144 /* L */ 2145 { SST(0x3B, 0x03, SS_RDEF, 2146 "Tape or electronic vertical forms unit not ready") }, 2147 /* L */ 2148 { SST(0x3B, 0x04, SS_RDEF, 2149 "Slew failure") }, 2150 /* L */ 2151 { SST(0x3B, 0x05, SS_RDEF, 2152 "Paper jam") }, 2153 /* L */ 2154 { SST(0x3B, 0x06, SS_RDEF, 2155 "Failed to sense top-of-form") }, 2156 /* L */ 2157 { SST(0x3B, 0x07, SS_RDEF, 2158 "Failed to sense bottom-of-form") }, 2159 /* T */ 2160 { SST(0x3B, 0x08, SS_RDEF, 2161 "Reposition error") }, 2162 /* */ 2163 { SST(0x3B, 0x09, SS_RDEF, 2164 "Read past end of medium") }, 2165 /* */ 2166 { SST(0x3B, 0x0A, SS_RDEF, 2167 "Read past beginning of medium") }, 2168 /* */ 2169 { SST(0x3B, 0x0B, SS_RDEF, 2170 "Position past end of medium") }, 2171 /* T */ 2172 { SST(0x3B, 0x0C, SS_RDEF, 2173 "Position past beginning of medium") }, 2174 /* DT WROM BK */ 2175 { SST(0x3B, 0x0D, SS_FATAL | ENOSPC, 2176 "Medium destination element full") }, 2177 /* DT WROM BK */ 2178 { SST(0x3B, 0x0E, SS_RDEF, 2179 "Medium source element empty") }, 2180 /* R */ 2181 { SST(0x3B, 0x0F, SS_RDEF, 2182 "End of medium reached") }, 2183 /* DT WROM BK */ 2184 { SST(0x3B, 0x11, SS_RDEF, 2185 "Medium magazine not accessible") }, 2186 /* DT WROM BK */ 2187 { SST(0x3B, 0x12, SS_RDEF, 2188 "Medium magazine removed") }, 2189 /* DT WROM BK */ 2190 { SST(0x3B, 0x13, SS_RDEF, 2191 "Medium magazine inserted") }, 2192 /* DT WROM BK */ 2193 { SST(0x3B, 0x14, SS_RDEF, 2194 "Medium magazine locked") }, 2195 /* DT WROM BK */ 2196 { SST(0x3B, 0x15, SS_RDEF, 2197 "Medium magazine unlocked") }, 2198 /* R */ 2199 { SST(0x3B, 0x16, SS_RDEF, /* XXX TBD */ 2200 "Mechanical positioning or changer error") }, 2201 /* F */ 2202 { SST(0x3B, 0x17, SS_RDEF, /* XXX TBD */ 2203 "Read past end of user object") }, 2204 /* M */ 2205 { SST(0x3B, 0x18, SS_RDEF, /* XXX TBD */ 2206 "Element disabled") }, 2207 /* M */ 2208 { SST(0x3B, 0x19, SS_RDEF, /* XXX TBD */ 2209 "Element enabled") }, 2210 /* M */ 2211 { SST(0x3B, 0x1A, SS_RDEF, /* XXX TBD */ 2212 "Data transfer device removed") }, 2213 /* M */ 2214 { SST(0x3B, 0x1B, SS_RDEF, /* XXX TBD */ 2215 "Data transfer device inserted") }, 2216 /* T */ 2217 { SST(0x3B, 0x1C, SS_RDEF, /* XXX TBD */ 2218 "Too many logical objects on partition to support operation") }, 2219 /* DTLPWROMAE K */ 2220 { SST(0x3D, 0x00, SS_RDEF, 2221 "Invalid bits in IDENTIFY message") }, 2222 /* DTLPWROMAEBKVF */ 2223 { SST(0x3E, 0x00, SS_RDEF, 2224 "Logical unit has not self-configured yet") }, 2225 /* DTLPWROMAEBKVF */ 2226 { SST(0x3E, 0x01, SS_RDEF, 2227 "Logical unit failure") }, 2228 /* DTLPWROMAEBKVF */ 2229 { SST(0x3E, 0x02, SS_RDEF, 2230 "Timeout on logical unit") }, 2231 /* DTLPWROMAEBKVF */ 2232 { SST(0x3E, 0x03, SS_RDEF, /* XXX TBD */ 2233 "Logical unit failed self-test") }, 2234 /* DTLPWROMAEBKVF */ 2235 { SST(0x3E, 0x04, SS_RDEF, /* XXX TBD */ 2236 "Logical unit unable to update self-test log") }, 2237 /* DTLPWROMAEBKVF */ 2238 { SST(0x3F, 0x00, SS_RDEF, 2239 "Target operating conditions have changed") }, 2240 /* DTLPWROMAEBKVF */ 2241 { SST(0x3F, 0x01, SS_RDEF, 2242 "Microcode has been changed") }, 2243 /* DTLPWROM BK */ 2244 { SST(0x3F, 0x02, SS_RDEF, 2245 "Changed operating definition") }, 2246 /* DTLPWROMAEBKVF */ 2247 { SST(0x3F, 0x03, SS_RDEF, 2248 "INQUIRY data has changed") }, 2249 /* DT WROMAEBK */ 2250 { SST(0x3F, 0x04, SS_RDEF, 2251 "Component device attached") }, 2252 /* DT WROMAEBK */ 2253 { SST(0x3F, 0x05, SS_RDEF, 2254 "Device identifier changed") }, 2255 /* DT WROMAEB */ 2256 { SST(0x3F, 0x06, SS_RDEF, 2257 "Redundancy group created or modified") }, 2258 /* DT WROMAEB */ 2259 { SST(0x3F, 0x07, SS_RDEF, 2260 "Redundancy group deleted") }, 2261 /* DT WROMAEB */ 2262 { SST(0x3F, 0x08, SS_RDEF, 2263 "Spare created or modified") }, 2264 /* DT WROMAEB */ 2265 { SST(0x3F, 0x09, SS_RDEF, 2266 "Spare deleted") }, 2267 /* DT WROMAEBK */ 2268 { SST(0x3F, 0x0A, SS_RDEF, 2269 "Volume set created or modified") }, 2270 /* DT WROMAEBK */ 2271 { SST(0x3F, 0x0B, SS_RDEF, 2272 "Volume set deleted") }, 2273 /* DT WROMAEBK */ 2274 { SST(0x3F, 0x0C, SS_RDEF, 2275 "Volume set deassigned") }, 2276 /* DT WROMAEBK */ 2277 { SST(0x3F, 0x0D, SS_RDEF, 2278 "Volume set reassigned") }, 2279 /* DTLPWROMAE */ 2280 { SST(0x3F, 0x0E, SS_RDEF | SSQ_RESCAN , 2281 "Reported LUNs data has changed") }, 2282 /* DTLPWROMAEBKVF */ 2283 { SST(0x3F, 0x0F, SS_RDEF, /* XXX TBD */ 2284 "Echo buffer overwritten") }, 2285 /* DT WROM B */ 2286 { SST(0x3F, 0x10, SS_RDEF, /* XXX TBD */ 2287 "Medium loadable") }, 2288 /* DT WROM B */ 2289 { SST(0x3F, 0x11, SS_RDEF, /* XXX TBD */ 2290 "Medium auxiliary memory accessible") }, 2291 /* DTLPWR MAEBK F */ 2292 { SST(0x3F, 0x12, SS_RDEF, /* XXX TBD */ 2293 "iSCSI IP address added") }, 2294 /* DTLPWR MAEBK F */ 2295 { SST(0x3F, 0x13, SS_RDEF, /* XXX TBD */ 2296 "iSCSI IP address removed") }, 2297 /* DTLPWR MAEBK F */ 2298 { SST(0x3F, 0x14, SS_RDEF, /* XXX TBD */ 2299 "iSCSI IP address changed") }, 2300 /* DTLPWR MAEBK */ 2301 { SST(0x3F, 0x15, SS_RDEF, /* XXX TBD */ 2302 "Inspect referrals sense descriptors") }, 2303 /* DTLPWROMAEBKVF */ 2304 { SST(0x3F, 0x16, SS_RDEF, /* XXX TBD */ 2305 "Microcode has been changed without reset") }, 2306 /* D */ 2307 { SST(0x3F, 0x17, SS_RDEF, /* XXX TBD */ 2308 "Zone transition to full") }, 2309 /* D */ 2310 { SST(0x40, 0x00, SS_RDEF, 2311 "RAM failure") }, /* deprecated - use 40 NN instead */ 2312 /* DTLPWROMAEBKVF */ 2313 { SST(0x40, 0x80, SS_RDEF, 2314 "Diagnostic failure: ASCQ = Component ID") }, 2315 /* DTLPWROMAEBKVF */ 2316 { SST(0x40, 0xFF, SS_RDEF | SSQ_RANGE, 2317 NULL) }, /* Range 0x80->0xFF */ 2318 /* D */ 2319 { SST(0x41, 0x00, SS_RDEF, 2320 "Data path failure") }, /* deprecated - use 40 NN instead */ 2321 /* D */ 2322 { SST(0x42, 0x00, SS_RDEF, 2323 "Power-on or self-test failure") }, 2324 /* deprecated - use 40 NN instead */ 2325 /* DTLPWROMAEBKVF */ 2326 { SST(0x43, 0x00, SS_RDEF, 2327 "Message error") }, 2328 /* DTLPWROMAEBKVF */ 2329 { SST(0x44, 0x00, SS_RDEF, 2330 "Internal target failure") }, 2331 /* DT P MAEBKVF */ 2332 { SST(0x44, 0x01, SS_RDEF, /* XXX TBD */ 2333 "Persistent reservation information lost") }, 2334 /* DT B */ 2335 { SST(0x44, 0x71, SS_RDEF, /* XXX TBD */ 2336 "ATA device failed set features") }, 2337 /* DTLPWROMAEBKVF */ 2338 { SST(0x45, 0x00, SS_RDEF, 2339 "Select or reselect failure") }, 2340 /* DTLPWROM BK */ 2341 { SST(0x46, 0x00, SS_RDEF, 2342 "Unsuccessful soft reset") }, 2343 /* DTLPWROMAEBKVF */ 2344 { SST(0x47, 0x00, SS_RDEF, 2345 "SCSI parity error") }, 2346 /* DTLPWROMAEBKVF */ 2347 { SST(0x47, 0x01, SS_RDEF, /* XXX TBD */ 2348 "Data phase CRC error detected") }, 2349 /* DTLPWROMAEBKVF */ 2350 { SST(0x47, 0x02, SS_RDEF, /* XXX TBD */ 2351 "SCSI parity error detected during ST data phase") }, 2352 /* DTLPWROMAEBKVF */ 2353 { SST(0x47, 0x03, SS_RDEF, /* XXX TBD */ 2354 "Information unit iuCRC error detected") }, 2355 /* DTLPWROMAEBKVF */ 2356 { SST(0x47, 0x04, SS_RDEF, /* XXX TBD */ 2357 "Asynchronous information protection error detected") }, 2358 /* DTLPWROMAEBKVF */ 2359 { SST(0x47, 0x05, SS_RDEF, /* XXX TBD */ 2360 "Protocol service CRC error") }, 2361 /* DT MAEBKVF */ 2362 { SST(0x47, 0x06, SS_RDEF, /* XXX TBD */ 2363 "PHY test function in progress") }, 2364 /* DT PWROMAEBK */ 2365 { SST(0x47, 0x7F, SS_RDEF, /* XXX TBD */ 2366 "Some commands cleared by iSCSI protocol event") }, 2367 /* DTLPWROMAEBKVF */ 2368 { SST(0x48, 0x00, SS_RDEF, 2369 "Initiator detected error message received") }, 2370 /* DTLPWROMAEBKVF */ 2371 { SST(0x49, 0x00, SS_RDEF, 2372 "Invalid message error") }, 2373 /* DTLPWROMAEBKVF */ 2374 { SST(0x4A, 0x00, SS_RDEF, 2375 "Command phase error") }, 2376 /* DTLPWROMAEBKVF */ 2377 { SST(0x4B, 0x00, SS_RDEF, 2378 "Data phase error") }, 2379 /* DT PWROMAEBK */ 2380 { SST(0x4B, 0x01, SS_RDEF, /* XXX TBD */ 2381 "Invalid target port transfer tag received") }, 2382 /* DT PWROMAEBK */ 2383 { SST(0x4B, 0x02, SS_RDEF, /* XXX TBD */ 2384 "Too much write data") }, 2385 /* DT PWROMAEBK */ 2386 { SST(0x4B, 0x03, SS_RDEF, /* XXX TBD */ 2387 "ACK/NAK timeout") }, 2388 /* DT PWROMAEBK */ 2389 { SST(0x4B, 0x04, SS_RDEF, /* XXX TBD */ 2390 "NAK received") }, 2391 /* DT PWROMAEBK */ 2392 { SST(0x4B, 0x05, SS_RDEF, /* XXX TBD */ 2393 "Data offset error") }, 2394 /* DT PWROMAEBK */ 2395 { SST(0x4B, 0x06, SS_RDEF, /* XXX TBD */ 2396 "Initiator response timeout") }, 2397 /* DT PWROMAEBK F */ 2398 { SST(0x4B, 0x07, SS_RDEF, /* XXX TBD */ 2399 "Connection lost") }, 2400 /* DT PWROMAEBK F */ 2401 { SST(0x4B, 0x08, SS_RDEF, /* XXX TBD */ 2402 "Data-in buffer overflow - data buffer size") }, 2403 /* DT PWROMAEBK F */ 2404 { SST(0x4B, 0x09, SS_RDEF, /* XXX TBD */ 2405 "Data-in buffer overflow - data buffer descriptor area") }, 2406 /* DT PWROMAEBK F */ 2407 { SST(0x4B, 0x0A, SS_RDEF, /* XXX TBD */ 2408 "Data-in buffer error") }, 2409 /* DT PWROMAEBK F */ 2410 { SST(0x4B, 0x0B, SS_RDEF, /* XXX TBD */ 2411 "Data-out buffer overflow - data buffer size") }, 2412 /* DT PWROMAEBK F */ 2413 { SST(0x4B, 0x0C, SS_RDEF, /* XXX TBD */ 2414 "Data-out buffer overflow - data buffer descriptor area") }, 2415 /* DT PWROMAEBK F */ 2416 { SST(0x4B, 0x0D, SS_RDEF, /* XXX TBD */ 2417 "Data-out buffer error") }, 2418 /* DT PWROMAEBK F */ 2419 { SST(0x4B, 0x0E, SS_RDEF, /* XXX TBD */ 2420 "PCIe fabric error") }, 2421 /* DT PWROMAEBK F */ 2422 { SST(0x4B, 0x0F, SS_RDEF, /* XXX TBD */ 2423 "PCIe completion timeout") }, 2424 /* DT PWROMAEBK F */ 2425 { SST(0x4B, 0x10, SS_RDEF, /* XXX TBD */ 2426 "PCIe completer abort") }, 2427 /* DT PWROMAEBK F */ 2428 { SST(0x4B, 0x11, SS_RDEF, /* XXX TBD */ 2429 "PCIe poisoned TLP received") }, 2430 /* DT PWROMAEBK F */ 2431 { SST(0x4B, 0x12, SS_RDEF, /* XXX TBD */ 2432 "PCIe ECRC check failed") }, 2433 /* DT PWROMAEBK F */ 2434 { SST(0x4B, 0x13, SS_RDEF, /* XXX TBD */ 2435 "PCIe unsupported request") }, 2436 /* DT PWROMAEBK F */ 2437 { SST(0x4B, 0x14, SS_RDEF, /* XXX TBD */ 2438 "PCIe ACS violation") }, 2439 /* DT PWROMAEBK F */ 2440 { SST(0x4B, 0x15, SS_RDEF, /* XXX TBD */ 2441 "PCIe TLP prefix blocket") }, 2442 /* DTLPWROMAEBKVF */ 2443 { SST(0x4C, 0x00, SS_RDEF, 2444 "Logical unit failed self-configuration") }, 2445 /* DTLPWROMAEBKVF */ 2446 { SST(0x4D, 0x00, SS_RDEF, 2447 "Tagged overlapped commands: ASCQ = Queue tag ID") }, 2448 /* DTLPWROMAEBKVF */ 2449 { SST(0x4D, 0xFF, SS_RDEF | SSQ_RANGE, 2450 NULL) }, /* Range 0x00->0xFF */ 2451 /* DTLPWROMAEBKVF */ 2452 { SST(0x4E, 0x00, SS_RDEF, 2453 "Overlapped commands attempted") }, 2454 /* T */ 2455 { SST(0x50, 0x00, SS_RDEF, 2456 "Write append error") }, 2457 /* T */ 2458 { SST(0x50, 0x01, SS_RDEF, 2459 "Write append position error") }, 2460 /* T */ 2461 { SST(0x50, 0x02, SS_RDEF, 2462 "Position error related to timing") }, 2463 /* T RO */ 2464 { SST(0x51, 0x00, SS_RDEF, 2465 "Erase failure") }, 2466 /* R */ 2467 { SST(0x51, 0x01, SS_RDEF, /* XXX TBD */ 2468 "Erase failure - incomplete erase operation detected") }, 2469 /* T */ 2470 { SST(0x52, 0x00, SS_RDEF, 2471 "Cartridge fault") }, 2472 /* DTL WROM BK */ 2473 { SST(0x53, 0x00, SS_RDEF, 2474 "Media load or eject failed") }, 2475 /* T */ 2476 { SST(0x53, 0x01, SS_RDEF, 2477 "Unload tape failure") }, 2478 /* DT WROM BK */ 2479 { SST(0x53, 0x02, SS_RDEF, 2480 "Medium removal prevented") }, 2481 /* M */ 2482 { SST(0x53, 0x03, SS_RDEF, /* XXX TBD */ 2483 "Medium removal prevented by data transfer element") }, 2484 /* T */ 2485 { SST(0x53, 0x04, SS_RDEF, /* XXX TBD */ 2486 "Medium thread or unthread failure") }, 2487 /* M */ 2488 { SST(0x53, 0x05, SS_RDEF, /* XXX TBD */ 2489 "Volume identifier invalid") }, 2490 /* T */ 2491 { SST(0x53, 0x06, SS_RDEF, /* XXX TBD */ 2492 "Volume identifier missing") }, 2493 /* M */ 2494 { SST(0x53, 0x07, SS_RDEF, /* XXX TBD */ 2495 "Duplicate volume identifier") }, 2496 /* M */ 2497 { SST(0x53, 0x08, SS_RDEF, /* XXX TBD */ 2498 "Element status unknown") }, 2499 /* M */ 2500 { SST(0x53, 0x09, SS_RDEF, /* XXX TBD */ 2501 "Data transfer device error - load failed") }, 2502 /* M */ 2503 { SST(0x53, 0x0A, SS_RDEF, /* XXX TBD */ 2504 "Data transfer device error - unload failed") }, 2505 /* M */ 2506 { SST(0x53, 0x0B, SS_RDEF, /* XXX TBD */ 2507 "Data transfer device error - unload missing") }, 2508 /* M */ 2509 { SST(0x53, 0x0C, SS_RDEF, /* XXX TBD */ 2510 "Data transfer device error - eject failed") }, 2511 /* M */ 2512 { SST(0x53, 0x0D, SS_RDEF, /* XXX TBD */ 2513 "Data transfer device error - library communication failed") }, 2514 /* P */ 2515 { SST(0x54, 0x00, SS_RDEF, 2516 "SCSI to host system interface failure") }, 2517 /* P */ 2518 { SST(0x55, 0x00, SS_RDEF, 2519 "System resource failure") }, 2520 /* D O BK */ 2521 { SST(0x55, 0x01, SS_FATAL | ENOSPC, 2522 "System buffer full") }, 2523 /* DTLPWROMAE K */ 2524 { SST(0x55, 0x02, SS_RDEF, /* XXX TBD */ 2525 "Insufficient reservation resources") }, 2526 /* DTLPWROMAE K */ 2527 { SST(0x55, 0x03, SS_RDEF, /* XXX TBD */ 2528 "Insufficient resources") }, 2529 /* DTLPWROMAE K */ 2530 { SST(0x55, 0x04, SS_RDEF, /* XXX TBD */ 2531 "Insufficient registration resources") }, 2532 /* DT PWROMAEBK */ 2533 { SST(0x55, 0x05, SS_RDEF, /* XXX TBD */ 2534 "Insufficient access control resources") }, 2535 /* DT WROM B */ 2536 { SST(0x55, 0x06, SS_RDEF, /* XXX TBD */ 2537 "Auxiliary memory out of space") }, 2538 /* F */ 2539 { SST(0x55, 0x07, SS_RDEF, /* XXX TBD */ 2540 "Quota error") }, 2541 /* T */ 2542 { SST(0x55, 0x08, SS_RDEF, /* XXX TBD */ 2543 "Maximum number of supplemental decryption keys exceeded") }, 2544 /* M */ 2545 { SST(0x55, 0x09, SS_RDEF, /* XXX TBD */ 2546 "Medium auxiliary memory not accessible") }, 2547 /* M */ 2548 { SST(0x55, 0x0A, SS_RDEF, /* XXX TBD */ 2549 "Data currently unavailable") }, 2550 /* DTLPWROMAEBKVF */ 2551 { SST(0x55, 0x0B, SS_RDEF, /* XXX TBD */ 2552 "Insufficient power for operation") }, 2553 /* DT P B */ 2554 { SST(0x55, 0x0C, SS_RDEF, /* XXX TBD */ 2555 "Insufficient resources to create ROD") }, 2556 /* DT P B */ 2557 { SST(0x55, 0x0D, SS_RDEF, /* XXX TBD */ 2558 "Insufficient resources to create ROD token") }, 2559 /* D */ 2560 { SST(0x55, 0x0E, SS_RDEF, /* XXX TBD */ 2561 "Insufficient zone resources") }, 2562 /* D */ 2563 { SST(0x55, 0x0F, SS_RDEF, /* XXX TBD */ 2564 "Insufficient zone resources to complete write") }, 2565 /* D */ 2566 { SST(0x55, 0x10, SS_RDEF, /* XXX TBD */ 2567 "Maximum number of streams open") }, 2568 /* R */ 2569 { SST(0x57, 0x00, SS_RDEF, 2570 "Unable to recover table-of-contents") }, 2571 /* O */ 2572 { SST(0x58, 0x00, SS_RDEF, 2573 "Generation does not exist") }, 2574 /* O */ 2575 { SST(0x59, 0x00, SS_RDEF, 2576 "Updated block read") }, 2577 /* DTLPWRO BK */ 2578 { SST(0x5A, 0x00, SS_RDEF, 2579 "Operator request or state change input") }, 2580 /* DT WROM BK */ 2581 { SST(0x5A, 0x01, SS_RDEF, 2582 "Operator medium removal request") }, 2583 /* DT WRO A BK */ 2584 { SST(0x5A, 0x02, SS_RDEF, 2585 "Operator selected write protect") }, 2586 /* DT WRO A BK */ 2587 { SST(0x5A, 0x03, SS_RDEF, 2588 "Operator selected write permit") }, 2589 /* DTLPWROM K */ 2590 { SST(0x5B, 0x00, SS_RDEF, 2591 "Log exception") }, 2592 /* DTLPWROM K */ 2593 { SST(0x5B, 0x01, SS_RDEF, 2594 "Threshold condition met") }, 2595 /* DTLPWROM K */ 2596 { SST(0x5B, 0x02, SS_RDEF, 2597 "Log counter at maximum") }, 2598 /* DTLPWROM K */ 2599 { SST(0x5B, 0x03, SS_RDEF, 2600 "Log list codes exhausted") }, 2601 /* D O */ 2602 { SST(0x5C, 0x00, SS_RDEF, 2603 "RPL status change") }, 2604 /* D O */ 2605 { SST(0x5C, 0x01, SS_NOP | SSQ_PRINT_SENSE, 2606 "Spindles synchronized") }, 2607 /* D O */ 2608 { SST(0x5C, 0x02, SS_RDEF, 2609 "Spindles not synchronized") }, 2610 /* DTLPWROMAEBKVF */ 2611 { SST(0x5D, 0x00, SS_NOP | SSQ_PRINT_SENSE, 2612 "Failure prediction threshold exceeded") }, 2613 /* R B */ 2614 { SST(0x5D, 0x01, SS_NOP | SSQ_PRINT_SENSE, 2615 "Media failure prediction threshold exceeded") }, 2616 /* R */ 2617 { SST(0x5D, 0x02, SS_NOP | SSQ_PRINT_SENSE, 2618 "Logical unit failure prediction threshold exceeded") }, 2619 /* R */ 2620 { SST(0x5D, 0x03, SS_NOP | SSQ_PRINT_SENSE, 2621 "Spare area exhaustion prediction threshold exceeded") }, 2622 /* D B */ 2623 { SST(0x5D, 0x10, SS_NOP | SSQ_PRINT_SENSE, 2624 "Hardware impending failure general hard drive failure") }, 2625 /* D B */ 2626 { SST(0x5D, 0x11, SS_NOP | SSQ_PRINT_SENSE, 2627 "Hardware impending failure drive error rate too high") }, 2628 /* D B */ 2629 { SST(0x5D, 0x12, SS_NOP | SSQ_PRINT_SENSE, 2630 "Hardware impending failure data error rate too high") }, 2631 /* D B */ 2632 { SST(0x5D, 0x13, SS_NOP | SSQ_PRINT_SENSE, 2633 "Hardware impending failure seek error rate too high") }, 2634 /* D B */ 2635 { SST(0x5D, 0x14, SS_NOP | SSQ_PRINT_SENSE, 2636 "Hardware impending failure too many block reassigns") }, 2637 /* D B */ 2638 { SST(0x5D, 0x15, SS_NOP | SSQ_PRINT_SENSE, 2639 "Hardware impending failure access times too high") }, 2640 /* D B */ 2641 { SST(0x5D, 0x16, SS_NOP | SSQ_PRINT_SENSE, 2642 "Hardware impending failure start unit times too high") }, 2643 /* D B */ 2644 { SST(0x5D, 0x17, SS_NOP | SSQ_PRINT_SENSE, 2645 "Hardware impending failure channel parametrics") }, 2646 /* D B */ 2647 { SST(0x5D, 0x18, SS_NOP | SSQ_PRINT_SENSE, 2648 "Hardware impending failure controller detected") }, 2649 /* D B */ 2650 { SST(0x5D, 0x19, SS_NOP | SSQ_PRINT_SENSE, 2651 "Hardware impending failure throughput performance") }, 2652 /* D B */ 2653 { SST(0x5D, 0x1A, SS_NOP | SSQ_PRINT_SENSE, 2654 "Hardware impending failure seek time performance") }, 2655 /* D B */ 2656 { SST(0x5D, 0x1B, SS_NOP | SSQ_PRINT_SENSE, 2657 "Hardware impending failure spin-up retry count") }, 2658 /* D B */ 2659 { SST(0x5D, 0x1C, SS_NOP | SSQ_PRINT_SENSE, 2660 "Hardware impending failure drive calibration retry count") }, 2661 /* D B */ 2662 { SST(0x5D, 0x1D, SS_NOP | SSQ_PRINT_SENSE, 2663 "Hardware impending failure power loss protection circuit") }, 2664 /* D B */ 2665 { SST(0x5D, 0x20, SS_NOP | SSQ_PRINT_SENSE, 2666 "Controller impending failure general hard drive failure") }, 2667 /* D B */ 2668 { SST(0x5D, 0x21, SS_NOP | SSQ_PRINT_SENSE, 2669 "Controller impending failure drive error rate too high") }, 2670 /* D B */ 2671 { SST(0x5D, 0x22, SS_NOP | SSQ_PRINT_SENSE, 2672 "Controller impending failure data error rate too high") }, 2673 /* D B */ 2674 { SST(0x5D, 0x23, SS_NOP | SSQ_PRINT_SENSE, 2675 "Controller impending failure seek error rate too high") }, 2676 /* D B */ 2677 { SST(0x5D, 0x24, SS_NOP | SSQ_PRINT_SENSE, 2678 "Controller impending failure too many block reassigns") }, 2679 /* D B */ 2680 { SST(0x5D, 0x25, SS_NOP | SSQ_PRINT_SENSE, 2681 "Controller impending failure access times too high") }, 2682 /* D B */ 2683 { SST(0x5D, 0x26, SS_NOP | SSQ_PRINT_SENSE, 2684 "Controller impending failure start unit times too high") }, 2685 /* D B */ 2686 { SST(0x5D, 0x27, SS_NOP | SSQ_PRINT_SENSE, 2687 "Controller impending failure channel parametrics") }, 2688 /* D B */ 2689 { SST(0x5D, 0x28, SS_NOP | SSQ_PRINT_SENSE, 2690 "Controller impending failure controller detected") }, 2691 /* D B */ 2692 { SST(0x5D, 0x29, SS_NOP | SSQ_PRINT_SENSE, 2693 "Controller impending failure throughput performance") }, 2694 /* D B */ 2695 { SST(0x5D, 0x2A, SS_NOP | SSQ_PRINT_SENSE, 2696 "Controller impending failure seek time performance") }, 2697 /* D B */ 2698 { SST(0x5D, 0x2B, SS_NOP | SSQ_PRINT_SENSE, 2699 "Controller impending failure spin-up retry count") }, 2700 /* D B */ 2701 { SST(0x5D, 0x2C, SS_NOP | SSQ_PRINT_SENSE, 2702 "Controller impending failure drive calibration retry count") }, 2703 /* D B */ 2704 { SST(0x5D, 0x30, SS_NOP | SSQ_PRINT_SENSE, 2705 "Data channel impending failure general hard drive failure") }, 2706 /* D B */ 2707 { SST(0x5D, 0x31, SS_NOP | SSQ_PRINT_SENSE, 2708 "Data channel impending failure drive error rate too high") }, 2709 /* D B */ 2710 { SST(0x5D, 0x32, SS_NOP | SSQ_PRINT_SENSE, 2711 "Data channel impending failure data error rate too high") }, 2712 /* D B */ 2713 { SST(0x5D, 0x33, SS_NOP | SSQ_PRINT_SENSE, 2714 "Data channel impending failure seek error rate too high") }, 2715 /* D B */ 2716 { SST(0x5D, 0x34, SS_NOP | SSQ_PRINT_SENSE, 2717 "Data channel impending failure too many block reassigns") }, 2718 /* D B */ 2719 { SST(0x5D, 0x35, SS_NOP | SSQ_PRINT_SENSE, 2720 "Data channel impending failure access times too high") }, 2721 /* D B */ 2722 { SST(0x5D, 0x36, SS_NOP | SSQ_PRINT_SENSE, 2723 "Data channel impending failure start unit times too high") }, 2724 /* D B */ 2725 { SST(0x5D, 0x37, SS_NOP | SSQ_PRINT_SENSE, 2726 "Data channel impending failure channel parametrics") }, 2727 /* D B */ 2728 { SST(0x5D, 0x38, SS_NOP | SSQ_PRINT_SENSE, 2729 "Data channel impending failure controller detected") }, 2730 /* D B */ 2731 { SST(0x5D, 0x39, SS_NOP | SSQ_PRINT_SENSE, 2732 "Data channel impending failure throughput performance") }, 2733 /* D B */ 2734 { SST(0x5D, 0x3A, SS_NOP | SSQ_PRINT_SENSE, 2735 "Data channel impending failure seek time performance") }, 2736 /* D B */ 2737 { SST(0x5D, 0x3B, SS_NOP | SSQ_PRINT_SENSE, 2738 "Data channel impending failure spin-up retry count") }, 2739 /* D B */ 2740 { SST(0x5D, 0x3C, SS_NOP | SSQ_PRINT_SENSE, 2741 "Data channel impending failure drive calibration retry count") }, 2742 /* D B */ 2743 { SST(0x5D, 0x40, SS_NOP | SSQ_PRINT_SENSE, 2744 "Servo impending failure general hard drive failure") }, 2745 /* D B */ 2746 { SST(0x5D, 0x41, SS_NOP | SSQ_PRINT_SENSE, 2747 "Servo impending failure drive error rate too high") }, 2748 /* D B */ 2749 { SST(0x5D, 0x42, SS_NOP | SSQ_PRINT_SENSE, 2750 "Servo impending failure data error rate too high") }, 2751 /* D B */ 2752 { SST(0x5D, 0x43, SS_NOP | SSQ_PRINT_SENSE, 2753 "Servo impending failure seek error rate too high") }, 2754 /* D B */ 2755 { SST(0x5D, 0x44, SS_NOP | SSQ_PRINT_SENSE, 2756 "Servo impending failure too many block reassigns") }, 2757 /* D B */ 2758 { SST(0x5D, 0x45, SS_NOP | SSQ_PRINT_SENSE, 2759 "Servo impending failure access times too high") }, 2760 /* D B */ 2761 { SST(0x5D, 0x46, SS_NOP | SSQ_PRINT_SENSE, 2762 "Servo impending failure start unit times too high") }, 2763 /* D B */ 2764 { SST(0x5D, 0x47, SS_NOP | SSQ_PRINT_SENSE, 2765 "Servo impending failure channel parametrics") }, 2766 /* D B */ 2767 { SST(0x5D, 0x48, SS_NOP | SSQ_PRINT_SENSE, 2768 "Servo impending failure controller detected") }, 2769 /* D B */ 2770 { SST(0x5D, 0x49, SS_NOP | SSQ_PRINT_SENSE, 2771 "Servo impending failure throughput performance") }, 2772 /* D B */ 2773 { SST(0x5D, 0x4A, SS_NOP | SSQ_PRINT_SENSE, 2774 "Servo impending failure seek time performance") }, 2775 /* D B */ 2776 { SST(0x5D, 0x4B, SS_NOP | SSQ_PRINT_SENSE, 2777 "Servo impending failure spin-up retry count") }, 2778 /* D B */ 2779 { SST(0x5D, 0x4C, SS_NOP | SSQ_PRINT_SENSE, 2780 "Servo impending failure drive calibration retry count") }, 2781 /* D B */ 2782 { SST(0x5D, 0x50, SS_NOP | SSQ_PRINT_SENSE, 2783 "Spindle impending failure general hard drive failure") }, 2784 /* D B */ 2785 { SST(0x5D, 0x51, SS_NOP | SSQ_PRINT_SENSE, 2786 "Spindle impending failure drive error rate too high") }, 2787 /* D B */ 2788 { SST(0x5D, 0x52, SS_NOP | SSQ_PRINT_SENSE, 2789 "Spindle impending failure data error rate too high") }, 2790 /* D B */ 2791 { SST(0x5D, 0x53, SS_NOP | SSQ_PRINT_SENSE, 2792 "Spindle impending failure seek error rate too high") }, 2793 /* D B */ 2794 { SST(0x5D, 0x54, SS_NOP | SSQ_PRINT_SENSE, 2795 "Spindle impending failure too many block reassigns") }, 2796 /* D B */ 2797 { SST(0x5D, 0x55, SS_NOP | SSQ_PRINT_SENSE, 2798 "Spindle impending failure access times too high") }, 2799 /* D B */ 2800 { SST(0x5D, 0x56, SS_NOP | SSQ_PRINT_SENSE, 2801 "Spindle impending failure start unit times too high") }, 2802 /* D B */ 2803 { SST(0x5D, 0x57, SS_NOP | SSQ_PRINT_SENSE, 2804 "Spindle impending failure channel parametrics") }, 2805 /* D B */ 2806 { SST(0x5D, 0x58, SS_NOP | SSQ_PRINT_SENSE, 2807 "Spindle impending failure controller detected") }, 2808 /* D B */ 2809 { SST(0x5D, 0x59, SS_NOP | SSQ_PRINT_SENSE, 2810 "Spindle impending failure throughput performance") }, 2811 /* D B */ 2812 { SST(0x5D, 0x5A, SS_NOP | SSQ_PRINT_SENSE, 2813 "Spindle impending failure seek time performance") }, 2814 /* D B */ 2815 { SST(0x5D, 0x5B, SS_NOP | SSQ_PRINT_SENSE, 2816 "Spindle impending failure spin-up retry count") }, 2817 /* D B */ 2818 { SST(0x5D, 0x5C, SS_NOP | SSQ_PRINT_SENSE, 2819 "Spindle impending failure drive calibration retry count") }, 2820 /* D B */ 2821 { SST(0x5D, 0x60, SS_NOP | SSQ_PRINT_SENSE, 2822 "Firmware impending failure general hard drive failure") }, 2823 /* D B */ 2824 { SST(0x5D, 0x61, SS_NOP | SSQ_PRINT_SENSE, 2825 "Firmware impending failure drive error rate too high") }, 2826 /* D B */ 2827 { SST(0x5D, 0x62, SS_NOP | SSQ_PRINT_SENSE, 2828 "Firmware impending failure data error rate too high") }, 2829 /* D B */ 2830 { SST(0x5D, 0x63, SS_NOP | SSQ_PRINT_SENSE, 2831 "Firmware impending failure seek error rate too high") }, 2832 /* D B */ 2833 { SST(0x5D, 0x64, SS_NOP | SSQ_PRINT_SENSE, 2834 "Firmware impending failure too many block reassigns") }, 2835 /* D B */ 2836 { SST(0x5D, 0x65, SS_NOP | SSQ_PRINT_SENSE, 2837 "Firmware impending failure access times too high") }, 2838 /* D B */ 2839 { SST(0x5D, 0x66, SS_NOP | SSQ_PRINT_SENSE, 2840 "Firmware impending failure start unit times too high") }, 2841 /* D B */ 2842 { SST(0x5D, 0x67, SS_NOP | SSQ_PRINT_SENSE, 2843 "Firmware impending failure channel parametrics") }, 2844 /* D B */ 2845 { SST(0x5D, 0x68, SS_NOP | SSQ_PRINT_SENSE, 2846 "Firmware impending failure controller detected") }, 2847 /* D B */ 2848 { SST(0x5D, 0x69, SS_NOP | SSQ_PRINT_SENSE, 2849 "Firmware impending failure throughput performance") }, 2850 /* D B */ 2851 { SST(0x5D, 0x6A, SS_NOP | SSQ_PRINT_SENSE, 2852 "Firmware impending failure seek time performance") }, 2853 /* D B */ 2854 { SST(0x5D, 0x6B, SS_NOP | SSQ_PRINT_SENSE, 2855 "Firmware impending failure spin-up retry count") }, 2856 /* D B */ 2857 { SST(0x5D, 0x6C, SS_NOP | SSQ_PRINT_SENSE, 2858 "Firmware impending failure drive calibration retry count") }, 2859 /* D B */ 2860 { SST(0x5D, 0x73, SS_NOP | SSQ_PRINT_SENSE, 2861 "Media impending failure endurance limit met") }, 2862 /* DTLPWROMAEBKVF */ 2863 { SST(0x5D, 0xFF, SS_NOP | SSQ_PRINT_SENSE, 2864 "Failure prediction threshold exceeded (false)") }, 2865 /* DTLPWRO A K */ 2866 { SST(0x5E, 0x00, SS_RDEF, 2867 "Low power condition on") }, 2868 /* DTLPWRO A K */ 2869 { SST(0x5E, 0x01, SS_RDEF, 2870 "Idle condition activated by timer") }, 2871 /* DTLPWRO A K */ 2872 { SST(0x5E, 0x02, SS_RDEF, 2873 "Standby condition activated by timer") }, 2874 /* DTLPWRO A K */ 2875 { SST(0x5E, 0x03, SS_RDEF, 2876 "Idle condition activated by command") }, 2877 /* DTLPWRO A K */ 2878 { SST(0x5E, 0x04, SS_RDEF, 2879 "Standby condition activated by command") }, 2880 /* DTLPWRO A K */ 2881 { SST(0x5E, 0x05, SS_RDEF, 2882 "Idle-B condition activated by timer") }, 2883 /* DTLPWRO A K */ 2884 { SST(0x5E, 0x06, SS_RDEF, 2885 "Idle-B condition activated by command") }, 2886 /* DTLPWRO A K */ 2887 { SST(0x5E, 0x07, SS_RDEF, 2888 "Idle-C condition activated by timer") }, 2889 /* DTLPWRO A K */ 2890 { SST(0x5E, 0x08, SS_RDEF, 2891 "Idle-C condition activated by command") }, 2892 /* DTLPWRO A K */ 2893 { SST(0x5E, 0x09, SS_RDEF, 2894 "Standby-Y condition activated by timer") }, 2895 /* DTLPWRO A K */ 2896 { SST(0x5E, 0x0A, SS_RDEF, 2897 "Standby-Y condition activated by command") }, 2898 /* B */ 2899 { SST(0x5E, 0x41, SS_RDEF, /* XXX TBD */ 2900 "Power state change to active") }, 2901 /* B */ 2902 { SST(0x5E, 0x42, SS_RDEF, /* XXX TBD */ 2903 "Power state change to idle") }, 2904 /* B */ 2905 { SST(0x5E, 0x43, SS_RDEF, /* XXX TBD */ 2906 "Power state change to standby") }, 2907 /* B */ 2908 { SST(0x5E, 0x45, SS_RDEF, /* XXX TBD */ 2909 "Power state change to sleep") }, 2910 /* BK */ 2911 { SST(0x5E, 0x47, SS_RDEF, /* XXX TBD */ 2912 "Power state change to device control") }, 2913 /* */ 2914 { SST(0x60, 0x00, SS_RDEF, 2915 "Lamp failure") }, 2916 /* */ 2917 { SST(0x61, 0x00, SS_RDEF, 2918 "Video acquisition error") }, 2919 /* */ 2920 { SST(0x61, 0x01, SS_RDEF, 2921 "Unable to acquire video") }, 2922 /* */ 2923 { SST(0x61, 0x02, SS_RDEF, 2924 "Out of focus") }, 2925 /* */ 2926 { SST(0x62, 0x00, SS_RDEF, 2927 "Scan head positioning error") }, 2928 /* R */ 2929 { SST(0x63, 0x00, SS_RDEF, 2930 "End of user area encountered on this track") }, 2931 /* R */ 2932 { SST(0x63, 0x01, SS_FATAL | ENOSPC, 2933 "Packet does not fit in available space") }, 2934 /* R */ 2935 { SST(0x64, 0x00, SS_FATAL | ENXIO, 2936 "Illegal mode for this track") }, 2937 /* R */ 2938 { SST(0x64, 0x01, SS_RDEF, 2939 "Invalid packet size") }, 2940 /* DTLPWROMAEBKVF */ 2941 { SST(0x65, 0x00, SS_RDEF, 2942 "Voltage fault") }, 2943 /* */ 2944 { SST(0x66, 0x00, SS_RDEF, 2945 "Automatic document feeder cover up") }, 2946 /* */ 2947 { SST(0x66, 0x01, SS_RDEF, 2948 "Automatic document feeder lift up") }, 2949 /* */ 2950 { SST(0x66, 0x02, SS_RDEF, 2951 "Document jam in automatic document feeder") }, 2952 /* */ 2953 { SST(0x66, 0x03, SS_RDEF, 2954 "Document miss feed automatic in document feeder") }, 2955 /* A */ 2956 { SST(0x67, 0x00, SS_RDEF, 2957 "Configuration failure") }, 2958 /* A */ 2959 { SST(0x67, 0x01, SS_RDEF, 2960 "Configuration of incapable logical units failed") }, 2961 /* A */ 2962 { SST(0x67, 0x02, SS_RDEF, 2963 "Add logical unit failed") }, 2964 /* A */ 2965 { SST(0x67, 0x03, SS_RDEF, 2966 "Modification of logical unit failed") }, 2967 /* A */ 2968 { SST(0x67, 0x04, SS_RDEF, 2969 "Exchange of logical unit failed") }, 2970 /* A */ 2971 { SST(0x67, 0x05, SS_RDEF, 2972 "Remove of logical unit failed") }, 2973 /* A */ 2974 { SST(0x67, 0x06, SS_RDEF, 2975 "Attachment of logical unit failed") }, 2976 /* A */ 2977 { SST(0x67, 0x07, SS_RDEF, 2978 "Creation of logical unit failed") }, 2979 /* A */ 2980 { SST(0x67, 0x08, SS_RDEF, /* XXX TBD */ 2981 "Assign failure occurred") }, 2982 /* A */ 2983 { SST(0x67, 0x09, SS_RDEF, /* XXX TBD */ 2984 "Multiply assigned logical unit") }, 2985 /* DTLPWROMAEBKVF */ 2986 { SST(0x67, 0x0A, SS_RDEF, /* XXX TBD */ 2987 "Set target port groups command failed") }, 2988 /* DT B */ 2989 { SST(0x67, 0x0B, SS_RDEF, /* XXX TBD */ 2990 "ATA device feature not enabled") }, 2991 /* A */ 2992 { SST(0x68, 0x00, SS_RDEF, 2993 "Logical unit not configured") }, 2994 /* D */ 2995 { SST(0x68, 0x01, SS_RDEF, 2996 "Subsidiary logical unit not configured") }, 2997 /* A */ 2998 { SST(0x69, 0x00, SS_RDEF, 2999 "Data loss on logical unit") }, 3000 /* A */ 3001 { SST(0x69, 0x01, SS_RDEF, 3002 "Multiple logical unit failures") }, 3003 /* A */ 3004 { SST(0x69, 0x02, SS_RDEF, 3005 "Parity/data mismatch") }, 3006 /* A */ 3007 { SST(0x6A, 0x00, SS_RDEF, 3008 "Informational, refer to log") }, 3009 /* A */ 3010 { SST(0x6B, 0x00, SS_RDEF, 3011 "State change has occurred") }, 3012 /* A */ 3013 { SST(0x6B, 0x01, SS_RDEF, 3014 "Redundancy level got better") }, 3015 /* A */ 3016 { SST(0x6B, 0x02, SS_RDEF, 3017 "Redundancy level got worse") }, 3018 /* A */ 3019 { SST(0x6C, 0x00, SS_RDEF, 3020 "Rebuild failure occurred") }, 3021 /* A */ 3022 { SST(0x6D, 0x00, SS_RDEF, 3023 "Recalculate failure occurred") }, 3024 /* A */ 3025 { SST(0x6E, 0x00, SS_RDEF, 3026 "Command to logical unit failed") }, 3027 /* R */ 3028 { SST(0x6F, 0x00, SS_RDEF, /* XXX TBD */ 3029 "Copy protection key exchange failure - authentication failure") }, 3030 /* R */ 3031 { SST(0x6F, 0x01, SS_RDEF, /* XXX TBD */ 3032 "Copy protection key exchange failure - key not present") }, 3033 /* R */ 3034 { SST(0x6F, 0x02, SS_RDEF, /* XXX TBD */ 3035 "Copy protection key exchange failure - key not established") }, 3036 /* R */ 3037 { SST(0x6F, 0x03, SS_RDEF, /* XXX TBD */ 3038 "Read of scrambled sector without authentication") }, 3039 /* R */ 3040 { SST(0x6F, 0x04, SS_RDEF, /* XXX TBD */ 3041 "Media region code is mismatched to logical unit region") }, 3042 /* R */ 3043 { SST(0x6F, 0x05, SS_RDEF, /* XXX TBD */ 3044 "Drive region must be permanent/region reset count error") }, 3045 /* R */ 3046 { SST(0x6F, 0x06, SS_RDEF, /* XXX TBD */ 3047 "Insufficient block count for binding NONCE recording") }, 3048 /* R */ 3049 { SST(0x6F, 0x07, SS_RDEF, /* XXX TBD */ 3050 "Conflict in binding NONCE recording") }, 3051 /* T */ 3052 { SST(0x70, 0x00, SS_RDEF, 3053 "Decompression exception short: ASCQ = Algorithm ID") }, 3054 /* T */ 3055 { SST(0x70, 0xFF, SS_RDEF | SSQ_RANGE, 3056 NULL) }, /* Range 0x00 -> 0xFF */ 3057 /* T */ 3058 { SST(0x71, 0x00, SS_RDEF, 3059 "Decompression exception long: ASCQ = Algorithm ID") }, 3060 /* T */ 3061 { SST(0x71, 0xFF, SS_RDEF | SSQ_RANGE, 3062 NULL) }, /* Range 0x00 -> 0xFF */ 3063 /* R */ 3064 { SST(0x72, 0x00, SS_RDEF, 3065 "Session fixation error") }, 3066 /* R */ 3067 { SST(0x72, 0x01, SS_RDEF, 3068 "Session fixation error writing lead-in") }, 3069 /* R */ 3070 { SST(0x72, 0x02, SS_RDEF, 3071 "Session fixation error writing lead-out") }, 3072 /* R */ 3073 { SST(0x72, 0x03, SS_RDEF, 3074 "Session fixation error - incomplete track in session") }, 3075 /* R */ 3076 { SST(0x72, 0x04, SS_RDEF, 3077 "Empty or partially written reserved track") }, 3078 /* R */ 3079 { SST(0x72, 0x05, SS_RDEF, /* XXX TBD */ 3080 "No more track reservations allowed") }, 3081 /* R */ 3082 { SST(0x72, 0x06, SS_RDEF, /* XXX TBD */ 3083 "RMZ extension is not allowed") }, 3084 /* R */ 3085 { SST(0x72, 0x07, SS_RDEF, /* XXX TBD */ 3086 "No more test zone extensions are allowed") }, 3087 /* R */ 3088 { SST(0x73, 0x00, SS_RDEF, 3089 "CD control error") }, 3090 /* R */ 3091 { SST(0x73, 0x01, SS_RDEF, 3092 "Power calibration area almost full") }, 3093 /* R */ 3094 { SST(0x73, 0x02, SS_FATAL | ENOSPC, 3095 "Power calibration area is full") }, 3096 /* R */ 3097 { SST(0x73, 0x03, SS_RDEF, 3098 "Power calibration area error") }, 3099 /* R */ 3100 { SST(0x73, 0x04, SS_RDEF, 3101 "Program memory area update failure") }, 3102 /* R */ 3103 { SST(0x73, 0x05, SS_RDEF, 3104 "Program memory area is full") }, 3105 /* R */ 3106 { SST(0x73, 0x06, SS_RDEF, /* XXX TBD */ 3107 "RMA/PMA is almost full") }, 3108 /* R */ 3109 { SST(0x73, 0x10, SS_RDEF, /* XXX TBD */ 3110 "Current power calibration area almost full") }, 3111 /* R */ 3112 { SST(0x73, 0x11, SS_RDEF, /* XXX TBD */ 3113 "Current power calibration area is full") }, 3114 /* R */ 3115 { SST(0x73, 0x17, SS_RDEF, /* XXX TBD */ 3116 "RDZ is full") }, 3117 /* T */ 3118 { SST(0x74, 0x00, SS_RDEF, /* XXX TBD */ 3119 "Security error") }, 3120 /* T */ 3121 { SST(0x74, 0x01, SS_RDEF, /* XXX TBD */ 3122 "Unable to decrypt data") }, 3123 /* T */ 3124 { SST(0x74, 0x02, SS_RDEF, /* XXX TBD */ 3125 "Unencrypted data encountered while decrypting") }, 3126 /* T */ 3127 { SST(0x74, 0x03, SS_RDEF, /* XXX TBD */ 3128 "Incorrect data encryption key") }, 3129 /* T */ 3130 { SST(0x74, 0x04, SS_RDEF, /* XXX TBD */ 3131 "Cryptographic integrity validation failed") }, 3132 /* T */ 3133 { SST(0x74, 0x05, SS_RDEF, /* XXX TBD */ 3134 "Error decrypting data") }, 3135 /* T */ 3136 { SST(0x74, 0x06, SS_RDEF, /* XXX TBD */ 3137 "Unknown signature verification key") }, 3138 /* T */ 3139 { SST(0x74, 0x07, SS_RDEF, /* XXX TBD */ 3140 "Encryption parameters not useable") }, 3141 /* DT R M E VF */ 3142 { SST(0x74, 0x08, SS_RDEF, /* XXX TBD */ 3143 "Digital signature validation failure") }, 3144 /* T */ 3145 { SST(0x74, 0x09, SS_RDEF, /* XXX TBD */ 3146 "Encryption mode mismatch on read") }, 3147 /* T */ 3148 { SST(0x74, 0x0A, SS_RDEF, /* XXX TBD */ 3149 "Encrypted block not raw read enabled") }, 3150 /* T */ 3151 { SST(0x74, 0x0B, SS_RDEF, /* XXX TBD */ 3152 "Incorrect encryption parameters") }, 3153 /* DT R MAEBKV */ 3154 { SST(0x74, 0x0C, SS_RDEF, /* XXX TBD */ 3155 "Unable to decrypt parameter list") }, 3156 /* T */ 3157 { SST(0x74, 0x0D, SS_RDEF, /* XXX TBD */ 3158 "Encryption algorithm disabled") }, 3159 /* DT R MAEBKV */ 3160 { SST(0x74, 0x10, SS_RDEF, /* XXX TBD */ 3161 "SA creation parameter value invalid") }, 3162 /* DT R MAEBKV */ 3163 { SST(0x74, 0x11, SS_RDEF, /* XXX TBD */ 3164 "SA creation parameter value rejected") }, 3165 /* DT R MAEBKV */ 3166 { SST(0x74, 0x12, SS_RDEF, /* XXX TBD */ 3167 "Invalid SA usage") }, 3168 /* T */ 3169 { SST(0x74, 0x21, SS_RDEF, /* XXX TBD */ 3170 "Data encryption configuration prevented") }, 3171 /* DT R MAEBKV */ 3172 { SST(0x74, 0x30, SS_RDEF, /* XXX TBD */ 3173 "SA creation parameter not supported") }, 3174 /* DT R MAEBKV */ 3175 { SST(0x74, 0x40, SS_RDEF, /* XXX TBD */ 3176 "Authentication failed") }, 3177 /* V */ 3178 { SST(0x74, 0x61, SS_RDEF, /* XXX TBD */ 3179 "External data encryption key manager access error") }, 3180 /* V */ 3181 { SST(0x74, 0x62, SS_RDEF, /* XXX TBD */ 3182 "External data encryption key manager error") }, 3183 /* V */ 3184 { SST(0x74, 0x63, SS_RDEF, /* XXX TBD */ 3185 "External data encryption key not found") }, 3186 /* V */ 3187 { SST(0x74, 0x64, SS_RDEF, /* XXX TBD */ 3188 "External data encryption request not authorized") }, 3189 /* T */ 3190 { SST(0x74, 0x6E, SS_RDEF, /* XXX TBD */ 3191 "External data encryption control timeout") }, 3192 /* T */ 3193 { SST(0x74, 0x6F, SS_RDEF, /* XXX TBD */ 3194 "External data encryption control error") }, 3195 /* DT R M E V */ 3196 { SST(0x74, 0x71, SS_FATAL | EACCES, 3197 "Logical unit access not authorized") }, 3198 /* D */ 3199 { SST(0x74, 0x79, SS_FATAL | EACCES, 3200 "Security conflict in translated device") } 3201}; 3202 3203const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]); 3204 3205struct asc_key 3206{ 3207 int asc; 3208 int ascq; 3209}; 3210 3211static int 3212ascentrycomp(const void *key, const void *member) 3213{ 3214 int asc; 3215 int ascq; 3216 const struct asc_table_entry *table_entry; 3217 3218 asc = ((const struct asc_key *)key)->asc; 3219 ascq = ((const struct asc_key *)key)->ascq; 3220 table_entry = (const struct asc_table_entry *)member; 3221 3222 if (asc >= table_entry->asc) { 3223 3224 if (asc > table_entry->asc) 3225 return (1); 3226 3227 if (ascq <= table_entry->ascq) { 3228 /* Check for ranges */ 3229 if (ascq == table_entry->ascq 3230 || ((table_entry->action & SSQ_RANGE) != 0 3231 && ascq >= (table_entry - 1)->ascq)) 3232 return (0); 3233 return (-1); 3234 } 3235 return (1); 3236 } 3237 return (-1); 3238} 3239 3240static int 3241senseentrycomp(const void *key, const void *member) 3242{ 3243 int sense_key; 3244 const struct sense_key_table_entry *table_entry; 3245 3246 sense_key = *((const int *)key); 3247 table_entry = (const struct sense_key_table_entry *)member; 3248 3249 if (sense_key >= table_entry->sense_key) { 3250 if (sense_key == table_entry->sense_key) 3251 return (0); 3252 return (1); 3253 } 3254 return (-1); 3255} 3256 3257static void 3258fetchtableentries(int sense_key, int asc, int ascq, 3259 struct scsi_inquiry_data *inq_data, 3260 const struct sense_key_table_entry **sense_entry, 3261 const struct asc_table_entry **asc_entry) 3262{ 3263 caddr_t match; 3264 const struct asc_table_entry *asc_tables[2]; 3265 const struct sense_key_table_entry *sense_tables[2]; 3266 struct asc_key asc_ascq; 3267 size_t asc_tables_size[2]; 3268 size_t sense_tables_size[2]; 3269 int num_asc_tables; 3270 int num_sense_tables; 3271 int i; 3272 3273 /* Default to failure */ 3274 *sense_entry = NULL; 3275 *asc_entry = NULL; 3276 match = NULL; 3277 if (inq_data != NULL) 3278 match = cam_quirkmatch((caddr_t)inq_data, 3279 (caddr_t)sense_quirk_table, 3280 sense_quirk_table_size, 3281 sizeof(*sense_quirk_table), 3282 scsi_inquiry_match); 3283 3284 if (match != NULL) { 3285 struct scsi_sense_quirk_entry *quirk; 3286 3287 quirk = (struct scsi_sense_quirk_entry *)match; 3288 asc_tables[0] = quirk->asc_info; 3289 asc_tables_size[0] = quirk->num_ascs; 3290 asc_tables[1] = asc_table; 3291 asc_tables_size[1] = asc_table_size; 3292 num_asc_tables = 2; 3293 sense_tables[0] = quirk->sense_key_info; 3294 sense_tables_size[0] = quirk->num_sense_keys; 3295 sense_tables[1] = sense_key_table; 3296 sense_tables_size[1] = sense_key_table_size; 3297 num_sense_tables = 2; 3298 } else { 3299 asc_tables[0] = asc_table; 3300 asc_tables_size[0] = asc_table_size; 3301 num_asc_tables = 1; 3302 sense_tables[0] = sense_key_table; 3303 sense_tables_size[0] = sense_key_table_size; 3304 num_sense_tables = 1; 3305 } 3306 3307 asc_ascq.asc = asc; 3308 asc_ascq.ascq = ascq; 3309 for (i = 0; i < num_asc_tables; i++) { 3310 void *found_entry; 3311 3312 found_entry = bsearch(&asc_ascq, asc_tables[i], 3313 asc_tables_size[i], 3314 sizeof(**asc_tables), 3315 ascentrycomp); 3316 3317 if (found_entry) { 3318 *asc_entry = (struct asc_table_entry *)found_entry; 3319 break; 3320 } 3321 } 3322 3323 for (i = 0; i < num_sense_tables; i++) { 3324 void *found_entry; 3325 3326 found_entry = bsearch(&sense_key, sense_tables[i], 3327 sense_tables_size[i], 3328 sizeof(**sense_tables), 3329 senseentrycomp); 3330 3331 if (found_entry) { 3332 *sense_entry = 3333 (struct sense_key_table_entry *)found_entry; 3334 break; 3335 } 3336 } 3337} 3338 3339void 3340scsi_sense_desc(int sense_key, int asc, int ascq, 3341 struct scsi_inquiry_data *inq_data, 3342 const char **sense_key_desc, const char **asc_desc) 3343{ 3344 const struct asc_table_entry *asc_entry; 3345 const struct sense_key_table_entry *sense_entry; 3346 3347 fetchtableentries(sense_key, asc, ascq, 3348 inq_data, 3349 &sense_entry, 3350 &asc_entry); 3351 3352 if (sense_entry != NULL) 3353 *sense_key_desc = sense_entry->desc; 3354 else 3355 *sense_key_desc = "Invalid Sense Key"; 3356 3357 if (asc_entry != NULL) 3358 *asc_desc = asc_entry->desc; 3359 else if (asc >= 0x80 && asc <= 0xff) 3360 *asc_desc = "Vendor Specific ASC"; 3361 else if (ascq >= 0x80 && ascq <= 0xff) 3362 *asc_desc = "Vendor Specific ASCQ"; 3363 else 3364 *asc_desc = "Reserved ASC/ASCQ pair"; 3365} 3366 3367/* 3368 * Given sense and device type information, return the appropriate action. 3369 * If we do not understand the specific error as identified by the ASC/ASCQ 3370 * pair, fall back on the more generic actions derived from the sense key. 3371 */ 3372scsi_sense_action 3373scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data, 3374 u_int32_t sense_flags) 3375{ 3376 const struct asc_table_entry *asc_entry; 3377 const struct sense_key_table_entry *sense_entry; 3378 int error_code, sense_key, asc, ascq; 3379 scsi_sense_action action; 3380 3381 if (!scsi_extract_sense_ccb((union ccb *)csio, 3382 &error_code, &sense_key, &asc, &ascq)) { 3383 action = SS_RETRY | SSQ_DECREMENT_COUNT | SSQ_PRINT_SENSE | EIO; 3384 } else if ((error_code == SSD_DEFERRED_ERROR) 3385 || (error_code == SSD_DESC_DEFERRED_ERROR)) { 3386 /* 3387 * XXX dufault@FreeBSD.org 3388 * This error doesn't relate to the command associated 3389 * with this request sense. A deferred error is an error 3390 * for a command that has already returned GOOD status 3391 * (see SCSI2 8.2.14.2). 3392 * 3393 * By my reading of that section, it looks like the current 3394 * command has been cancelled, we should now clean things up 3395 * (hopefully recovering any lost data) and then retry the 3396 * current command. There are two easy choices, both wrong: 3397 * 3398 * 1. Drop through (like we had been doing), thus treating 3399 * this as if the error were for the current command and 3400 * return and stop the current command. 3401 * 3402 * 2. Issue a retry (like I made it do) thus hopefully 3403 * recovering the current transfer, and ignoring the 3404 * fact that we've dropped a command. 3405 * 3406 * These should probably be handled in a device specific 3407 * sense handler or punted back up to a user mode daemon 3408 */ 3409 action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE; 3410 } else { 3411 fetchtableentries(sense_key, asc, ascq, 3412 inq_data, 3413 &sense_entry, 3414 &asc_entry); 3415 3416 /* 3417 * Override the 'No additional Sense' entry (0,0) 3418 * with the error action of the sense key. 3419 */ 3420 if (asc_entry != NULL 3421 && (asc != 0 || ascq != 0)) 3422 action = asc_entry->action; 3423 else if (sense_entry != NULL) 3424 action = sense_entry->action; 3425 else 3426 action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE; 3427 3428 if (sense_key == SSD_KEY_RECOVERED_ERROR) { 3429 /* 3430 * The action succeeded but the device wants 3431 * the user to know that some recovery action 3432 * was required. 3433 */ 3434 action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK); 3435 action |= SS_NOP|SSQ_PRINT_SENSE; 3436 } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) { 3437 if ((sense_flags & SF_QUIET_IR) != 0) 3438 action &= ~SSQ_PRINT_SENSE; 3439 } else if (sense_key == SSD_KEY_UNIT_ATTENTION) { 3440 if ((sense_flags & SF_RETRY_UA) != 0 3441 && (action & SS_MASK) == SS_FAIL) { 3442 action &= ~(SS_MASK|SSQ_MASK); 3443 action |= SS_RETRY|SSQ_DECREMENT_COUNT| 3444 SSQ_PRINT_SENSE; 3445 } 3446 action |= SSQ_UA; 3447 } 3448 } 3449 if ((action & SS_MASK) >= SS_START && 3450 (sense_flags & SF_NO_RECOVERY)) { 3451 action &= ~SS_MASK; 3452 action |= SS_FAIL; 3453 } else if ((action & SS_MASK) == SS_RETRY && 3454 (sense_flags & SF_NO_RETRY)) { 3455 action &= ~SS_MASK; 3456 action |= SS_FAIL; 3457 } 3458 if ((sense_flags & SF_PRINT_ALWAYS) != 0) 3459 action |= SSQ_PRINT_SENSE; 3460 else if ((sense_flags & SF_NO_PRINT) != 0) 3461 action &= ~SSQ_PRINT_SENSE; 3462 3463 return (action); 3464} 3465 3466char * 3467scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len) 3468{ 3469 struct sbuf sb; 3470 int error; 3471 3472 if (len == 0) 3473 return (""); 3474 3475 sbuf_new(&sb, cdb_string, len, SBUF_FIXEDLEN); 3476 3477 scsi_cdb_sbuf(cdb_ptr, &sb); 3478 3479 /* ENOMEM just means that the fixed buffer is full, OK to ignore */ 3480 error = sbuf_finish(&sb); 3481 if (error != 0 && error != ENOMEM) 3482 return (""); 3483 3484 return(sbuf_data(&sb)); 3485} 3486 3487void 3488scsi_cdb_sbuf(u_int8_t *cdb_ptr, struct sbuf *sb) 3489{ 3490 u_int8_t cdb_len; 3491 int i; 3492 3493 if (cdb_ptr == NULL) 3494 return; 3495 3496 /* 3497 * This is taken from the SCSI-3 draft spec. 3498 * (T10/1157D revision 0.3) 3499 * The top 3 bits of an opcode are the group code. The next 5 bits 3500 * are the command code. 3501 * Group 0: six byte commands 3502 * Group 1: ten byte commands 3503 * Group 2: ten byte commands 3504 * Group 3: reserved 3505 * Group 4: sixteen byte commands 3506 * Group 5: twelve byte commands 3507 * Group 6: vendor specific 3508 * Group 7: vendor specific 3509 */ 3510 switch((*cdb_ptr >> 5) & 0x7) { 3511 case 0: 3512 cdb_len = 6; 3513 break; 3514 case 1: 3515 case 2: 3516 cdb_len = 10; 3517 break; 3518 case 3: 3519 case 6: 3520 case 7: 3521 /* in this case, just print out the opcode */ 3522 cdb_len = 1; 3523 break; 3524 case 4: 3525 cdb_len = 16; 3526 break; 3527 case 5: 3528 cdb_len = 12; 3529 break; 3530 } 3531 3532 for (i = 0; i < cdb_len; i++) 3533 sbuf_printf(sb, "%02hhx ", cdb_ptr[i]); 3534 3535 return; 3536} 3537 3538const char * 3539scsi_status_string(struct ccb_scsiio *csio) 3540{ 3541 switch(csio->scsi_status) { 3542 case SCSI_STATUS_OK: 3543 return("OK"); 3544 case SCSI_STATUS_CHECK_COND: 3545 return("Check Condition"); 3546 case SCSI_STATUS_BUSY: 3547 return("Busy"); 3548 case SCSI_STATUS_INTERMED: 3549 return("Intermediate"); 3550 case SCSI_STATUS_INTERMED_COND_MET: 3551 return("Intermediate-Condition Met"); 3552 case SCSI_STATUS_RESERV_CONFLICT: 3553 return("Reservation Conflict"); 3554 case SCSI_STATUS_CMD_TERMINATED: 3555 return("Command Terminated"); 3556 case SCSI_STATUS_QUEUE_FULL: 3557 return("Queue Full"); 3558 case SCSI_STATUS_ACA_ACTIVE: 3559 return("ACA Active"); 3560 case SCSI_STATUS_TASK_ABORTED: 3561 return("Task Aborted"); 3562 default: { 3563 static char unkstr[64]; 3564 snprintf(unkstr, sizeof(unkstr), "Unknown %#x", 3565 csio->scsi_status); 3566 return(unkstr); 3567 } 3568 } 3569} 3570 3571/* 3572 * scsi_command_string() returns 0 for success and -1 for failure. 3573 */ 3574#ifdef _KERNEL 3575int 3576scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb) 3577#else /* !_KERNEL */ 3578int 3579scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio, 3580 struct sbuf *sb) 3581#endif /* _KERNEL/!_KERNEL */ 3582{ 3583 struct scsi_inquiry_data *inq_data; 3584#ifdef _KERNEL 3585 struct ccb_getdev *cgd; 3586#endif /* _KERNEL */ 3587 3588#ifdef _KERNEL 3589 if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL) 3590 return(-1); 3591 /* 3592 * Get the device information. 3593 */ 3594 xpt_setup_ccb(&cgd->ccb_h, 3595 csio->ccb_h.path, 3596 CAM_PRIORITY_NORMAL); 3597 cgd->ccb_h.func_code = XPT_GDEV_TYPE; 3598 xpt_action((union ccb *)cgd); 3599 3600 /* 3601 * If the device is unconfigured, just pretend that it is a hard 3602 * drive. scsi_op_desc() needs this. 3603 */ 3604 if (cgd->ccb_h.status == CAM_DEV_NOT_THERE) 3605 cgd->inq_data.device = T_DIRECT; 3606 3607 inq_data = &cgd->inq_data; 3608 3609#else /* !_KERNEL */ 3610 3611 inq_data = &device->inq_data; 3612 3613#endif /* _KERNEL/!_KERNEL */ 3614 3615 sbuf_printf(sb, "%s. CDB: ", 3616 scsi_op_desc(scsiio_cdb_ptr(csio)[0], inq_data)); 3617 scsi_cdb_sbuf(scsiio_cdb_ptr(csio), sb); 3618 3619#ifdef _KERNEL 3620 xpt_free_ccb((union ccb *)cgd); 3621#endif 3622 3623 return(0); 3624} 3625 3626/* 3627 * Iterate over sense descriptors. Each descriptor is passed into iter_func(). 3628 * If iter_func() returns 0, list traversal continues. If iter_func() 3629 * returns non-zero, list traversal is stopped. 3630 */ 3631void 3632scsi_desc_iterate(struct scsi_sense_data_desc *sense, u_int sense_len, 3633 int (*iter_func)(struct scsi_sense_data_desc *sense, 3634 u_int, struct scsi_sense_desc_header *, 3635 void *), void *arg) 3636{ 3637 int cur_pos; 3638 int desc_len; 3639 3640 /* 3641 * First make sure the extra length field is present. 3642 */ 3643 if (SSD_DESC_IS_PRESENT(sense, sense_len, extra_len) == 0) 3644 return; 3645 3646 /* 3647 * The length of data actually returned may be different than the 3648 * extra_len recorded in the structure. 3649 */ 3650 desc_len = sense_len -offsetof(struct scsi_sense_data_desc, sense_desc); 3651 3652 /* 3653 * Limit this further by the extra length reported, and the maximum 3654 * allowed extra length. 3655 */ 3656 desc_len = MIN(desc_len, MIN(sense->extra_len, SSD_EXTRA_MAX)); 3657 3658 /* 3659 * Subtract the size of the header from the descriptor length. 3660 * This is to ensure that we have at least the header left, so we 3661 * don't have to check that inside the loop. This can wind up 3662 * being a negative value. 3663 */ 3664 desc_len -= sizeof(struct scsi_sense_desc_header); 3665 3666 for (cur_pos = 0; cur_pos < desc_len;) { 3667 struct scsi_sense_desc_header *header; 3668 3669 header = (struct scsi_sense_desc_header *) 3670 &sense->sense_desc[cur_pos]; 3671 3672 /* 3673 * Check to make sure we have the entire descriptor. We 3674 * don't call iter_func() unless we do. 3675 * 3676 * Note that although cur_pos is at the beginning of the 3677 * descriptor, desc_len already has the header length 3678 * subtracted. So the comparison of the length in the 3679 * header (which does not include the header itself) to 3680 * desc_len - cur_pos is correct. 3681 */ 3682 if (header->length > (desc_len - cur_pos)) 3683 break; 3684 3685 if (iter_func(sense, sense_len, header, arg) != 0) 3686 break; 3687 3688 cur_pos += sizeof(*header) + header->length; 3689 } 3690} 3691 3692struct scsi_find_desc_info { 3693 uint8_t desc_type; 3694 struct scsi_sense_desc_header *header; 3695}; 3696 3697static int 3698scsi_find_desc_func(struct scsi_sense_data_desc *sense, u_int sense_len, 3699 struct scsi_sense_desc_header *header, void *arg) 3700{ 3701 struct scsi_find_desc_info *desc_info; 3702 3703 desc_info = (struct scsi_find_desc_info *)arg; 3704 3705 if (header->desc_type == desc_info->desc_type) { 3706 desc_info->header = header; 3707 3708 /* We found the descriptor, tell the iterator to stop. */ 3709 return (1); 3710 } else 3711 return (0); 3712} 3713 3714/* 3715 * Given a descriptor type, return a pointer to it if it is in the sense 3716 * data and not truncated. Avoiding truncating sense data will simplify 3717 * things significantly for the caller. 3718 */ 3719uint8_t * 3720scsi_find_desc(struct scsi_sense_data_desc *sense, u_int sense_len, 3721 uint8_t desc_type) 3722{ 3723 struct scsi_find_desc_info desc_info; 3724 3725 desc_info.desc_type = desc_type; 3726 desc_info.header = NULL; 3727 3728 scsi_desc_iterate(sense, sense_len, scsi_find_desc_func, &desc_info); 3729 3730 return ((uint8_t *)desc_info.header); 3731} 3732 3733/* 3734 * Fill in SCSI descriptor sense data with the specified parameters. 3735 */ 3736static void 3737scsi_set_sense_data_desc_va(struct scsi_sense_data *sense_data, 3738 u_int *sense_len, scsi_sense_data_type sense_format, int current_error, 3739 int sense_key, int asc, int ascq, va_list ap) 3740{ 3741 struct scsi_sense_data_desc *sense; 3742 scsi_sense_elem_type elem_type; 3743 int space, len; 3744 uint8_t *desc, *data; 3745 3746 memset(sense_data, 0, sizeof(*sense_data)); 3747 sense = (struct scsi_sense_data_desc *)sense_data; 3748 if (current_error != 0) 3749 sense->error_code = SSD_DESC_CURRENT_ERROR; 3750 else 3751 sense->error_code = SSD_DESC_DEFERRED_ERROR; 3752 sense->sense_key = sense_key; 3753 sense->add_sense_code = asc; 3754 sense->add_sense_code_qual = ascq; 3755 sense->flags = 0; 3756 3757 desc = &sense->sense_desc[0]; 3758 space = *sense_len - offsetof(struct scsi_sense_data_desc, sense_desc); 3759 while ((elem_type = va_arg(ap, scsi_sense_elem_type)) != 3760 SSD_ELEM_NONE) { 3761 if (elem_type >= SSD_ELEM_MAX) { 3762 printf("%s: invalid sense type %d\n", __func__, 3763 elem_type); 3764 break; 3765 } 3766 len = va_arg(ap, int); 3767 data = va_arg(ap, uint8_t *); 3768 3769 switch (elem_type) { 3770 case SSD_ELEM_SKIP: 3771 break; 3772 case SSD_ELEM_DESC: 3773 if (space < len) { 3774 sense->flags |= SSDD_SDAT_OVFL; 3775 break; 3776 } 3777 bcopy(data, desc, len); 3778 desc += len; 3779 space -= len; 3780 break; 3781 case SSD_ELEM_SKS: { 3782 struct scsi_sense_sks *sks = (void *)desc; 3783 3784 if (len > sizeof(sks->sense_key_spec)) 3785 break; 3786 if (space < sizeof(*sks)) { 3787 sense->flags |= SSDD_SDAT_OVFL; 3788 break; 3789 } 3790 sks->desc_type = SSD_DESC_SKS; 3791 sks->length = sizeof(*sks) - 3792 (offsetof(struct scsi_sense_sks, length) + 1); 3793 bcopy(data, &sks->sense_key_spec, len); 3794 desc += sizeof(*sks); 3795 space -= sizeof(*sks); 3796 break; 3797 } 3798 case SSD_ELEM_COMMAND: { 3799 struct scsi_sense_command *cmd = (void *)desc; 3800 3801 if (len > sizeof(cmd->command_info)) 3802 break; 3803 if (space < sizeof(*cmd)) { 3804 sense->flags |= SSDD_SDAT_OVFL; 3805 break; 3806 } 3807 cmd->desc_type = SSD_DESC_COMMAND; 3808 cmd->length = sizeof(*cmd) - 3809 (offsetof(struct scsi_sense_command, length) + 1); 3810 bcopy(data, &cmd->command_info[ 3811 sizeof(cmd->command_info) - len], len); 3812 desc += sizeof(*cmd); 3813 space -= sizeof(*cmd); 3814 break; 3815 } 3816 case SSD_ELEM_INFO: { 3817 struct scsi_sense_info *info = (void *)desc; 3818 3819 if (len > sizeof(info->info)) 3820 break; 3821 if (space < sizeof(*info)) { 3822 sense->flags |= SSDD_SDAT_OVFL; 3823 break; 3824 } 3825 info->desc_type = SSD_DESC_INFO; 3826 info->length = sizeof(*info) - 3827 (offsetof(struct scsi_sense_info, length) + 1); 3828 info->byte2 = SSD_INFO_VALID; 3829 bcopy(data, &info->info[sizeof(info->info) - len], len); 3830 desc += sizeof(*info); 3831 space -= sizeof(*info); 3832 break; 3833 } 3834 case SSD_ELEM_FRU: { 3835 struct scsi_sense_fru *fru = (void *)desc; 3836 3837 if (len > sizeof(fru->fru)) 3838 break; 3839 if (space < sizeof(*fru)) { 3840 sense->flags |= SSDD_SDAT_OVFL; 3841 break; 3842 } 3843 fru->desc_type = SSD_DESC_FRU; 3844 fru->length = sizeof(*fru) - 3845 (offsetof(struct scsi_sense_fru, length) + 1); 3846 fru->fru = *data; 3847 desc += sizeof(*fru); 3848 space -= sizeof(*fru); 3849 break; 3850 } 3851 case SSD_ELEM_STREAM: { 3852 struct scsi_sense_stream *stream = (void *)desc; 3853 3854 if (len > sizeof(stream->byte3)) 3855 break; 3856 if (space < sizeof(*stream)) { 3857 sense->flags |= SSDD_SDAT_OVFL; 3858 break; 3859 } 3860 stream->desc_type = SSD_DESC_STREAM; 3861 stream->length = sizeof(*stream) - 3862 (offsetof(struct scsi_sense_stream, length) + 1); 3863 stream->byte3 = *data; 3864 desc += sizeof(*stream); 3865 space -= sizeof(*stream); 3866 break; 3867 } 3868 default: 3869 /* 3870 * We shouldn't get here, but if we do, do nothing. 3871 * We've already consumed the arguments above. 3872 */ 3873 break; 3874 } 3875 } 3876 sense->extra_len = desc - &sense->sense_desc[0]; 3877 *sense_len = offsetof(struct scsi_sense_data_desc, extra_len) + 1 + 3878 sense->extra_len; 3879} 3880 3881/* 3882 * Fill in SCSI fixed sense data with the specified parameters. 3883 */ 3884static void 3885scsi_set_sense_data_fixed_va(struct scsi_sense_data *sense_data, 3886 u_int *sense_len, scsi_sense_data_type sense_format, int current_error, 3887 int sense_key, int asc, int ascq, va_list ap) 3888{ 3889 struct scsi_sense_data_fixed *sense; 3890 scsi_sense_elem_type elem_type; 3891 uint8_t *data; 3892 int len; 3893 3894 memset(sense_data, 0, sizeof(*sense_data)); 3895 sense = (struct scsi_sense_data_fixed *)sense_data; 3896 if (current_error != 0) 3897 sense->error_code = SSD_CURRENT_ERROR; 3898 else 3899 sense->error_code = SSD_DEFERRED_ERROR; 3900 sense->flags = sense_key & SSD_KEY; 3901 sense->extra_len = 0; 3902 if (*sense_len >= 13) { 3903 sense->add_sense_code = asc; 3904 sense->extra_len = MAX(sense->extra_len, 5); 3905 } else 3906 sense->flags |= SSD_SDAT_OVFL; 3907 if (*sense_len >= 14) { 3908 sense->add_sense_code_qual = ascq; 3909 sense->extra_len = MAX(sense->extra_len, 6); 3910 } else 3911 sense->flags |= SSD_SDAT_OVFL; 3912 3913 while ((elem_type = va_arg(ap, scsi_sense_elem_type)) != 3914 SSD_ELEM_NONE) { 3915 if (elem_type >= SSD_ELEM_MAX) { 3916 printf("%s: invalid sense type %d\n", __func__, 3917 elem_type); 3918 break; 3919 } 3920 len = va_arg(ap, int); 3921 data = va_arg(ap, uint8_t *); 3922 3923 switch (elem_type) { 3924 case SSD_ELEM_SKIP: 3925 break; 3926 case SSD_ELEM_SKS: 3927 if (len > sizeof(sense->sense_key_spec)) 3928 break; 3929 if (*sense_len < 18) { 3930 sense->flags |= SSD_SDAT_OVFL; 3931 break; 3932 } 3933 bcopy(data, &sense->sense_key_spec[0], len); 3934 sense->extra_len = MAX(sense->extra_len, 10); 3935 break; 3936 case SSD_ELEM_COMMAND: 3937 if (*sense_len < 12) { 3938 sense->flags |= SSD_SDAT_OVFL; 3939 break; 3940 } 3941 if (len > sizeof(sense->cmd_spec_info)) { 3942 data += len - sizeof(sense->cmd_spec_info); 3943 len -= len - sizeof(sense->cmd_spec_info); 3944 } 3945 bcopy(data, &sense->cmd_spec_info[ 3946 sizeof(sense->cmd_spec_info) - len], len); 3947 sense->extra_len = MAX(sense->extra_len, 4); 3948 break; 3949 case SSD_ELEM_INFO: 3950 /* Set VALID bit only if no overflow. */ 3951 sense->error_code |= SSD_ERRCODE_VALID; 3952 while (len > sizeof(sense->info)) { 3953 if (data[0] != 0) 3954 sense->error_code &= ~SSD_ERRCODE_VALID; 3955 data ++; 3956 len --; 3957 } 3958 bcopy(data, &sense->info[sizeof(sense->info) - len], len); 3959 break; 3960 case SSD_ELEM_FRU: 3961 if (*sense_len < 15) { 3962 sense->flags |= SSD_SDAT_OVFL; 3963 break; 3964 } 3965 sense->fru = *data; 3966 sense->extra_len = MAX(sense->extra_len, 7); 3967 break; 3968 case SSD_ELEM_STREAM: 3969 sense->flags |= *data & 3970 (SSD_ILI | SSD_EOM | SSD_FILEMARK); 3971 break; 3972 default: 3973 3974 /* 3975 * We can't handle that in fixed format. Skip it. 3976 */ 3977 break; 3978 } 3979 } 3980 *sense_len = offsetof(struct scsi_sense_data_fixed, extra_len) + 1 + 3981 sense->extra_len; 3982} 3983 3984/* 3985 * Fill in SCSI sense data with the specified parameters. This routine can 3986 * fill in either fixed or descriptor type sense data. 3987 */ 3988void 3989scsi_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len, 3990 scsi_sense_data_type sense_format, int current_error, 3991 int sense_key, int asc, int ascq, va_list ap) 3992{ 3993 3994 if (*sense_len > SSD_FULL_SIZE) 3995 *sense_len = SSD_FULL_SIZE; 3996 if (sense_format == SSD_TYPE_DESC) 3997 scsi_set_sense_data_desc_va(sense_data, sense_len, 3998 sense_format, current_error, sense_key, asc, ascq, ap); 3999 else 4000 scsi_set_sense_data_fixed_va(sense_data, sense_len, 4001 sense_format, current_error, sense_key, asc, ascq, ap); 4002} 4003 4004void 4005scsi_set_sense_data(struct scsi_sense_data *sense_data, 4006 scsi_sense_data_type sense_format, int current_error, 4007 int sense_key, int asc, int ascq, ...) 4008{ 4009 va_list ap; 4010 u_int sense_len = SSD_FULL_SIZE; 4011 4012 va_start(ap, ascq); 4013 scsi_set_sense_data_va(sense_data, &sense_len, sense_format, 4014 current_error, sense_key, asc, ascq, ap); 4015 va_end(ap); 4016} 4017 4018void 4019scsi_set_sense_data_len(struct scsi_sense_data *sense_data, u_int *sense_len, 4020 scsi_sense_data_type sense_format, int current_error, 4021 int sense_key, int asc, int ascq, ...) 4022{ 4023 va_list ap; 4024 4025 va_start(ap, ascq); 4026 scsi_set_sense_data_va(sense_data, sense_len, sense_format, 4027 current_error, sense_key, asc, ascq, ap); 4028 va_end(ap); 4029} 4030 4031/* 4032 * Get sense information for three similar sense data types. 4033 */ 4034int 4035scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len, 4036 uint8_t info_type, uint64_t *info, int64_t *signed_info) 4037{ 4038 scsi_sense_data_type sense_type; 4039 4040 if (sense_len == 0) 4041 goto bailout; 4042 4043 sense_type = scsi_sense_type(sense_data); 4044 4045 switch (sense_type) { 4046 case SSD_TYPE_DESC: { 4047 struct scsi_sense_data_desc *sense; 4048 uint8_t *desc; 4049 4050 sense = (struct scsi_sense_data_desc *)sense_data; 4051 4052 desc = scsi_find_desc(sense, sense_len, info_type); 4053 if (desc == NULL) 4054 goto bailout; 4055 4056 switch (info_type) { 4057 case SSD_DESC_INFO: { 4058 struct scsi_sense_info *info_desc; 4059 4060 info_desc = (struct scsi_sense_info *)desc; 4061 *info = scsi_8btou64(info_desc->info); 4062 if (signed_info != NULL) 4063 *signed_info = *info; 4064 break; 4065 } 4066 case SSD_DESC_COMMAND: { 4067 struct scsi_sense_command *cmd_desc; 4068 4069 cmd_desc = (struct scsi_sense_command *)desc; 4070 4071 *info = scsi_8btou64(cmd_desc->command_info); 4072 if (signed_info != NULL) 4073 *signed_info = *info; 4074 break; 4075 } 4076 case SSD_DESC_FRU: { 4077 struct scsi_sense_fru *fru_desc; 4078 4079 fru_desc = (struct scsi_sense_fru *)desc; 4080 4081 *info = fru_desc->fru; 4082 if (signed_info != NULL) 4083 *signed_info = (int8_t)fru_desc->fru; 4084 break; 4085 } 4086 default: 4087 goto bailout; 4088 break; 4089 } 4090 break; 4091 } 4092 case SSD_TYPE_FIXED: { 4093 struct scsi_sense_data_fixed *sense; 4094 4095 sense = (struct scsi_sense_data_fixed *)sense_data; 4096 4097 switch (info_type) { 4098 case SSD_DESC_INFO: { 4099 uint32_t info_val; 4100 4101 if ((sense->error_code & SSD_ERRCODE_VALID) == 0) 4102 goto bailout; 4103 4104 if (SSD_FIXED_IS_PRESENT(sense, sense_len, info) == 0) 4105 goto bailout; 4106 4107 info_val = scsi_4btoul(sense->info); 4108 4109 *info = info_val; 4110 if (signed_info != NULL) 4111 *signed_info = (int32_t)info_val; 4112 break; 4113 } 4114 case SSD_DESC_COMMAND: { 4115 uint32_t cmd_val; 4116 4117 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, 4118 cmd_spec_info) == 0) 4119 || (SSD_FIXED_IS_FILLED(sense, cmd_spec_info) == 0)) 4120 goto bailout; 4121 4122 cmd_val = scsi_4btoul(sense->cmd_spec_info); 4123 if (cmd_val == 0) 4124 goto bailout; 4125 4126 *info = cmd_val; 4127 if (signed_info != NULL) 4128 *signed_info = (int32_t)cmd_val; 4129 break; 4130 } 4131 case SSD_DESC_FRU: 4132 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, fru) == 0) 4133 || (SSD_FIXED_IS_FILLED(sense, fru) == 0)) 4134 goto bailout; 4135 4136 if (sense->fru == 0) 4137 goto bailout; 4138 4139 *info = sense->fru; 4140 if (signed_info != NULL) 4141 *signed_info = (int8_t)sense->fru; 4142 break; 4143 default: 4144 goto bailout; 4145 break; 4146 } 4147 break; 4148 } 4149 default: 4150 goto bailout; 4151 break; 4152 } 4153 4154 return (0); 4155bailout: 4156 return (1); 4157} 4158 4159int 4160scsi_get_sks(struct scsi_sense_data *sense_data, u_int sense_len, uint8_t *sks) 4161{ 4162 scsi_sense_data_type sense_type; 4163 4164 if (sense_len == 0) 4165 goto bailout; 4166 4167 sense_type = scsi_sense_type(sense_data); 4168 4169 switch (sense_type) { 4170 case SSD_TYPE_DESC: { 4171 struct scsi_sense_data_desc *sense; 4172 struct scsi_sense_sks *desc; 4173 4174 sense = (struct scsi_sense_data_desc *)sense_data; 4175 4176 desc = (struct scsi_sense_sks *)scsi_find_desc(sense, sense_len, 4177 SSD_DESC_SKS); 4178 if (desc == NULL) 4179 goto bailout; 4180 4181 /* 4182 * No need to check the SKS valid bit for descriptor sense. 4183 * If the descriptor is present, it is valid. 4184 */ 4185 bcopy(desc->sense_key_spec, sks, sizeof(desc->sense_key_spec)); 4186 break; 4187 } 4188 case SSD_TYPE_FIXED: { 4189 struct scsi_sense_data_fixed *sense; 4190 4191 sense = (struct scsi_sense_data_fixed *)sense_data; 4192 4193 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, sense_key_spec)== 0) 4194 || (SSD_FIXED_IS_FILLED(sense, sense_key_spec) == 0)) 4195 goto bailout; 4196 4197 if ((sense->sense_key_spec[0] & SSD_SCS_VALID) == 0) 4198 goto bailout; 4199 4200 bcopy(sense->sense_key_spec, sks,sizeof(sense->sense_key_spec)); 4201 break; 4202 } 4203 default: 4204 goto bailout; 4205 break; 4206 } 4207 return (0); 4208bailout: 4209 return (1); 4210} 4211 4212/* 4213 * Provide a common interface for fixed and descriptor sense to detect 4214 * whether we have block-specific sense information. It is clear by the 4215 * presence of the block descriptor in descriptor mode, but we have to 4216 * infer from the inquiry data and ILI bit in fixed mode. 4217 */ 4218int 4219scsi_get_block_info(struct scsi_sense_data *sense_data, u_int sense_len, 4220 struct scsi_inquiry_data *inq_data, uint8_t *block_bits) 4221{ 4222 scsi_sense_data_type sense_type; 4223 4224 if (inq_data != NULL) { 4225 switch (SID_TYPE(inq_data)) { 4226 case T_DIRECT: 4227 case T_RBC: 4228 break; 4229 default: 4230 goto bailout; 4231 break; 4232 } 4233 } 4234 4235 sense_type = scsi_sense_type(sense_data); 4236 4237 switch (sense_type) { 4238 case SSD_TYPE_DESC: { 4239 struct scsi_sense_data_desc *sense; 4240 struct scsi_sense_block *block; 4241 4242 sense = (struct scsi_sense_data_desc *)sense_data; 4243 4244 block = (struct scsi_sense_block *)scsi_find_desc(sense, 4245 sense_len, SSD_DESC_BLOCK); 4246 if (block == NULL) 4247 goto bailout; 4248 4249 *block_bits = block->byte3; 4250 break; 4251 } 4252 case SSD_TYPE_FIXED: { 4253 struct scsi_sense_data_fixed *sense; 4254 4255 sense = (struct scsi_sense_data_fixed *)sense_data; 4256 4257 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0) 4258 goto bailout; 4259 4260 if ((sense->flags & SSD_ILI) == 0) 4261 goto bailout; 4262 4263 *block_bits = sense->flags & SSD_ILI; 4264 break; 4265 } 4266 default: 4267 goto bailout; 4268 break; 4269 } 4270 return (0); 4271bailout: 4272 return (1); 4273} 4274 4275int 4276scsi_get_stream_info(struct scsi_sense_data *sense_data, u_int sense_len, 4277 struct scsi_inquiry_data *inq_data, uint8_t *stream_bits) 4278{ 4279 scsi_sense_data_type sense_type; 4280 4281 if (inq_data != NULL) { 4282 switch (SID_TYPE(inq_data)) { 4283 case T_SEQUENTIAL: 4284 break; 4285 default: 4286 goto bailout; 4287 break; 4288 } 4289 } 4290 4291 sense_type = scsi_sense_type(sense_data); 4292 4293 switch (sense_type) { 4294 case SSD_TYPE_DESC: { 4295 struct scsi_sense_data_desc *sense; 4296 struct scsi_sense_stream *stream; 4297 4298 sense = (struct scsi_sense_data_desc *)sense_data; 4299 4300 stream = (struct scsi_sense_stream *)scsi_find_desc(sense, 4301 sense_len, SSD_DESC_STREAM); 4302 if (stream == NULL) 4303 goto bailout; 4304 4305 *stream_bits = stream->byte3; 4306 break; 4307 } 4308 case SSD_TYPE_FIXED: { 4309 struct scsi_sense_data_fixed *sense; 4310 4311 sense = (struct scsi_sense_data_fixed *)sense_data; 4312 4313 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0) 4314 goto bailout; 4315 4316 if ((sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) == 0) 4317 goto bailout; 4318 4319 *stream_bits = sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK); 4320 break; 4321 } 4322 default: 4323 goto bailout; 4324 break; 4325 } 4326 return (0); 4327bailout: 4328 return (1); 4329} 4330 4331void 4332scsi_info_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len, 4333 struct scsi_inquiry_data *inq_data, uint64_t info) 4334{ 4335 sbuf_printf(sb, "Info: %#jx", info); 4336} 4337 4338void 4339scsi_command_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len, 4340 struct scsi_inquiry_data *inq_data, uint64_t csi) 4341{ 4342 sbuf_printf(sb, "Command Specific Info: %#jx", csi); 4343} 4344 4345 4346void 4347scsi_progress_sbuf(struct sbuf *sb, uint16_t progress) 4348{ 4349 sbuf_printf(sb, "Progress: %d%% (%d/%d) complete", 4350 (progress * 100) / SSD_SKS_PROGRESS_DENOM, 4351 progress, SSD_SKS_PROGRESS_DENOM); 4352} 4353 4354/* 4355 * Returns 1 for failure (i.e. SKS isn't valid) and 0 for success. 4356 */ 4357int 4358scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks) 4359{ 4360 if ((sks[0] & SSD_SKS_VALID) == 0) 4361 return (1); 4362 4363 switch (sense_key) { 4364 case SSD_KEY_ILLEGAL_REQUEST: { 4365 struct scsi_sense_sks_field *field; 4366 int bad_command; 4367 char tmpstr[40]; 4368 4369 /*Field Pointer*/ 4370 field = (struct scsi_sense_sks_field *)sks; 4371 4372 if (field->byte0 & SSD_SKS_FIELD_CMD) 4373 bad_command = 1; 4374 else 4375 bad_command = 0; 4376 4377 tmpstr[0] = '\0'; 4378 4379 /* Bit pointer is valid */ 4380 if (field->byte0 & SSD_SKS_BPV) 4381 snprintf(tmpstr, sizeof(tmpstr), "bit %d ", 4382 field->byte0 & SSD_SKS_BIT_VALUE); 4383 4384 sbuf_printf(sb, "%s byte %d %sis invalid", 4385 bad_command ? "Command" : "Data", 4386 scsi_2btoul(field->field), tmpstr); 4387 break; 4388 } 4389 case SSD_KEY_UNIT_ATTENTION: { 4390 struct scsi_sense_sks_overflow *overflow; 4391 4392 overflow = (struct scsi_sense_sks_overflow *)sks; 4393 4394 /*UA Condition Queue Overflow*/ 4395 sbuf_printf(sb, "Unit Attention Condition Queue %s", 4396 (overflow->byte0 & SSD_SKS_OVERFLOW_SET) ? 4397 "Overflowed" : "Did Not Overflow??"); 4398 break; 4399 } 4400 case SSD_KEY_RECOVERED_ERROR: 4401 case SSD_KEY_HARDWARE_ERROR: 4402 case SSD_KEY_MEDIUM_ERROR: { 4403 struct scsi_sense_sks_retry *retry; 4404 4405 /*Actual Retry Count*/ 4406 retry = (struct scsi_sense_sks_retry *)sks; 4407 4408 sbuf_printf(sb, "Actual Retry Count: %d", 4409 scsi_2btoul(retry->actual_retry_count)); 4410 break; 4411 } 4412 case SSD_KEY_NO_SENSE: 4413 case SSD_KEY_NOT_READY: { 4414 struct scsi_sense_sks_progress *progress; 4415 int progress_val; 4416 4417 /*Progress Indication*/ 4418 progress = (struct scsi_sense_sks_progress *)sks; 4419 progress_val = scsi_2btoul(progress->progress); 4420 4421 scsi_progress_sbuf(sb, progress_val); 4422 break; 4423 } 4424 case SSD_KEY_COPY_ABORTED: { 4425 struct scsi_sense_sks_segment *segment; 4426 char tmpstr[40]; 4427 4428 /*Segment Pointer*/ 4429 segment = (struct scsi_sense_sks_segment *)sks; 4430 4431 tmpstr[0] = '\0'; 4432 4433 if (segment->byte0 & SSD_SKS_SEGMENT_BPV) 4434 snprintf(tmpstr, sizeof(tmpstr), "bit %d ", 4435 segment->byte0 & SSD_SKS_SEGMENT_BITPTR); 4436 4437 sbuf_printf(sb, "%s byte %d %sis invalid", (segment->byte0 & 4438 SSD_SKS_SEGMENT_SD) ? "Segment" : "Data", 4439 scsi_2btoul(segment->field), tmpstr); 4440 break; 4441 } 4442 default: 4443 sbuf_printf(sb, "Sense Key Specific: %#x,%#x", sks[0], 4444 scsi_2btoul(&sks[1])); 4445 break; 4446 } 4447 4448 return (0); 4449} 4450 4451void 4452scsi_fru_sbuf(struct sbuf *sb, uint64_t fru) 4453{ 4454 sbuf_printf(sb, "Field Replaceable Unit: %d", (int)fru); 4455} 4456 4457void 4458scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info) 4459{ 4460 int need_comma; 4461 4462 need_comma = 0; 4463 /* 4464 * XXX KDM this needs more descriptive decoding. 4465 */ 4466 if (stream_bits & SSD_DESC_STREAM_FM) { 4467 sbuf_printf(sb, "Filemark"); 4468 need_comma = 1; 4469 } 4470 4471 if (stream_bits & SSD_DESC_STREAM_EOM) { 4472 sbuf_printf(sb, "%sEOM", (need_comma) ? "," : ""); 4473 need_comma = 1; 4474 } 4475 4476 if (stream_bits & SSD_DESC_STREAM_ILI) 4477 sbuf_printf(sb, "%sILI", (need_comma) ? "," : ""); 4478 4479 sbuf_printf(sb, ": Info: %#jx", (uintmax_t) info); 4480} 4481 4482void 4483scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info) 4484{ 4485 if (block_bits & SSD_DESC_BLOCK_ILI) 4486 sbuf_printf(sb, "ILI: residue %#jx", (uintmax_t) info); 4487} 4488 4489void 4490scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4491 u_int sense_len, uint8_t *cdb, int cdb_len, 4492 struct scsi_inquiry_data *inq_data, 4493 struct scsi_sense_desc_header *header) 4494{ 4495 struct scsi_sense_info *info; 4496 4497 info = (struct scsi_sense_info *)header; 4498 4499 scsi_info_sbuf(sb, cdb, cdb_len, inq_data, scsi_8btou64(info->info)); 4500} 4501 4502void 4503scsi_sense_command_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4504 u_int sense_len, uint8_t *cdb, int cdb_len, 4505 struct scsi_inquiry_data *inq_data, 4506 struct scsi_sense_desc_header *header) 4507{ 4508 struct scsi_sense_command *command; 4509 4510 command = (struct scsi_sense_command *)header; 4511 4512 scsi_command_sbuf(sb, cdb, cdb_len, inq_data, 4513 scsi_8btou64(command->command_info)); 4514} 4515 4516void 4517scsi_sense_sks_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4518 u_int sense_len, uint8_t *cdb, int cdb_len, 4519 struct scsi_inquiry_data *inq_data, 4520 struct scsi_sense_desc_header *header) 4521{ 4522 struct scsi_sense_sks *sks; 4523 int error_code, sense_key, asc, ascq; 4524 4525 sks = (struct scsi_sense_sks *)header; 4526 4527 scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key, 4528 &asc, &ascq, /*show_errors*/ 1); 4529 4530 scsi_sks_sbuf(sb, sense_key, sks->sense_key_spec); 4531} 4532 4533void 4534scsi_sense_fru_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4535 u_int sense_len, uint8_t *cdb, int cdb_len, 4536 struct scsi_inquiry_data *inq_data, 4537 struct scsi_sense_desc_header *header) 4538{ 4539 struct scsi_sense_fru *fru; 4540 4541 fru = (struct scsi_sense_fru *)header; 4542 4543 scsi_fru_sbuf(sb, (uint64_t)fru->fru); 4544} 4545 4546void 4547scsi_sense_stream_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4548 u_int sense_len, uint8_t *cdb, int cdb_len, 4549 struct scsi_inquiry_data *inq_data, 4550 struct scsi_sense_desc_header *header) 4551{ 4552 struct scsi_sense_stream *stream; 4553 uint64_t info; 4554 4555 stream = (struct scsi_sense_stream *)header; 4556 info = 0; 4557 4558 scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL); 4559 4560 scsi_stream_sbuf(sb, stream->byte3, info); 4561} 4562 4563void 4564scsi_sense_block_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4565 u_int sense_len, uint8_t *cdb, int cdb_len, 4566 struct scsi_inquiry_data *inq_data, 4567 struct scsi_sense_desc_header *header) 4568{ 4569 struct scsi_sense_block *block; 4570 uint64_t info; 4571 4572 block = (struct scsi_sense_block *)header; 4573 info = 0; 4574 4575 scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL); 4576 4577 scsi_block_sbuf(sb, block->byte3, info); 4578} 4579 4580void 4581scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4582 u_int sense_len, uint8_t *cdb, int cdb_len, 4583 struct scsi_inquiry_data *inq_data, 4584 struct scsi_sense_desc_header *header) 4585{ 4586 struct scsi_sense_progress *progress; 4587 const char *sense_key_desc; 4588 const char *asc_desc; 4589 int progress_val; 4590 4591 progress = (struct scsi_sense_progress *)header; 4592 4593 /* 4594 * Get descriptions for the sense key, ASC, and ASCQ in the 4595 * progress descriptor. These could be different than the values 4596 * in the overall sense data. 4597 */ 4598 scsi_sense_desc(progress->sense_key, progress->add_sense_code, 4599 progress->add_sense_code_qual, inq_data, 4600 &sense_key_desc, &asc_desc); 4601 4602 progress_val = scsi_2btoul(progress->progress); 4603 4604 /* 4605 * The progress indicator is for the operation described by the 4606 * sense key, ASC, and ASCQ in the descriptor. 4607 */ 4608 sbuf_cat(sb, sense_key_desc); 4609 sbuf_printf(sb, " asc:%x,%x (%s): ", progress->add_sense_code, 4610 progress->add_sense_code_qual, asc_desc); 4611 scsi_progress_sbuf(sb, progress_val); 4612} 4613 4614void 4615scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4616 u_int sense_len, uint8_t *cdb, int cdb_len, 4617 struct scsi_inquiry_data *inq_data, 4618 struct scsi_sense_desc_header *header) 4619{ 4620 struct scsi_sense_ata_ret_desc *res; 4621 4622 res = (struct scsi_sense_ata_ret_desc *)header; 4623 4624 sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s), ", 4625 res->status, 4626 (res->status & 0x80) ? "BSY " : "", 4627 (res->status & 0x40) ? "DRDY " : "", 4628 (res->status & 0x20) ? "DF " : "", 4629 (res->status & 0x10) ? "SERV " : "", 4630 (res->status & 0x08) ? "DRQ " : "", 4631 (res->status & 0x04) ? "CORR " : "", 4632 (res->status & 0x02) ? "IDX " : "", 4633 (res->status & 0x01) ? "ERR" : ""); 4634 if (res->status & 1) { 4635 sbuf_printf(sb, "error: %02x (%s%s%s%s%s%s%s%s), ", 4636 res->error, 4637 (res->error & 0x80) ? "ICRC " : "", 4638 (res->error & 0x40) ? "UNC " : "", 4639 (res->error & 0x20) ? "MC " : "", 4640 (res->error & 0x10) ? "IDNF " : "", 4641 (res->error & 0x08) ? "MCR " : "", 4642 (res->error & 0x04) ? "ABRT " : "", 4643 (res->error & 0x02) ? "NM " : "", 4644 (res->error & 0x01) ? "ILI" : ""); 4645 } 4646 4647 if (res->flags & SSD_DESC_ATA_FLAG_EXTEND) { 4648 sbuf_printf(sb, "count: %02x%02x, ", 4649 res->count_15_8, res->count_7_0); 4650 sbuf_printf(sb, "LBA: %02x%02x%02x%02x%02x%02x, ", 4651 res->lba_47_40, res->lba_39_32, res->lba_31_24, 4652 res->lba_23_16, res->lba_15_8, res->lba_7_0); 4653 } else { 4654 sbuf_printf(sb, "count: %02x, ", res->count_7_0); 4655 sbuf_printf(sb, "LBA: %02x%02x%02x, ", 4656 res->lba_23_16, res->lba_15_8, res->lba_7_0); 4657 } 4658 sbuf_printf(sb, "device: %02x, ", res->device); 4659} 4660 4661void 4662scsi_sense_forwarded_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4663 u_int sense_len, uint8_t *cdb, int cdb_len, 4664 struct scsi_inquiry_data *inq_data, 4665 struct scsi_sense_desc_header *header) 4666{ 4667 struct scsi_sense_forwarded *forwarded; 4668 const char *sense_key_desc; 4669 const char *asc_desc; 4670 int error_code, sense_key, asc, ascq; 4671 4672 forwarded = (struct scsi_sense_forwarded *)header; 4673 scsi_extract_sense_len((struct scsi_sense_data *)forwarded->sense_data, 4674 forwarded->length - 2, &error_code, &sense_key, &asc, &ascq, 1); 4675 scsi_sense_desc(sense_key, asc, ascq, NULL, &sense_key_desc, &asc_desc); 4676 4677 sbuf_printf(sb, "Forwarded sense: %s asc:%x,%x (%s): ", 4678 sense_key_desc, asc, ascq, asc_desc); 4679} 4680 4681/* 4682 * Generic sense descriptor printing routine. This is used when we have 4683 * not yet implemented a specific printing routine for this descriptor. 4684 */ 4685void 4686scsi_sense_generic_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4687 u_int sense_len, uint8_t *cdb, int cdb_len, 4688 struct scsi_inquiry_data *inq_data, 4689 struct scsi_sense_desc_header *header) 4690{ 4691 int i; 4692 uint8_t *buf_ptr; 4693 4694 sbuf_printf(sb, "Descriptor %#x:", header->desc_type); 4695 4696 buf_ptr = (uint8_t *)&header[1]; 4697 4698 for (i = 0; i < header->length; i++, buf_ptr++) 4699 sbuf_printf(sb, " %02x", *buf_ptr); 4700} 4701 4702/* 4703 * Keep this list in numeric order. This speeds the array traversal. 4704 */ 4705struct scsi_sense_desc_printer { 4706 uint8_t desc_type; 4707 /* 4708 * The function arguments here are the superset of what is needed 4709 * to print out various different descriptors. Command and 4710 * information descriptors need inquiry data and command type. 4711 * Sense key specific descriptors need the sense key. 4712 * 4713 * The sense, cdb, and inquiry data arguments may be NULL, but the 4714 * information printed may not be fully decoded as a result. 4715 */ 4716 void (*print_func)(struct sbuf *sb, struct scsi_sense_data *sense, 4717 u_int sense_len, uint8_t *cdb, int cdb_len, 4718 struct scsi_inquiry_data *inq_data, 4719 struct scsi_sense_desc_header *header); 4720} scsi_sense_printers[] = { 4721 {SSD_DESC_INFO, scsi_sense_info_sbuf}, 4722 {SSD_DESC_COMMAND, scsi_sense_command_sbuf}, 4723 {SSD_DESC_SKS, scsi_sense_sks_sbuf}, 4724 {SSD_DESC_FRU, scsi_sense_fru_sbuf}, 4725 {SSD_DESC_STREAM, scsi_sense_stream_sbuf}, 4726 {SSD_DESC_BLOCK, scsi_sense_block_sbuf}, 4727 {SSD_DESC_ATA, scsi_sense_ata_sbuf}, 4728 {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf}, 4729 {SSD_DESC_FORWARDED, scsi_sense_forwarded_sbuf} 4730}; 4731 4732void 4733scsi_sense_desc_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, 4734 u_int sense_len, uint8_t *cdb, int cdb_len, 4735 struct scsi_inquiry_data *inq_data, 4736 struct scsi_sense_desc_header *header) 4737{ 4738 int i; 4739 4740 for (i = 0; i < (sizeof(scsi_sense_printers) / 4741 sizeof(scsi_sense_printers[0])); i++) { 4742 struct scsi_sense_desc_printer *printer; 4743 4744 printer = &scsi_sense_printers[i]; 4745 4746 /* 4747 * The list is sorted, so quit if we've passed our 4748 * descriptor number. 4749 */ 4750 if (printer->desc_type > header->desc_type) 4751 break; 4752 4753 if (printer->desc_type != header->desc_type) 4754 continue; 4755 4756 printer->print_func(sb, sense, sense_len, cdb, cdb_len, 4757 inq_data, header); 4758 4759 return; 4760 } 4761 4762 /* 4763 * No specific printing routine, so use the generic routine. 4764 */ 4765 scsi_sense_generic_sbuf(sb, sense, sense_len, cdb, cdb_len, 4766 inq_data, header); 4767} 4768 4769scsi_sense_data_type 4770scsi_sense_type(struct scsi_sense_data *sense_data) 4771{ 4772 switch (sense_data->error_code & SSD_ERRCODE) { 4773 case SSD_DESC_CURRENT_ERROR: 4774 case SSD_DESC_DEFERRED_ERROR: 4775 return (SSD_TYPE_DESC); 4776 break; 4777 case SSD_CURRENT_ERROR: 4778 case SSD_DEFERRED_ERROR: 4779 return (SSD_TYPE_FIXED); 4780 break; 4781 default: 4782 break; 4783 } 4784 4785 return (SSD_TYPE_NONE); 4786} 4787 4788struct scsi_print_sense_info { 4789 struct sbuf *sb; 4790 char *path_str; 4791 uint8_t *cdb; 4792 int cdb_len; 4793 struct scsi_inquiry_data *inq_data; 4794}; 4795 4796static int 4797scsi_print_desc_func(struct scsi_sense_data_desc *sense, u_int sense_len, 4798 struct scsi_sense_desc_header *header, void *arg) 4799{ 4800 struct scsi_print_sense_info *print_info; 4801 4802 print_info = (struct scsi_print_sense_info *)arg; 4803 4804 switch (header->desc_type) { 4805 case SSD_DESC_INFO: 4806 case SSD_DESC_FRU: 4807 case SSD_DESC_COMMAND: 4808 case SSD_DESC_SKS: 4809 case SSD_DESC_BLOCK: 4810 case SSD_DESC_STREAM: 4811 /* 4812 * We have already printed these descriptors, if they are 4813 * present. 4814 */ 4815 break; 4816 default: { 4817 sbuf_printf(print_info->sb, "%s", print_info->path_str); 4818 scsi_sense_desc_sbuf(print_info->sb, 4819 (struct scsi_sense_data *)sense, sense_len, 4820 print_info->cdb, print_info->cdb_len, 4821 print_info->inq_data, header); 4822 sbuf_printf(print_info->sb, "\n"); 4823 break; 4824 } 4825 } 4826 4827 /* 4828 * Tell the iterator that we want to see more descriptors if they 4829 * are present. 4830 */ 4831 return (0); 4832} 4833 4834void 4835scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len, 4836 struct sbuf *sb, char *path_str, 4837 struct scsi_inquiry_data *inq_data, uint8_t *cdb, 4838 int cdb_len) 4839{ 4840 int error_code, sense_key, asc, ascq; 4841 4842 sbuf_cat(sb, path_str); 4843 4844 scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key, 4845 &asc, &ascq, /*show_errors*/ 1); 4846 4847 sbuf_printf(sb, "SCSI sense: "); 4848 switch (error_code) { 4849 case SSD_DEFERRED_ERROR: 4850 case SSD_DESC_DEFERRED_ERROR: 4851 sbuf_printf(sb, "Deferred error: "); 4852 4853 /* FALLTHROUGH */ 4854 case SSD_CURRENT_ERROR: 4855 case SSD_DESC_CURRENT_ERROR: 4856 { 4857 struct scsi_sense_data_desc *desc_sense; 4858 struct scsi_print_sense_info print_info; 4859 const char *sense_key_desc; 4860 const char *asc_desc; 4861 uint8_t sks[3]; 4862 uint64_t val; 4863 int info_valid; 4864 4865 /* 4866 * Get descriptions for the sense key, ASC, and ASCQ. If 4867 * these aren't present in the sense data (i.e. the sense 4868 * data isn't long enough), the -1 values that 4869 * scsi_extract_sense_len() returns will yield default 4870 * or error descriptions. 4871 */ 4872 scsi_sense_desc(sense_key, asc, ascq, inq_data, 4873 &sense_key_desc, &asc_desc); 4874 4875 /* 4876 * We first print the sense key and ASC/ASCQ. 4877 */ 4878 sbuf_cat(sb, sense_key_desc); 4879 sbuf_printf(sb, " asc:%x,%x (%s)\n", asc, ascq, asc_desc); 4880 4881 /* 4882 * Get the info field if it is valid. 4883 */ 4884 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, 4885 &val, NULL) == 0) 4886 info_valid = 1; 4887 else 4888 info_valid = 0; 4889 4890 if (info_valid != 0) { 4891 uint8_t bits; 4892 4893 /* 4894 * Determine whether we have any block or stream 4895 * device-specific information. 4896 */ 4897 if (scsi_get_block_info(sense, sense_len, inq_data, 4898 &bits) == 0) { 4899 sbuf_cat(sb, path_str); 4900 scsi_block_sbuf(sb, bits, val); 4901 sbuf_printf(sb, "\n"); 4902 } else if (scsi_get_stream_info(sense, sense_len, 4903 inq_data, &bits) == 0) { 4904 sbuf_cat(sb, path_str); 4905 scsi_stream_sbuf(sb, bits, val); 4906 sbuf_printf(sb, "\n"); 4907 } else if (val != 0) { 4908 /* 4909 * The information field can be valid but 0. 4910 * If the block or stream bits aren't set, 4911 * and this is 0, it isn't terribly useful 4912 * to print it out. 4913 */ 4914 sbuf_cat(sb, path_str); 4915 scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val); 4916 sbuf_printf(sb, "\n"); 4917 } 4918 } 4919 4920 /* 4921 * Print the FRU. 4922 */ 4923 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_FRU, 4924 &val, NULL) == 0) { 4925 sbuf_cat(sb, path_str); 4926 scsi_fru_sbuf(sb, val); 4927 sbuf_printf(sb, "\n"); 4928 } 4929 4930 /* 4931 * Print any command-specific information. 4932 */ 4933 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_COMMAND, 4934 &val, NULL) == 0) { 4935 sbuf_cat(sb, path_str); 4936 scsi_command_sbuf(sb, cdb, cdb_len, inq_data, val); 4937 sbuf_printf(sb, "\n"); 4938 } 4939 4940 /* 4941 * Print out any sense-key-specific information. 4942 */ 4943 if (scsi_get_sks(sense, sense_len, sks) == 0) { 4944 sbuf_cat(sb, path_str); 4945 scsi_sks_sbuf(sb, sense_key, sks); 4946 sbuf_printf(sb, "\n"); 4947 } 4948 4949 /* 4950 * If this is fixed sense, we're done. If we have 4951 * descriptor sense, we might have more information 4952 * available. 4953 */ 4954 if (scsi_sense_type(sense) != SSD_TYPE_DESC) 4955 break; 4956 4957 desc_sense = (struct scsi_sense_data_desc *)sense; 4958 4959 print_info.sb = sb; 4960 print_info.path_str = path_str; 4961 print_info.cdb = cdb; 4962 print_info.cdb_len = cdb_len; 4963 print_info.inq_data = inq_data; 4964 4965 /* 4966 * Print any sense descriptors that we have not already printed. 4967 */ 4968 scsi_desc_iterate(desc_sense, sense_len, scsi_print_desc_func, 4969 &print_info); 4970 break; 4971 4972 } 4973 case -1: 4974 /* 4975 * scsi_extract_sense_len() sets values to -1 if the 4976 * show_errors flag is set and they aren't present in the 4977 * sense data. This means that sense_len is 0. 4978 */ 4979 sbuf_printf(sb, "No sense data present\n"); 4980 break; 4981 default: { 4982 sbuf_printf(sb, "Error code 0x%x", error_code); 4983 if (sense->error_code & SSD_ERRCODE_VALID) { 4984 struct scsi_sense_data_fixed *fixed_sense; 4985 4986 fixed_sense = (struct scsi_sense_data_fixed *)sense; 4987 4988 if (SSD_FIXED_IS_PRESENT(fixed_sense, sense_len, info)){ 4989 uint32_t info; 4990 4991 info = scsi_4btoul(fixed_sense->info); 4992 4993 sbuf_printf(sb, " at block no. %d (decimal)", 4994 info); 4995 } 4996 } 4997 sbuf_printf(sb, "\n"); 4998 break; 4999 } 5000 } 5001} 5002 5003/* 5004 * scsi_sense_sbuf() returns 0 for success and -1 for failure. 5005 */ 5006#ifdef _KERNEL 5007int 5008scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb, 5009 scsi_sense_string_flags flags) 5010#else /* !_KERNEL */ 5011int 5012scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio, 5013 struct sbuf *sb, scsi_sense_string_flags flags) 5014#endif /* _KERNEL/!_KERNEL */ 5015{ 5016 struct scsi_sense_data *sense; 5017 struct scsi_inquiry_data *inq_data; 5018#ifdef _KERNEL 5019 struct ccb_getdev *cgd; 5020#endif /* _KERNEL */ 5021 char path_str[64]; 5022 5023#ifndef _KERNEL 5024 if (device == NULL) 5025 return(-1); 5026#endif /* !_KERNEL */ 5027 if ((csio == NULL) || (sb == NULL)) 5028 return(-1); 5029 5030 /* 5031 * If the CDB is a physical address, we can't deal with it.. 5032 */ 5033 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) 5034 flags &= ~SSS_FLAG_PRINT_COMMAND; 5035 5036#ifdef _KERNEL 5037 xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str)); 5038#else /* !_KERNEL */ 5039 cam_path_string(device, path_str, sizeof(path_str)); 5040#endif /* _KERNEL/!_KERNEL */ 5041 5042#ifdef _KERNEL 5043 if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL) 5044 return(-1); 5045 /* 5046 * Get the device information. 5047 */ 5048 xpt_setup_ccb(&cgd->ccb_h, 5049 csio->ccb_h.path, 5050 CAM_PRIORITY_NORMAL); 5051 cgd->ccb_h.func_code = XPT_GDEV_TYPE; 5052 xpt_action((union ccb *)cgd); 5053 5054 /* 5055 * If the device is unconfigured, just pretend that it is a hard 5056 * drive. scsi_op_desc() needs this. 5057 */ 5058 if (cgd->ccb_h.status == CAM_DEV_NOT_THERE) 5059 cgd->inq_data.device = T_DIRECT; 5060 5061 inq_data = &cgd->inq_data; 5062 5063#else /* !_KERNEL */ 5064 5065 inq_data = &device->inq_data; 5066 5067#endif /* _KERNEL/!_KERNEL */ 5068 5069 sense = NULL; 5070 5071 if (flags & SSS_FLAG_PRINT_COMMAND) { 5072 5073 sbuf_cat(sb, path_str); 5074 5075#ifdef _KERNEL 5076 scsi_command_string(csio, sb); 5077#else /* !_KERNEL */ 5078 scsi_command_string(device, csio, sb); 5079#endif /* _KERNEL/!_KERNEL */ 5080 sbuf_printf(sb, "\n"); 5081 } 5082 5083 /* 5084 * If the sense data is a physical pointer, forget it. 5085 */ 5086 if (csio->ccb_h.flags & CAM_SENSE_PTR) { 5087 if (csio->ccb_h.flags & CAM_SENSE_PHYS) { 5088#ifdef _KERNEL 5089 xpt_free_ccb((union ccb*)cgd); 5090#endif /* _KERNEL/!_KERNEL */ 5091 return(-1); 5092 } else { 5093 /* 5094 * bcopy the pointer to avoid unaligned access 5095 * errors on finicky architectures. We don't 5096 * ensure that the sense data is pointer aligned. 5097 */ 5098 bcopy(&csio->sense_data, &sense, 5099 sizeof(struct scsi_sense_data *)); 5100 } 5101 } else { 5102 /* 5103 * If the physical sense flag is set, but the sense pointer 5104 * is not also set, we assume that the user is an idiot and 5105 * return. (Well, okay, it could be that somehow, the 5106 * entire csio is physical, but we would have probably core 5107 * dumped on one of the bogus pointer deferences above 5108 * already.) 5109 */ 5110 if (csio->ccb_h.flags & CAM_SENSE_PHYS) { 5111#ifdef _KERNEL 5112 xpt_free_ccb((union ccb*)cgd); 5113#endif /* _KERNEL/!_KERNEL */ 5114 return(-1); 5115 } else 5116 sense = &csio->sense_data; 5117 } 5118 5119 scsi_sense_only_sbuf(sense, csio->sense_len - csio->sense_resid, sb, 5120 path_str, inq_data, scsiio_cdb_ptr(csio), csio->cdb_len); 5121 5122#ifdef _KERNEL 5123 xpt_free_ccb((union ccb*)cgd); 5124#endif /* _KERNEL/!_KERNEL */ 5125 return(0); 5126} 5127 5128 5129 5130#ifdef _KERNEL 5131char * 5132scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len) 5133#else /* !_KERNEL */ 5134char * 5135scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio, 5136 char *str, int str_len) 5137#endif /* _KERNEL/!_KERNEL */ 5138{ 5139 struct sbuf sb; 5140 5141 sbuf_new(&sb, str, str_len, 0); 5142 5143#ifdef _KERNEL 5144 scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND); 5145#else /* !_KERNEL */ 5146 scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND); 5147#endif /* _KERNEL/!_KERNEL */ 5148 5149 sbuf_finish(&sb); 5150 5151 return(sbuf_data(&sb)); 5152} 5153 5154#ifdef _KERNEL 5155void 5156scsi_sense_print(struct ccb_scsiio *csio) 5157{ 5158 struct sbuf sb; 5159 char str[512]; 5160 5161 sbuf_new(&sb, str, sizeof(str), 0); 5162 5163 scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND); 5164 5165 sbuf_finish(&sb); 5166 5167 printf("%s", sbuf_data(&sb)); 5168} 5169 5170#else /* !_KERNEL */ 5171void 5172scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, 5173 FILE *ofile) 5174{ 5175 struct sbuf sb; 5176 char str[512]; 5177 5178 if ((device == NULL) || (csio == NULL) || (ofile == NULL)) 5179 return; 5180 5181 sbuf_new(&sb, str, sizeof(str), 0); 5182 5183 scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND); 5184 5185 sbuf_finish(&sb); 5186 5187 fprintf(ofile, "%s", sbuf_data(&sb)); 5188} 5189 5190#endif /* _KERNEL/!_KERNEL */ 5191 5192/* 5193 * Extract basic sense information. This is backward-compatible with the 5194 * previous implementation. For new implementations, 5195 * scsi_extract_sense_len() is recommended. 5196 */ 5197void 5198scsi_extract_sense(struct scsi_sense_data *sense_data, int *error_code, 5199 int *sense_key, int *asc, int *ascq) 5200{ 5201 scsi_extract_sense_len(sense_data, sizeof(*sense_data), error_code, 5202 sense_key, asc, ascq, /*show_errors*/ 0); 5203} 5204 5205/* 5206 * Extract basic sense information from SCSI I/O CCB structure. 5207 */ 5208int 5209scsi_extract_sense_ccb(union ccb *ccb, 5210 int *error_code, int *sense_key, int *asc, int *ascq) 5211{ 5212 struct scsi_sense_data *sense_data; 5213 5214 /* Make sure there are some sense data we can access. */ 5215 if (ccb->ccb_h.func_code != XPT_SCSI_IO || 5216 (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR || 5217 (ccb->csio.scsi_status != SCSI_STATUS_CHECK_COND) || 5218 (ccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0 || 5219 (ccb->ccb_h.flags & CAM_SENSE_PHYS)) 5220 return (0); 5221 5222 if (ccb->ccb_h.flags & CAM_SENSE_PTR) 5223 bcopy(&ccb->csio.sense_data, &sense_data, 5224 sizeof(struct scsi_sense_data *)); 5225 else 5226 sense_data = &ccb->csio.sense_data; 5227 scsi_extract_sense_len(sense_data, 5228 ccb->csio.sense_len - ccb->csio.sense_resid, 5229 error_code, sense_key, asc, ascq, 1); 5230 if (*error_code == -1) 5231 return (0); 5232 return (1); 5233} 5234 5235/* 5236 * Extract basic sense information. If show_errors is set, sense values 5237 * will be set to -1 if they are not present. 5238 */ 5239void 5240scsi_extract_sense_len(struct scsi_sense_data *sense_data, u_int sense_len, 5241 int *error_code, int *sense_key, int *asc, int *ascq, 5242 int show_errors) 5243{ 5244 /* 5245 * If we have no length, we have no sense. 5246 */ 5247 if (sense_len == 0) { 5248 if (show_errors == 0) { 5249 *error_code = 0; 5250 *sense_key = 0; 5251 *asc = 0; 5252 *ascq = 0; 5253 } else { 5254 *error_code = -1; 5255 *sense_key = -1; 5256 *asc = -1; 5257 *ascq = -1; 5258 } 5259 return; 5260 } 5261 5262 *error_code = sense_data->error_code & SSD_ERRCODE; 5263 5264 switch (*error_code) { 5265 case SSD_DESC_CURRENT_ERROR: 5266 case SSD_DESC_DEFERRED_ERROR: { 5267 struct scsi_sense_data_desc *sense; 5268 5269 sense = (struct scsi_sense_data_desc *)sense_data; 5270 5271 if (SSD_DESC_IS_PRESENT(sense, sense_len, sense_key)) 5272 *sense_key = sense->sense_key & SSD_KEY; 5273 else 5274 *sense_key = (show_errors) ? -1 : 0; 5275 5276 if (SSD_DESC_IS_PRESENT(sense, sense_len, add_sense_code)) 5277 *asc = sense->add_sense_code; 5278 else 5279 *asc = (show_errors) ? -1 : 0; 5280 5281 if (SSD_DESC_IS_PRESENT(sense, sense_len, add_sense_code_qual)) 5282 *ascq = sense->add_sense_code_qual; 5283 else 5284 *ascq = (show_errors) ? -1 : 0; 5285 break; 5286 } 5287 case SSD_CURRENT_ERROR: 5288 case SSD_DEFERRED_ERROR: 5289 default: { 5290 struct scsi_sense_data_fixed *sense; 5291 5292 sense = (struct scsi_sense_data_fixed *)sense_data; 5293 5294 if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags)) 5295 *sense_key = sense->flags & SSD_KEY; 5296 else 5297 *sense_key = (show_errors) ? -1 : 0; 5298 5299 if ((SSD_FIXED_IS_PRESENT(sense, sense_len, add_sense_code)) 5300 && (SSD_FIXED_IS_FILLED(sense, add_sense_code))) 5301 *asc = sense->add_sense_code; 5302 else 5303 *asc = (show_errors) ? -1 : 0; 5304 5305 if ((SSD_FIXED_IS_PRESENT(sense, sense_len,add_sense_code_qual)) 5306 && (SSD_FIXED_IS_FILLED(sense, add_sense_code_qual))) 5307 *ascq = sense->add_sense_code_qual; 5308 else 5309 *ascq = (show_errors) ? -1 : 0; 5310 break; 5311 } 5312 } 5313} 5314 5315int 5316scsi_get_sense_key(struct scsi_sense_data *sense_data, u_int sense_len, 5317 int show_errors) 5318{ 5319 int error_code, sense_key, asc, ascq; 5320 5321 scsi_extract_sense_len(sense_data, sense_len, &error_code, 5322 &sense_key, &asc, &ascq, show_errors); 5323 5324 return (sense_key); 5325} 5326 5327int 5328scsi_get_asc(struct scsi_sense_data *sense_data, u_int sense_len, 5329 int show_errors) 5330{ 5331 int error_code, sense_key, asc, ascq; 5332 5333 scsi_extract_sense_len(sense_data, sense_len, &error_code, 5334 &sense_key, &asc, &ascq, show_errors); 5335 5336 return (asc); 5337} 5338 5339int 5340scsi_get_ascq(struct scsi_sense_data *sense_data, u_int sense_len, 5341 int show_errors) 5342{ 5343 int error_code, sense_key, asc, ascq; 5344 5345 scsi_extract_sense_len(sense_data, sense_len, &error_code, 5346 &sense_key, &asc, &ascq, show_errors); 5347 5348 return (ascq); 5349} 5350 5351/* 5352 * This function currently requires at least 36 bytes, or 5353 * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this 5354 * function needs more or less data in the future, another length should be 5355 * defined in scsi_all.h to indicate the minimum amount of data necessary 5356 * for this routine to function properly. 5357 */ 5358void 5359scsi_print_inquiry(struct scsi_inquiry_data *inq_data) 5360{ 5361 u_int8_t type; 5362 char *dtype, *qtype; 5363 char vendor[16], product[48], revision[16], rstr[12]; 5364 5365 type = SID_TYPE(inq_data); 5366 5367 /* 5368 * Figure out basic device type and qualifier. 5369 */ 5370 if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) { 5371 qtype = " (vendor-unique qualifier)"; 5372 } else { 5373 switch (SID_QUAL(inq_data)) { 5374 case SID_QUAL_LU_CONNECTED: 5375 qtype = ""; 5376 break; 5377 5378 case SID_QUAL_LU_OFFLINE: 5379 qtype = " (offline)"; 5380 break; 5381 5382 case SID_QUAL_RSVD: 5383 qtype = " (reserved qualifier)"; 5384 break; 5385 default: 5386 case SID_QUAL_BAD_LU: 5387 qtype = " (LUN not supported)"; 5388 break; 5389 } 5390 } 5391 5392 switch (type) { 5393 case T_DIRECT: 5394 dtype = "Direct Access"; 5395 break; 5396 case T_SEQUENTIAL: 5397 dtype = "Sequential Access"; 5398 break; 5399 case T_PRINTER: 5400 dtype = "Printer"; 5401 break; 5402 case T_PROCESSOR: 5403 dtype = "Processor"; 5404 break; 5405 case T_WORM: 5406 dtype = "WORM"; 5407 break; 5408 case T_CDROM: 5409 dtype = "CD-ROM"; 5410 break; 5411 case T_SCANNER: 5412 dtype = "Scanner"; 5413 break; 5414 case T_OPTICAL: 5415 dtype = "Optical"; 5416 break; 5417 case T_CHANGER: 5418 dtype = "Changer"; 5419 break; 5420 case T_COMM: 5421 dtype = "Communication"; 5422 break; 5423 case T_STORARRAY: 5424 dtype = "Storage Array"; 5425 break; 5426 case T_ENCLOSURE: 5427 dtype = "Enclosure Services"; 5428 break; 5429 case T_RBC: 5430 dtype = "Simplified Direct Access"; 5431 break; 5432 case T_OCRW: 5433 dtype = "Optical Card Read/Write"; 5434 break; 5435 case T_OSD: 5436 dtype = "Object-Based Storage"; 5437 break; 5438 case T_ADC: 5439 dtype = "Automation/Drive Interface"; 5440 break; 5441 case T_NODEVICE: 5442 dtype = "Uninstalled"; 5443 break; 5444 default: 5445 dtype = "unknown"; 5446 break; 5447 } 5448 5449 cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), 5450 sizeof(vendor)); 5451 cam_strvis(product, inq_data->product, sizeof(inq_data->product), 5452 sizeof(product)); 5453 cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), 5454 sizeof(revision)); 5455 5456 if (SID_ANSI_REV(inq_data) == SCSI_REV_0) 5457 snprintf(rstr, sizeof(rstr), "SCSI"); 5458 else if (SID_ANSI_REV(inq_data) <= SCSI_REV_SPC) { 5459 snprintf(rstr, sizeof(rstr), "SCSI-%d", 5460 SID_ANSI_REV(inq_data)); 5461 } else { 5462 snprintf(rstr, sizeof(rstr), "SPC-%d SCSI", 5463 SID_ANSI_REV(inq_data) - 2); 5464 } 5465 printf("<%s %s %s> %s %s %s device%s\n", 5466 vendor, product, revision, 5467 SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", 5468 dtype, rstr, qtype); 5469} 5470 5471void 5472scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data) 5473{ 5474 char vendor[16], product[48], revision[16]; 5475 5476 cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), 5477 sizeof(vendor)); 5478 cam_strvis(product, inq_data->product, sizeof(inq_data->product), 5479 sizeof(product)); 5480 cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), 5481 sizeof(revision)); 5482 5483 printf("<%s %s %s>", vendor, product, revision); 5484} 5485 5486/* 5487 * Table of syncrates that don't follow the "divisible by 4" 5488 * rule. This table will be expanded in future SCSI specs. 5489 */ 5490static struct { 5491 u_int period_factor; 5492 u_int period; /* in 100ths of ns */ 5493} scsi_syncrates[] = { 5494 { 0x08, 625 }, /* FAST-160 */ 5495 { 0x09, 1250 }, /* FAST-80 */ 5496 { 0x0a, 2500 }, /* FAST-40 40MHz */ 5497 { 0x0b, 3030 }, /* FAST-40 33MHz */ 5498 { 0x0c, 5000 } /* FAST-20 */ 5499}; 5500 5501/* 5502 * Return the frequency in kHz corresponding to the given 5503 * sync period factor. 5504 */ 5505u_int 5506scsi_calc_syncsrate(u_int period_factor) 5507{ 5508 int i; 5509 int num_syncrates; 5510 5511 /* 5512 * It's a bug if period is zero, but if it is anyway, don't 5513 * die with a divide fault- instead return something which 5514 * 'approximates' async 5515 */ 5516 if (period_factor == 0) { 5517 return (3300); 5518 } 5519 5520 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); 5521 /* See if the period is in the "exception" table */ 5522 for (i = 0; i < num_syncrates; i++) { 5523 5524 if (period_factor == scsi_syncrates[i].period_factor) { 5525 /* Period in kHz */ 5526 return (100000000 / scsi_syncrates[i].period); 5527 } 5528 } 5529 5530 /* 5531 * Wasn't in the table, so use the standard 5532 * 4 times conversion. 5533 */ 5534 return (10000000 / (period_factor * 4 * 10)); 5535} 5536 5537/* 5538 * Return the SCSI sync parameter that corresponsd to 5539 * the passed in period in 10ths of ns. 5540 */ 5541u_int 5542scsi_calc_syncparam(u_int period) 5543{ 5544 int i; 5545 int num_syncrates; 5546 5547 if (period == 0) 5548 return (~0); /* Async */ 5549 5550 /* Adjust for exception table being in 100ths. */ 5551 period *= 10; 5552 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); 5553 /* See if the period is in the "exception" table */ 5554 for (i = 0; i < num_syncrates; i++) { 5555 5556 if (period <= scsi_syncrates[i].period) { 5557 /* Period in 100ths of ns */ 5558 return (scsi_syncrates[i].period_factor); 5559 } 5560 } 5561 5562 /* 5563 * Wasn't in the table, so use the standard 5564 * 1/4 period in ns conversion. 5565 */ 5566 return (period/400); 5567} 5568 5569int 5570scsi_devid_is_naa_ieee_reg(uint8_t *bufp) 5571{ 5572 struct scsi_vpd_id_descriptor *descr; 5573 struct scsi_vpd_id_naa_basic *naa; 5574 5575 descr = (struct scsi_vpd_id_descriptor *)bufp; 5576 naa = (struct scsi_vpd_id_naa_basic *)descr->identifier; 5577 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA) 5578 return 0; 5579 if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg)) 5580 return 0; 5581 if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG) 5582 return 0; 5583 return 1; 5584} 5585 5586int 5587scsi_devid_is_sas_target(uint8_t *bufp) 5588{ 5589 struct scsi_vpd_id_descriptor *descr; 5590 5591 descr = (struct scsi_vpd_id_descriptor *)bufp; 5592 if (!scsi_devid_is_naa_ieee_reg(bufp)) 5593 return 0; 5594 if ((descr->id_type & SVPD_ID_PIV) == 0) /* proto field reserved */ 5595 return 0; 5596 if ((descr->proto_codeset >> SVPD_ID_PROTO_SHIFT) != SCSI_PROTO_SAS) 5597 return 0; 5598 return 1; 5599} 5600 5601int 5602scsi_devid_is_lun_eui64(uint8_t *bufp) 5603{ 5604 struct scsi_vpd_id_descriptor *descr; 5605 5606 descr = (struct scsi_vpd_id_descriptor *)bufp; 5607 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5608 return 0; 5609 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_EUI64) 5610 return 0; 5611 return 1; 5612} 5613 5614int 5615scsi_devid_is_lun_naa(uint8_t *bufp) 5616{ 5617 struct scsi_vpd_id_descriptor *descr; 5618 5619 descr = (struct scsi_vpd_id_descriptor *)bufp; 5620 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5621 return 0; 5622 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA) 5623 return 0; 5624 return 1; 5625} 5626 5627int 5628scsi_devid_is_lun_t10(uint8_t *bufp) 5629{ 5630 struct scsi_vpd_id_descriptor *descr; 5631 5632 descr = (struct scsi_vpd_id_descriptor *)bufp; 5633 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5634 return 0; 5635 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_T10) 5636 return 0; 5637 return 1; 5638} 5639 5640int 5641scsi_devid_is_lun_name(uint8_t *bufp) 5642{ 5643 struct scsi_vpd_id_descriptor *descr; 5644 5645 descr = (struct scsi_vpd_id_descriptor *)bufp; 5646 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5647 return 0; 5648 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_SCSI_NAME) 5649 return 0; 5650 return 1; 5651} 5652 5653int 5654scsi_devid_is_lun_md5(uint8_t *bufp) 5655{ 5656 struct scsi_vpd_id_descriptor *descr; 5657 5658 descr = (struct scsi_vpd_id_descriptor *)bufp; 5659 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5660 return 0; 5661 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_MD5_LUN_ID) 5662 return 0; 5663 return 1; 5664} 5665 5666int 5667scsi_devid_is_lun_uuid(uint8_t *bufp) 5668{ 5669 struct scsi_vpd_id_descriptor *descr; 5670 5671 descr = (struct scsi_vpd_id_descriptor *)bufp; 5672 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_LUN) 5673 return 0; 5674 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_UUID) 5675 return 0; 5676 return 1; 5677} 5678 5679int 5680scsi_devid_is_port_naa(uint8_t *bufp) 5681{ 5682 struct scsi_vpd_id_descriptor *descr; 5683 5684 descr = (struct scsi_vpd_id_descriptor *)bufp; 5685 if ((descr->id_type & SVPD_ID_ASSOC_MASK) != SVPD_ID_ASSOC_PORT) 5686 return 0; 5687 if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA) 5688 return 0; 5689 return 1; 5690} 5691 5692struct scsi_vpd_id_descriptor * 5693scsi_get_devid_desc(struct scsi_vpd_id_descriptor *desc, uint32_t len, 5694 scsi_devid_checkfn_t ck_fn) 5695{ 5696 uint8_t *desc_buf_end; 5697 5698 desc_buf_end = (uint8_t *)desc + len; 5699 5700 for (; desc->identifier <= desc_buf_end && 5701 desc->identifier + desc->length <= desc_buf_end; 5702 desc = (struct scsi_vpd_id_descriptor *)(desc->identifier 5703 + desc->length)) { 5704 5705 if (ck_fn == NULL || ck_fn((uint8_t *)desc) != 0) 5706 return (desc); 5707 } 5708 return (NULL); 5709} 5710 5711struct scsi_vpd_id_descriptor * 5712scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t page_len, 5713 scsi_devid_checkfn_t ck_fn) 5714{ 5715 uint32_t len; 5716 5717 if (page_len < sizeof(*id)) 5718 return (NULL); 5719 len = MIN(scsi_2btoul(id->length), page_len - sizeof(*id)); 5720 return (scsi_get_devid_desc((struct scsi_vpd_id_descriptor *) 5721 id->desc_list, len, ck_fn)); 5722} 5723 5724int 5725scsi_transportid_sbuf(struct sbuf *sb, struct scsi_transportid_header *hdr, 5726 uint32_t valid_len) 5727{ 5728 switch (hdr->format_protocol & SCSI_TRN_PROTO_MASK) { 5729 case SCSI_PROTO_FC: { 5730 struct scsi_transportid_fcp *fcp; 5731 uint64_t n_port_name; 5732 5733 fcp = (struct scsi_transportid_fcp *)hdr; 5734 5735 n_port_name = scsi_8btou64(fcp->n_port_name); 5736 5737 sbuf_printf(sb, "FCP address: 0x%.16jx",(uintmax_t)n_port_name); 5738 break; 5739 } 5740 case SCSI_PROTO_SPI: { 5741 struct scsi_transportid_spi *spi; 5742 5743 spi = (struct scsi_transportid_spi *)hdr; 5744 5745 sbuf_printf(sb, "SPI address: %u,%u", 5746 scsi_2btoul(spi->scsi_addr), 5747 scsi_2btoul(spi->rel_trgt_port_id)); 5748 break; 5749 } 5750 case SCSI_PROTO_SSA: 5751 /* 5752 * XXX KDM there is no transport ID defined in SPC-4 for 5753 * SSA. 5754 */ 5755 break; 5756 case SCSI_PROTO_1394: { 5757 struct scsi_transportid_1394 *sbp; 5758 uint64_t eui64; 5759 5760 sbp = (struct scsi_transportid_1394 *)hdr; 5761 5762 eui64 = scsi_8btou64(sbp->eui64); 5763 sbuf_printf(sb, "SBP address: 0x%.16jx", (uintmax_t)eui64); 5764 break; 5765 } 5766 case SCSI_PROTO_RDMA: { 5767 struct scsi_transportid_rdma *rdma; 5768 unsigned int i; 5769 5770 rdma = (struct scsi_transportid_rdma *)hdr; 5771 5772 sbuf_printf(sb, "RDMA address: 0x"); 5773 for (i = 0; i < sizeof(rdma->initiator_port_id); i++) 5774 sbuf_printf(sb, "%02x", rdma->initiator_port_id[i]); 5775 break; 5776 } 5777 case SCSI_PROTO_ISCSI: { 5778 uint32_t add_len, i; 5779 uint8_t *iscsi_name = NULL; 5780 int nul_found = 0; 5781 5782 sbuf_printf(sb, "iSCSI address: "); 5783 if ((hdr->format_protocol & SCSI_TRN_FORMAT_MASK) == 5784 SCSI_TRN_ISCSI_FORMAT_DEVICE) { 5785 struct scsi_transportid_iscsi_device *dev; 5786 5787 dev = (struct scsi_transportid_iscsi_device *)hdr; 5788 5789 /* 5790 * Verify how much additional data we really have. 5791 */ 5792 add_len = scsi_2btoul(dev->additional_length); 5793 add_len = MIN(add_len, valid_len - 5794 __offsetof(struct scsi_transportid_iscsi_device, 5795 iscsi_name)); 5796 iscsi_name = &dev->iscsi_name[0]; 5797 5798 } else if ((hdr->format_protocol & SCSI_TRN_FORMAT_MASK) == 5799 SCSI_TRN_ISCSI_FORMAT_PORT) { 5800 struct scsi_transportid_iscsi_port *port; 5801 5802 port = (struct scsi_transportid_iscsi_port *)hdr; 5803 5804 add_len = scsi_2btoul(port->additional_length); 5805 add_len = MIN(add_len, valid_len - 5806 __offsetof(struct scsi_transportid_iscsi_port, 5807 iscsi_name)); 5808 iscsi_name = &port->iscsi_name[0]; 5809 } else { 5810 sbuf_printf(sb, "unknown format %x", 5811 (hdr->format_protocol & 5812 SCSI_TRN_FORMAT_MASK) >> 5813 SCSI_TRN_FORMAT_SHIFT); 5814 break; 5815 } 5816 if (add_len == 0) { 5817 sbuf_printf(sb, "not enough data"); 5818 break; 5819 } 5820 /* 5821 * This is supposed to be a NUL-terminated ASCII 5822 * string, but you never know. So we're going to 5823 * check. We need to do this because there is no 5824 * sbuf equivalent of strncat(). 5825 */ 5826 for (i = 0; i < add_len; i++) { 5827 if (iscsi_name[i] == '\0') { 5828 nul_found = 1; 5829 break; 5830 } 5831 } 5832 /* 5833 * If there is a NUL in the name, we can just use 5834 * sbuf_cat(). Otherwise we need to use sbuf_bcat(). 5835 */ 5836 if (nul_found != 0) 5837 sbuf_cat(sb, iscsi_name); 5838 else 5839 sbuf_bcat(sb, iscsi_name, add_len); 5840 break; 5841 } 5842 case SCSI_PROTO_SAS: { 5843 struct scsi_transportid_sas *sas; 5844 uint64_t sas_addr; 5845 5846 sas = (struct scsi_transportid_sas *)hdr; 5847 5848 sas_addr = scsi_8btou64(sas->sas_address); 5849 sbuf_printf(sb, "SAS address: 0x%.16jx", (uintmax_t)sas_addr); 5850 break; 5851 } 5852 case SCSI_PROTO_ADITP: 5853 case SCSI_PROTO_ATA: 5854 case SCSI_PROTO_UAS: 5855 /* 5856 * No Transport ID format for ADI, ATA or USB is defined in 5857 * SPC-4. 5858 */ 5859 sbuf_printf(sb, "No known Transport ID format for protocol " 5860 "%#x", hdr->format_protocol & SCSI_TRN_PROTO_MASK); 5861 break; 5862 case SCSI_PROTO_SOP: { 5863 struct scsi_transportid_sop *sop; 5864 struct scsi_sop_routing_id_norm *rid; 5865 5866 sop = (struct scsi_transportid_sop *)hdr; 5867 rid = (struct scsi_sop_routing_id_norm *)sop->routing_id; 5868 5869 /* 5870 * Note that there is no alternate format specified in SPC-4 5871 * for the PCIe routing ID, so we don't really have a way 5872 * to know whether the second byte of the routing ID is 5873 * a device and function or just a function. So we just 5874 * assume bus,device,function. 5875 */ 5876 sbuf_printf(sb, "SOP Routing ID: %u,%u,%u", 5877 rid->bus, rid->devfunc >> SCSI_TRN_SOP_DEV_SHIFT, 5878 rid->devfunc & SCSI_TRN_SOP_FUNC_NORM_MAX); 5879 break; 5880 } 5881 case SCSI_PROTO_NONE: 5882 default: 5883 sbuf_printf(sb, "Unknown protocol %#x", 5884 hdr->format_protocol & SCSI_TRN_PROTO_MASK); 5885 break; 5886 } 5887 5888 return (0); 5889} 5890 5891struct scsi_nv scsi_proto_map[] = { 5892 { "fcp", SCSI_PROTO_FC }, 5893 { "spi", SCSI_PROTO_SPI }, 5894 { "ssa", SCSI_PROTO_SSA }, 5895 { "sbp", SCSI_PROTO_1394 }, 5896 { "1394", SCSI_PROTO_1394 }, 5897 { "srp", SCSI_PROTO_RDMA }, 5898 { "rdma", SCSI_PROTO_RDMA }, 5899 { "iscsi", SCSI_PROTO_ISCSI }, 5900 { "iqn", SCSI_PROTO_ISCSI }, 5901 { "sas", SCSI_PROTO_SAS }, 5902 { "aditp", SCSI_PROTO_ADITP }, 5903 { "ata", SCSI_PROTO_ATA }, 5904 { "uas", SCSI_PROTO_UAS }, 5905 { "usb", SCSI_PROTO_UAS }, 5906 { "sop", SCSI_PROTO_SOP } 5907}; 5908 5909const char * 5910scsi_nv_to_str(struct scsi_nv *table, int num_table_entries, uint64_t value) 5911{ 5912 int i; 5913 5914 for (i = 0; i < num_table_entries; i++) { 5915 if (table[i].value == value) 5916 return (table[i].name); 5917 } 5918 5919 return (NULL); 5920} 5921 5922/* 5923 * Given a name/value table, find a value matching the given name. 5924 * Return values: 5925 * SCSI_NV_FOUND - match found 5926 * SCSI_NV_AMBIGUOUS - more than one match, none of them exact 5927 * SCSI_NV_NOT_FOUND - no match found 5928 */ 5929scsi_nv_status 5930scsi_get_nv(struct scsi_nv *table, int num_table_entries, 5931 char *name, int *table_entry, scsi_nv_flags flags) 5932{ 5933 int i, num_matches = 0; 5934 5935 for (i = 0; i < num_table_entries; i++) { 5936 size_t table_len, name_len; 5937 5938 table_len = strlen(table[i].name); 5939 name_len = strlen(name); 5940 5941 if ((((flags & SCSI_NV_FLAG_IG_CASE) != 0) 5942 && (strncasecmp(table[i].name, name, name_len) == 0)) 5943 || (((flags & SCSI_NV_FLAG_IG_CASE) == 0) 5944 && (strncmp(table[i].name, name, name_len) == 0))) { 5945 *table_entry = i; 5946 5947 /* 5948 * Check for an exact match. If we have the same 5949 * number of characters in the table as the argument, 5950 * and we already know they're the same, we have 5951 * an exact match. 5952 */ 5953 if (table_len == name_len) 5954 return (SCSI_NV_FOUND); 5955 5956 /* 5957 * Otherwise, bump up the number of matches. We'll 5958 * see later how many we have. 5959 */ 5960 num_matches++; 5961 } 5962 } 5963 5964 if (num_matches > 1) 5965 return (SCSI_NV_AMBIGUOUS); 5966 else if (num_matches == 1) 5967 return (SCSI_NV_FOUND); 5968 else 5969 return (SCSI_NV_NOT_FOUND); 5970} 5971 5972/* 5973 * Parse transport IDs for Fibre Channel, 1394 and SAS. Since these are 5974 * all 64-bit numbers, the code is similar. 5975 */ 5976int 5977scsi_parse_transportid_64bit(int proto_id, char *id_str, 5978 struct scsi_transportid_header **hdr, 5979 unsigned int *alloc_len, 5980#ifdef _KERNEL 5981 struct malloc_type *type, int flags, 5982#endif 5983 char *error_str, int error_str_len) 5984{ 5985 uint64_t value; 5986 char *endptr; 5987 int retval; 5988 size_t alloc_size; 5989 5990 retval = 0; 5991 5992 value = strtouq(id_str, &endptr, 0); 5993 if (*endptr != '\0') { 5994 if (error_str != NULL) { 5995 snprintf(error_str, error_str_len, "%s: error " 5996 "parsing ID %s, 64-bit number required", 5997 __func__, id_str); 5998 } 5999 retval = 1; 6000 goto bailout; 6001 } 6002 6003 switch (proto_id) { 6004 case SCSI_PROTO_FC: 6005 alloc_size = sizeof(struct scsi_transportid_fcp); 6006 break; 6007 case SCSI_PROTO_1394: 6008 alloc_size = sizeof(struct scsi_transportid_1394); 6009 break; 6010 case SCSI_PROTO_SAS: 6011 alloc_size = sizeof(struct scsi_transportid_sas); 6012 break; 6013 default: 6014 if (error_str != NULL) { 6015 snprintf(error_str, error_str_len, "%s: unsupoprted " 6016 "protocol %d", __func__, proto_id); 6017 } 6018 retval = 1; 6019 goto bailout; 6020 break; /* NOTREACHED */ 6021 } 6022#ifdef _KERNEL 6023 *hdr = malloc(alloc_size, type, flags); 6024#else /* _KERNEL */ 6025 *hdr = malloc(alloc_size); 6026#endif /*_KERNEL */ 6027 if (*hdr == NULL) { 6028 if (error_str != NULL) { 6029 snprintf(error_str, error_str_len, "%s: unable to " 6030 "allocate %zu bytes", __func__, alloc_size); 6031 } 6032 retval = 1; 6033 goto bailout; 6034 } 6035 6036 *alloc_len = alloc_size; 6037 6038 bzero(*hdr, alloc_size); 6039 6040 switch (proto_id) { 6041 case SCSI_PROTO_FC: { 6042 struct scsi_transportid_fcp *fcp; 6043 6044 fcp = (struct scsi_transportid_fcp *)(*hdr); 6045 fcp->format_protocol = SCSI_PROTO_FC | 6046 SCSI_TRN_FCP_FORMAT_DEFAULT; 6047 scsi_u64to8b(value, fcp->n_port_name); 6048 break; 6049 } 6050 case SCSI_PROTO_1394: { 6051 struct scsi_transportid_1394 *sbp; 6052 6053 sbp = (struct scsi_transportid_1394 *)(*hdr); 6054 sbp->format_protocol = SCSI_PROTO_1394 | 6055 SCSI_TRN_1394_FORMAT_DEFAULT; 6056 scsi_u64to8b(value, sbp->eui64); 6057 break; 6058 } 6059 case SCSI_PROTO_SAS: { 6060 struct scsi_transportid_sas *sas; 6061 6062 sas = (struct scsi_transportid_sas *)(*hdr); 6063 sas->format_protocol = SCSI_PROTO_SAS | 6064 SCSI_TRN_SAS_FORMAT_DEFAULT; 6065 scsi_u64to8b(value, sas->sas_address); 6066 break; 6067 } 6068 default: 6069 break; 6070 } 6071bailout: 6072 return (retval); 6073} 6074 6075/* 6076 * Parse a SPI (Parallel SCSI) address of the form: id,rel_tgt_port 6077 */ 6078int 6079scsi_parse_transportid_spi(char *id_str, struct scsi_transportid_header **hdr, 6080 unsigned int *alloc_len, 6081#ifdef _KERNEL 6082 struct malloc_type *type, int flags, 6083#endif 6084 char *error_str, int error_str_len) 6085{ 6086 unsigned long scsi_addr, target_port; 6087 struct scsi_transportid_spi *spi; 6088 char *tmpstr, *endptr; 6089 int retval; 6090 6091 retval = 0; 6092 6093 tmpstr = strsep(&id_str, ","); 6094 if (tmpstr == NULL) { 6095 if (error_str != NULL) { 6096 snprintf(error_str, error_str_len, 6097 "%s: no ID found", __func__); 6098 } 6099 retval = 1; 6100 goto bailout; 6101 } 6102 scsi_addr = strtoul(tmpstr, &endptr, 0); 6103 if (*endptr != '\0') { 6104 if (error_str != NULL) { 6105 snprintf(error_str, error_str_len, "%s: error " 6106 "parsing SCSI ID %s, number required", 6107 __func__, tmpstr); 6108 } 6109 retval = 1; 6110 goto bailout; 6111 } 6112 6113 if (id_str == NULL) { 6114 if (error_str != NULL) { 6115 snprintf(error_str, error_str_len, "%s: no relative " 6116 "target port found", __func__); 6117 } 6118 retval = 1; 6119 goto bailout; 6120 } 6121 6122 target_port = strtoul(id_str, &endptr, 0); 6123 if (*endptr != '\0') { 6124 if (error_str != NULL) { 6125 snprintf(error_str, error_str_len, "%s: error " 6126 "parsing relative target port %s, number " 6127 "required", __func__, id_str); 6128 } 6129 retval = 1; 6130 goto bailout; 6131 } 6132#ifdef _KERNEL 6133 spi = malloc(sizeof(*spi), type, flags); 6134#else 6135 spi = malloc(sizeof(*spi)); 6136#endif 6137 if (spi == NULL) { 6138 if (error_str != NULL) { 6139 snprintf(error_str, error_str_len, "%s: unable to " 6140 "allocate %zu bytes", __func__, 6141 sizeof(*spi)); 6142 } 6143 retval = 1; 6144 goto bailout; 6145 } 6146 *alloc_len = sizeof(*spi); 6147 bzero(spi, sizeof(*spi)); 6148 6149 spi->format_protocol = SCSI_PROTO_SPI | SCSI_TRN_SPI_FORMAT_DEFAULT; 6150 scsi_ulto2b(scsi_addr, spi->scsi_addr); 6151 scsi_ulto2b(target_port, spi->rel_trgt_port_id); 6152 6153 *hdr = (struct scsi_transportid_header *)spi; 6154bailout: 6155 return (retval); 6156} 6157 6158/* 6159 * Parse an RDMA/SRP Initiator Port ID string. This is 32 hexadecimal digits, 6160 * optionally prefixed by "0x" or "0X". 6161 */ 6162int 6163scsi_parse_transportid_rdma(char *id_str, struct scsi_transportid_header **hdr, 6164 unsigned int *alloc_len, 6165#ifdef _KERNEL 6166 struct malloc_type *type, int flags, 6167#endif 6168 char *error_str, int error_str_len) 6169{ 6170 struct scsi_transportid_rdma *rdma; 6171 int retval; 6172 size_t id_len, rdma_id_size; 6173 uint8_t rdma_id[SCSI_TRN_RDMA_PORT_LEN]; 6174 char *tmpstr; 6175 unsigned int i, j; 6176 6177 retval = 0; 6178 id_len = strlen(id_str); 6179 rdma_id_size = SCSI_TRN_RDMA_PORT_LEN; 6180 6181 /* 6182 * Check the size. It needs to be either 32 or 34 characters long. 6183 */ 6184 if ((id_len != (rdma_id_size * 2)) 6185 && (id_len != ((rdma_id_size * 2) + 2))) { 6186 if (error_str != NULL) { 6187 snprintf(error_str, error_str_len, "%s: RDMA ID " 6188 "must be 32 hex digits (0x prefix " 6189 "optional), only %zu seen", __func__, id_len); 6190 } 6191 retval = 1; 6192 goto bailout; 6193 } 6194 6195 tmpstr = id_str; 6196 /* 6197 * If the user gave us 34 characters, the string needs to start 6198 * with '0x'. 6199 */ 6200 if (id_len == ((rdma_id_size * 2) + 2)) { 6201 if ((tmpstr[0] == '0') 6202 && ((tmpstr[1] == 'x') || (tmpstr[1] == 'X'))) { 6203 tmpstr += 2; 6204 } else { 6205 if (error_str != NULL) { 6206 snprintf(error_str, error_str_len, "%s: RDMA " 6207 "ID prefix, if used, must be \"0x\", " 6208 "got %s", __func__, tmpstr); 6209 } 6210 retval = 1; 6211 goto bailout; 6212 } 6213 } 6214 bzero(rdma_id, sizeof(rdma_id)); 6215 6216 /* 6217 * Convert ASCII hex into binary bytes. There is no standard 6218 * 128-bit integer type, and so no strtou128t() routine to convert 6219 * from hex into a large integer. In the end, we're not going to 6220 * an integer, but rather to a byte array, so that and the fact 6221 * that we require the user to give us 32 hex digits simplifies the 6222 * logic. 6223 */ 6224 for (i = 0; i < (rdma_id_size * 2); i++) { 6225 int cur_shift; 6226 unsigned char c; 6227 6228 /* Increment the byte array one for every 2 hex digits */ 6229 j = i >> 1; 6230 6231 /* 6232 * The first digit in every pair is the most significant 6233 * 4 bits. The second is the least significant 4 bits. 6234 */ 6235 if ((i % 2) == 0) 6236 cur_shift = 4; 6237 else 6238 cur_shift = 0; 6239 6240 c = tmpstr[i]; 6241 /* Convert the ASCII hex character into a number */ 6242 if (isdigit(c)) 6243 c -= '0'; 6244 else if (isalpha(c)) 6245 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 6246 else { 6247 if (error_str != NULL) { 6248 snprintf(error_str, error_str_len, "%s: " 6249 "RDMA ID must be hex digits, got " 6250 "invalid character %c", __func__, 6251 tmpstr[i]); 6252 } 6253 retval = 1; 6254 goto bailout; 6255 } 6256 /* 6257 * The converted number can't be less than 0; the type is 6258 * unsigned, and the subtraction logic will not give us 6259 * a negative number. So we only need to make sure that 6260 * the value is not greater than 0xf. (i.e. make sure the 6261 * user didn't give us a value like "0x12jklmno"). 6262 */ 6263 if (c > 0xf) { 6264 if (error_str != NULL) { 6265 snprintf(error_str, error_str_len, "%s: " 6266 "RDMA ID must be hex digits, got " 6267 "invalid character %c", __func__, 6268 tmpstr[i]); 6269 } 6270 retval = 1; 6271 goto bailout; 6272 } 6273 6274 rdma_id[j] |= c << cur_shift; 6275 } 6276 6277#ifdef _KERNEL 6278 rdma = malloc(sizeof(*rdma), type, flags); 6279#else 6280 rdma = malloc(sizeof(*rdma)); 6281#endif 6282 if (rdma == NULL) { 6283 if (error_str != NULL) { 6284 snprintf(error_str, error_str_len, "%s: unable to " 6285 "allocate %zu bytes", __func__, 6286 sizeof(*rdma)); 6287 } 6288 retval = 1; 6289 goto bailout; 6290 } 6291 *alloc_len = sizeof(*rdma); 6292 bzero(rdma, *alloc_len); 6293 6294 rdma->format_protocol = SCSI_PROTO_RDMA | SCSI_TRN_RDMA_FORMAT_DEFAULT; 6295 bcopy(rdma_id, rdma->initiator_port_id, SCSI_TRN_RDMA_PORT_LEN); 6296 6297 *hdr = (struct scsi_transportid_header *)rdma; 6298 6299bailout: 6300 return (retval); 6301} 6302 6303/* 6304 * Parse an iSCSI name. The format is either just the name: 6305 * 6306 * iqn.2012-06.com.example:target0 6307 * or the name, separator and initiator session ID: 6308 * 6309 * iqn.2012-06.com.example:target0,i,0x123 6310 * 6311 * The separator format is exact. 6312 */ 6313int 6314scsi_parse_transportid_iscsi(char *id_str, struct scsi_transportid_header **hdr, 6315 unsigned int *alloc_len, 6316#ifdef _KERNEL 6317 struct malloc_type *type, int flags, 6318#endif 6319 char *error_str, int error_str_len) 6320{ 6321 size_t id_len, sep_len, id_size, name_len; 6322 int retval; 6323 unsigned int i, sep_pos, sep_found; 6324 const char *sep_template = ",i,0x"; 6325 const char *iqn_prefix = "iqn."; 6326 struct scsi_transportid_iscsi_device *iscsi; 6327 6328 retval = 0; 6329 sep_found = 0; 6330 6331 id_len = strlen(id_str); 6332 sep_len = strlen(sep_template); 6333 6334 /* 6335 * The separator is defined as exactly ',i,0x'. Any other commas, 6336 * or any other form, is an error. So look for a comma, and once 6337 * we find that, the next few characters must match the separator 6338 * exactly. Once we get through the separator, there should be at 6339 * least one character. 6340 */ 6341 for (i = 0, sep_pos = 0; i < id_len; i++) { 6342 if (sep_pos == 0) { 6343 if (id_str[i] == sep_template[sep_pos]) 6344 sep_pos++; 6345 6346 continue; 6347 } 6348 if (sep_pos < sep_len) { 6349 if (id_str[i] == sep_template[sep_pos]) { 6350 sep_pos++; 6351 continue; 6352 } 6353 if (error_str != NULL) { 6354 snprintf(error_str, error_str_len, "%s: " 6355 "invalid separator in iSCSI name " 6356 "\"%s\"", 6357 __func__, id_str); 6358 } 6359 retval = 1; 6360 goto bailout; 6361 } else { 6362 sep_found = 1; 6363 break; 6364 } 6365 } 6366 6367 /* 6368 * Check to see whether we have a separator but no digits after it. 6369 */ 6370 if ((sep_pos != 0) 6371 && (sep_found == 0)) { 6372 if (error_str != NULL) { 6373 snprintf(error_str, error_str_len, "%s: no digits " 6374 "found after separator in iSCSI name \"%s\"", 6375 __func__, id_str); 6376 } 6377 retval = 1; 6378 goto bailout; 6379 } 6380 6381 /* 6382 * The incoming ID string has the "iqn." prefix stripped off. We 6383 * need enough space for the base structure (the structures are the 6384 * same for the two iSCSI forms), the prefix, the ID string and a 6385 * terminating NUL. 6386 */ 6387 id_size = sizeof(*iscsi) + strlen(iqn_prefix) + id_len + 1; 6388 6389#ifdef _KERNEL 6390 iscsi = malloc(id_size, type, flags); 6391#else 6392 iscsi = malloc(id_size); 6393#endif 6394 if (iscsi == NULL) { 6395 if (error_str != NULL) { 6396 snprintf(error_str, error_str_len, "%s: unable to " 6397 "allocate %zu bytes", __func__, id_size); 6398 } 6399 retval = 1; 6400 goto bailout; 6401 } 6402 *alloc_len = id_size; 6403 bzero(iscsi, id_size); 6404 6405 iscsi->format_protocol = SCSI_PROTO_ISCSI; 6406 if (sep_found == 0) 6407 iscsi->format_protocol |= SCSI_TRN_ISCSI_FORMAT_DEVICE; 6408 else 6409 iscsi->format_protocol |= SCSI_TRN_ISCSI_FORMAT_PORT; 6410 name_len = id_size - sizeof(*iscsi); 6411 scsi_ulto2b(name_len, iscsi->additional_length); 6412 snprintf(iscsi->iscsi_name, name_len, "%s%s", iqn_prefix, id_str); 6413 6414 *hdr = (struct scsi_transportid_header *)iscsi; 6415 6416bailout: 6417 return (retval); 6418} 6419 6420/* 6421 * Parse a SCSI over PCIe (SOP) identifier. The Routing ID can either be 6422 * of the form 'bus,device,function' or 'bus,function'. 6423 */ 6424int 6425scsi_parse_transportid_sop(char *id_str, struct scsi_transportid_header **hdr, 6426 unsigned int *alloc_len, 6427#ifdef _KERNEL 6428 struct malloc_type *type, int flags, 6429#endif 6430 char *error_str, int error_str_len) 6431{ 6432 struct scsi_transportid_sop *sop; 6433 unsigned long bus, device, function; 6434 char *tmpstr, *endptr; 6435 int retval, device_spec; 6436 6437 retval = 0; 6438 device_spec = 0; 6439 device = 0; 6440 6441 tmpstr = strsep(&id_str, ","); 6442 if ((tmpstr == NULL) 6443 || (*tmpstr == '\0')) { 6444 if (error_str != NULL) { 6445 snprintf(error_str, error_str_len, "%s: no ID found", 6446 __func__); 6447 } 6448 retval = 1; 6449 goto bailout; 6450 } 6451 bus = strtoul(tmpstr, &endptr, 0); 6452 if (*endptr != '\0') { 6453 if (error_str != NULL) { 6454 snprintf(error_str, error_str_len, "%s: error " 6455 "parsing PCIe bus %s, number required", 6456 __func__, tmpstr); 6457 } 6458 retval = 1; 6459 goto bailout; 6460 } 6461 if ((id_str == NULL) 6462 || (*id_str == '\0')) { 6463 if (error_str != NULL) { 6464 snprintf(error_str, error_str_len, "%s: no PCIe " 6465 "device or function found", __func__); 6466 } 6467 retval = 1; 6468 goto bailout; 6469 } 6470 tmpstr = strsep(&id_str, ","); 6471 function = strtoul(tmpstr, &endptr, 0); 6472 if (*endptr != '\0') { 6473 if (error_str != NULL) { 6474 snprintf(error_str, error_str_len, "%s: error " 6475 "parsing PCIe device/function %s, number " 6476 "required", __func__, tmpstr); 6477 } 6478 retval = 1; 6479 goto bailout; 6480 } 6481 /* 6482 * Check to see whether the user specified a third value. If so, 6483 * the second is the device. 6484 */ 6485 if (id_str != NULL) { 6486 if (*id_str == '\0') { 6487 if (error_str != NULL) { 6488 snprintf(error_str, error_str_len, "%s: " 6489 "no PCIe function found", __func__); 6490 } 6491 retval = 1; 6492 goto bailout; 6493 } 6494 device = function; 6495 device_spec = 1; 6496 function = strtoul(id_str, &endptr, 0); 6497 if (*endptr != '\0') { 6498 if (error_str != NULL) { 6499 snprintf(error_str, error_str_len, "%s: " 6500 "error parsing PCIe function %s, " 6501 "number required", __func__, id_str); 6502 } 6503 retval = 1; 6504 goto bailout; 6505 } 6506 } 6507 if (bus > SCSI_TRN_SOP_BUS_MAX) { 6508 if (error_str != NULL) { 6509 snprintf(error_str, error_str_len, "%s: bus value " 6510 "%lu greater than maximum %u", __func__, 6511 bus, SCSI_TRN_SOP_BUS_MAX); 6512 } 6513 retval = 1; 6514 goto bailout; 6515 } 6516 6517 if ((device_spec != 0) 6518 && (device > SCSI_TRN_SOP_DEV_MASK)) { 6519 if (error_str != NULL) { 6520 snprintf(error_str, error_str_len, "%s: device value " 6521 "%lu greater than maximum %u", __func__, 6522 device, SCSI_TRN_SOP_DEV_MAX); 6523 } 6524 retval = 1; 6525 goto bailout; 6526 } 6527 6528 if (((device_spec != 0) 6529 && (function > SCSI_TRN_SOP_FUNC_NORM_MAX)) 6530 || ((device_spec == 0) 6531 && (function > SCSI_TRN_SOP_FUNC_ALT_MAX))) { 6532 if (error_str != NULL) { 6533 snprintf(error_str, error_str_len, "%s: function value " 6534 "%lu greater than maximum %u", __func__, 6535 function, (device_spec == 0) ? 6536 SCSI_TRN_SOP_FUNC_ALT_MAX : 6537 SCSI_TRN_SOP_FUNC_NORM_MAX); 6538 } 6539 retval = 1; 6540 goto bailout; 6541 } 6542 6543#ifdef _KERNEL 6544 sop = malloc(sizeof(*sop), type, flags); 6545#else 6546 sop = malloc(sizeof(*sop)); 6547#endif 6548 if (sop == NULL) { 6549 if (error_str != NULL) { 6550 snprintf(error_str, error_str_len, "%s: unable to " 6551 "allocate %zu bytes", __func__, sizeof(*sop)); 6552 } 6553 retval = 1; 6554 goto bailout; 6555 } 6556 *alloc_len = sizeof(*sop); 6557 bzero(sop, sizeof(*sop)); 6558 sop->format_protocol = SCSI_PROTO_SOP | SCSI_TRN_SOP_FORMAT_DEFAULT; 6559 if (device_spec != 0) { 6560 struct scsi_sop_routing_id_norm rid; 6561 6562 rid.bus = bus; 6563 rid.devfunc = (device << SCSI_TRN_SOP_DEV_SHIFT) | function; 6564 bcopy(&rid, sop->routing_id, MIN(sizeof(rid), 6565 sizeof(sop->routing_id))); 6566 } else { 6567 struct scsi_sop_routing_id_alt rid; 6568 6569 rid.bus = bus; 6570 rid.function = function; 6571 bcopy(&rid, sop->routing_id, MIN(sizeof(rid), 6572 sizeof(sop->routing_id))); 6573 } 6574 6575 *hdr = (struct scsi_transportid_header *)sop; 6576bailout: 6577 return (retval); 6578} 6579 6580/* 6581 * transportid_str: NUL-terminated string with format: protcol,id 6582 * The ID is protocol specific. 6583 * hdr: Storage will be allocated for the transport ID. 6584 * alloc_len: The amount of memory allocated is returned here. 6585 * type: Malloc bucket (kernel only). 6586 * flags: Malloc flags (kernel only). 6587 * error_str: If non-NULL, it will contain error information (without 6588 * a terminating newline) if an error is returned. 6589 * error_str_len: Allocated length of the error string. 6590 * 6591 * Returns 0 for success, non-zero for failure. 6592 */ 6593int 6594scsi_parse_transportid(char *transportid_str, 6595 struct scsi_transportid_header **hdr, 6596 unsigned int *alloc_len, 6597#ifdef _KERNEL 6598 struct malloc_type *type, int flags, 6599#endif 6600 char *error_str, int error_str_len) 6601{ 6602 char *tmpstr; 6603 scsi_nv_status status; 6604 int retval, num_proto_entries, table_entry; 6605 6606 retval = 0; 6607 table_entry = 0; 6608 6609 /* 6610 * We do allow a period as well as a comma to separate the protocol 6611 * from the ID string. This is to accommodate iSCSI names, which 6612 * start with "iqn.". 6613 */ 6614 tmpstr = strsep(&transportid_str, ",."); 6615 if (tmpstr == NULL) { 6616 if (error_str != NULL) { 6617 snprintf(error_str, error_str_len, 6618 "%s: transportid_str is NULL", __func__); 6619 } 6620 retval = 1; 6621 goto bailout; 6622 } 6623 6624 num_proto_entries = sizeof(scsi_proto_map) / 6625 sizeof(scsi_proto_map[0]); 6626 status = scsi_get_nv(scsi_proto_map, num_proto_entries, tmpstr, 6627 &table_entry, SCSI_NV_FLAG_IG_CASE); 6628 if (status != SCSI_NV_FOUND) { 6629 if (error_str != NULL) { 6630 snprintf(error_str, error_str_len, "%s: %s protocol " 6631 "name %s", __func__, 6632 (status == SCSI_NV_AMBIGUOUS) ? "ambiguous" : 6633 "invalid", tmpstr); 6634 } 6635 retval = 1; 6636 goto bailout; 6637 } 6638 switch (scsi_proto_map[table_entry].value) { 6639 case SCSI_PROTO_FC: 6640 case SCSI_PROTO_1394: 6641 case SCSI_PROTO_SAS: 6642 retval = scsi_parse_transportid_64bit( 6643 scsi_proto_map[table_entry].value, transportid_str, hdr, 6644 alloc_len, 6645#ifdef _KERNEL 6646 type, flags, 6647#endif 6648 error_str, error_str_len); 6649 break; 6650 case SCSI_PROTO_SPI: 6651 retval = scsi_parse_transportid_spi(transportid_str, hdr, 6652 alloc_len, 6653#ifdef _KERNEL 6654 type, flags, 6655#endif 6656 error_str, error_str_len); 6657 break; 6658 case SCSI_PROTO_RDMA: 6659 retval = scsi_parse_transportid_rdma(transportid_str, hdr, 6660 alloc_len, 6661#ifdef _KERNEL 6662 type, flags, 6663#endif 6664 error_str, error_str_len); 6665 break; 6666 case SCSI_PROTO_ISCSI: 6667 retval = scsi_parse_transportid_iscsi(transportid_str, hdr, 6668 alloc_len, 6669#ifdef _KERNEL 6670 type, flags, 6671#endif 6672 error_str, error_str_len); 6673 break; 6674 case SCSI_PROTO_SOP: 6675 retval = scsi_parse_transportid_sop(transportid_str, hdr, 6676 alloc_len, 6677#ifdef _KERNEL 6678 type, flags, 6679#endif 6680 error_str, error_str_len); 6681 break; 6682 case SCSI_PROTO_SSA: 6683 case SCSI_PROTO_ADITP: 6684 case SCSI_PROTO_ATA: 6685 case SCSI_PROTO_UAS: 6686 case SCSI_PROTO_NONE: 6687 default: 6688 /* 6689 * There is no format defined for a Transport ID for these 6690 * protocols. So even if the user gives us something, we 6691 * have no way to turn it into a standard SCSI Transport ID. 6692 */ 6693 retval = 1; 6694 if (error_str != NULL) { 6695 snprintf(error_str, error_str_len, "%s: no Transport " 6696 "ID format exists for protocol %s", 6697 __func__, tmpstr); 6698 } 6699 goto bailout; 6700 break; /* NOTREACHED */ 6701 } 6702bailout: 6703 return (retval); 6704} 6705 6706struct scsi_attrib_table_entry scsi_mam_attr_table[] = { 6707 { SMA_ATTR_REM_CAP_PARTITION, SCSI_ATTR_FLAG_NONE, 6708 "Remaining Capacity in Partition", 6709 /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf,/*parse_str*/ NULL }, 6710 { SMA_ATTR_MAX_CAP_PARTITION, SCSI_ATTR_FLAG_NONE, 6711 "Maximum Capacity in Partition", 6712 /*suffix*/"MB", /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, 6713 { SMA_ATTR_TAPEALERT_FLAGS, SCSI_ATTR_FLAG_HEX, 6714 "TapeAlert Flags", 6715 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, 6716 { SMA_ATTR_LOAD_COUNT, SCSI_ATTR_FLAG_NONE, 6717 "Load Count", 6718 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, 6719 { SMA_ATTR_MAM_SPACE_REMAINING, SCSI_ATTR_FLAG_NONE, 6720 "MAM Space Remaining", 6721 /*suffix*/"bytes", /*to_str*/ scsi_attrib_int_sbuf, 6722 /*parse_str*/ NULL }, 6723 { SMA_ATTR_DEV_ASSIGNING_ORG, SCSI_ATTR_FLAG_NONE, 6724 "Assigning Organization", 6725 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6726 /*parse_str*/ NULL }, 6727 { SMA_ATTR_FORMAT_DENSITY_CODE, SCSI_ATTR_FLAG_HEX, 6728 "Format Density Code", 6729 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, 6730 { SMA_ATTR_INITIALIZATION_COUNT, SCSI_ATTR_FLAG_NONE, 6731 "Initialization Count", 6732 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, /*parse_str*/ NULL }, 6733 { SMA_ATTR_VOLUME_ID, SCSI_ATTR_FLAG_NONE, 6734 "Volume Identifier", 6735 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6736 /*parse_str*/ NULL }, 6737 { SMA_ATTR_VOLUME_CHANGE_REF, SCSI_ATTR_FLAG_HEX, 6738 "Volume Change Reference", 6739 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6740 /*parse_str*/ NULL }, 6741 { SMA_ATTR_DEV_SERIAL_LAST_LOAD, SCSI_ATTR_FLAG_NONE, 6742 "Device Vendor/Serial at Last Load", 6743 /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, 6744 /*parse_str*/ NULL }, 6745 { SMA_ATTR_DEV_SERIAL_LAST_LOAD_1, SCSI_ATTR_FLAG_NONE, 6746 "Device Vendor/Serial at Last Load - 1", 6747 /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, 6748 /*parse_str*/ NULL }, 6749 { SMA_ATTR_DEV_SERIAL_LAST_LOAD_2, SCSI_ATTR_FLAG_NONE, 6750 "Device Vendor/Serial at Last Load - 2", 6751 /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, 6752 /*parse_str*/ NULL }, 6753 { SMA_ATTR_DEV_SERIAL_LAST_LOAD_3, SCSI_ATTR_FLAG_NONE, 6754 "Device Vendor/Serial at Last Load - 3", 6755 /*suffix*/NULL, /*to_str*/ scsi_attrib_vendser_sbuf, 6756 /*parse_str*/ NULL }, 6757 { SMA_ATTR_TOTAL_MB_WRITTEN_LT, SCSI_ATTR_FLAG_NONE, 6758 "Total MB Written in Medium Life", 6759 /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, 6760 /*parse_str*/ NULL }, 6761 { SMA_ATTR_TOTAL_MB_READ_LT, SCSI_ATTR_FLAG_NONE, 6762 "Total MB Read in Medium Life", 6763 /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, 6764 /*parse_str*/ NULL }, 6765 { SMA_ATTR_TOTAL_MB_WRITTEN_CUR, SCSI_ATTR_FLAG_NONE, 6766 "Total MB Written in Current/Last Load", 6767 /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, 6768 /*parse_str*/ NULL }, 6769 { SMA_ATTR_TOTAL_MB_READ_CUR, SCSI_ATTR_FLAG_NONE, 6770 "Total MB Read in Current/Last Load", 6771 /*suffix*/ "MB", /*to_str*/ scsi_attrib_int_sbuf, 6772 /*parse_str*/ NULL }, 6773 { SMA_ATTR_FIRST_ENC_BLOCK, SCSI_ATTR_FLAG_NONE, 6774 "Logical Position of First Encrypted Block", 6775 /*suffix*/ NULL, /*to_str*/ scsi_attrib_int_sbuf, 6776 /*parse_str*/ NULL }, 6777 { SMA_ATTR_NEXT_UNENC_BLOCK, SCSI_ATTR_FLAG_NONE, 6778 "Logical Position of First Unencrypted Block after First " 6779 "Encrypted Block", 6780 /*suffix*/ NULL, /*to_str*/ scsi_attrib_int_sbuf, 6781 /*parse_str*/ NULL }, 6782 { SMA_ATTR_MEDIUM_USAGE_HIST, SCSI_ATTR_FLAG_NONE, 6783 "Medium Usage History", 6784 /*suffix*/ NULL, /*to_str*/ NULL, 6785 /*parse_str*/ NULL }, 6786 { SMA_ATTR_PART_USAGE_HIST, SCSI_ATTR_FLAG_NONE, 6787 "Partition Usage History", 6788 /*suffix*/ NULL, /*to_str*/ NULL, 6789 /*parse_str*/ NULL }, 6790 { SMA_ATTR_MED_MANUF, SCSI_ATTR_FLAG_NONE, 6791 "Medium Manufacturer", 6792 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6793 /*parse_str*/ NULL }, 6794 { SMA_ATTR_MED_SERIAL, SCSI_ATTR_FLAG_NONE, 6795 "Medium Serial Number", 6796 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6797 /*parse_str*/ NULL }, 6798 { SMA_ATTR_MED_LENGTH, SCSI_ATTR_FLAG_NONE, 6799 "Medium Length", 6800 /*suffix*/"m", /*to_str*/ scsi_attrib_int_sbuf, 6801 /*parse_str*/ NULL }, 6802 { SMA_ATTR_MED_WIDTH, SCSI_ATTR_FLAG_FP | SCSI_ATTR_FLAG_DIV_10 | 6803 SCSI_ATTR_FLAG_FP_1DIGIT, 6804 "Medium Width", 6805 /*suffix*/"mm", /*to_str*/ scsi_attrib_int_sbuf, 6806 /*parse_str*/ NULL }, 6807 { SMA_ATTR_MED_ASSIGNING_ORG, SCSI_ATTR_FLAG_NONE, 6808 "Assigning Organization", 6809 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6810 /*parse_str*/ NULL }, 6811 { SMA_ATTR_MED_DENSITY_CODE, SCSI_ATTR_FLAG_HEX, 6812 "Medium Density Code", 6813 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6814 /*parse_str*/ NULL }, 6815 { SMA_ATTR_MED_MANUF_DATE, SCSI_ATTR_FLAG_NONE, 6816 "Medium Manufacture Date", 6817 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6818 /*parse_str*/ NULL }, 6819 { SMA_ATTR_MAM_CAPACITY, SCSI_ATTR_FLAG_NONE, 6820 "MAM Capacity", 6821 /*suffix*/"bytes", /*to_str*/ scsi_attrib_int_sbuf, 6822 /*parse_str*/ NULL }, 6823 { SMA_ATTR_MED_TYPE, SCSI_ATTR_FLAG_HEX, 6824 "Medium Type", 6825 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6826 /*parse_str*/ NULL }, 6827 { SMA_ATTR_MED_TYPE_INFO, SCSI_ATTR_FLAG_HEX, 6828 "Medium Type Information", 6829 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6830 /*parse_str*/ NULL }, 6831 { SMA_ATTR_MED_SERIAL_NUM, SCSI_ATTR_FLAG_NONE, 6832 "Medium Serial Number", 6833 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6834 /*parse_str*/ NULL }, 6835 { SMA_ATTR_APP_VENDOR, SCSI_ATTR_FLAG_NONE, 6836 "Application Vendor", 6837 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6838 /*parse_str*/ NULL }, 6839 { SMA_ATTR_APP_NAME, SCSI_ATTR_FLAG_NONE, 6840 "Application Name", 6841 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6842 /*parse_str*/ NULL }, 6843 { SMA_ATTR_APP_VERSION, SCSI_ATTR_FLAG_NONE, 6844 "Application Version", 6845 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6846 /*parse_str*/ NULL }, 6847 { SMA_ATTR_USER_MED_TEXT_LABEL, SCSI_ATTR_FLAG_NONE, 6848 "User Medium Text Label", 6849 /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, 6850 /*parse_str*/ NULL }, 6851 { SMA_ATTR_LAST_WRITTEN_TIME, SCSI_ATTR_FLAG_NONE, 6852 "Date and Time Last Written", 6853 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6854 /*parse_str*/ NULL }, 6855 { SMA_ATTR_TEXT_LOCAL_ID, SCSI_ATTR_FLAG_HEX, 6856 "Text Localization Identifier", 6857 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6858 /*parse_str*/ NULL }, 6859 { SMA_ATTR_BARCODE, SCSI_ATTR_FLAG_NONE, 6860 "Barcode", 6861 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6862 /*parse_str*/ NULL }, 6863 { SMA_ATTR_HOST_OWNER_NAME, SCSI_ATTR_FLAG_NONE, 6864 "Owning Host Textual Name", 6865 /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, 6866 /*parse_str*/ NULL }, 6867 { SMA_ATTR_MEDIA_POOL, SCSI_ATTR_FLAG_NONE, 6868 "Media Pool", 6869 /*suffix*/NULL, /*to_str*/ scsi_attrib_text_sbuf, 6870 /*parse_str*/ NULL }, 6871 { SMA_ATTR_PART_USER_LABEL, SCSI_ATTR_FLAG_NONE, 6872 "Partition User Text Label", 6873 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6874 /*parse_str*/ NULL }, 6875 { SMA_ATTR_LOAD_UNLOAD_AT_PART, SCSI_ATTR_FLAG_NONE, 6876 "Load/Unload at Partition", 6877 /*suffix*/NULL, /*to_str*/ scsi_attrib_int_sbuf, 6878 /*parse_str*/ NULL }, 6879 { SMA_ATTR_APP_FORMAT_VERSION, SCSI_ATTR_FLAG_NONE, 6880 "Application Format Version", 6881 /*suffix*/NULL, /*to_str*/ scsi_attrib_ascii_sbuf, 6882 /*parse_str*/ NULL }, 6883 { SMA_ATTR_VOL_COHERENCY_INFO, SCSI_ATTR_FLAG_NONE, 6884 "Volume Coherency Information", 6885 /*suffix*/NULL, /*to_str*/ scsi_attrib_volcoh_sbuf, 6886 /*parse_str*/ NULL }, 6887 { 0x0ff1, SCSI_ATTR_FLAG_NONE, 6888 "Spectra MLM Creation", 6889 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6890 /*parse_str*/ NULL }, 6891 { 0x0ff2, SCSI_ATTR_FLAG_NONE, 6892 "Spectra MLM C3", 6893 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6894 /*parse_str*/ NULL }, 6895 { 0x0ff3, SCSI_ATTR_FLAG_NONE, 6896 "Spectra MLM RW", 6897 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6898 /*parse_str*/ NULL }, 6899 { 0x0ff4, SCSI_ATTR_FLAG_NONE, 6900 "Spectra MLM SDC List", 6901 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6902 /*parse_str*/ NULL }, 6903 { 0x0ff7, SCSI_ATTR_FLAG_NONE, 6904 "Spectra MLM Post Scan", 6905 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6906 /*parse_str*/ NULL }, 6907 { 0x0ffe, SCSI_ATTR_FLAG_NONE, 6908 "Spectra MLM Checksum", 6909 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6910 /*parse_str*/ NULL }, 6911 { 0x17f1, SCSI_ATTR_FLAG_NONE, 6912 "Spectra MLM Creation", 6913 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6914 /*parse_str*/ NULL }, 6915 { 0x17f2, SCSI_ATTR_FLAG_NONE, 6916 "Spectra MLM C3", 6917 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6918 /*parse_str*/ NULL }, 6919 { 0x17f3, SCSI_ATTR_FLAG_NONE, 6920 "Spectra MLM RW", 6921 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6922 /*parse_str*/ NULL }, 6923 { 0x17f4, SCSI_ATTR_FLAG_NONE, 6924 "Spectra MLM SDC List", 6925 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6926 /*parse_str*/ NULL }, 6927 { 0x17f7, SCSI_ATTR_FLAG_NONE, 6928 "Spectra MLM Post Scan", 6929 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6930 /*parse_str*/ NULL }, 6931 { 0x17ff, SCSI_ATTR_FLAG_NONE, 6932 "Spectra MLM Checksum", 6933 /*suffix*/NULL, /*to_str*/ scsi_attrib_hexdump_sbuf, 6934 /*parse_str*/ NULL }, 6935}; 6936 6937/* 6938 * Print out Volume Coherency Information (Attribute 0x080c). 6939 * This field has two variable length members, including one at the 6940 * beginning, so it isn't practical to have a fixed structure definition. 6941 * This is current as of SSC4r03 (see section 4.2.21.3), dated March 25, 6942 * 2013. 6943 */ 6944int 6945scsi_attrib_volcoh_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 6946 uint32_t valid_len, uint32_t flags, 6947 uint32_t output_flags, char *error_str, 6948 int error_str_len) 6949{ 6950 size_t avail_len; 6951 uint32_t field_size; 6952 uint64_t tmp_val; 6953 uint8_t *cur_ptr; 6954 int retval; 6955 int vcr_len, as_len; 6956 6957 retval = 0; 6958 tmp_val = 0; 6959 6960 field_size = scsi_2btoul(hdr->length); 6961 avail_len = valid_len - sizeof(*hdr); 6962 if (field_size > avail_len) { 6963 if (error_str != NULL) { 6964 snprintf(error_str, error_str_len, "Available " 6965 "length of attribute ID 0x%.4x %zu < field " 6966 "length %u", scsi_2btoul(hdr->id), avail_len, 6967 field_size); 6968 } 6969 retval = 1; 6970 goto bailout; 6971 } else if (field_size == 0) { 6972 /* 6973 * It isn't clear from the spec whether a field length of 6974 * 0 is invalid here. It probably is, but be lenient here 6975 * to avoid inconveniencing the user. 6976 */ 6977 goto bailout; 6978 } 6979 cur_ptr = hdr->attribute; 6980 vcr_len = *cur_ptr; 6981 cur_ptr++; 6982 6983 sbuf_printf(sb, "\n\tVolume Change Reference Value:"); 6984 6985 switch (vcr_len) { 6986 case 0: 6987 if (error_str != NULL) { 6988 snprintf(error_str, error_str_len, "Volume Change " 6989 "Reference value has length of 0"); 6990 } 6991 retval = 1; 6992 goto bailout; 6993 break; /*NOTREACHED*/ 6994 case 1: 6995 tmp_val = *cur_ptr; 6996 break; 6997 case 2: 6998 tmp_val = scsi_2btoul(cur_ptr); 6999 break; 7000 case 3: 7001 tmp_val = scsi_3btoul(cur_ptr); 7002 break; 7003 case 4: 7004 tmp_val = scsi_4btoul(cur_ptr); 7005 break; 7006 case 8: 7007 tmp_val = scsi_8btou64(cur_ptr); 7008 break; 7009 default: 7010 sbuf_printf(sb, "\n"); 7011 sbuf_hexdump(sb, cur_ptr, vcr_len, NULL, 0); 7012 break; 7013 } 7014 if (vcr_len <= 8) 7015 sbuf_printf(sb, " 0x%jx\n", (uintmax_t)tmp_val); 7016 7017 cur_ptr += vcr_len; 7018 tmp_val = scsi_8btou64(cur_ptr); 7019 sbuf_printf(sb, "\tVolume Coherency Count: %ju\n", (uintmax_t)tmp_val); 7020 7021 cur_ptr += sizeof(tmp_val); 7022 tmp_val = scsi_8btou64(cur_ptr); 7023 sbuf_printf(sb, "\tVolume Coherency Set Identifier: 0x%jx\n", 7024 (uintmax_t)tmp_val); 7025 7026 /* 7027 * Figure out how long the Application Client Specific Information 7028 * is and produce a hexdump. 7029 */ 7030 cur_ptr += sizeof(tmp_val); 7031 as_len = scsi_2btoul(cur_ptr); 7032 cur_ptr += sizeof(uint16_t); 7033 sbuf_printf(sb, "\tApplication Client Specific Information: "); 7034 if (((as_len == SCSI_LTFS_VER0_LEN) 7035 || (as_len == SCSI_LTFS_VER1_LEN)) 7036 && (strncmp(cur_ptr, SCSI_LTFS_STR_NAME, SCSI_LTFS_STR_LEN) == 0)) { 7037 sbuf_printf(sb, "LTFS\n"); 7038 cur_ptr += SCSI_LTFS_STR_LEN + 1; 7039 if (cur_ptr[SCSI_LTFS_UUID_LEN] != '\0') 7040 cur_ptr[SCSI_LTFS_UUID_LEN] = '\0'; 7041 sbuf_printf(sb, "\tLTFS UUID: %s\n", cur_ptr); 7042 cur_ptr += SCSI_LTFS_UUID_LEN + 1; 7043 /* XXX KDM check the length */ 7044 sbuf_printf(sb, "\tLTFS Version: %d\n", *cur_ptr); 7045 } else { 7046 sbuf_printf(sb, "Unknown\n"); 7047 sbuf_hexdump(sb, cur_ptr, as_len, NULL, 0); 7048 } 7049 7050bailout: 7051 return (retval); 7052} 7053 7054int 7055scsi_attrib_vendser_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7056 uint32_t valid_len, uint32_t flags, 7057 uint32_t output_flags, char *error_str, 7058 int error_str_len) 7059{ 7060 size_t avail_len; 7061 uint32_t field_size; 7062 struct scsi_attrib_vendser *vendser; 7063 cam_strvis_flags strvis_flags; 7064 int retval = 0; 7065 7066 field_size = scsi_2btoul(hdr->length); 7067 avail_len = valid_len - sizeof(*hdr); 7068 if (field_size > avail_len) { 7069 if (error_str != NULL) { 7070 snprintf(error_str, error_str_len, "Available " 7071 "length of attribute ID 0x%.4x %zu < field " 7072 "length %u", scsi_2btoul(hdr->id), avail_len, 7073 field_size); 7074 } 7075 retval = 1; 7076 goto bailout; 7077 } else if (field_size == 0) { 7078 /* 7079 * A field size of 0 doesn't make sense here. The device 7080 * can at least give you the vendor ID, even if it can't 7081 * give you the serial number. 7082 */ 7083 if (error_str != NULL) { 7084 snprintf(error_str, error_str_len, "The length of " 7085 "attribute ID 0x%.4x is 0", 7086 scsi_2btoul(hdr->id)); 7087 } 7088 retval = 1; 7089 goto bailout; 7090 } 7091 vendser = (struct scsi_attrib_vendser *)hdr->attribute; 7092 7093 switch (output_flags & SCSI_ATTR_OUTPUT_NONASCII_MASK) { 7094 case SCSI_ATTR_OUTPUT_NONASCII_TRIM: 7095 strvis_flags = CAM_STRVIS_FLAG_NONASCII_TRIM; 7096 break; 7097 case SCSI_ATTR_OUTPUT_NONASCII_RAW: 7098 strvis_flags = CAM_STRVIS_FLAG_NONASCII_RAW; 7099 break; 7100 case SCSI_ATTR_OUTPUT_NONASCII_ESC: 7101 default: 7102 strvis_flags = CAM_STRVIS_FLAG_NONASCII_ESC; 7103 break;; 7104 } 7105 cam_strvis_sbuf(sb, vendser->vendor, sizeof(vendser->vendor), 7106 strvis_flags); 7107 sbuf_putc(sb, ' '); 7108 cam_strvis_sbuf(sb, vendser->serial_num, sizeof(vendser->serial_num), 7109 strvis_flags); 7110bailout: 7111 return (retval); 7112} 7113 7114int 7115scsi_attrib_hexdump_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7116 uint32_t valid_len, uint32_t flags, 7117 uint32_t output_flags, char *error_str, 7118 int error_str_len) 7119{ 7120 uint32_t field_size; 7121 ssize_t avail_len; 7122 uint32_t print_len; 7123 uint8_t *num_ptr; 7124 int retval = 0; 7125 7126 field_size = scsi_2btoul(hdr->length); 7127 avail_len = valid_len - sizeof(*hdr); 7128 print_len = MIN(avail_len, field_size); 7129 num_ptr = hdr->attribute; 7130 7131 if (print_len > 0) { 7132 sbuf_printf(sb, "\n"); 7133 sbuf_hexdump(sb, num_ptr, print_len, NULL, 0); 7134 } 7135 7136 return (retval); 7137} 7138 7139int 7140scsi_attrib_int_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7141 uint32_t valid_len, uint32_t flags, 7142 uint32_t output_flags, char *error_str, 7143 int error_str_len) 7144{ 7145 uint64_t print_number; 7146 size_t avail_len; 7147 uint32_t number_size; 7148 int retval = 0; 7149 7150 number_size = scsi_2btoul(hdr->length); 7151 7152 avail_len = valid_len - sizeof(*hdr); 7153 if (avail_len < number_size) { 7154 if (error_str != NULL) { 7155 snprintf(error_str, error_str_len, "Available " 7156 "length of attribute ID 0x%.4x %zu < field " 7157 "length %u", scsi_2btoul(hdr->id), avail_len, 7158 number_size); 7159 } 7160 retval = 1; 7161 goto bailout; 7162 } 7163 7164 switch (number_size) { 7165 case 0: 7166 /* 7167 * We don't treat this as an error, since there may be 7168 * scenarios where a device reports a field but then gives 7169 * a length of 0. See the note in scsi_attrib_ascii_sbuf(). 7170 */ 7171 goto bailout; 7172 break; /*NOTREACHED*/ 7173 case 1: 7174 print_number = hdr->attribute[0]; 7175 break; 7176 case 2: 7177 print_number = scsi_2btoul(hdr->attribute); 7178 break; 7179 case 3: 7180 print_number = scsi_3btoul(hdr->attribute); 7181 break; 7182 case 4: 7183 print_number = scsi_4btoul(hdr->attribute); 7184 break; 7185 case 8: 7186 print_number = scsi_8btou64(hdr->attribute); 7187 break; 7188 default: 7189 /* 7190 * If we wind up here, the number is too big to print 7191 * normally, so just do a hexdump. 7192 */ 7193 retval = scsi_attrib_hexdump_sbuf(sb, hdr, valid_len, 7194 flags, output_flags, 7195 error_str, error_str_len); 7196 goto bailout; 7197 break; 7198 } 7199 7200 if (flags & SCSI_ATTR_FLAG_FP) { 7201#ifndef _KERNEL 7202 long double num_float; 7203 7204 num_float = (long double)print_number; 7205 7206 if (flags & SCSI_ATTR_FLAG_DIV_10) 7207 num_float /= 10; 7208 7209 sbuf_printf(sb, "%.*Lf", (flags & SCSI_ATTR_FLAG_FP_1DIGIT) ? 7210 1 : 0, num_float); 7211#else /* _KERNEL */ 7212 sbuf_printf(sb, "%ju", (flags & SCSI_ATTR_FLAG_DIV_10) ? 7213 (print_number / 10) : print_number); 7214#endif /* _KERNEL */ 7215 } else if (flags & SCSI_ATTR_FLAG_HEX) { 7216 sbuf_printf(sb, "0x%jx", (uintmax_t)print_number); 7217 } else 7218 sbuf_printf(sb, "%ju", (uintmax_t)print_number); 7219 7220bailout: 7221 return (retval); 7222} 7223 7224int 7225scsi_attrib_ascii_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7226 uint32_t valid_len, uint32_t flags, 7227 uint32_t output_flags, char *error_str, 7228 int error_str_len) 7229{ 7230 size_t avail_len; 7231 uint32_t field_size, print_size; 7232 int retval = 0; 7233 7234 avail_len = valid_len - sizeof(*hdr); 7235 field_size = scsi_2btoul(hdr->length); 7236 print_size = MIN(avail_len, field_size); 7237 7238 if (print_size > 0) { 7239 cam_strvis_flags strvis_flags; 7240 7241 switch (output_flags & SCSI_ATTR_OUTPUT_NONASCII_MASK) { 7242 case SCSI_ATTR_OUTPUT_NONASCII_TRIM: 7243 strvis_flags = CAM_STRVIS_FLAG_NONASCII_TRIM; 7244 break; 7245 case SCSI_ATTR_OUTPUT_NONASCII_RAW: 7246 strvis_flags = CAM_STRVIS_FLAG_NONASCII_RAW; 7247 break; 7248 case SCSI_ATTR_OUTPUT_NONASCII_ESC: 7249 default: 7250 strvis_flags = CAM_STRVIS_FLAG_NONASCII_ESC; 7251 break; 7252 } 7253 cam_strvis_sbuf(sb, hdr->attribute, print_size, strvis_flags); 7254 } else if (avail_len < field_size) { 7255 /* 7256 * We only report an error if the user didn't allocate 7257 * enough space to hold the full value of this field. If 7258 * the field length is 0, that is allowed by the spec. 7259 * e.g. in SPC-4r37, section 7.4.2.2.5, VOLUME IDENTIFIER 7260 * "This attribute indicates the current volume identifier 7261 * (see SMC-3) of the medium. If the device server supports 7262 * this attribute but does not have access to the volume 7263 * identifier, the device server shall report this attribute 7264 * with an attribute length value of zero." 7265 */ 7266 if (error_str != NULL) { 7267 snprintf(error_str, error_str_len, "Available " 7268 "length of attribute ID 0x%.4x %zu < field " 7269 "length %u", scsi_2btoul(hdr->id), avail_len, 7270 field_size); 7271 } 7272 retval = 1; 7273 } 7274 7275 return (retval); 7276} 7277 7278int 7279scsi_attrib_text_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7280 uint32_t valid_len, uint32_t flags, 7281 uint32_t output_flags, char *error_str, 7282 int error_str_len) 7283{ 7284 size_t avail_len; 7285 uint32_t field_size, print_size; 7286 int retval = 0; 7287 int esc_text = 1; 7288 7289 avail_len = valid_len - sizeof(*hdr); 7290 field_size = scsi_2btoul(hdr->length); 7291 print_size = MIN(avail_len, field_size); 7292 7293 if ((output_flags & SCSI_ATTR_OUTPUT_TEXT_MASK) == 7294 SCSI_ATTR_OUTPUT_TEXT_RAW) 7295 esc_text = 0; 7296 7297 if (print_size > 0) { 7298 uint32_t i; 7299 7300 for (i = 0; i < print_size; i++) { 7301 if (hdr->attribute[i] == '\0') 7302 continue; 7303 else if (((unsigned char)hdr->attribute[i] < 0x80) 7304 || (esc_text == 0)) 7305 sbuf_putc(sb, hdr->attribute[i]); 7306 else 7307 sbuf_printf(sb, "%%%02x", 7308 (unsigned char)hdr->attribute[i]); 7309 } 7310 } else if (avail_len < field_size) { 7311 /* 7312 * We only report an error if the user didn't allocate 7313 * enough space to hold the full value of this field. 7314 */ 7315 if (error_str != NULL) { 7316 snprintf(error_str, error_str_len, "Available " 7317 "length of attribute ID 0x%.4x %zu < field " 7318 "length %u", scsi_2btoul(hdr->id), avail_len, 7319 field_size); 7320 } 7321 retval = 1; 7322 } 7323 7324 return (retval); 7325} 7326 7327struct scsi_attrib_table_entry * 7328scsi_find_attrib_entry(struct scsi_attrib_table_entry *table, 7329 size_t num_table_entries, uint32_t id) 7330{ 7331 uint32_t i; 7332 7333 for (i = 0; i < num_table_entries; i++) { 7334 if (table[i].id == id) 7335 return (&table[i]); 7336 } 7337 7338 return (NULL); 7339} 7340 7341struct scsi_attrib_table_entry * 7342scsi_get_attrib_entry(uint32_t id) 7343{ 7344 return (scsi_find_attrib_entry(scsi_mam_attr_table, 7345 sizeof(scsi_mam_attr_table) / sizeof(scsi_mam_attr_table[0]), 7346 id)); 7347} 7348 7349int 7350scsi_attrib_value_sbuf(struct sbuf *sb, uint32_t valid_len, 7351 struct scsi_mam_attribute_header *hdr, uint32_t output_flags, 7352 char *error_str, size_t error_str_len) 7353{ 7354 int retval; 7355 7356 switch (hdr->byte2 & SMA_FORMAT_MASK) { 7357 case SMA_FORMAT_ASCII: 7358 retval = scsi_attrib_ascii_sbuf(sb, hdr, valid_len, 7359 SCSI_ATTR_FLAG_NONE, output_flags, error_str,error_str_len); 7360 break; 7361 case SMA_FORMAT_BINARY: 7362 if (scsi_2btoul(hdr->length) <= 8) 7363 retval = scsi_attrib_int_sbuf(sb, hdr, valid_len, 7364 SCSI_ATTR_FLAG_NONE, output_flags, error_str, 7365 error_str_len); 7366 else 7367 retval = scsi_attrib_hexdump_sbuf(sb, hdr, valid_len, 7368 SCSI_ATTR_FLAG_NONE, output_flags, error_str, 7369 error_str_len); 7370 break; 7371 case SMA_FORMAT_TEXT: 7372 retval = scsi_attrib_text_sbuf(sb, hdr, valid_len, 7373 SCSI_ATTR_FLAG_NONE, output_flags, error_str, 7374 error_str_len); 7375 break; 7376 default: 7377 if (error_str != NULL) { 7378 snprintf(error_str, error_str_len, "Unknown attribute " 7379 "format 0x%x", hdr->byte2 & SMA_FORMAT_MASK); 7380 } 7381 retval = 1; 7382 goto bailout; 7383 break; /*NOTREACHED*/ 7384 } 7385 7386 sbuf_trim(sb); 7387 7388bailout: 7389 7390 return (retval); 7391} 7392 7393void 7394scsi_attrib_prefix_sbuf(struct sbuf *sb, uint32_t output_flags, 7395 struct scsi_mam_attribute_header *hdr, 7396 uint32_t valid_len, const char *desc) 7397{ 7398 int need_space = 0; 7399 uint32_t len; 7400 uint32_t id; 7401 7402 /* 7403 * We can't do anything if we don't have enough valid data for the 7404 * header. 7405 */ 7406 if (valid_len < sizeof(*hdr)) 7407 return; 7408 7409 id = scsi_2btoul(hdr->id); 7410 /* 7411 * Note that we print out the value of the attribute listed in the 7412 * header, regardless of whether we actually got that many bytes 7413 * back from the device through the controller. A truncated result 7414 * could be the result of a failure to ask for enough data; the 7415 * header indicates how many bytes are allocated for this attribute 7416 * in the MAM. 7417 */ 7418 len = scsi_2btoul(hdr->length); 7419 7420 if ((output_flags & SCSI_ATTR_OUTPUT_FIELD_MASK) == 7421 SCSI_ATTR_OUTPUT_FIELD_NONE) 7422 return; 7423 7424 if ((output_flags & SCSI_ATTR_OUTPUT_FIELD_DESC) 7425 && (desc != NULL)) { 7426 sbuf_printf(sb, "%s", desc); 7427 need_space = 1; 7428 } 7429 7430 if (output_flags & SCSI_ATTR_OUTPUT_FIELD_NUM) { 7431 sbuf_printf(sb, "%s(0x%.4x)", (need_space) ? " " : "", id); 7432 need_space = 0; 7433 } 7434 7435 if (output_flags & SCSI_ATTR_OUTPUT_FIELD_SIZE) { 7436 sbuf_printf(sb, "%s[%d]", (need_space) ? " " : "", len); 7437 need_space = 0; 7438 } 7439 if (output_flags & SCSI_ATTR_OUTPUT_FIELD_RW) { 7440 sbuf_printf(sb, "%s(%s)", (need_space) ? " " : "", 7441 (hdr->byte2 & SMA_READ_ONLY) ? "RO" : "RW"); 7442 } 7443 sbuf_printf(sb, ": "); 7444} 7445 7446int 7447scsi_attrib_sbuf(struct sbuf *sb, struct scsi_mam_attribute_header *hdr, 7448 uint32_t valid_len, struct scsi_attrib_table_entry *user_table, 7449 size_t num_user_entries, int prefer_user_table, 7450 uint32_t output_flags, char *error_str, int error_str_len) 7451{ 7452 int retval; 7453 struct scsi_attrib_table_entry *table1 = NULL, *table2 = NULL; 7454 struct scsi_attrib_table_entry *entry = NULL; 7455 size_t table1_size = 0, table2_size = 0; 7456 uint32_t id; 7457 7458 retval = 0; 7459 7460 if (valid_len < sizeof(*hdr)) { 7461 retval = 1; 7462 goto bailout; 7463 } 7464 7465 id = scsi_2btoul(hdr->id); 7466 7467 if (user_table != NULL) { 7468 if (prefer_user_table != 0) { 7469 table1 = user_table; 7470 table1_size = num_user_entries; 7471 table2 = scsi_mam_attr_table; 7472 table2_size = sizeof(scsi_mam_attr_table) / 7473 sizeof(scsi_mam_attr_table[0]); 7474 } else { 7475 table1 = scsi_mam_attr_table; 7476 table1_size = sizeof(scsi_mam_attr_table) / 7477 sizeof(scsi_mam_attr_table[0]); 7478 table2 = user_table; 7479 table2_size = num_user_entries; 7480 } 7481 } else { 7482 table1 = scsi_mam_attr_table; 7483 table1_size = sizeof(scsi_mam_attr_table) / 7484 sizeof(scsi_mam_attr_table[0]); 7485 } 7486 7487 entry = scsi_find_attrib_entry(table1, table1_size, id); 7488 if (entry != NULL) { 7489 scsi_attrib_prefix_sbuf(sb, output_flags, hdr, valid_len, 7490 entry->desc); 7491 if (entry->to_str == NULL) 7492 goto print_default; 7493 retval = entry->to_str(sb, hdr, valid_len, entry->flags, 7494 output_flags, error_str, error_str_len); 7495 goto bailout; 7496 } 7497 if (table2 != NULL) { 7498 entry = scsi_find_attrib_entry(table2, table2_size, id); 7499 if (entry != NULL) { 7500 if (entry->to_str == NULL) 7501 goto print_default; 7502 7503 scsi_attrib_prefix_sbuf(sb, output_flags, hdr, 7504 valid_len, entry->desc); 7505 retval = entry->to_str(sb, hdr, valid_len, entry->flags, 7506 output_flags, error_str, 7507 error_str_len); 7508 goto bailout; 7509 } 7510 } 7511 7512 scsi_attrib_prefix_sbuf(sb, output_flags, hdr, valid_len, NULL); 7513 7514print_default: 7515 retval = scsi_attrib_value_sbuf(sb, valid_len, hdr, output_flags, 7516 error_str, error_str_len); 7517bailout: 7518 if (retval == 0) { 7519 if ((entry != NULL) 7520 && (entry->suffix != NULL)) 7521 sbuf_printf(sb, " %s", entry->suffix); 7522 7523 sbuf_trim(sb); 7524 sbuf_printf(sb, "\n"); 7525 } 7526 7527 return (retval); 7528} 7529 7530void 7531scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, 7532 void (*cbfcnp)(struct cam_periph *, union ccb *), 7533 u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout) 7534{ 7535 struct scsi_test_unit_ready *scsi_cmd; 7536 7537 cam_fill_csio(csio, 7538 retries, 7539 cbfcnp, 7540 CAM_DIR_NONE, 7541 tag_action, 7542 /*data_ptr*/NULL, 7543 /*dxfer_len*/0, 7544 sense_len, 7545 sizeof(*scsi_cmd), 7546 timeout); 7547 7548 scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes; 7549 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7550 scsi_cmd->opcode = TEST_UNIT_READY; 7551} 7552 7553void 7554scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries, 7555 void (*cbfcnp)(struct cam_periph *, union ccb *), 7556 void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action, 7557 u_int8_t sense_len, u_int32_t timeout) 7558{ 7559 struct scsi_request_sense *scsi_cmd; 7560 7561 cam_fill_csio(csio, 7562 retries, 7563 cbfcnp, 7564 CAM_DIR_IN, 7565 tag_action, 7566 data_ptr, 7567 dxfer_len, 7568 sense_len, 7569 sizeof(*scsi_cmd), 7570 timeout); 7571 7572 scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes; 7573 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7574 scsi_cmd->opcode = REQUEST_SENSE; 7575 scsi_cmd->length = dxfer_len; 7576} 7577 7578void 7579scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries, 7580 void (*cbfcnp)(struct cam_periph *, union ccb *), 7581 u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len, 7582 int evpd, u_int8_t page_code, u_int8_t sense_len, 7583 u_int32_t timeout) 7584{ 7585 struct scsi_inquiry *scsi_cmd; 7586 7587 cam_fill_csio(csio, 7588 retries, 7589 cbfcnp, 7590 /*flags*/CAM_DIR_IN, 7591 tag_action, 7592 /*data_ptr*/inq_buf, 7593 /*dxfer_len*/inq_len, 7594 sense_len, 7595 sizeof(*scsi_cmd), 7596 timeout); 7597 7598 scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes; 7599 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7600 scsi_cmd->opcode = INQUIRY; 7601 if (evpd) { 7602 scsi_cmd->byte2 |= SI_EVPD; 7603 scsi_cmd->page_code = page_code; 7604 } 7605 scsi_ulto2b(inq_len, scsi_cmd->length); 7606} 7607 7608void 7609scsi_mode_sense(struct ccb_scsiio *csio, uint32_t retries, 7610 void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, 7611 int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, 7612 uint8_t sense_len, uint32_t timeout) 7613{ 7614 7615 scsi_mode_sense_subpage(csio, retries, cbfcnp, tag_action, dbd, 7616 pc, page, 0, param_buf, param_len, 0, sense_len, timeout); 7617} 7618 7619void 7620scsi_mode_sense_len(struct ccb_scsiio *csio, uint32_t retries, 7621 void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, 7622 int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, 7623 int minimum_cmd_size, uint8_t sense_len, uint32_t timeout) 7624{ 7625 7626 scsi_mode_sense_subpage(csio, retries, cbfcnp, tag_action, dbd, 7627 pc, page, 0, param_buf, param_len, minimum_cmd_size, 7628 sense_len, timeout); 7629} 7630 7631void 7632scsi_mode_sense_subpage(struct ccb_scsiio *csio, uint32_t retries, 7633 void (*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, 7634 int dbd, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t *param_buf, 7635 uint32_t param_len, int minimum_cmd_size, uint8_t sense_len, 7636 uint32_t timeout) 7637{ 7638 u_int8_t cdb_len; 7639 7640 /* 7641 * Use the smallest possible command to perform the operation. 7642 */ 7643 if ((param_len < 256) 7644 && (minimum_cmd_size < 10)) { 7645 /* 7646 * We can fit in a 6 byte cdb. 7647 */ 7648 struct scsi_mode_sense_6 *scsi_cmd; 7649 7650 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes; 7651 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7652 scsi_cmd->opcode = MODE_SENSE_6; 7653 if (dbd != 0) 7654 scsi_cmd->byte2 |= SMS_DBD; 7655 scsi_cmd->page = pc | page; 7656 scsi_cmd->subpage = subpage; 7657 scsi_cmd->length = param_len; 7658 cdb_len = sizeof(*scsi_cmd); 7659 } else { 7660 /* 7661 * Need a 10 byte cdb. 7662 */ 7663 struct scsi_mode_sense_10 *scsi_cmd; 7664 7665 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes; 7666 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7667 scsi_cmd->opcode = MODE_SENSE_10; 7668 if (dbd != 0) 7669 scsi_cmd->byte2 |= SMS_DBD; 7670 scsi_cmd->page = pc | page; 7671 scsi_cmd->subpage = subpage; 7672 scsi_ulto2b(param_len, scsi_cmd->length); 7673 cdb_len = sizeof(*scsi_cmd); 7674 } 7675 cam_fill_csio(csio, 7676 retries, 7677 cbfcnp, 7678 CAM_DIR_IN, 7679 tag_action, 7680 param_buf, 7681 param_len, 7682 sense_len, 7683 cdb_len, 7684 timeout); 7685} 7686 7687void 7688scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries, 7689 void (*cbfcnp)(struct cam_periph *, union ccb *), 7690 u_int8_t tag_action, int scsi_page_fmt, int save_pages, 7691 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len, 7692 u_int32_t timeout) 7693{ 7694 scsi_mode_select_len(csio, retries, cbfcnp, tag_action, 7695 scsi_page_fmt, save_pages, param_buf, 7696 param_len, 0, sense_len, timeout); 7697} 7698 7699void 7700scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries, 7701 void (*cbfcnp)(struct cam_periph *, union ccb *), 7702 u_int8_t tag_action, int scsi_page_fmt, int save_pages, 7703 u_int8_t *param_buf, u_int32_t param_len, 7704 int minimum_cmd_size, u_int8_t sense_len, 7705 u_int32_t timeout) 7706{ 7707 u_int8_t cdb_len; 7708 7709 /* 7710 * Use the smallest possible command to perform the operation. 7711 */ 7712 if ((param_len < 256) 7713 && (minimum_cmd_size < 10)) { 7714 /* 7715 * We can fit in a 6 byte cdb. 7716 */ 7717 struct scsi_mode_select_6 *scsi_cmd; 7718 7719 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes; 7720 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7721 scsi_cmd->opcode = MODE_SELECT_6; 7722 if (scsi_page_fmt != 0) 7723 scsi_cmd->byte2 |= SMS_PF; 7724 if (save_pages != 0) 7725 scsi_cmd->byte2 |= SMS_SP; 7726 scsi_cmd->length = param_len; 7727 cdb_len = sizeof(*scsi_cmd); 7728 } else { 7729 /* 7730 * Need a 10 byte cdb. 7731 */ 7732 struct scsi_mode_select_10 *scsi_cmd; 7733 7734 scsi_cmd = 7735 (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes; 7736 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7737 scsi_cmd->opcode = MODE_SELECT_10; 7738 if (scsi_page_fmt != 0) 7739 scsi_cmd->byte2 |= SMS_PF; 7740 if (save_pages != 0) 7741 scsi_cmd->byte2 |= SMS_SP; 7742 scsi_ulto2b(param_len, scsi_cmd->length); 7743 cdb_len = sizeof(*scsi_cmd); 7744 } 7745 cam_fill_csio(csio, 7746 retries, 7747 cbfcnp, 7748 CAM_DIR_OUT, 7749 tag_action, 7750 param_buf, 7751 param_len, 7752 sense_len, 7753 cdb_len, 7754 timeout); 7755} 7756 7757void 7758scsi_log_sense(struct ccb_scsiio *csio, u_int32_t retries, 7759 void (*cbfcnp)(struct cam_periph *, union ccb *), 7760 u_int8_t tag_action, u_int8_t page_code, u_int8_t page, 7761 int save_pages, int ppc, u_int32_t paramptr, 7762 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len, 7763 u_int32_t timeout) 7764{ 7765 struct scsi_log_sense *scsi_cmd; 7766 u_int8_t cdb_len; 7767 7768 scsi_cmd = (struct scsi_log_sense *)&csio->cdb_io.cdb_bytes; 7769 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7770 scsi_cmd->opcode = LOG_SENSE; 7771 scsi_cmd->page = page_code | page; 7772 if (save_pages != 0) 7773 scsi_cmd->byte2 |= SLS_SP; 7774 if (ppc != 0) 7775 scsi_cmd->byte2 |= SLS_PPC; 7776 scsi_ulto2b(paramptr, scsi_cmd->paramptr); 7777 scsi_ulto2b(param_len, scsi_cmd->length); 7778 cdb_len = sizeof(*scsi_cmd); 7779 7780 cam_fill_csio(csio, 7781 retries, 7782 cbfcnp, 7783 /*flags*/CAM_DIR_IN, 7784 tag_action, 7785 /*data_ptr*/param_buf, 7786 /*dxfer_len*/param_len, 7787 sense_len, 7788 cdb_len, 7789 timeout); 7790} 7791 7792void 7793scsi_log_select(struct ccb_scsiio *csio, u_int32_t retries, 7794 void (*cbfcnp)(struct cam_periph *, union ccb *), 7795 u_int8_t tag_action, u_int8_t page_code, int save_pages, 7796 int pc_reset, u_int8_t *param_buf, u_int32_t param_len, 7797 u_int8_t sense_len, u_int32_t timeout) 7798{ 7799 struct scsi_log_select *scsi_cmd; 7800 u_int8_t cdb_len; 7801 7802 scsi_cmd = (struct scsi_log_select *)&csio->cdb_io.cdb_bytes; 7803 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7804 scsi_cmd->opcode = LOG_SELECT; 7805 scsi_cmd->page = page_code & SLS_PAGE_CODE; 7806 if (save_pages != 0) 7807 scsi_cmd->byte2 |= SLS_SP; 7808 if (pc_reset != 0) 7809 scsi_cmd->byte2 |= SLS_PCR; 7810 scsi_ulto2b(param_len, scsi_cmd->length); 7811 cdb_len = sizeof(*scsi_cmd); 7812 7813 cam_fill_csio(csio, 7814 retries, 7815 cbfcnp, 7816 /*flags*/CAM_DIR_OUT, 7817 tag_action, 7818 /*data_ptr*/param_buf, 7819 /*dxfer_len*/param_len, 7820 sense_len, 7821 cdb_len, 7822 timeout); 7823} 7824 7825/* 7826 * Prevent or allow the user to remove the media 7827 */ 7828void 7829scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries, 7830 void (*cbfcnp)(struct cam_periph *, union ccb *), 7831 u_int8_t tag_action, u_int8_t action, 7832 u_int8_t sense_len, u_int32_t timeout) 7833{ 7834 struct scsi_prevent *scsi_cmd; 7835 7836 cam_fill_csio(csio, 7837 retries, 7838 cbfcnp, 7839 /*flags*/CAM_DIR_NONE, 7840 tag_action, 7841 /*data_ptr*/NULL, 7842 /*dxfer_len*/0, 7843 sense_len, 7844 sizeof(*scsi_cmd), 7845 timeout); 7846 7847 scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes; 7848 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7849 scsi_cmd->opcode = PREVENT_ALLOW; 7850 scsi_cmd->how = action; 7851} 7852 7853/* XXX allow specification of address and PMI bit and LBA */ 7854void 7855scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries, 7856 void (*cbfcnp)(struct cam_periph *, union ccb *), 7857 u_int8_t tag_action, 7858 struct scsi_read_capacity_data *rcap_buf, 7859 u_int8_t sense_len, u_int32_t timeout) 7860{ 7861 struct scsi_read_capacity *scsi_cmd; 7862 7863 cam_fill_csio(csio, 7864 retries, 7865 cbfcnp, 7866 /*flags*/CAM_DIR_IN, 7867 tag_action, 7868 /*data_ptr*/(u_int8_t *)rcap_buf, 7869 /*dxfer_len*/sizeof(*rcap_buf), 7870 sense_len, 7871 sizeof(*scsi_cmd), 7872 timeout); 7873 7874 scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes; 7875 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7876 scsi_cmd->opcode = READ_CAPACITY; 7877} 7878 7879void 7880scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries, 7881 void (*cbfcnp)(struct cam_periph *, union ccb *), 7882 uint8_t tag_action, uint64_t lba, int reladr, int pmi, 7883 uint8_t *rcap_buf, int rcap_buf_len, uint8_t sense_len, 7884 uint32_t timeout) 7885{ 7886 struct scsi_read_capacity_16 *scsi_cmd; 7887 7888 7889 cam_fill_csio(csio, 7890 retries, 7891 cbfcnp, 7892 /*flags*/CAM_DIR_IN, 7893 tag_action, 7894 /*data_ptr*/(u_int8_t *)rcap_buf, 7895 /*dxfer_len*/rcap_buf_len, 7896 sense_len, 7897 sizeof(*scsi_cmd), 7898 timeout); 7899 scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; 7900 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7901 scsi_cmd->opcode = SERVICE_ACTION_IN; 7902 scsi_cmd->service_action = SRC16_SERVICE_ACTION; 7903 scsi_u64to8b(lba, scsi_cmd->addr); 7904 scsi_ulto4b(rcap_buf_len, scsi_cmd->alloc_len); 7905 if (pmi) 7906 reladr |= SRC16_PMI; 7907 if (reladr) 7908 reladr |= SRC16_RELADR; 7909} 7910 7911void 7912scsi_report_luns(struct ccb_scsiio *csio, u_int32_t retries, 7913 void (*cbfcnp)(struct cam_periph *, union ccb *), 7914 u_int8_t tag_action, u_int8_t select_report, 7915 struct scsi_report_luns_data *rpl_buf, u_int32_t alloc_len, 7916 u_int8_t sense_len, u_int32_t timeout) 7917{ 7918 struct scsi_report_luns *scsi_cmd; 7919 7920 cam_fill_csio(csio, 7921 retries, 7922 cbfcnp, 7923 /*flags*/CAM_DIR_IN, 7924 tag_action, 7925 /*data_ptr*/(u_int8_t *)rpl_buf, 7926 /*dxfer_len*/alloc_len, 7927 sense_len, 7928 sizeof(*scsi_cmd), 7929 timeout); 7930 scsi_cmd = (struct scsi_report_luns *)&csio->cdb_io.cdb_bytes; 7931 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7932 scsi_cmd->opcode = REPORT_LUNS; 7933 scsi_cmd->select_report = select_report; 7934 scsi_ulto4b(alloc_len, scsi_cmd->length); 7935} 7936 7937void 7938scsi_report_target_group(struct ccb_scsiio *csio, u_int32_t retries, 7939 void (*cbfcnp)(struct cam_periph *, union ccb *), 7940 u_int8_t tag_action, u_int8_t pdf, 7941 void *buf, u_int32_t alloc_len, 7942 u_int8_t sense_len, u_int32_t timeout) 7943{ 7944 struct scsi_target_group *scsi_cmd; 7945 7946 cam_fill_csio(csio, 7947 retries, 7948 cbfcnp, 7949 /*flags*/CAM_DIR_IN, 7950 tag_action, 7951 /*data_ptr*/(u_int8_t *)buf, 7952 /*dxfer_len*/alloc_len, 7953 sense_len, 7954 sizeof(*scsi_cmd), 7955 timeout); 7956 scsi_cmd = (struct scsi_target_group *)&csio->cdb_io.cdb_bytes; 7957 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7958 scsi_cmd->opcode = MAINTENANCE_IN; 7959 scsi_cmd->service_action = REPORT_TARGET_PORT_GROUPS | pdf; 7960 scsi_ulto4b(alloc_len, scsi_cmd->length); 7961} 7962 7963void 7964scsi_set_target_group(struct ccb_scsiio *csio, u_int32_t retries, 7965 void (*cbfcnp)(struct cam_periph *, union ccb *), 7966 u_int8_t tag_action, void *buf, u_int32_t alloc_len, 7967 u_int8_t sense_len, u_int32_t timeout) 7968{ 7969 struct scsi_target_group *scsi_cmd; 7970 7971 cam_fill_csio(csio, 7972 retries, 7973 cbfcnp, 7974 /*flags*/CAM_DIR_OUT, 7975 tag_action, 7976 /*data_ptr*/(u_int8_t *)buf, 7977 /*dxfer_len*/alloc_len, 7978 sense_len, 7979 sizeof(*scsi_cmd), 7980 timeout); 7981 scsi_cmd = (struct scsi_target_group *)&csio->cdb_io.cdb_bytes; 7982 bzero(scsi_cmd, sizeof(*scsi_cmd)); 7983 scsi_cmd->opcode = MAINTENANCE_OUT; 7984 scsi_cmd->service_action = SET_TARGET_PORT_GROUPS; 7985 scsi_ulto4b(alloc_len, scsi_cmd->length); 7986} 7987 7988/* 7989 * Syncronize the media to the contents of the cache for 7990 * the given lba/count pair. Specifying 0/0 means sync 7991 * the whole cache. 7992 */ 7993void 7994scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries, 7995 void (*cbfcnp)(struct cam_periph *, union ccb *), 7996 u_int8_t tag_action, u_int32_t begin_lba, 7997 u_int16_t lb_count, u_int8_t sense_len, 7998 u_int32_t timeout) 7999{ 8000 struct scsi_sync_cache *scsi_cmd; 8001 8002 cam_fill_csio(csio, 8003 retries, 8004 cbfcnp, 8005 /*flags*/CAM_DIR_NONE, 8006 tag_action, 8007 /*data_ptr*/NULL, 8008 /*dxfer_len*/0, 8009 sense_len, 8010 sizeof(*scsi_cmd), 8011 timeout); 8012 8013 scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes; 8014 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8015 scsi_cmd->opcode = SYNCHRONIZE_CACHE; 8016 scsi_ulto4b(begin_lba, scsi_cmd->begin_lba); 8017 scsi_ulto2b(lb_count, scsi_cmd->lb_count); 8018} 8019 8020void 8021scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, 8022 void (*cbfcnp)(struct cam_periph *, union ccb *), 8023 u_int8_t tag_action, int readop, u_int8_t byte2, 8024 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, 8025 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 8026 u_int32_t timeout) 8027{ 8028 int read; 8029 u_int8_t cdb_len; 8030 8031 read = (readop & SCSI_RW_DIRMASK) == SCSI_RW_READ; 8032 8033 /* 8034 * Use the smallest possible command to perform the operation 8035 * as some legacy hardware does not support the 10 byte commands. 8036 * If any of the bits in byte2 is set, we have to go with a larger 8037 * command. 8038 */ 8039 if ((minimum_cmd_size < 10) 8040 && ((lba & 0x1fffff) == lba) 8041 && ((block_count & 0xff) == block_count) 8042 && (byte2 == 0)) { 8043 /* 8044 * We can fit in a 6 byte cdb. 8045 */ 8046 struct scsi_rw_6 *scsi_cmd; 8047 8048 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes; 8049 scsi_cmd->opcode = read ? READ_6 : WRITE_6; 8050 scsi_ulto3b(lba, scsi_cmd->addr); 8051 scsi_cmd->length = block_count & 0xff; 8052 scsi_cmd->control = 0; 8053 cdb_len = sizeof(*scsi_cmd); 8054 8055 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 8056 ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0], 8057 scsi_cmd->addr[1], scsi_cmd->addr[2], 8058 scsi_cmd->length, dxfer_len)); 8059 } else if ((minimum_cmd_size < 12) 8060 && ((block_count & 0xffff) == block_count) 8061 && ((lba & 0xffffffff) == lba)) { 8062 /* 8063 * Need a 10 byte cdb. 8064 */ 8065 struct scsi_rw_10 *scsi_cmd; 8066 8067 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes; 8068 scsi_cmd->opcode = read ? READ_10 : WRITE_10; 8069 scsi_cmd->byte2 = byte2; 8070 scsi_ulto4b(lba, scsi_cmd->addr); 8071 scsi_cmd->reserved = 0; 8072 scsi_ulto2b(block_count, scsi_cmd->length); 8073 scsi_cmd->control = 0; 8074 cdb_len = sizeof(*scsi_cmd); 8075 8076 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 8077 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0], 8078 scsi_cmd->addr[1], scsi_cmd->addr[2], 8079 scsi_cmd->addr[3], scsi_cmd->length[0], 8080 scsi_cmd->length[1], dxfer_len)); 8081 } else if ((minimum_cmd_size < 16) 8082 && ((block_count & 0xffffffff) == block_count) 8083 && ((lba & 0xffffffff) == lba)) { 8084 /* 8085 * The block count is too big for a 10 byte CDB, use a 12 8086 * byte CDB. 8087 */ 8088 struct scsi_rw_12 *scsi_cmd; 8089 8090 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes; 8091 scsi_cmd->opcode = read ? READ_12 : WRITE_12; 8092 scsi_cmd->byte2 = byte2; 8093 scsi_ulto4b(lba, scsi_cmd->addr); 8094 scsi_cmd->reserved = 0; 8095 scsi_ulto4b(block_count, scsi_cmd->length); 8096 scsi_cmd->control = 0; 8097 cdb_len = sizeof(*scsi_cmd); 8098 8099 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 8100 ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0], 8101 scsi_cmd->addr[1], scsi_cmd->addr[2], 8102 scsi_cmd->addr[3], scsi_cmd->length[0], 8103 scsi_cmd->length[1], scsi_cmd->length[2], 8104 scsi_cmd->length[3], dxfer_len)); 8105 } else { 8106 /* 8107 * 16 byte CDB. We'll only get here if the LBA is larger 8108 * than 2^32, or if the user asks for a 16 byte command. 8109 */ 8110 struct scsi_rw_16 *scsi_cmd; 8111 8112 scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes; 8113 scsi_cmd->opcode = read ? READ_16 : WRITE_16; 8114 scsi_cmd->byte2 = byte2; 8115 scsi_u64to8b(lba, scsi_cmd->addr); 8116 scsi_cmd->reserved = 0; 8117 scsi_ulto4b(block_count, scsi_cmd->length); 8118 scsi_cmd->control = 0; 8119 cdb_len = sizeof(*scsi_cmd); 8120 } 8121 cam_fill_csio(csio, 8122 retries, 8123 cbfcnp, 8124 (read ? CAM_DIR_IN : CAM_DIR_OUT) | 8125 ((readop & SCSI_RW_BIO) != 0 ? CAM_DATA_BIO : 0), 8126 tag_action, 8127 data_ptr, 8128 dxfer_len, 8129 sense_len, 8130 cdb_len, 8131 timeout); 8132} 8133 8134void 8135scsi_write_same(struct ccb_scsiio *csio, u_int32_t retries, 8136 void (*cbfcnp)(struct cam_periph *, union ccb *), 8137 u_int8_t tag_action, u_int8_t byte2, 8138 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, 8139 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 8140 u_int32_t timeout) 8141{ 8142 u_int8_t cdb_len; 8143 if ((minimum_cmd_size < 16) && 8144 ((block_count & 0xffff) == block_count) && 8145 ((lba & 0xffffffff) == lba)) { 8146 /* 8147 * Need a 10 byte cdb. 8148 */ 8149 struct scsi_write_same_10 *scsi_cmd; 8150 8151 scsi_cmd = (struct scsi_write_same_10 *)&csio->cdb_io.cdb_bytes; 8152 scsi_cmd->opcode = WRITE_SAME_10; 8153 scsi_cmd->byte2 = byte2; 8154 scsi_ulto4b(lba, scsi_cmd->addr); 8155 scsi_cmd->group = 0; 8156 scsi_ulto2b(block_count, scsi_cmd->length); 8157 scsi_cmd->control = 0; 8158 cdb_len = sizeof(*scsi_cmd); 8159 8160 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 8161 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0], 8162 scsi_cmd->addr[1], scsi_cmd->addr[2], 8163 scsi_cmd->addr[3], scsi_cmd->length[0], 8164 scsi_cmd->length[1], dxfer_len)); 8165 } else { 8166 /* 8167 * 16 byte CDB. We'll only get here if the LBA is larger 8168 * than 2^32, or if the user asks for a 16 byte command. 8169 */ 8170 struct scsi_write_same_16 *scsi_cmd; 8171 8172 scsi_cmd = (struct scsi_write_same_16 *)&csio->cdb_io.cdb_bytes; 8173 scsi_cmd->opcode = WRITE_SAME_16; 8174 scsi_cmd->byte2 = byte2; 8175 scsi_u64to8b(lba, scsi_cmd->addr); 8176 scsi_ulto4b(block_count, scsi_cmd->length); 8177 scsi_cmd->group = 0; 8178 scsi_cmd->control = 0; 8179 cdb_len = sizeof(*scsi_cmd); 8180 8181 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 8182 ("16byte: %x%x%x%x%x%x%x%x:%x%x%x%x: %d\n", 8183 scsi_cmd->addr[0], scsi_cmd->addr[1], 8184 scsi_cmd->addr[2], scsi_cmd->addr[3], 8185 scsi_cmd->addr[4], scsi_cmd->addr[5], 8186 scsi_cmd->addr[6], scsi_cmd->addr[7], 8187 scsi_cmd->length[0], scsi_cmd->length[1], 8188 scsi_cmd->length[2], scsi_cmd->length[3], 8189 dxfer_len)); 8190 } 8191 cam_fill_csio(csio, 8192 retries, 8193 cbfcnp, 8194 /*flags*/CAM_DIR_OUT, 8195 tag_action, 8196 data_ptr, 8197 dxfer_len, 8198 sense_len, 8199 cdb_len, 8200 timeout); 8201} 8202 8203void 8204scsi_ata_identify(struct ccb_scsiio *csio, u_int32_t retries, 8205 void (*cbfcnp)(struct cam_periph *, union ccb *), 8206 u_int8_t tag_action, u_int8_t *data_ptr, 8207 u_int16_t dxfer_len, u_int8_t sense_len, 8208 u_int32_t timeout) 8209{ 8210 scsi_ata_pass_16(csio, 8211 retries, 8212 cbfcnp, 8213 /*flags*/CAM_DIR_IN, 8214 tag_action, 8215 /*protocol*/AP_PROTO_PIO_IN, 8216 /*ata_flags*/AP_FLAG_TDIR_FROM_DEV| 8217 AP_FLAG_BYT_BLOK_BYTES|AP_FLAG_TLEN_SECT_CNT, 8218 /*features*/0, 8219 /*sector_count*/dxfer_len, 8220 /*lba*/0, 8221 /*command*/ATA_ATA_IDENTIFY, 8222 /*control*/0, 8223 data_ptr, 8224 dxfer_len, 8225 sense_len, 8226 timeout); 8227} 8228 8229void 8230scsi_ata_trim(struct ccb_scsiio *csio, u_int32_t retries, 8231 void (*cbfcnp)(struct cam_periph *, union ccb *), 8232 u_int8_t tag_action, u_int16_t block_count, 8233 u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, 8234 u_int32_t timeout) 8235{ 8236 scsi_ata_pass_16(csio, 8237 retries, 8238 cbfcnp, 8239 /*flags*/CAM_DIR_OUT, 8240 tag_action, 8241 /*protocol*/AP_EXTEND|AP_PROTO_DMA, 8242 /*ata_flags*/AP_FLAG_TLEN_SECT_CNT|AP_FLAG_BYT_BLOK_BLOCKS, 8243 /*features*/ATA_DSM_TRIM, 8244 /*sector_count*/block_count, 8245 /*lba*/0, 8246 /*command*/ATA_DATA_SET_MANAGEMENT, 8247 /*control*/0, 8248 data_ptr, 8249 dxfer_len, 8250 sense_len, 8251 timeout); 8252} 8253 8254void 8255scsi_ata_pass_16(struct ccb_scsiio *csio, u_int32_t retries, 8256 void (*cbfcnp)(struct cam_periph *, union ccb *), 8257 u_int32_t flags, u_int8_t tag_action, 8258 u_int8_t protocol, u_int8_t ata_flags, u_int16_t features, 8259 u_int16_t sector_count, uint64_t lba, u_int8_t command, 8260 u_int8_t control, u_int8_t *data_ptr, u_int16_t dxfer_len, 8261 u_int8_t sense_len, u_int32_t timeout) 8262{ 8263 struct ata_pass_16 *ata_cmd; 8264 8265 ata_cmd = (struct ata_pass_16 *)&csio->cdb_io.cdb_bytes; 8266 ata_cmd->opcode = ATA_PASS_16; 8267 ata_cmd->protocol = protocol; 8268 ata_cmd->flags = ata_flags; 8269 ata_cmd->features_ext = features >> 8; 8270 ata_cmd->features = features; 8271 ata_cmd->sector_count_ext = sector_count >> 8; 8272 ata_cmd->sector_count = sector_count; 8273 ata_cmd->lba_low = lba; 8274 ata_cmd->lba_mid = lba >> 8; 8275 ata_cmd->lba_high = lba >> 16; 8276 ata_cmd->device = ATA_DEV_LBA; 8277 if (protocol & AP_EXTEND) { 8278 ata_cmd->lba_low_ext = lba >> 24; 8279 ata_cmd->lba_mid_ext = lba >> 32; 8280 ata_cmd->lba_high_ext = lba >> 40; 8281 } else 8282 ata_cmd->device |= (lba >> 24) & 0x0f; 8283 ata_cmd->command = command; 8284 ata_cmd->control = control; 8285 8286 cam_fill_csio(csio, 8287 retries, 8288 cbfcnp, 8289 flags, 8290 tag_action, 8291 data_ptr, 8292 dxfer_len, 8293 sense_len, 8294 sizeof(*ata_cmd), 8295 timeout); 8296} 8297 8298void 8299scsi_unmap(struct ccb_scsiio *csio, u_int32_t retries, 8300 void (*cbfcnp)(struct cam_periph *, union ccb *), 8301 u_int8_t tag_action, u_int8_t byte2, 8302 u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, 8303 u_int32_t timeout) 8304{ 8305 struct scsi_unmap *scsi_cmd; 8306 8307 scsi_cmd = (struct scsi_unmap *)&csio->cdb_io.cdb_bytes; 8308 scsi_cmd->opcode = UNMAP; 8309 scsi_cmd->byte2 = byte2; 8310 scsi_ulto4b(0, scsi_cmd->reserved); 8311 scsi_cmd->group = 0; 8312 scsi_ulto2b(dxfer_len, scsi_cmd->length); 8313 scsi_cmd->control = 0; 8314 8315 cam_fill_csio(csio, 8316 retries, 8317 cbfcnp, 8318 /*flags*/CAM_DIR_OUT, 8319 tag_action, 8320 data_ptr, 8321 dxfer_len, 8322 sense_len, 8323 sizeof(*scsi_cmd), 8324 timeout); 8325} 8326 8327void 8328scsi_receive_diagnostic_results(struct ccb_scsiio *csio, u_int32_t retries, 8329 void (*cbfcnp)(struct cam_periph *, union ccb*), 8330 uint8_t tag_action, int pcv, uint8_t page_code, 8331 uint8_t *data_ptr, uint16_t allocation_length, 8332 uint8_t sense_len, uint32_t timeout) 8333{ 8334 struct scsi_receive_diag *scsi_cmd; 8335 8336 scsi_cmd = (struct scsi_receive_diag *)&csio->cdb_io.cdb_bytes; 8337 memset(scsi_cmd, 0, sizeof(*scsi_cmd)); 8338 scsi_cmd->opcode = RECEIVE_DIAGNOSTIC; 8339 if (pcv) { 8340 scsi_cmd->byte2 |= SRD_PCV; 8341 scsi_cmd->page_code = page_code; 8342 } 8343 scsi_ulto2b(allocation_length, scsi_cmd->length); 8344 8345 cam_fill_csio(csio, 8346 retries, 8347 cbfcnp, 8348 /*flags*/CAM_DIR_IN, 8349 tag_action, 8350 data_ptr, 8351 allocation_length, 8352 sense_len, 8353 sizeof(*scsi_cmd), 8354 timeout); 8355} 8356 8357void 8358scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries, 8359 void (*cbfcnp)(struct cam_periph *, union ccb *), 8360 uint8_t tag_action, int unit_offline, int device_offline, 8361 int self_test, int page_format, int self_test_code, 8362 uint8_t *data_ptr, uint16_t param_list_length, 8363 uint8_t sense_len, uint32_t timeout) 8364{ 8365 struct scsi_send_diag *scsi_cmd; 8366 8367 scsi_cmd = (struct scsi_send_diag *)&csio->cdb_io.cdb_bytes; 8368 memset(scsi_cmd, 0, sizeof(*scsi_cmd)); 8369 scsi_cmd->opcode = SEND_DIAGNOSTIC; 8370 8371 /* 8372 * The default self-test mode control and specific test 8373 * control are mutually exclusive. 8374 */ 8375 if (self_test) 8376 self_test_code = SSD_SELF_TEST_CODE_NONE; 8377 8378 scsi_cmd->byte2 = ((self_test_code << SSD_SELF_TEST_CODE_SHIFT) 8379 & SSD_SELF_TEST_CODE_MASK) 8380 | (unit_offline ? SSD_UNITOFFL : 0) 8381 | (device_offline ? SSD_DEVOFFL : 0) 8382 | (self_test ? SSD_SELFTEST : 0) 8383 | (page_format ? SSD_PF : 0); 8384 scsi_ulto2b(param_list_length, scsi_cmd->length); 8385 8386 cam_fill_csio(csio, 8387 retries, 8388 cbfcnp, 8389 /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE, 8390 tag_action, 8391 data_ptr, 8392 param_list_length, 8393 sense_len, 8394 sizeof(*scsi_cmd), 8395 timeout); 8396} 8397 8398void 8399scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries, 8400 void (*cbfcnp)(struct cam_periph *, union ccb*), 8401 uint8_t tag_action, int mode, 8402 uint8_t buffer_id, u_int32_t offset, 8403 uint8_t *data_ptr, uint32_t allocation_length, 8404 uint8_t sense_len, uint32_t timeout) 8405{ 8406 struct scsi_read_buffer *scsi_cmd; 8407 8408 scsi_cmd = (struct scsi_read_buffer *)&csio->cdb_io.cdb_bytes; 8409 memset(scsi_cmd, 0, sizeof(*scsi_cmd)); 8410 scsi_cmd->opcode = READ_BUFFER; 8411 scsi_cmd->byte2 = mode; 8412 scsi_cmd->buffer_id = buffer_id; 8413 scsi_ulto3b(offset, scsi_cmd->offset); 8414 scsi_ulto3b(allocation_length, scsi_cmd->length); 8415 8416 cam_fill_csio(csio, 8417 retries, 8418 cbfcnp, 8419 /*flags*/CAM_DIR_IN, 8420 tag_action, 8421 data_ptr, 8422 allocation_length, 8423 sense_len, 8424 sizeof(*scsi_cmd), 8425 timeout); 8426} 8427 8428void 8429scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries, 8430 void (*cbfcnp)(struct cam_periph *, union ccb *), 8431 uint8_t tag_action, int mode, 8432 uint8_t buffer_id, u_int32_t offset, 8433 uint8_t *data_ptr, uint32_t param_list_length, 8434 uint8_t sense_len, uint32_t timeout) 8435{ 8436 struct scsi_write_buffer *scsi_cmd; 8437 8438 scsi_cmd = (struct scsi_write_buffer *)&csio->cdb_io.cdb_bytes; 8439 memset(scsi_cmd, 0, sizeof(*scsi_cmd)); 8440 scsi_cmd->opcode = WRITE_BUFFER; 8441 scsi_cmd->byte2 = mode; 8442 scsi_cmd->buffer_id = buffer_id; 8443 scsi_ulto3b(offset, scsi_cmd->offset); 8444 scsi_ulto3b(param_list_length, scsi_cmd->length); 8445 8446 cam_fill_csio(csio, 8447 retries, 8448 cbfcnp, 8449 /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE, 8450 tag_action, 8451 data_ptr, 8452 param_list_length, 8453 sense_len, 8454 sizeof(*scsi_cmd), 8455 timeout); 8456} 8457 8458void 8459scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, 8460 void (*cbfcnp)(struct cam_periph *, union ccb *), 8461 u_int8_t tag_action, int start, int load_eject, 8462 int immediate, u_int8_t sense_len, u_int32_t timeout) 8463{ 8464 struct scsi_start_stop_unit *scsi_cmd; 8465 int extra_flags = 0; 8466 8467 scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes; 8468 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8469 scsi_cmd->opcode = START_STOP_UNIT; 8470 if (start != 0) { 8471 scsi_cmd->how |= SSS_START; 8472 /* it takes a lot of power to start a drive */ 8473 extra_flags |= CAM_HIGH_POWER; 8474 } 8475 if (load_eject != 0) 8476 scsi_cmd->how |= SSS_LOEJ; 8477 if (immediate != 0) 8478 scsi_cmd->byte2 |= SSS_IMMED; 8479 8480 cam_fill_csio(csio, 8481 retries, 8482 cbfcnp, 8483 /*flags*/CAM_DIR_NONE | extra_flags, 8484 tag_action, 8485 /*data_ptr*/NULL, 8486 /*dxfer_len*/0, 8487 sense_len, 8488 sizeof(*scsi_cmd), 8489 timeout); 8490} 8491 8492void 8493scsi_read_attribute(struct ccb_scsiio *csio, u_int32_t retries, 8494 void (*cbfcnp)(struct cam_periph *, union ccb *), 8495 u_int8_t tag_action, u_int8_t service_action, 8496 uint32_t element, u_int8_t elem_type, int logical_volume, 8497 int partition, u_int32_t first_attribute, int cache, 8498 u_int8_t *data_ptr, u_int32_t length, int sense_len, 8499 u_int32_t timeout) 8500{ 8501 struct scsi_read_attribute *scsi_cmd; 8502 8503 scsi_cmd = (struct scsi_read_attribute *)&csio->cdb_io.cdb_bytes; 8504 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8505 8506 scsi_cmd->opcode = READ_ATTRIBUTE; 8507 scsi_cmd->service_action = service_action; 8508 scsi_ulto2b(element, scsi_cmd->element); 8509 scsi_cmd->elem_type = elem_type; 8510 scsi_cmd->logical_volume = logical_volume; 8511 scsi_cmd->partition = partition; 8512 scsi_ulto2b(first_attribute, scsi_cmd->first_attribute); 8513 scsi_ulto4b(length, scsi_cmd->length); 8514 if (cache != 0) 8515 scsi_cmd->cache |= SRA_CACHE; 8516 8517 cam_fill_csio(csio, 8518 retries, 8519 cbfcnp, 8520 /*flags*/CAM_DIR_IN, 8521 tag_action, 8522 /*data_ptr*/data_ptr, 8523 /*dxfer_len*/length, 8524 sense_len, 8525 sizeof(*scsi_cmd), 8526 timeout); 8527} 8528 8529void 8530scsi_write_attribute(struct ccb_scsiio *csio, u_int32_t retries, 8531 void (*cbfcnp)(struct cam_periph *, union ccb *), 8532 u_int8_t tag_action, uint32_t element, int logical_volume, 8533 int partition, int wtc, u_int8_t *data_ptr, 8534 u_int32_t length, int sense_len, u_int32_t timeout) 8535{ 8536 struct scsi_write_attribute *scsi_cmd; 8537 8538 scsi_cmd = (struct scsi_write_attribute *)&csio->cdb_io.cdb_bytes; 8539 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8540 8541 scsi_cmd->opcode = WRITE_ATTRIBUTE; 8542 if (wtc != 0) 8543 scsi_cmd->byte2 = SWA_WTC; 8544 scsi_ulto3b(element, scsi_cmd->element); 8545 scsi_cmd->logical_volume = logical_volume; 8546 scsi_cmd->partition = partition; 8547 scsi_ulto4b(length, scsi_cmd->length); 8548 8549 cam_fill_csio(csio, 8550 retries, 8551 cbfcnp, 8552 /*flags*/CAM_DIR_OUT, 8553 tag_action, 8554 /*data_ptr*/data_ptr, 8555 /*dxfer_len*/length, 8556 sense_len, 8557 sizeof(*scsi_cmd), 8558 timeout); 8559} 8560 8561void 8562scsi_persistent_reserve_in(struct ccb_scsiio *csio, uint32_t retries, 8563 void (*cbfcnp)(struct cam_periph *, union ccb *), 8564 uint8_t tag_action, int service_action, 8565 uint8_t *data_ptr, uint32_t dxfer_len, int sense_len, 8566 int timeout) 8567{ 8568 struct scsi_per_res_in *scsi_cmd; 8569 8570 scsi_cmd = (struct scsi_per_res_in *)&csio->cdb_io.cdb_bytes; 8571 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8572 8573 scsi_cmd->opcode = PERSISTENT_RES_IN; 8574 scsi_cmd->action = service_action; 8575 scsi_ulto2b(dxfer_len, scsi_cmd->length); 8576 8577 cam_fill_csio(csio, 8578 retries, 8579 cbfcnp, 8580 /*flags*/CAM_DIR_IN, 8581 tag_action, 8582 data_ptr, 8583 dxfer_len, 8584 sense_len, 8585 sizeof(*scsi_cmd), 8586 timeout); 8587} 8588 8589void 8590scsi_persistent_reserve_out(struct ccb_scsiio *csio, uint32_t retries, 8591 void (*cbfcnp)(struct cam_periph *, union ccb *), 8592 uint8_t tag_action, int service_action, 8593 int scope, int res_type, uint8_t *data_ptr, 8594 uint32_t dxfer_len, int sense_len, int timeout) 8595{ 8596 struct scsi_per_res_out *scsi_cmd; 8597 8598 scsi_cmd = (struct scsi_per_res_out *)&csio->cdb_io.cdb_bytes; 8599 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8600 8601 scsi_cmd->opcode = PERSISTENT_RES_OUT; 8602 scsi_cmd->action = service_action; 8603 scsi_cmd->scope_type = scope | res_type; 8604 scsi_ulto4b(dxfer_len, scsi_cmd->length); 8605 8606 cam_fill_csio(csio, 8607 retries, 8608 cbfcnp, 8609 /*flags*/CAM_DIR_OUT, 8610 tag_action, 8611 /*data_ptr*/data_ptr, 8612 /*dxfer_len*/dxfer_len, 8613 sense_len, 8614 sizeof(*scsi_cmd), 8615 timeout); 8616} 8617 8618void 8619scsi_security_protocol_in(struct ccb_scsiio *csio, uint32_t retries, 8620 void (*cbfcnp)(struct cam_periph *, union ccb *), 8621 uint8_t tag_action, uint32_t security_protocol, 8622 uint32_t security_protocol_specific, int byte4, 8623 uint8_t *data_ptr, uint32_t dxfer_len, int sense_len, 8624 int timeout) 8625{ 8626 struct scsi_security_protocol_in *scsi_cmd; 8627 8628 scsi_cmd = (struct scsi_security_protocol_in *)&csio->cdb_io.cdb_bytes; 8629 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8630 8631 scsi_cmd->opcode = SECURITY_PROTOCOL_IN; 8632 8633 scsi_cmd->security_protocol = security_protocol; 8634 scsi_ulto2b(security_protocol_specific, 8635 scsi_cmd->security_protocol_specific); 8636 scsi_cmd->byte4 = byte4; 8637 scsi_ulto4b(dxfer_len, scsi_cmd->length); 8638 8639 cam_fill_csio(csio, 8640 retries, 8641 cbfcnp, 8642 /*flags*/CAM_DIR_IN, 8643 tag_action, 8644 data_ptr, 8645 dxfer_len, 8646 sense_len, 8647 sizeof(*scsi_cmd), 8648 timeout); 8649} 8650 8651void 8652scsi_security_protocol_out(struct ccb_scsiio *csio, uint32_t retries, 8653 void (*cbfcnp)(struct cam_periph *, union ccb *), 8654 uint8_t tag_action, uint32_t security_protocol, 8655 uint32_t security_protocol_specific, int byte4, 8656 uint8_t *data_ptr, uint32_t dxfer_len, int sense_len, 8657 int timeout) 8658{ 8659 struct scsi_security_protocol_out *scsi_cmd; 8660 8661 scsi_cmd = (struct scsi_security_protocol_out *)&csio->cdb_io.cdb_bytes; 8662 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8663 8664 scsi_cmd->opcode = SECURITY_PROTOCOL_OUT; 8665 8666 scsi_cmd->security_protocol = security_protocol; 8667 scsi_ulto2b(security_protocol_specific, 8668 scsi_cmd->security_protocol_specific); 8669 scsi_cmd->byte4 = byte4; 8670 scsi_ulto4b(dxfer_len, scsi_cmd->length); 8671 8672 cam_fill_csio(csio, 8673 retries, 8674 cbfcnp, 8675 /*flags*/CAM_DIR_OUT, 8676 tag_action, 8677 data_ptr, 8678 dxfer_len, 8679 sense_len, 8680 sizeof(*scsi_cmd), 8681 timeout); 8682} 8683 8684void 8685scsi_report_supported_opcodes(struct ccb_scsiio *csio, uint32_t retries, 8686 void (*cbfcnp)(struct cam_periph *, union ccb *), 8687 uint8_t tag_action, int options, int req_opcode, 8688 int req_service_action, uint8_t *data_ptr, 8689 uint32_t dxfer_len, int sense_len, int timeout) 8690{ 8691 struct scsi_report_supported_opcodes *scsi_cmd; 8692 8693 scsi_cmd = (struct scsi_report_supported_opcodes *) 8694 &csio->cdb_io.cdb_bytes; 8695 bzero(scsi_cmd, sizeof(*scsi_cmd)); 8696 8697 scsi_cmd->opcode = MAINTENANCE_IN; 8698 scsi_cmd->service_action = REPORT_SUPPORTED_OPERATION_CODES; 8699 scsi_cmd->options = options; 8700 scsi_cmd->requested_opcode = req_opcode; 8701 scsi_ulto2b(req_service_action, scsi_cmd->requested_service_action); 8702 scsi_ulto4b(dxfer_len, scsi_cmd->length); 8703 8704 cam_fill_csio(csio, 8705 retries, 8706 cbfcnp, 8707 /*flags*/CAM_DIR_IN, 8708 tag_action, 8709 data_ptr, 8710 dxfer_len, 8711 sense_len, 8712 sizeof(*scsi_cmd), 8713 timeout); 8714} 8715 8716/* 8717 * Try make as good a match as possible with 8718 * available sub drivers 8719 */ 8720int 8721scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 8722{ 8723 struct scsi_inquiry_pattern *entry; 8724 struct scsi_inquiry_data *inq; 8725 8726 entry = (struct scsi_inquiry_pattern *)table_entry; 8727 inq = (struct scsi_inquiry_data *)inqbuffer; 8728 8729 if (((SID_TYPE(inq) == entry->type) 8730 || (entry->type == T_ANY)) 8731 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 8732 : entry->media_type & SIP_MEDIA_FIXED) 8733 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 8734 && (cam_strmatch(inq->product, entry->product, 8735 sizeof(inq->product)) == 0) 8736 && (cam_strmatch(inq->revision, entry->revision, 8737 sizeof(inq->revision)) == 0)) { 8738 return (0); 8739 } 8740 return (-1); 8741} 8742 8743/* 8744 * Try make as good a match as possible with 8745 * available sub drivers 8746 */ 8747int 8748scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 8749{ 8750 struct scsi_static_inquiry_pattern *entry; 8751 struct scsi_inquiry_data *inq; 8752 8753 entry = (struct scsi_static_inquiry_pattern *)table_entry; 8754 inq = (struct scsi_inquiry_data *)inqbuffer; 8755 8756 if (((SID_TYPE(inq) == entry->type) 8757 || (entry->type == T_ANY)) 8758 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 8759 : entry->media_type & SIP_MEDIA_FIXED) 8760 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 8761 && (cam_strmatch(inq->product, entry->product, 8762 sizeof(inq->product)) == 0) 8763 && (cam_strmatch(inq->revision, entry->revision, 8764 sizeof(inq->revision)) == 0)) { 8765 return (0); 8766 } 8767 return (-1); 8768} 8769 8770/** 8771 * Compare two buffers of vpd device descriptors for a match. 8772 * 8773 * \param lhs Pointer to first buffer of descriptors to compare. 8774 * \param lhs_len The length of the first buffer. 8775 * \param rhs Pointer to second buffer of descriptors to compare. 8776 * \param rhs_len The length of the second buffer. 8777 * 8778 * \return 0 on a match, -1 otherwise. 8779 * 8780 * Treat rhs and lhs as arrays of vpd device id descriptors. Walk lhs matching 8781 * against each element in rhs until all data are exhausted or we have found 8782 * a match. 8783 */ 8784int 8785scsi_devid_match(uint8_t *lhs, size_t lhs_len, uint8_t *rhs, size_t rhs_len) 8786{ 8787 struct scsi_vpd_id_descriptor *lhs_id; 8788 struct scsi_vpd_id_descriptor *lhs_last; 8789 struct scsi_vpd_id_descriptor *rhs_last; 8790 uint8_t *lhs_end; 8791 uint8_t *rhs_end; 8792 8793 lhs_end = lhs + lhs_len; 8794 rhs_end = rhs + rhs_len; 8795 8796 /* 8797 * rhs_last and lhs_last are the last posible position of a valid 8798 * descriptor assuming it had a zero length identifier. We use 8799 * these variables to insure we can safely dereference the length 8800 * field in our loop termination tests. 8801 */ 8802 lhs_last = (struct scsi_vpd_id_descriptor *) 8803 (lhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier)); 8804 rhs_last = (struct scsi_vpd_id_descriptor *) 8805 (rhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier)); 8806 8807 lhs_id = (struct scsi_vpd_id_descriptor *)lhs; 8808 while (lhs_id <= lhs_last 8809 && (lhs_id->identifier + lhs_id->length) <= lhs_end) { 8810 struct scsi_vpd_id_descriptor *rhs_id; 8811 8812 rhs_id = (struct scsi_vpd_id_descriptor *)rhs; 8813 while (rhs_id <= rhs_last 8814 && (rhs_id->identifier + rhs_id->length) <= rhs_end) { 8815 8816 if ((rhs_id->id_type & 8817 (SVPD_ID_ASSOC_MASK | SVPD_ID_TYPE_MASK)) == 8818 (lhs_id->id_type & 8819 (SVPD_ID_ASSOC_MASK | SVPD_ID_TYPE_MASK)) 8820 && rhs_id->length == lhs_id->length 8821 && memcmp(rhs_id->identifier, lhs_id->identifier, 8822 rhs_id->length) == 0) 8823 return (0); 8824 8825 rhs_id = (struct scsi_vpd_id_descriptor *) 8826 (rhs_id->identifier + rhs_id->length); 8827 } 8828 lhs_id = (struct scsi_vpd_id_descriptor *) 8829 (lhs_id->identifier + lhs_id->length); 8830 } 8831 return (-1); 8832} 8833 8834#ifdef _KERNEL 8835int 8836scsi_vpd_supported_page(struct cam_periph *periph, uint8_t page_id) 8837{ 8838 struct cam_ed *device; 8839 struct scsi_vpd_supported_pages *vpds; 8840 int i, num_pages; 8841 8842 device = periph->path->device; 8843 vpds = (struct scsi_vpd_supported_pages *)device->supported_vpds; 8844 8845 if (vpds != NULL) { 8846 num_pages = device->supported_vpds_len - 8847 SVPD_SUPPORTED_PAGES_HDR_LEN; 8848 for (i = 0; i < num_pages; i++) { 8849 if (vpds->page_list[i] == page_id) 8850 return (1); 8851 } 8852 } 8853 8854 return (0); 8855} 8856 8857static void 8858init_scsi_delay(void) 8859{ 8860 int delay; 8861 8862 delay = SCSI_DELAY; 8863 TUNABLE_INT_FETCH("kern.cam.scsi_delay", &delay); 8864 8865 if (set_scsi_delay(delay) != 0) { 8866 printf("cam: invalid value for tunable kern.cam.scsi_delay\n"); 8867 set_scsi_delay(SCSI_DELAY); 8868 } 8869} 8870SYSINIT(scsi_delay, SI_SUB_TUNABLES, SI_ORDER_ANY, init_scsi_delay, NULL); 8871 8872static int 8873sysctl_scsi_delay(SYSCTL_HANDLER_ARGS) 8874{ 8875 int error, delay; 8876 8877 delay = scsi_delay; 8878 error = sysctl_handle_int(oidp, &delay, 0, req); 8879 if (error != 0 || req->newptr == NULL) 8880 return (error); 8881 return (set_scsi_delay(delay)); 8882} 8883SYSCTL_PROC(_kern_cam, OID_AUTO, scsi_delay, CTLTYPE_INT|CTLFLAG_RW, 8884 0, 0, sysctl_scsi_delay, "I", 8885 "Delay to allow devices to settle after a SCSI bus reset (ms)"); 8886 8887static int 8888set_scsi_delay(int delay) 8889{ 8890 /* 8891 * If someone sets this to 0, we assume that they want the 8892 * minimum allowable bus settle delay. 8893 */ 8894 if (delay == 0) { 8895 printf("cam: using minimum scsi_delay (%dms)\n", 8896 SCSI_MIN_DELAY); 8897 delay = SCSI_MIN_DELAY; 8898 } 8899 if (delay < SCSI_MIN_DELAY) 8900 return (EINVAL); 8901 scsi_delay = delay; 8902 return (0); 8903} 8904#endif /* _KERNEL */ 8905