1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  */
25fcf3ce44SJohn Forte 
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte /*LINTLIBRARY*/
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte /*
30fcf3ce44SJohn Forte  *
31fcf3ce44SJohn Forte  *	This module is part of the photon Command Line
32fcf3ce44SJohn Forte  *	Interface program.
33fcf3ce44SJohn Forte  *
34fcf3ce44SJohn Forte  */
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte /*
37fcf3ce44SJohn Forte  * I18N message number ranges
38fcf3ce44SJohn Forte  *  This file: 11500 - 11999
39fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
40fcf3ce44SJohn Forte  */
41fcf3ce44SJohn Forte 
42fcf3ce44SJohn Forte /* #define		_POSIX_SOURCE 1 */
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte /*	Includes	*/
45fcf3ce44SJohn Forte #include	<stdlib.h>
46fcf3ce44SJohn Forte #include	<stdio.h>
47fcf3ce44SJohn Forte #include	<string.h>
48fcf3ce44SJohn Forte #include	<sys/file.h>
49fcf3ce44SJohn Forte #include	<sys/types.h>
50fcf3ce44SJohn Forte #include	<fcntl.h>
51fcf3ce44SJohn Forte #include	<sys/sunddi.h>
52fcf3ce44SJohn Forte #include	<sys/systm.h>
53fcf3ce44SJohn Forte #include	<sys/scsi/scsi.h>
54fcf3ce44SJohn Forte #include	<nl_types.h>
55fcf3ce44SJohn Forte #include	<unistd.h>
56fcf3ce44SJohn Forte #include	<l_common.h>
57fcf3ce44SJohn Forte #include	<stgcom.h>
58fcf3ce44SJohn Forte #include	<l_error.h>
59fcf3ce44SJohn Forte #include	<g_state.h>
60fcf3ce44SJohn Forte #include	<errno.h>
61fcf3ce44SJohn Forte #include	<devid.h>
62fcf3ce44SJohn Forte #include	<libdevinfo.h>
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte 
65fcf3ce44SJohn Forte /*	Defines		*/
66fcf3ce44SJohn Forte /* Because of a bug in Unisys Envsen card,  Bug ID:1266986. */
67fcf3ce44SJohn Forte #define	SCSI_ESI_PCV	0x01		/* Page Code Valid */
68fcf3ce44SJohn Forte #define	SCSI_ESI_PF	0x10		/* Page Format */
69fcf3ce44SJohn Forte #define	ACTION_MASK	0x1f		/* Persistent Reserve In command */
70fcf3ce44SJohn Forte #define	IMMED		1		/* make the stop immediate */
71fcf3ce44SJohn Forte #define	DAK_PROD_STR	"SUNWGS INT FCBPL"
72fcf3ce44SJohn Forte #define	DAK_BOXNAME_LEN	16		/* The length of the daktari boxname */
73fcf3ce44SJohn Forte #define	DAK_BOXNAME_OFF	36		/* The offset of the daktari boxname */
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte /*	Global variables	*/
78fcf3ce44SJohn Forte extern	nl_catd l_catd;
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte /*	Forward declarations	*/
82fcf3ce44SJohn Forte static int scsi_read_capacity_16_cmd(int, struct scsi_capacity_16 *, int);
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte /*	External functions	*/
86fcf3ce44SJohn Forte 
87fcf3ce44SJohn Forte 
88fcf3ce44SJohn Forte int
g_scsi_persistent_reserve_in_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t action)89fcf3ce44SJohn Forte g_scsi_persistent_reserve_in_cmd(int fd, uchar_t *buf_ptr,
90fcf3ce44SJohn Forte 	int buf_len, uchar_t action)
91fcf3ce44SJohn Forte {
92fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
93fcf3ce44SJohn Forte my_cdb_g1	cdb = {SCMD_PERS_RESERV_IN, 0, 0, 0, 0, 0, 0, 0, 0, 0};
94fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
95fcf3ce44SJohn Forte 
96fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
97fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
98fcf3ce44SJohn Forte 	}
99fcf3ce44SJohn Forte 
100fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
101fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
102fcf3ce44SJohn Forte 	cdb.byte1 = action & ACTION_MASK;
103fcf3ce44SJohn Forte 	cdb.byte7 = (buf_len>>8) & 0xff;
104fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
105fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
106fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
107fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
108fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
109fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
110fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
111fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 	if (buf_len & 0x03) {
114fcf3ce44SJohn Forte 		return (L_PR_INVLD_TRNSFR_LEN);
115fcf3ce44SJohn Forte 	}
116fcf3ce44SJohn Forte 	/* Do in SILENT mode as cmd may not be supported. */
117fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT));
118fcf3ce44SJohn Forte }
119fcf3ce44SJohn Forte /*
120fcf3ce44SJohn Forte  *	Send Diagnostic command
121fcf3ce44SJohn Forte  *
122fcf3ce44SJohn Forte  *	NOTE: This function includes a delay.
123fcf3ce44SJohn Forte  */
124fcf3ce44SJohn Forte int
g_scsi_send_diag_cmd(int fd,uchar_t * buf_ptr,int buf_len)125fcf3ce44SJohn Forte g_scsi_send_diag_cmd(int fd, uchar_t *buf_ptr, int buf_len)
126fcf3ce44SJohn Forte {
127fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
128fcf3ce44SJohn Forte uchar_t	cdb[] = {SCMD_SDIAG, SCSI_ESI_PF, 0, 0, 0, 0};
129fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
130fcf3ce44SJohn Forte int		err;
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
133fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
134fcf3ce44SJohn Forte 	}
135fcf3ce44SJohn Forte 
136fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
137fcf3ce44SJohn Forte 	cdb[3] = (buf_len>>8) & 0xff;
138fcf3ce44SJohn Forte 	cdb[4] = buf_len & 0xff;
139fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)cdb;
140fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
141fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
142fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
143fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
144fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
145fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
146fcf3ce44SJohn Forte 
147fcf3ce44SJohn Forte 	if (err = cmd(fd, &ucmd, USCSI_WRITE)) {
148fcf3ce44SJohn Forte 		return (err);
149fcf3ce44SJohn Forte 	}
150fcf3ce44SJohn Forte 	/*
151fcf3ce44SJohn Forte 	 * Allow time for things to stabilize.
152fcf3ce44SJohn Forte 	 */
153fcf3ce44SJohn Forte 	sleep(5);
154fcf3ce44SJohn Forte 	return (0);
155fcf3ce44SJohn Forte }
156fcf3ce44SJohn Forte 
157fcf3ce44SJohn Forte /*
158fcf3ce44SJohn Forte  * Internal routine to allow manipulation of the cdb[1] byte
159fcf3ce44SJohn Forte  * in receive diag.
160fcf3ce44SJohn Forte  */
161fcf3ce44SJohn Forte static int
rec_diag_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t page_code,uchar_t cdb_one)162fcf3ce44SJohn Forte rec_diag_cmd(int fd, uchar_t *buf_ptr, int buf_len, uchar_t page_code,
163fcf3ce44SJohn Forte 	uchar_t cdb_one)
164fcf3ce44SJohn Forte {
165fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
166fcf3ce44SJohn Forte uchar_t	cdb[] = {SCMD_GDIAG, 0, 0, 0, 0, 0};
167fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
168fcf3ce44SJohn Forte 
169fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
170fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
171fcf3ce44SJohn Forte 	}
172fcf3ce44SJohn Forte 
173fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
174fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
175fcf3ce44SJohn Forte 	cdb[1] = cdb_one;
176fcf3ce44SJohn Forte 	cdb[2] = page_code;
177fcf3ce44SJohn Forte 	cdb[3] = (buf_len>>8) & 0xff;
178fcf3ce44SJohn Forte 	cdb[4] = buf_len & 0xff;
179fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)cdb;
180fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
181fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
182fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
183fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
184fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
185fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
186fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ));
187fcf3ce44SJohn Forte }
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte /*
191fcf3ce44SJohn Forte  *	Receive Diagnostic command
192fcf3ce44SJohn Forte  */
193fcf3ce44SJohn Forte int
g_scsi_rec_diag_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t page_code)194fcf3ce44SJohn Forte g_scsi_rec_diag_cmd(int fd, uchar_t *buf_ptr, int buf_len, uchar_t page_code)
195fcf3ce44SJohn Forte {
196fcf3ce44SJohn Forte int	status;
197fcf3ce44SJohn Forte 
198fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
199fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
200fcf3ce44SJohn Forte 	}
201fcf3ce44SJohn Forte 
202fcf3ce44SJohn Forte 	if (buf_len & 0x03) {
203fcf3ce44SJohn Forte 		return (L_RD_INVLD_TRNSFR_LEN);
204fcf3ce44SJohn Forte 	}
205fcf3ce44SJohn Forte 
206fcf3ce44SJohn Forte 	/*
207fcf3ce44SJohn Forte 	 * The a5k and newer enclosures abide by the SCSI spec
208fcf3ce44SJohn Forte 	 * (SPC-2: 7.15) but the SSA does not.  It requires
209fcf3ce44SJohn Forte 	 * 0x10 to be present in cdb[1].
210fcf3ce44SJohn Forte 	 *
211fcf3ce44SJohn Forte 	 * For enclosures that abide by the spec, the first call
212fcf3ce44SJohn Forte 	 * will work.  For SSAs the first call will fail, at which
213fcf3ce44SJohn Forte 	 * point we try again with the SSA specific value.
214fcf3ce44SJohn Forte 	 */
215fcf3ce44SJohn Forte 	status = rec_diag_cmd(fd, buf_ptr, buf_len, page_code, SCSI_ESI_PCV);
216fcf3ce44SJohn Forte 	if (status != 0) {
217fcf3ce44SJohn Forte 	    status = rec_diag_cmd(fd, buf_ptr, buf_len, page_code, SCSI_ESI_PF);
218fcf3ce44SJohn Forte 	}
219fcf3ce44SJohn Forte 	return (status);
220fcf3ce44SJohn Forte }
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte /*
223fcf3ce44SJohn Forte  *		Write buffer command set up to download firmware
224fcf3ce44SJohn Forte  */
225fcf3ce44SJohn Forte int
g_scsi_writebuffer_cmd(int fd,int off,uchar_t * buf_ptr,int buf_len,int sp,int bid)226fcf3ce44SJohn Forte g_scsi_writebuffer_cmd(int fd, int off, uchar_t *buf_ptr, int buf_len,
227fcf3ce44SJohn Forte 				int sp, int bid)
228fcf3ce44SJohn Forte {
229fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
230fcf3ce44SJohn Forte my_cdb_g1	cdb = {SCMD_WRITE_BUFFER, 0x4, 0, 0, 0, 0, 0, 0, 0, 0};
231fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
234fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
235fcf3ce44SJohn Forte 	}
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
238fcf3ce44SJohn Forte 	cdb.byte1 |= sp;		/* set the save bit */
239fcf3ce44SJohn Forte 	cdb.byte2 = (char)(bid & 0xff);
240fcf3ce44SJohn Forte 	cdb.byte3 = off>>16;	/* bytes 3-5 contain file offset */
241fcf3ce44SJohn Forte 	cdb.byte4 = (off>>8) & 0xff;
242fcf3ce44SJohn Forte 	cdb.byte5 = off & 0xff;
243fcf3ce44SJohn Forte 	cdb.byte6 = buf_len>>16;	/* bytes 6-8 contain file length */
244fcf3ce44SJohn Forte 	cdb.byte7 = (buf_len>>8) & 0xff;
245fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
246fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
247fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
248fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
249fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
250fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
251fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
252fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 240;	/* long timeout required */
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_WRITE));
255fcf3ce44SJohn Forte }
256fcf3ce44SJohn Forte 
257fcf3ce44SJohn Forte /*
258fcf3ce44SJohn Forte  *	Read buffer command set up to upload firmware
259fcf3ce44SJohn Forte  *	Reads from code image starting at offset
260fcf3ce44SJohn Forte  *	"code_off" for "buf_len" bytes.
261fcf3ce44SJohn Forte  */
262fcf3ce44SJohn Forte int
g_scsi_readbuffer_cmd(int fd,uchar_t * buf_ptr,int buf_len,int code_off)263fcf3ce44SJohn Forte g_scsi_readbuffer_cmd(int fd, uchar_t *buf_ptr, int buf_len, int code_off)
264fcf3ce44SJohn Forte {
265fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
266fcf3ce44SJohn Forte my_cdb_g1	cdb = {SCMD_READ_BUFFER, 0x5, 0, 0, 0, 0, 0, 0, 0, 0};
267fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
270fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
271fcf3ce44SJohn Forte 	}
272fcf3ce44SJohn Forte 
273fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
274fcf3ce44SJohn Forte 	cdb.byte3 = (code_off >> 16) & 0xff;
275fcf3ce44SJohn Forte 	cdb.byte4 = (code_off >> 8) & 0xff;
276fcf3ce44SJohn Forte 	cdb.byte5 = code_off & 0xff;
277fcf3ce44SJohn Forte 	cdb.byte6 = buf_len>>16;	/* bytes 6-8 contain file length */
278fcf3ce44SJohn Forte 	cdb.byte7 = (buf_len>>8) & 0xff;
279fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
280fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
281fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
282fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
283fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
284fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
285fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
286fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
287fcf3ce44SJohn Forte 
288fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ));
289fcf3ce44SJohn Forte }
290fcf3ce44SJohn Forte 
291fcf3ce44SJohn Forte int
g_scsi_inquiry_cmd(int fd,uchar_t * buf_ptr,int buf_len)292fcf3ce44SJohn Forte g_scsi_inquiry_cmd(int fd, uchar_t *buf_ptr, int buf_len)
293fcf3ce44SJohn Forte {
294fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
295fcf3ce44SJohn Forte my_cdb_g0	cdb = {SCMD_INQUIRY, 0, 0, 0, 0, 0};
296fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
297fcf3ce44SJohn Forte int	myreturn;
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
300fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
301fcf3ce44SJohn Forte 	}
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
304fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
305fcf3ce44SJohn Forte 	cdb.count = (uchar_t)buf_len;
306fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
307fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
308fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
309fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
310fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
311fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
312fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
313fcf3ce44SJohn Forte 
314fcf3ce44SJohn Forte 	myreturn = cmd(fd, &ucmd, USCSI_READ | USCSI_SILENT);
315fcf3ce44SJohn Forte 	if (myreturn) {
316fcf3ce44SJohn Forte 	    return (myreturn);	    /* != 0, error just return */
317fcf3ce44SJohn Forte 	}
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 	/*
320fcf3ce44SJohn Forte 	 * This is a work around for the format of Daktari's
321fcf3ce44SJohn Forte 	 * SCSI inquiry page information.  The name of the enclosure
322fcf3ce44SJohn Forte 	 * is not in the same place that products like the a5000 place it
323fcf3ce44SJohn Forte 	 * so we have to copy the string to the expected location.
324fcf3ce44SJohn Forte 	 */
325fcf3ce44SJohn Forte 	if (strncmp((char *)&buf_ptr[16], DAK_PROD_STR,
326fcf3ce44SJohn Forte 			strlen(DAK_PROD_STR)) == 0) {
327fcf3ce44SJohn Forte 		strncpy((char *)&buf_ptr[96], (char *)&buf_ptr[DAK_BOXNAME_OFF],
328fcf3ce44SJohn Forte 		    DAK_BOXNAME_LEN);
329fcf3ce44SJohn Forte 	}
330fcf3ce44SJohn Forte 
331fcf3ce44SJohn Forte 	return (myreturn);
332fcf3ce44SJohn Forte }
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte int
g_scsi_log_sense_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t page_code)335fcf3ce44SJohn Forte g_scsi_log_sense_cmd(int fd, uchar_t *buf_ptr, int buf_len, uchar_t page_code)
336fcf3ce44SJohn Forte {
337fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
338fcf3ce44SJohn Forte my_cdb_g1	cdb =  {SCMD_LOG_SENSE, 0, 0x40, 0, 0, 0, 0, 0, 0, 0};
339fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
340fcf3ce44SJohn Forte 
341fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
342fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
343fcf3ce44SJohn Forte 	}
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 	/* clear buffers on cmds that read data */
346fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
347fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
348fcf3ce44SJohn Forte 	cdb.byte2 |= page_code;			/* requested page */
349fcf3ce44SJohn Forte 	cdb.byte7 = buf_len>>8;
350fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
351fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
352fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
353fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
354fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
355fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
356fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
357fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
358fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ));
359fcf3ce44SJohn Forte }
360fcf3ce44SJohn Forte 
361fcf3ce44SJohn Forte /*
362fcf3ce44SJohn Forte  *		MODE SELECT
363fcf3ce44SJohn Forte  *
364fcf3ce44SJohn Forte  *		MODE SELECT USCSI command
365fcf3ce44SJohn Forte  *
366fcf3ce44SJohn Forte  *		sp is the save pages bit  - Must be bit 0 -
367fcf3ce44SJohn Forte  *
368fcf3ce44SJohn Forte  */
369fcf3ce44SJohn Forte int
g_scsi_mode_select_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t sp)370fcf3ce44SJohn Forte g_scsi_mode_select_cmd(int fd, uchar_t *buf_ptr, int buf_len, uchar_t sp)
371fcf3ce44SJohn Forte {
372fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
373fcf3ce44SJohn Forte /* 10 byte Mode Select cmd */
374fcf3ce44SJohn Forte my_cdb_g1	cdb =  {SCMD_MODE_SELECT_G1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
375fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
376fcf3ce44SJohn Forte 
377fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
378fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
379fcf3ce44SJohn Forte 	}
380fcf3ce44SJohn Forte 
381fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
382fcf3ce44SJohn Forte 	cdb.byte1 = (sp & 1) | 0x10;		/* 0x10 is the PF bit  */
383fcf3ce44SJohn Forte 	cdb.byte7 = buf_len>>8;
384fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
385fcf3ce44SJohn Forte 
386fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
387fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
388fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
389fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
390fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
391fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
392fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_WRITE));
395fcf3ce44SJohn Forte }
396fcf3ce44SJohn Forte 
397fcf3ce44SJohn Forte 
398fcf3ce44SJohn Forte /*
399fcf3ce44SJohn Forte  *		MODE SENSE USCSI command
400fcf3ce44SJohn Forte  *
401fcf3ce44SJohn Forte  *
402fcf3ce44SJohn Forte  *		pc = page control field
403fcf3ce44SJohn Forte  *		page_code = Pages to return
404fcf3ce44SJohn Forte  */
405fcf3ce44SJohn Forte int
g_scsi_mode_sense_cmd(int fd,uchar_t * buf_ptr,int buf_len,uchar_t pc,uchar_t page_code)406fcf3ce44SJohn Forte g_scsi_mode_sense_cmd(int fd,
407fcf3ce44SJohn Forte 	uchar_t *buf_ptr,
408fcf3ce44SJohn Forte 	int buf_len,
409fcf3ce44SJohn Forte 	uchar_t pc,
410fcf3ce44SJohn Forte 	uchar_t page_code)
411fcf3ce44SJohn Forte {
412fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
413fcf3ce44SJohn Forte /* 10 byte Mode Select cmd */
414fcf3ce44SJohn Forte my_cdb_g1	cdb =  {SCMD_MODE_SENSE_G1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
415fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
416fcf3ce44SJohn Forte int		status;
417fcf3ce44SJohn Forte static	int	uscsi_count;
418fcf3ce44SJohn Forte 
419fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
420fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
421fcf3ce44SJohn Forte 	}
422fcf3ce44SJohn Forte 
423fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
424fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
425fcf3ce44SJohn Forte 	/* Just for me  - a sanity check */
426fcf3ce44SJohn Forte 	if ((page_code > MODEPAGE_ALLPAGES) || (pc > 3) ||
427fcf3ce44SJohn Forte 		(buf_len > MAX_MODE_SENSE_LEN)) {
428fcf3ce44SJohn Forte 		return (L_ILLEGAL_MODE_SENSE_PAGE);
429fcf3ce44SJohn Forte 	}
430fcf3ce44SJohn Forte 	cdb.byte2 = (pc << 6) + page_code;
431fcf3ce44SJohn Forte 	cdb.byte7 = buf_len>>8;
432fcf3ce44SJohn Forte 	cdb.byte8 = buf_len & 0xff;
433fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
434fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
435fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
436fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
437fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
438fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
439fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 	status = cmd(fd, &ucmd, USCSI_READ);
442fcf3ce44SJohn Forte 	/* Bytes actually transfered */
443fcf3ce44SJohn Forte 	if (status == 0) {
444fcf3ce44SJohn Forte 		uscsi_count = buf_len - ucmd.uscsi_resid;
445fcf3ce44SJohn Forte 		S_DPRINTF("  Number of bytes read on "
446fcf3ce44SJohn Forte 			"Mode Sense 0x%x\n", uscsi_count);
447fcf3ce44SJohn Forte 		if (getenv("_LUX_D_DEBUG") != NULL) {
448fcf3ce44SJohn Forte 			(void) g_dump("  Mode Sense data: ", buf_ptr,
449fcf3ce44SJohn Forte 			uscsi_count, HEX_ASCII);
450fcf3ce44SJohn Forte 		}
451fcf3ce44SJohn Forte 	}
452fcf3ce44SJohn Forte 	return (status);
453fcf3ce44SJohn Forte }
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte int
g_scsi_read_capacity_cmd(int fd,uchar_t * buf_ptr,int buf_len)456fcf3ce44SJohn Forte g_scsi_read_capacity_cmd(int fd, uchar_t *buf_ptr, int buf_len)
457fcf3ce44SJohn Forte {
458fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
459fcf3ce44SJohn Forte my_cdb_g1	cdb = {SCMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
460fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte 	if ((fd < 0) || (buf_ptr == NULL) || (buf_len < 0)) {
463fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
464fcf3ce44SJohn Forte 	}
465fcf3ce44SJohn Forte 
466fcf3ce44SJohn Forte 	/* clear buffers on on cmds that read data */
467fcf3ce44SJohn Forte 	(void) memset(buf_ptr, 0, buf_len);
468fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
471fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
472fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)buf_ptr;
473fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
474fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
475fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
476fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
477fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ));
478fcf3ce44SJohn Forte }
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte int
g_scsi_read_capacity_1016_cmd(int fd,struct scsi_capacity_16 * cap_ptr,int buf_len)481fcf3ce44SJohn Forte g_scsi_read_capacity_1016_cmd(int fd,
482fcf3ce44SJohn Forte 		struct scsi_capacity_16 *cap_ptr, int buf_len)
483fcf3ce44SJohn Forte {
484fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
485fcf3ce44SJohn Forte my_cdb_g1	cdb = {SCMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
486fcf3ce44SJohn Forte struct scsi_extended_sense	sense;
487fcf3ce44SJohn Forte struct scsi_capacity	cap_old;
488fcf3ce44SJohn Forte int	ret;
489fcf3ce44SJohn Forte 
490fcf3ce44SJohn Forte 	if ((fd < 0) || (cap_ptr == NULL) ||
491fcf3ce44SJohn Forte 		(buf_len < sizeof (struct scsi_capacity_16))) {
492fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
493fcf3ce44SJohn Forte 	}
494fcf3ce44SJohn Forte 
495fcf3ce44SJohn Forte 	/* clear buffers on on cmds that read data */
496fcf3ce44SJohn Forte 	(void) memset((char *)&cap_old, 0, sizeof (cap_old));
497fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
498fcf3ce44SJohn Forte 
499fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
500fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP1;
501fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)&cap_old;
502fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = sizeof (cap_old);
503fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
504fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
505fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
506fcf3ce44SJohn Forte 
507fcf3ce44SJohn Forte 	ret = cmd(fd, &ucmd, USCSI_READ);
508fcf3ce44SJohn Forte 	if (cap_old.capacity == 0xffffffff) {
509fcf3ce44SJohn Forte 		/*
510fcf3ce44SJohn Forte 		 * A capacity of 0xffffffff in response to a
511fcf3ce44SJohn Forte 		 * READ CAPACITY 10 indicates that the lun
512fcf3ce44SJohn Forte 		 * is too large to report the size in a 32 bit
513fcf3ce44SJohn Forte 		 * value, and a READ CAPACITY 16 is required
514fcf3ce44SJohn Forte 		 * to get the correct size.
515fcf3ce44SJohn Forte 		 */
516fcf3ce44SJohn Forte 		ret = scsi_read_capacity_16_cmd(fd, cap_ptr, buf_len);
517fcf3ce44SJohn Forte 	} else {
518fcf3ce44SJohn Forte 		cap_ptr->sc_capacity = cap_old.capacity;
519fcf3ce44SJohn Forte 		cap_ptr->sc_lbasize = cap_old.lbasize;
520fcf3ce44SJohn Forte 	}
521fcf3ce44SJohn Forte 	return (ret);
522fcf3ce44SJohn Forte }
523fcf3ce44SJohn Forte 
524fcf3ce44SJohn Forte static int
scsi_read_capacity_16_cmd(int fd,struct scsi_capacity_16 * cap_ptr,int buf_len)525fcf3ce44SJohn Forte scsi_read_capacity_16_cmd(int fd,
526fcf3ce44SJohn Forte 		struct scsi_capacity_16 *cap_ptr, int buf_len)
527fcf3ce44SJohn Forte {
528fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
529fcf3ce44SJohn Forte union scsi_cdb		cdb;
530fcf3ce44SJohn Forte struct scsi_extended_sense	sense;
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte 	if ((fd < 0) || (cap_ptr == NULL) ||
533fcf3ce44SJohn Forte 		(buf_len < sizeof (struct scsi_capacity_16))) {
534fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
535fcf3ce44SJohn Forte 	}
536fcf3ce44SJohn Forte 	/* clear buffers on on cmds that read data */
537fcf3ce44SJohn Forte 	(void) memset((char *)cap_ptr, 0, buf_len);
538fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
539fcf3ce44SJohn Forte 	(void) memset((char *)&cdb, 0, sizeof (union scsi_cdb));
540fcf3ce44SJohn Forte 
541fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
542fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP4;
543fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = (caddr_t)cap_ptr;
544fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = buf_len;
545fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
546fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
547fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
548fcf3ce44SJohn Forte 
549fcf3ce44SJohn Forte 	/*
550fcf3ce44SJohn Forte 	 * Read Capacity (16) is a Service Action In command.  One
551fcf3ce44SJohn Forte 	 * command byte (0x9E) is overloaded for multiple operations,
552fcf3ce44SJohn Forte 	 * with the second CDB byte specifying the desired operation
553fcf3ce44SJohn Forte 	 */
554fcf3ce44SJohn Forte 	cdb.scc_cmd = SCMD_SVC_ACTION_IN_G4;
555fcf3ce44SJohn Forte 	cdb.cdb_opaque[1] = SSVC_ACTION_READ_CAPACITY_G4;
556fcf3ce44SJohn Forte 
557fcf3ce44SJohn Forte 	/*
558fcf3ce44SJohn Forte 	 * Fill in allocation length field
559fcf3ce44SJohn Forte 	 */
560fcf3ce44SJohn Forte 	cdb.cdb_opaque[10] =
561fcf3ce44SJohn Forte 		(uchar_t)((ucmd.uscsi_buflen & 0xff000000) >> 24);
562fcf3ce44SJohn Forte 	cdb.cdb_opaque[11] =
563fcf3ce44SJohn Forte 		(uchar_t)((ucmd.uscsi_buflen & 0x00ff0000) >> 16);
564fcf3ce44SJohn Forte 	cdb.cdb_opaque[12] =
565fcf3ce44SJohn Forte 		(uchar_t)((ucmd.uscsi_buflen & 0x0000ff00) >> 8);
566fcf3ce44SJohn Forte 	cdb.cdb_opaque[13] =
567fcf3ce44SJohn Forte 		(uchar_t)(ucmd.uscsi_buflen & 0x000000ff);
568fcf3ce44SJohn Forte 
569fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, USCSI_READ));
570fcf3ce44SJohn Forte }
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte int
g_scsi_release_cmd(int fd)573fcf3ce44SJohn Forte g_scsi_release_cmd(int fd)
574fcf3ce44SJohn Forte {
575fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
576fcf3ce44SJohn Forte const my_cdb_g0	cdb = {SCMD_RELEASE, 0, 0, 0, 0, 0};
577fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
578fcf3ce44SJohn Forte 
579fcf3ce44SJohn Forte 	if (fd < 0) {
580fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
581fcf3ce44SJohn Forte 	}
582fcf3ce44SJohn Forte 
583fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
586fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
587fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
588fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
589fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
590fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
591fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
592fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, 0));
593fcf3ce44SJohn Forte }
594fcf3ce44SJohn Forte 
595fcf3ce44SJohn Forte int
g_scsi_reserve_cmd(int fd)596fcf3ce44SJohn Forte g_scsi_reserve_cmd(int fd)
597fcf3ce44SJohn Forte {
598fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
599fcf3ce44SJohn Forte const my_cdb_g0	cdb = {SCMD_RESERVE, 0, 0, 0, 0, 0};
600fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte 	if (fd < 0) {
603fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
604fcf3ce44SJohn Forte 	}
605fcf3ce44SJohn Forte 
606fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
607fcf3ce44SJohn Forte 
608fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
609fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
610fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
611fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
612fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
613fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
614fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
615fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, 0));
616fcf3ce44SJohn Forte }
617fcf3ce44SJohn Forte 
618fcf3ce44SJohn Forte int
g_scsi_start_cmd(int fd)619fcf3ce44SJohn Forte g_scsi_start_cmd(int fd)
620fcf3ce44SJohn Forte {
621fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
622fcf3ce44SJohn Forte /*
623fcf3ce44SJohn Forte  * Use this to induce a SCSI error
624fcf3ce44SJohn Forte  *	const my_cdb_g0	cdb = {SCMD_START_STOP, 0, 0xff, 0, 1, 0};
625fcf3ce44SJohn Forte  */
626fcf3ce44SJohn Forte const my_cdb_g0	cdb = {SCMD_START_STOP, 0, 0, 0, 1, 0};
627fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	if (fd < 0) {
630fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
631fcf3ce44SJohn Forte 	}
632fcf3ce44SJohn Forte 
633fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
634fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
635fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
636fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
637fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
638fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
639fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
640fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 240;	/* takes a while to start all */
641fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, 0));
642fcf3ce44SJohn Forte }
643fcf3ce44SJohn Forte 
644fcf3ce44SJohn Forte int
g_scsi_stop_cmd(int fd,int immediate_flag)645fcf3ce44SJohn Forte g_scsi_stop_cmd(int fd, int immediate_flag)
646fcf3ce44SJohn Forte {
647fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
648fcf3ce44SJohn Forte my_cdb_g0	cdb = {SCMD_START_STOP, 0, 0, 0, 0, 0};
649fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
650fcf3ce44SJohn Forte 
651fcf3ce44SJohn Forte 	if (fd < 0) {
652fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
653fcf3ce44SJohn Forte 	}
654fcf3ce44SJohn Forte 
655fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
656fcf3ce44SJohn Forte 	if (immediate_flag) {
657fcf3ce44SJohn Forte 		cdb.lba_msb = IMMED;
658fcf3ce44SJohn Forte 	}
659fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
660fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
661fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
662fcf3ce44SJohn Forte 	ucmd.uscsi_buflen = 0;
663fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
664fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
665fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 120;
666fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, 0));
667fcf3ce44SJohn Forte }
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte int
g_scsi_tur(int fd)670fcf3ce44SJohn Forte g_scsi_tur(int fd)
671fcf3ce44SJohn Forte {
672fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
673fcf3ce44SJohn Forte const my_cdb_g0	cdb = {SCMD_TEST_UNIT_READY, 0, 0, 0, 0, 0};
674fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
675fcf3ce44SJohn Forte 
676fcf3ce44SJohn Forte 	if (fd < 0) {
677fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
678fcf3ce44SJohn Forte 	}
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
681fcf3ce44SJohn Forte 
682fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = (caddr_t)&cdb;
683fcf3ce44SJohn Forte 	ucmd.uscsi_cdblen = CDB_GROUP0;
684fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
685*926d645fSToomas Soome 	ucmd.uscsi_buflen = 0;
686fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
687fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
688fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
689fcf3ce44SJohn Forte 	return (cmd(fd, &ucmd, 0));
690fcf3ce44SJohn Forte }
691fcf3ce44SJohn Forte 
692fcf3ce44SJohn Forte /*
693fcf3ce44SJohn Forte  * NOTE: This function includes a delay.
694fcf3ce44SJohn Forte  */
695fcf3ce44SJohn Forte int
g_scsi_reset(int fd)696fcf3ce44SJohn Forte g_scsi_reset(int fd)
697fcf3ce44SJohn Forte {
698fcf3ce44SJohn Forte struct uscsi_cmd	ucmd;
699fcf3ce44SJohn Forte struct	scsi_extended_sense	sense;
700fcf3ce44SJohn Forte int	err;
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 	if (fd < 0) {
703fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
704fcf3ce44SJohn Forte 	}
705fcf3ce44SJohn Forte 
706fcf3ce44SJohn Forte 	(void) memset((char *)&ucmd, 0, sizeof (ucmd));
707fcf3ce44SJohn Forte 
708fcf3ce44SJohn Forte 	ucmd.uscsi_cdb = NULL;
709*926d645fSToomas Soome 	ucmd.uscsi_cdblen = 0;
710fcf3ce44SJohn Forte 	ucmd.uscsi_bufaddr = NULL;
711*926d645fSToomas Soome 	ucmd.uscsi_buflen = 0;
712fcf3ce44SJohn Forte 	ucmd.uscsi_rqbuf = (caddr_t)&sense;
713fcf3ce44SJohn Forte 	ucmd.uscsi_rqlen = sizeof (struct  scsi_extended_sense);
714fcf3ce44SJohn Forte 	ucmd.uscsi_timeout = 60;
715fcf3ce44SJohn Forte 	if (err = cmd(fd, &ucmd, USCSI_RESET)) {
716fcf3ce44SJohn Forte 		return (err);
717fcf3ce44SJohn Forte 	}
718fcf3ce44SJohn Forte 	/*
719fcf3ce44SJohn Forte 	 * Allow time for things to stabilize.
720fcf3ce44SJohn Forte 	 */
721fcf3ce44SJohn Forte 	sleep(20);
722fcf3ce44SJohn Forte 	return (0);
723fcf3ce44SJohn Forte }
724fcf3ce44SJohn Forte 
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte /*
727fcf3ce44SJohn Forte  * Description:
728fcf3ce44SJohn Forte  *    Retrieves a devid from a device path.
729fcf3ce44SJohn Forte  *
730fcf3ce44SJohn Forte  * Input Values:
731fcf3ce44SJohn Forte  *
732fcf3ce44SJohn Forte  *    devpath: Valid block device path.
733fcf3ce44SJohn Forte  *        Example:/devices/scsi_vhci/ssd@g280000602200416d6257333030303353:c,raw
734fcf3ce44SJohn Forte  *
735fcf3ce44SJohn Forte  *    devid: ptr to ddi_devid_t struct
736fcf3ce44SJohn Forte  *    root: root handle to device tree snapshot
737fcf3ce44SJohn Forte  *    drvr_name: driver name to start the node tree search
738fcf3ce44SJohn Forte  * On success, devid points to device tree handle to devid
739fcf3ce44SJohn Forte  * di_fini on root will invalidate devid pointer
740fcf3ce44SJohn Forte  *
741fcf3ce44SJohn Forte  * Return Value:
742fcf3ce44SJohn Forte  *    0 on success
743fcf3ce44SJohn Forte  *    non-zero on failure
744fcf3ce44SJohn Forte  */
745fcf3ce44SJohn Forte int
g_devid_get(char * devpath,ddi_devid_t * devid,di_node_t root,const char * drvr_name)746fcf3ce44SJohn Forte g_devid_get(char *devpath, ddi_devid_t *devid, di_node_t root,
747fcf3ce44SJohn Forte 		const char *drvr_name)
748fcf3ce44SJohn Forte {
749fcf3ce44SJohn Forte char *cptr;
750fcf3ce44SJohn Forte char rootpath[MAXPATHLEN];
751fcf3ce44SJohn Forte di_node_t node;
752fcf3ce44SJohn Forte char *devfs_path = NULL;
753fcf3ce44SJohn Forte hrtime_t	start_time, end_time;
754fcf3ce44SJohn Forte char *env = NULL;
755fcf3ce44SJohn Forte 
756fcf3ce44SJohn Forte 	if (devpath == NULL || devid == NULL || drvr_name == NULL) {
757fcf3ce44SJohn Forte 		return (L_INVALID_ARG);
758fcf3ce44SJohn Forte 	}
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 	if ((env = getenv("_LUX_T_DEBUG")) != NULL) {
761fcf3ce44SJohn Forte 		start_time = gethrtime();
762fcf3ce44SJohn Forte 	}
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 	*devid = NULL;
765fcf3ce44SJohn Forte 	rootpath[0] = '\0';
766fcf3ce44SJohn Forte 
767fcf3ce44SJohn Forte 	/*
768fcf3ce44SJohn Forte 	 * Form a valid root path by stripping off the /devices/ mount point
769fcf3ce44SJohn Forte 	 * prefix and the minor name (:a[,raw]).
770fcf3ce44SJohn Forte 	 */
771fcf3ce44SJohn Forte 	if (strstr(devpath, DEV_PREFIX)) {
772fcf3ce44SJohn Forte 		strcat(rootpath, devpath + strlen(DEV_PREFIX) - 1);
773fcf3ce44SJohn Forte 		if (strchr(devpath, ':')) {
774fcf3ce44SJohn Forte 			cptr = strrchr(rootpath, ':');
775fcf3ce44SJohn Forte 			*cptr = '\0';
776fcf3ce44SJohn Forte 		} else {
777fcf3ce44SJohn Forte 			return (L_INVALID_PATH);
778fcf3ce44SJohn Forte 		}
779fcf3ce44SJohn Forte 	} else {
780fcf3ce44SJohn Forte 		return (L_INVALID_PATH);
781fcf3ce44SJohn Forte 	}
782fcf3ce44SJohn Forte 
783fcf3ce44SJohn Forte 	/* point to first node which matches portdrvr */
784fcf3ce44SJohn Forte 	node = di_drv_first_node(drvr_name, root);
785fcf3ce44SJohn Forte 	if (node == DI_NODE_NIL) {
786fcf3ce44SJohn Forte 		/*
787fcf3ce44SJohn Forte 		 * Could not find driver node
788fcf3ce44SJohn Forte 		 */
789fcf3ce44SJohn Forte 		return (L_NO_DEVID);
790fcf3ce44SJohn Forte 	}
791fcf3ce44SJohn Forte 
792fcf3ce44SJohn Forte 	while (node != DI_NODE_NIL) {
793fcf3ce44SJohn Forte 		if ((devfs_path = di_devfs_path(node)) != NULL) {
794fcf3ce44SJohn Forte 			if (strcmp(rootpath, devfs_path) == 0) {
795fcf3ce44SJohn Forte 				*devid = di_devid(node);
796fcf3ce44SJohn Forte 				di_devfs_path_free(devfs_path);
797fcf3ce44SJohn Forte 				break;
798fcf3ce44SJohn Forte 			}
799fcf3ce44SJohn Forte 			di_devfs_path_free(devfs_path);
800fcf3ce44SJohn Forte 		}
801fcf3ce44SJohn Forte 		node = di_drv_next_node(node);
802fcf3ce44SJohn Forte 	}
803fcf3ce44SJohn Forte 
804fcf3ce44SJohn Forte 	if (env != NULL) {
805fcf3ce44SJohn Forte 		end_time = gethrtime();
806fcf3ce44SJohn Forte 		(void) fprintf(stdout,
807fcf3ce44SJohn Forte 		"      g_devid_get: "
808fcf3ce44SJohn Forte 		"\t\tTime = %lld millisec\n",
809fcf3ce44SJohn Forte 		(end_time - start_time)/1000000);
810fcf3ce44SJohn Forte 	}
811fcf3ce44SJohn Forte 	/* Did we get back a handle? */
812fcf3ce44SJohn Forte 	if (*devid != NULL) {
813fcf3ce44SJohn Forte 		return (0);
814fcf3ce44SJohn Forte 	} else { /* Couldn't get a devid. */
815fcf3ce44SJohn Forte 		return (L_NO_DEVID);
816fcf3ce44SJohn Forte 	}
817fcf3ce44SJohn Forte }
818