4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
31 * This module is part of the photon Command Line
37 * I18N message number ranges
38 * This file: 11500 - 11999
39 * Shared common messages: 1 - 1999
42 /* #define _POSIX_SOURCE 1 */
49 #include <sys/types.h>
51 #include <sys/sunddi.h>
52 #include <sys/systm.h>
53 #include <sys/scsi/scsi.h>
62 #include <libdevinfo.h>
66 /* Because of a bug in Unisys Envsen card, Bug ID:1266986. */
67 #define SCSI_ESI_PCV 0x01 /* Page Code Valid */
68 #define SCSI_ESI_PF 0x10 /* Page Format */
69 #define ACTION_MASK 0x1f /* Persistent Reserve In command */
70 #define IMMED 1 /* make the stop immediate */
71 #define DAK_PROD_STR "SUNWGS INT FCBPL"
72 #define DAK_BOXNAME_LEN 16 /* The length of the daktari boxname */
73 #define DAK_BOXNAME_OFF 36 /* The offset of the daktari boxname */
77 /* Global variables */
78 extern nl_catd l_catd
;
81 /* Forward declarations */
82 static int scsi_read_capacity_16_cmd(int, struct scsi_capacity_16
*, int);
85 /* External functions */
89 g_scsi_persistent_reserve_in_cmd(int fd
, uchar_t
*buf_ptr
,
90 int buf_len
, uchar_t action
)
92 struct uscsi_cmd ucmd
;
93 my_cdb_g1 cdb
= {SCMD_PERS_RESERV_IN
, 0, 0, 0, 0, 0, 0, 0, 0, 0};
94 struct scsi_extended_sense sense
;
96 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
97 return (L_INVALID_ARG
);
100 (void) memset(buf_ptr
, 0, buf_len
);
101 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
102 cdb
.byte1
= action
& ACTION_MASK
;
103 cdb
.byte7
= (buf_len
>>8) & 0xff;
104 cdb
.byte8
= buf_len
& 0xff;
105 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
106 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
107 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
108 ucmd
.uscsi_buflen
= buf_len
;
109 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
110 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
111 ucmd
.uscsi_timeout
= 60;
113 if (buf_len
& 0x03) {
114 return (L_PR_INVLD_TRNSFR_LEN
);
116 /* Do in SILENT mode as cmd may not be supported. */
117 return (cmd(fd
, &ucmd
, USCSI_READ
| USCSI_SILENT
));
120 * Send Diagnostic command
122 * NOTE: This function includes a delay.
125 g_scsi_send_diag_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
)
127 struct uscsi_cmd ucmd
;
128 uchar_t cdb
[] = {SCMD_SDIAG
, SCSI_ESI_PF
, 0, 0, 0, 0};
129 struct scsi_extended_sense sense
;
132 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
133 return (L_INVALID_ARG
);
136 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
137 cdb
[3] = (buf_len
>>8) & 0xff;
138 cdb
[4] = buf_len
& 0xff;
139 ucmd
.uscsi_cdb
= (caddr_t
)cdb
;
140 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
141 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
142 ucmd
.uscsi_buflen
= buf_len
;
143 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
144 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
145 ucmd
.uscsi_timeout
= 60;
147 if (err
= cmd(fd
, &ucmd
, USCSI_WRITE
)) {
151 * Allow time for things to stabilize.
158 * Internal routine to allow manipulation of the cdb[1] byte
162 rec_diag_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
, uchar_t page_code
,
165 struct uscsi_cmd ucmd
;
166 uchar_t cdb
[] = {SCMD_GDIAG
, 0, 0, 0, 0, 0};
167 struct scsi_extended_sense sense
;
169 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
170 return (L_INVALID_ARG
);
173 (void) memset(buf_ptr
, 0, buf_len
);
174 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
177 cdb
[3] = (buf_len
>>8) & 0xff;
178 cdb
[4] = buf_len
& 0xff;
179 ucmd
.uscsi_cdb
= (caddr_t
)cdb
;
180 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
181 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
182 ucmd
.uscsi_buflen
= buf_len
;
183 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
184 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
185 ucmd
.uscsi_timeout
= 60;
186 return (cmd(fd
, &ucmd
, USCSI_READ
));
191 * Receive Diagnostic command
194 g_scsi_rec_diag_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
, uchar_t page_code
)
198 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
199 return (L_INVALID_ARG
);
202 if (buf_len
& 0x03) {
203 return (L_RD_INVLD_TRNSFR_LEN
);
207 * The a5k and newer enclosures abide by the SCSI spec
208 * (SPC-2: 7.15) but the SSA does not. It requires
209 * 0x10 to be present in cdb[1].
211 * For enclosures that abide by the spec, the first call
212 * will work. For SSAs the first call will fail, at which
213 * point we try again with the SSA specific value.
215 status
= rec_diag_cmd(fd
, buf_ptr
, buf_len
, page_code
, SCSI_ESI_PCV
);
217 status
= rec_diag_cmd(fd
, buf_ptr
, buf_len
, page_code
, SCSI_ESI_PF
);
223 * Write buffer command set up to download firmware
226 g_scsi_writebuffer_cmd(int fd
, int off
, uchar_t
*buf_ptr
, int buf_len
,
229 struct uscsi_cmd ucmd
;
230 my_cdb_g1 cdb
= {SCMD_WRITE_BUFFER
, 0x4, 0, 0, 0, 0, 0, 0, 0, 0};
231 struct scsi_extended_sense sense
;
233 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
234 return (L_INVALID_ARG
);
237 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
238 cdb
.byte1
|= sp
; /* set the save bit */
239 cdb
.byte2
= (char)(bid
& 0xff);
240 cdb
.byte3
= off
>>16; /* bytes 3-5 contain file offset */
241 cdb
.byte4
= (off
>>8) & 0xff;
242 cdb
.byte5
= off
& 0xff;
243 cdb
.byte6
= buf_len
>>16; /* bytes 6-8 contain file length */
244 cdb
.byte7
= (buf_len
>>8) & 0xff;
245 cdb
.byte8
= buf_len
& 0xff;
246 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
247 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
248 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
249 ucmd
.uscsi_buflen
= buf_len
;
250 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
251 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
252 ucmd
.uscsi_timeout
= 240; /* long timeout required */
254 return (cmd(fd
, &ucmd
, USCSI_WRITE
));
258 * Read buffer command set up to upload firmware
259 * Reads from code image starting at offset
260 * "code_off" for "buf_len" bytes.
263 g_scsi_readbuffer_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
, int code_off
)
265 struct uscsi_cmd ucmd
;
266 my_cdb_g1 cdb
= {SCMD_READ_BUFFER
, 0x5, 0, 0, 0, 0, 0, 0, 0, 0};
267 struct scsi_extended_sense sense
;
269 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
270 return (L_INVALID_ARG
);
273 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
274 cdb
.byte3
= (code_off
>> 16) & 0xff;
275 cdb
.byte4
= (code_off
>> 8) & 0xff;
276 cdb
.byte5
= code_off
& 0xff;
277 cdb
.byte6
= buf_len
>>16; /* bytes 6-8 contain file length */
278 cdb
.byte7
= (buf_len
>>8) & 0xff;
279 cdb
.byte8
= buf_len
& 0xff;
280 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
281 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
282 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
283 ucmd
.uscsi_buflen
= buf_len
;
284 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
285 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
286 ucmd
.uscsi_timeout
= 120;
288 return (cmd(fd
, &ucmd
, USCSI_READ
));
292 g_scsi_inquiry_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
)
294 struct uscsi_cmd ucmd
;
295 my_cdb_g0 cdb
= {SCMD_INQUIRY
, 0, 0, 0, 0, 0};
296 struct scsi_extended_sense sense
;
299 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
300 return (L_INVALID_ARG
);
303 (void) memset(buf_ptr
, 0, buf_len
);
304 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
305 cdb
.count
= (uchar_t
)buf_len
;
306 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
307 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
308 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
309 ucmd
.uscsi_buflen
= buf_len
;
310 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
311 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
312 ucmd
.uscsi_timeout
= 60;
314 myreturn
= cmd(fd
, &ucmd
, USCSI_READ
| USCSI_SILENT
);
316 return (myreturn
); /* != 0, error just return */
320 * This is a work around for the format of Daktari's
321 * SCSI inquiry page information. The name of the enclosure
322 * is not in the same place that products like the a5000 place it
323 * so we have to copy the string to the expected location.
325 if (strncmp((char *)&buf_ptr
[16], DAK_PROD_STR
,
326 strlen(DAK_PROD_STR
)) == 0) {
327 strncpy((char *)&buf_ptr
[96], (char *)&buf_ptr
[DAK_BOXNAME_OFF
],
335 g_scsi_log_sense_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
, uchar_t page_code
)
337 struct uscsi_cmd ucmd
;
338 my_cdb_g1 cdb
= {SCMD_LOG_SENSE
, 0, 0x40, 0, 0, 0, 0, 0, 0, 0};
339 struct scsi_extended_sense sense
;
341 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
342 return (L_INVALID_ARG
);
345 /* clear buffers on cmds that read data */
346 (void) memset(buf_ptr
, 0, buf_len
);
347 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
348 cdb
.byte2
|= page_code
; /* requested page */
349 cdb
.byte7
= buf_len
>>8;
350 cdb
.byte8
= buf_len
& 0xff;
351 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
352 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
353 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
354 ucmd
.uscsi_buflen
= buf_len
;
355 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
356 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
357 ucmd
.uscsi_timeout
= 120;
358 return (cmd(fd
, &ucmd
, USCSI_READ
));
364 * MODE SELECT USCSI command
366 * sp is the save pages bit - Must be bit 0 -
370 g_scsi_mode_select_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
, uchar_t sp
)
372 struct uscsi_cmd ucmd
;
373 /* 10 byte Mode Select cmd */
374 my_cdb_g1 cdb
= {SCMD_MODE_SELECT_G1
, 0, 0, 0, 0, 0, 0, 0, 0, 0};
375 struct scsi_extended_sense sense
;
377 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
378 return (L_INVALID_ARG
);
381 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
382 cdb
.byte1
= (sp
& 1) | 0x10; /* 0x10 is the PF bit */
383 cdb
.byte7
= buf_len
>>8;
384 cdb
.byte8
= buf_len
& 0xff;
386 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
387 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
388 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
389 ucmd
.uscsi_buflen
= buf_len
;
390 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
391 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
392 ucmd
.uscsi_timeout
= 120;
394 return (cmd(fd
, &ucmd
, USCSI_WRITE
));
399 * MODE SENSE USCSI command
402 * pc = page control field
403 * page_code = Pages to return
406 g_scsi_mode_sense_cmd(int fd
,
412 struct uscsi_cmd ucmd
;
413 /* 10 byte Mode Select cmd */
414 my_cdb_g1 cdb
= {SCMD_MODE_SENSE_G1
, 0, 0, 0, 0, 0, 0, 0, 0, 0};
415 struct scsi_extended_sense sense
;
417 static int uscsi_count
;
419 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
420 return (L_INVALID_ARG
);
423 (void) memset(buf_ptr
, 0, buf_len
);
424 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
425 /* Just for me - a sanity check */
426 if ((page_code
> MODEPAGE_ALLPAGES
) || (pc
> 3) ||
427 (buf_len
> MAX_MODE_SENSE_LEN
)) {
428 return (L_ILLEGAL_MODE_SENSE_PAGE
);
430 cdb
.byte2
= (pc
<< 6) + page_code
;
431 cdb
.byte7
= buf_len
>>8;
432 cdb
.byte8
= buf_len
& 0xff;
433 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
434 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
435 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
436 ucmd
.uscsi_buflen
= buf_len
;
437 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
438 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
439 ucmd
.uscsi_timeout
= 120;
441 status
= cmd(fd
, &ucmd
, USCSI_READ
);
442 /* Bytes actually transfered */
444 uscsi_count
= buf_len
- ucmd
.uscsi_resid
;
445 S_DPRINTF(" Number of bytes read on "
446 "Mode Sense 0x%x\n", uscsi_count
);
447 if (getenv("_LUX_D_DEBUG") != NULL
) {
448 (void) g_dump(" Mode Sense data: ", buf_ptr
,
449 uscsi_count
, HEX_ASCII
);
456 g_scsi_read_capacity_cmd(int fd
, uchar_t
*buf_ptr
, int buf_len
)
458 struct uscsi_cmd ucmd
;
459 my_cdb_g1 cdb
= {SCMD_READ_CAPACITY
, 0, 0, 0, 0, 0, 0, 0, 0, 0};
460 struct scsi_extended_sense sense
;
462 if ((fd
< 0) || (buf_ptr
== NULL
) || (buf_len
< 0)) {
463 return (L_INVALID_ARG
);
466 /* clear buffers on on cmds that read data */
467 (void) memset(buf_ptr
, 0, buf_len
);
468 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
470 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
471 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
472 ucmd
.uscsi_bufaddr
= (caddr_t
)buf_ptr
;
473 ucmd
.uscsi_buflen
= buf_len
;
474 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
475 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
476 ucmd
.uscsi_timeout
= 60;
477 return (cmd(fd
, &ucmd
, USCSI_READ
));
481 g_scsi_read_capacity_1016_cmd(int fd
,
482 struct scsi_capacity_16
*cap_ptr
, int buf_len
)
484 struct uscsi_cmd ucmd
;
485 my_cdb_g1 cdb
= {SCMD_READ_CAPACITY
, 0, 0, 0, 0, 0, 0, 0, 0, 0};
486 struct scsi_extended_sense sense
;
487 struct scsi_capacity cap_old
;
490 if ((fd
< 0) || (cap_ptr
== NULL
) ||
491 (buf_len
< sizeof (struct scsi_capacity_16
))) {
492 return (L_INVALID_ARG
);
495 /* clear buffers on on cmds that read data */
496 (void) memset((char *)&cap_old
, 0, sizeof (cap_old
));
497 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
499 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
500 ucmd
.uscsi_cdblen
= CDB_GROUP1
;
501 ucmd
.uscsi_bufaddr
= (caddr_t
)&cap_old
;
502 ucmd
.uscsi_buflen
= sizeof (cap_old
);
503 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
504 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
505 ucmd
.uscsi_timeout
= 60;
507 ret
= cmd(fd
, &ucmd
, USCSI_READ
);
508 if (cap_old
.capacity
== 0xffffffff) {
510 * A capacity of 0xffffffff in response to a
511 * READ CAPACITY 10 indicates that the lun
512 * is too large to report the size in a 32 bit
513 * value, and a READ CAPACITY 16 is required
514 * to get the correct size.
516 ret
= scsi_read_capacity_16_cmd(fd
, cap_ptr
, buf_len
);
518 cap_ptr
->sc_capacity
= cap_old
.capacity
;
519 cap_ptr
->sc_lbasize
= cap_old
.lbasize
;
525 scsi_read_capacity_16_cmd(int fd
,
526 struct scsi_capacity_16
*cap_ptr
, int buf_len
)
528 struct uscsi_cmd ucmd
;
530 struct scsi_extended_sense sense
;
532 if ((fd
< 0) || (cap_ptr
== NULL
) ||
533 (buf_len
< sizeof (struct scsi_capacity_16
))) {
534 return (L_INVALID_ARG
);
536 /* clear buffers on on cmds that read data */
537 (void) memset((char *)cap_ptr
, 0, buf_len
);
538 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
539 (void) memset((char *)&cdb
, 0, sizeof (union scsi_cdb
));
541 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
542 ucmd
.uscsi_cdblen
= CDB_GROUP4
;
543 ucmd
.uscsi_bufaddr
= (caddr_t
)cap_ptr
;
544 ucmd
.uscsi_buflen
= buf_len
;
545 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
546 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
547 ucmd
.uscsi_timeout
= 60;
550 * Read Capacity (16) is a Service Action In command. One
551 * command byte (0x9E) is overloaded for multiple operations,
552 * with the second CDB byte specifying the desired operation
554 cdb
.scc_cmd
= SCMD_SVC_ACTION_IN_G4
;
555 cdb
.cdb_opaque
[1] = SSVC_ACTION_READ_CAPACITY_G4
;
558 * Fill in allocation length field
561 (uchar_t
)((ucmd
.uscsi_buflen
& 0xff000000) >> 24);
563 (uchar_t
)((ucmd
.uscsi_buflen
& 0x00ff0000) >> 16);
565 (uchar_t
)((ucmd
.uscsi_buflen
& 0x0000ff00) >> 8);
567 (uchar_t
)(ucmd
.uscsi_buflen
& 0x000000ff);
569 return (cmd(fd
, &ucmd
, USCSI_READ
));
573 g_scsi_release_cmd(int fd
)
575 struct uscsi_cmd ucmd
;
576 const my_cdb_g0 cdb
= {SCMD_RELEASE
, 0, 0, 0, 0, 0};
577 struct scsi_extended_sense sense
;
580 return (L_INVALID_ARG
);
583 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
585 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
586 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
587 ucmd
.uscsi_bufaddr
= NULL
;
588 ucmd
.uscsi_buflen
= 0;
589 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
590 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
591 ucmd
.uscsi_timeout
= 60;
592 return (cmd(fd
, &ucmd
, 0));
596 g_scsi_reserve_cmd(int fd
)
598 struct uscsi_cmd ucmd
;
599 const my_cdb_g0 cdb
= {SCMD_RESERVE
, 0, 0, 0, 0, 0};
600 struct scsi_extended_sense sense
;
603 return (L_INVALID_ARG
);
606 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
608 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
609 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
610 ucmd
.uscsi_bufaddr
= NULL
;
611 ucmd
.uscsi_buflen
= 0;
612 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
613 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
614 ucmd
.uscsi_timeout
= 60;
615 return (cmd(fd
, &ucmd
, 0));
619 g_scsi_start_cmd(int fd
)
621 struct uscsi_cmd ucmd
;
623 * Use this to induce a SCSI error
624 * const my_cdb_g0 cdb = {SCMD_START_STOP, 0, 0xff, 0, 1, 0};
626 const my_cdb_g0 cdb
= {SCMD_START_STOP
, 0, 0, 0, 1, 0};
627 struct scsi_extended_sense sense
;
630 return (L_INVALID_ARG
);
633 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
634 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
635 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
636 ucmd
.uscsi_bufaddr
= NULL
;
637 ucmd
.uscsi_buflen
= 0;
638 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
639 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
640 ucmd
.uscsi_timeout
= 240; /* takes a while to start all */
641 return (cmd(fd
, &ucmd
, 0));
645 g_scsi_stop_cmd(int fd
, int immediate_flag
)
647 struct uscsi_cmd ucmd
;
648 my_cdb_g0 cdb
= {SCMD_START_STOP
, 0, 0, 0, 0, 0};
649 struct scsi_extended_sense sense
;
652 return (L_INVALID_ARG
);
655 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
656 if (immediate_flag
) {
659 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
660 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
661 ucmd
.uscsi_bufaddr
= NULL
;
662 ucmd
.uscsi_buflen
= 0;
663 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
664 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
665 ucmd
.uscsi_timeout
= 120;
666 return (cmd(fd
, &ucmd
, 0));
672 struct uscsi_cmd ucmd
;
673 const my_cdb_g0 cdb
= {SCMD_TEST_UNIT_READY
, 0, 0, 0, 0, 0};
674 struct scsi_extended_sense sense
;
677 return (L_INVALID_ARG
);
680 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
682 ucmd
.uscsi_cdb
= (caddr_t
)&cdb
;
683 ucmd
.uscsi_cdblen
= CDB_GROUP0
;
684 ucmd
.uscsi_bufaddr
= NULL
;
685 ucmd
.uscsi_buflen
= NULL
;
686 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
687 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
688 ucmd
.uscsi_timeout
= 60;
689 return (cmd(fd
, &ucmd
, 0));
693 * NOTE: This function includes a delay.
698 struct uscsi_cmd ucmd
;
699 struct scsi_extended_sense sense
;
703 return (L_INVALID_ARG
);
706 (void) memset((char *)&ucmd
, 0, sizeof (ucmd
));
708 ucmd
.uscsi_cdb
= NULL
;
709 ucmd
.uscsi_cdblen
= NULL
;
710 ucmd
.uscsi_bufaddr
= NULL
;
711 ucmd
.uscsi_buflen
= NULL
;
712 ucmd
.uscsi_rqbuf
= (caddr_t
)&sense
;
713 ucmd
.uscsi_rqlen
= sizeof (struct scsi_extended_sense
);
714 ucmd
.uscsi_timeout
= 60;
715 if (err
= cmd(fd
, &ucmd
, USCSI_RESET
)) {
719 * Allow time for things to stabilize.
728 * Retrieves a devid from a device path.
732 * devpath: Valid block device path.
733 * Example:/devices/scsi_vhci/ssd@g280000602200416d6257333030303353:c,raw
735 * devid: ptr to ddi_devid_t struct
736 * root: root handle to device tree snapshot
737 * drvr_name: driver name to start the node tree search
738 * On success, devid points to device tree handle to devid
739 * di_fini on root will invalidate devid pointer
743 * non-zero on failure
746 g_devid_get(char *devpath
, ddi_devid_t
*devid
, di_node_t root
,
747 const char *drvr_name
)
750 char rootpath
[MAXPATHLEN
];
752 char *devfs_path
= NULL
;
753 hrtime_t start_time
, end_time
;
756 if (devpath
== NULL
|| devid
== NULL
|| drvr_name
== NULL
) {
757 return (L_INVALID_ARG
);
760 if ((env
= getenv("_LUX_T_DEBUG")) != NULL
) {
761 start_time
= gethrtime();
768 * Form a valid root path by stripping off the /devices/ mount point
769 * prefix and the minor name (:a[,raw]).
771 if (strstr(devpath
, DEV_PREFIX
)) {
772 strcat(rootpath
, devpath
+ strlen(DEV_PREFIX
) - 1);
773 if (strchr(devpath
, ':')) {
774 cptr
= strrchr(rootpath
, ':');
777 return (L_INVALID_PATH
);
780 return (L_INVALID_PATH
);
783 /* point to first node which matches portdrvr */
784 node
= di_drv_first_node(drvr_name
, root
);
785 if (node
== DI_NODE_NIL
) {
787 * Could not find driver node
792 while (node
!= DI_NODE_NIL
) {
793 if ((devfs_path
= di_devfs_path(node
)) != NULL
) {
794 if (strcmp(rootpath
, devfs_path
) == 0) {
795 *devid
= di_devid(node
);
796 di_devfs_path_free(devfs_path
);
799 di_devfs_path_free(devfs_path
);
801 node
= di_drv_next_node(node
);
805 end_time
= gethrtime();
806 (void) fprintf(stdout
,
808 "\t\tTime = %lld millisec\n",
809 (end_time
- start_time
)/1000000);
811 /* Did we get back a handle? */
812 if (*devid
!= NULL
) {
814 } else { /* Couldn't get a devid. */