1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * Enclosure Services Devices, SES Enclosure Routines
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/ses.h>
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate  * SES Diagnostic Page Codes
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate typedef enum {
42*7c478bd9Sstevel@tonic-gate 	SesConfigPage = 0x1,
43*7c478bd9Sstevel@tonic-gate 	SesControlPage,
44*7c478bd9Sstevel@tonic-gate #define	SesStatusPage SesControlPage
45*7c478bd9Sstevel@tonic-gate 	SesHelpTxt,
46*7c478bd9Sstevel@tonic-gate 	SesStringOut,
47*7c478bd9Sstevel@tonic-gate #define	SesStringIn	SesStringOut
48*7c478bd9Sstevel@tonic-gate 	SesThresholdOut,
49*7c478bd9Sstevel@tonic-gate #define	SesThresholdIn SesThresholdOut
50*7c478bd9Sstevel@tonic-gate 	SesArrayControl,
51*7c478bd9Sstevel@tonic-gate #define	SesArrayStatus	SesArrayControl
52*7c478bd9Sstevel@tonic-gate 	SesElementDescriptor,
53*7c478bd9Sstevel@tonic-gate 	SesShortStatus
54*7c478bd9Sstevel@tonic-gate } SesDiagPageCodes;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * minimal amounts
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * Minimum amount of data, starting from byte 0, to have
62*7c478bd9Sstevel@tonic-gate  * the config header.
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate #define	SES_CFGHDR_MINLEN	12
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /*
67*7c478bd9Sstevel@tonic-gate  * Minimum amount of data, starting from byte 0, to have
68*7c478bd9Sstevel@tonic-gate  * the config header and one enclosure header.
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate #define	SES_ENCHDR_MINLEN	48
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  * Take this value, subtract it from VEnclen and you know
74*7c478bd9Sstevel@tonic-gate  * the length of the vendor unique bytes.
75*7c478bd9Sstevel@tonic-gate  */
76*7c478bd9Sstevel@tonic-gate #define	SES_ENCHDR_VMIN		36
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  * SES Data Structures
80*7c478bd9Sstevel@tonic-gate  */
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate typedef struct {
83*7c478bd9Sstevel@tonic-gate 	ulong_t	GenCode;	/* Generation Code */
84*7c478bd9Sstevel@tonic-gate 	uchar_t	Nsubenc;	/* Number of Subenclosures */
85*7c478bd9Sstevel@tonic-gate } SesCfgHdr;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate typedef struct {
88*7c478bd9Sstevel@tonic-gate 	uchar_t	Subencid;	/* SubEnclosure Identifier */
89*7c478bd9Sstevel@tonic-gate 	uchar_t	Ntypes;		/* # of supported types */
90*7c478bd9Sstevel@tonic-gate 	uchar_t	VEnclen;	/* Enclosure Descriptor Length */
91*7c478bd9Sstevel@tonic-gate } SesEncHdr;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate typedef struct {
94*7c478bd9Sstevel@tonic-gate 	uchar_t	encWWN[8];	/* XXX- Not Right Yet */
95*7c478bd9Sstevel@tonic-gate 	uchar_t	encVid[8];
96*7c478bd9Sstevel@tonic-gate 	uchar_t	encPid[16];
97*7c478bd9Sstevel@tonic-gate 	uchar_t	encRev[4];
98*7c478bd9Sstevel@tonic-gate 	uchar_t	encVen[1];
99*7c478bd9Sstevel@tonic-gate } SesEncDesc;
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate typedef struct {
102*7c478bd9Sstevel@tonic-gate 	uchar_t	enc_type;		/* type of element */
103*7c478bd9Sstevel@tonic-gate 	uchar_t	enc_maxelt;		/* maximum supported */
104*7c478bd9Sstevel@tonic-gate 	uchar_t	enc_subenc;		/* in SubEnc # N */
105*7c478bd9Sstevel@tonic-gate 	uchar_t	enc_tlen;		/* Type Descriptor Text Length */
106*7c478bd9Sstevel@tonic-gate } SesThdr;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate typedef struct {
109*7c478bd9Sstevel@tonic-gate 	uchar_t	comstatus;
110*7c478bd9Sstevel@tonic-gate 	uchar_t	comstat[3];
111*7c478bd9Sstevel@tonic-gate } SesComStat;
112*7c478bd9Sstevel@tonic-gate #if	!defined(lint)
113*7c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("because I said so", SesComStat))
114*7c478bd9Sstevel@tonic-gate #endif
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate struct typidx {
117*7c478bd9Sstevel@tonic-gate 	int ses_tidx;
118*7c478bd9Sstevel@tonic-gate 	int ses_oidx;
119*7c478bd9Sstevel@tonic-gate };
120*7c478bd9Sstevel@tonic-gate #if	!defined(lint)
121*7c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("because I said so", typidx))
122*7c478bd9Sstevel@tonic-gate #endif
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate struct sscfg {
125*7c478bd9Sstevel@tonic-gate 	uchar_t ses_ntypes;	/* total number of types supported */
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	/*
128*7c478bd9Sstevel@tonic-gate 	 * We need to keep a type index as well as an object index
129*7c478bd9Sstevel@tonic-gate 	 * for each object in an enclosure.
130*7c478bd9Sstevel@tonic-gate 	 */
131*7c478bd9Sstevel@tonic-gate 	struct typidx *ses_typidx;
132*7c478bd9Sstevel@tonic-gate 	/*
133*7c478bd9Sstevel@tonic-gate 	 * We also need to keep track of the number of elements
134*7c478bd9Sstevel@tonic-gate 	 * per type of element. This is needed later so that we
135*7c478bd9Sstevel@tonic-gate 	 * can find precisely in the returned status data the
136*7c478bd9Sstevel@tonic-gate 	 * status for the Nth element of the Kth type.
137*7c478bd9Sstevel@tonic-gate 	 */
138*7c478bd9Sstevel@tonic-gate 	uchar_t *ses_eltmap;
139*7c478bd9Sstevel@tonic-gate };
140*7c478bd9Sstevel@tonic-gate #if	!defined(lint)
141*7c478bd9Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(scsi_device::sd_mutex, sscfg))
142*7c478bd9Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(sscfg))
143*7c478bd9Sstevel@tonic-gate #endif
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate /*
147*7c478bd9Sstevel@tonic-gate  * (de)canonicalization defines
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate #define	sbyte(x, byte)	((((ulong_t)(x)) >> (byte * 8)) & 0xff)
150*7c478bd9Sstevel@tonic-gate #define	sbit(x, bit)	(((ulong_t)(x)) << bit)
151*7c478bd9Sstevel@tonic-gate #define	sset8(outp, idx, sval)	\
152*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 0)
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate #define	sset16(outp, idx, sval)	\
155*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 1), \
156*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 0)
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate #define	sset24(outp, idx, sval)	\
160*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 2), \
161*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 1), \
162*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 0)
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate #define	sset32(outp, idx, sval)	\
166*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 3), \
167*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 2), \
168*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 1), \
169*7c478bd9Sstevel@tonic-gate 	(((uchar_t *)(outp))[idx++]) = sbyte(sval, 0)
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate #define	gbyte(x, byte)	((((ulong_t)(x)) & 0xff) << (byte * 8))
172*7c478bd9Sstevel@tonic-gate #define	gbit(lv, in, idx, shft, mask)	lv = ((in[idx] >> shft) & mask)
173*7c478bd9Sstevel@tonic-gate #define	sget8(inp, idx, lval)	lval = (((uchar_t *)(inp))[idx++])
174*7c478bd9Sstevel@tonic-gate #define	gget8(inp, idx, lval)	lval = (((uchar_t *)(inp))[idx])
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate #define	sget16(inp, idx, lval)	\
177*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 1) | \
178*7c478bd9Sstevel@tonic-gate 		(((uchar_t *)(inp))[idx+1]), idx += 2
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate #define	gget16(inp, idx, lval)	\
181*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 1) | \
182*7c478bd9Sstevel@tonic-gate 		(((uchar_t *)(inp))[idx+1])
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate #define	sget24(inp, idx, lval)	\
185*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 2) | \
186*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+1]), 1) | \
187*7c478bd9Sstevel@tonic-gate 			(((uchar_t *)(inp))[idx+2]), idx += 3
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate #define	gget24(inp, idx, lval)	\
190*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 2) | \
191*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+1]), 1) | \
192*7c478bd9Sstevel@tonic-gate 			(((uchar_t *)(inp))[idx+2])
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate #define	sget32(inp, idx, lval)	\
195*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 3) | \
196*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+1]), 2) | \
197*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+2]), 1) | \
198*7c478bd9Sstevel@tonic-gate 			(((uchar_t *)(inp))[idx+3]), idx += 4
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate #define	gget32(inp, idx, lval)	\
201*7c478bd9Sstevel@tonic-gate 	lval = gbyte((((uchar_t *)(inp))[idx]), 3) | \
202*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+1]), 2) | \
203*7c478bd9Sstevel@tonic-gate 		gbyte((((uchar_t *)(inp))[idx+2]), 1) | \
204*7c478bd9Sstevel@tonic-gate 			(((uchar_t *)(inp))[idx+3])
205*7c478bd9Sstevel@tonic-gate #define	skip8(idx)	idx += 1
206*7c478bd9Sstevel@tonic-gate #define	skip16(idx)	idx += 2
207*7c478bd9Sstevel@tonic-gate #define	skip24(idx)	idx += 3
208*7c478bd9Sstevel@tonic-gate #define	skip32(idx)	idx += 4
209*7c478bd9Sstevel@tonic-gate static int ses_cfghdr(uchar_t *, int, SesCfgHdr *);
210*7c478bd9Sstevel@tonic-gate static int ses_enchdr(uchar_t *, int, uchar_t, SesEncHdr *);
211*7c478bd9Sstevel@tonic-gate static int ses_encdesc(uchar_t *, int, uchar_t, SesEncDesc *);
212*7c478bd9Sstevel@tonic-gate static int ses_getthdr(uchar_t *, int,  int, SesThdr *);
213*7c478bd9Sstevel@tonic-gate static int ses_decode(char *, int, uchar_t *, int, int, SesComStat *);
214*7c478bd9Sstevel@tonic-gate static int ses_encode(char *, int, uchar_t *, int, int, SesComStat *);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate #define	SCSZ	0x4cc
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate static int
ses_getconfig(ses_softc_t * ssc)219*7c478bd9Sstevel@tonic-gate ses_getconfig(ses_softc_t *ssc)
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate 	struct sscfg *cc;
222*7c478bd9Sstevel@tonic-gate 	SesCfgHdr cf;
223*7c478bd9Sstevel@tonic-gate 	SesEncHdr hd;
224*7c478bd9Sstevel@tonic-gate 	SesEncDesc *cdp;
225*7c478bd9Sstevel@tonic-gate 	SesThdr thdr;
226*7c478bd9Sstevel@tonic-gate 	int err, amt, i, nobj, ntype, maxima;
227*7c478bd9Sstevel@tonic-gate 	Uscmd local, *lp = &local;
228*7c478bd9Sstevel@tonic-gate 	char storage[SCSZ], *sdata;
229*7c478bd9Sstevel@tonic-gate 	static char cdb[CDB_GROUP0] =
230*7c478bd9Sstevel@tonic-gate 	    { SCMD_GDIAG, 0x1, SesConfigPage, (char)(SCSZ >> 8),
231*7c478bd9Sstevel@tonic-gate 	    (char)(SCSZ & 0xff), 0 };
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	cc = ssc->ses_private;
234*7c478bd9Sstevel@tonic-gate 	if (cc == NULL) {
235*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	sdata = kmem_alloc(SCSZ, KM_SLEEP);
239*7c478bd9Sstevel@tonic-gate 	if (sdata == NULL)
240*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
243*7c478bd9Sstevel@tonic-gate 	lp->uscsi_timeout = ses_io_time;
244*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdb = cdb;
245*7c478bd9Sstevel@tonic-gate 	lp->uscsi_bufaddr = sdata;
246*7c478bd9Sstevel@tonic-gate 	lp->uscsi_buflen = SCSZ;
247*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdblen = sizeof (cdb);
248*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqbuf = storage;
249*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqlen = SENSE_LENGTH;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	err = ses_runcmd(ssc, lp);
252*7c478bd9Sstevel@tonic-gate 	if (err) {
253*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SCSZ);
254*7c478bd9Sstevel@tonic-gate 		return (err);
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 	amt = lp->uscsi_buflen - lp->uscsi_resid;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	if (ses_cfghdr((uchar_t *)sdata, amt, &cf)) {
259*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, CE_NOTE, "Unable to parse SES Config Header");
260*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SCSZ);
261*7c478bd9Sstevel@tonic-gate 		return (EIO);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 	if (amt < SES_ENCHDR_MINLEN) {
264*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, CE_NOTE, "runt enclosure length (%d)", amt);
265*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SCSZ);
266*7c478bd9Sstevel@tonic-gate 		return (EIO);
267*7c478bd9Sstevel@tonic-gate 	}
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	SES_LOG(ssc, SES_CE_DEBUG3, "GenCode %lx %d Subenclosures",
270*7c478bd9Sstevel@tonic-gate 	    cf.GenCode, cf.Nsubenc);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	/*
273*7c478bd9Sstevel@tonic-gate 	 * Now waltz through all the subenclosures toting up the
274*7c478bd9Sstevel@tonic-gate 	 * number of types available in each. For this, we only
275*7c478bd9Sstevel@tonic-gate 	 * really need the enclosure header. However, we get the
276*7c478bd9Sstevel@tonic-gate 	 * enclosure descriptor for debug purposes, as well
277*7c478bd9Sstevel@tonic-gate 	 * as self-consistency checking purposes.
278*7c478bd9Sstevel@tonic-gate 	 */
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	maxima = cf.Nsubenc + 1;
281*7c478bd9Sstevel@tonic-gate 	cdp = (SesEncDesc *) storage;
282*7c478bd9Sstevel@tonic-gate 	for (ntype = i = 0; i < maxima; i++) {
283*7c478bd9Sstevel@tonic-gate 		bzero((caddr_t)cdp, sizeof (*cdp));
284*7c478bd9Sstevel@tonic-gate 		if (ses_enchdr((uchar_t *)sdata, amt, i, &hd)) {
285*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, CE_NOTE,
286*7c478bd9Sstevel@tonic-gate 			    "Cannot Extract Enclosure Header %d", i);
287*7c478bd9Sstevel@tonic-gate 			kmem_free(sdata, SCSZ);
288*7c478bd9Sstevel@tonic-gate 			return (EIO);
289*7c478bd9Sstevel@tonic-gate 		}
290*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, SES_CE_DEBUG3,
291*7c478bd9Sstevel@tonic-gate 		    "\tSubEnclosure ID %d, %d Types With this ID, Enclosure "
292*7c478bd9Sstevel@tonic-gate 		    "Length %d\n", hd.Subencid, hd.Ntypes, hd.VEnclen);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		if (ses_encdesc((uchar_t *)sdata, amt, i, cdp)) {
295*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, CE_NOTE,
296*7c478bd9Sstevel@tonic-gate 			    "Cannot Extract Enclosure Descriptor %d", i);
297*7c478bd9Sstevel@tonic-gate 			kmem_free(sdata, SCSZ);
298*7c478bd9Sstevel@tonic-gate 			return (EIO);
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, SES_CE_DEBUG3,
302*7c478bd9Sstevel@tonic-gate 		    "\tWWN: %02x%02x%02x%02x%02x%02x%02x%02x", cdp->encWWN[0],
303*7c478bd9Sstevel@tonic-gate 		    cdp->encWWN[1], cdp->encWWN[2], cdp->encWWN[3],
304*7c478bd9Sstevel@tonic-gate 		    cdp->encWWN[4], cdp->encWWN[5], cdp->encWWN[6],
305*7c478bd9Sstevel@tonic-gate 		    cdp->encWWN[7]);
306*7c478bd9Sstevel@tonic-gate 		ntype += hd.Ntypes;
307*7c478bd9Sstevel@tonic-gate 	}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	/*
310*7c478bd9Sstevel@tonic-gate 	 * Now waltz through all the types that are available, getting
311*7c478bd9Sstevel@tonic-gate 	 * the type header so we can start adding up the number of
312*7c478bd9Sstevel@tonic-gate 	 * objects available.
313*7c478bd9Sstevel@tonic-gate 	 */
314*7c478bd9Sstevel@tonic-gate 	for (nobj = i = 0; i < ntype; i++) {
315*7c478bd9Sstevel@tonic-gate 		if (ses_getthdr((uchar_t *)sdata, amt, i, &thdr)) {
316*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, CE_NOTE,
317*7c478bd9Sstevel@tonic-gate 			    "Cannot Extract Enclosure Type Header %d", i);
318*7c478bd9Sstevel@tonic-gate 			kmem_free(sdata, SCSZ);
319*7c478bd9Sstevel@tonic-gate 			return (EIO);
320*7c478bd9Sstevel@tonic-gate 		}
321*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, SES_CE_DEBUG3,
322*7c478bd9Sstevel@tonic-gate 		    "\tType Desc[%d]: Type 0x%x, MaxElt %d, In Subenc %d, "
323*7c478bd9Sstevel@tonic-gate 		    "Text Length %d\n", i, thdr.enc_type, thdr.enc_maxelt,
324*7c478bd9Sstevel@tonic-gate 		    thdr.enc_subenc, thdr.enc_tlen);
325*7c478bd9Sstevel@tonic-gate 		nobj += thdr.enc_maxelt;
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	/*
330*7c478bd9Sstevel@tonic-gate 	 * Now allocate the object array and type map.
331*7c478bd9Sstevel@tonic-gate 	 */
332*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	ssc->ses_objmap = (encobj *)
336*7c478bd9Sstevel@tonic-gate 	    kmem_zalloc(nobj * sizeof (encobj), KM_SLEEP);
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	cc->ses_typidx = (struct typidx *)
339*7c478bd9Sstevel@tonic-gate 	    kmem_zalloc(nobj * sizeof (struct typidx), KM_SLEEP);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	cc->ses_eltmap = kmem_zalloc(ntype, KM_SLEEP);
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	if (ssc->ses_objmap == NULL || cc->ses_typidx == NULL ||
344*7c478bd9Sstevel@tonic-gate 	    cc->ses_eltmap == NULL) {
345*7c478bd9Sstevel@tonic-gate 		if (ssc->ses_objmap) {
346*7c478bd9Sstevel@tonic-gate 			kmem_free(ssc->ses_objmap, (nobj * sizeof (encobj)));
347*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap = NULL;
348*7c478bd9Sstevel@tonic-gate 		}
349*7c478bd9Sstevel@tonic-gate 		if (cc->ses_typidx) {
350*7c478bd9Sstevel@tonic-gate 			kmem_free(cc->ses_typidx,
351*7c478bd9Sstevel@tonic-gate 			    (nobj * sizeof (struct typidx)));
352*7c478bd9Sstevel@tonic-gate 			cc->ses_typidx = NULL;
353*7c478bd9Sstevel@tonic-gate 		}
354*7c478bd9Sstevel@tonic-gate 		if (cc->ses_eltmap) {
355*7c478bd9Sstevel@tonic-gate 			kmem_free(cc->ses_eltmap, ntype);
356*7c478bd9Sstevel@tonic-gate 			cc->ses_eltmap = NULL;
357*7c478bd9Sstevel@tonic-gate 		}
358*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
359*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SCSZ);
360*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
361*7c478bd9Sstevel@tonic-gate 	}
362*7c478bd9Sstevel@tonic-gate 	cc->ses_ntypes = (uchar_t)ntype;
363*7c478bd9Sstevel@tonic-gate 	ssc->ses_nobjects = nobj;
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	/*
366*7c478bd9Sstevel@tonic-gate 	 * Now waltz through the # of types again to fill in the types
367*7c478bd9Sstevel@tonic-gate 	 * (and subenclosure ids) of the allocated objects.
368*7c478bd9Sstevel@tonic-gate 	 */
369*7c478bd9Sstevel@tonic-gate 	nobj = 0;
370*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ntype; i++) {
371*7c478bd9Sstevel@tonic-gate 		int j;
372*7c478bd9Sstevel@tonic-gate 		if (ses_getthdr((uchar_t *)sdata, amt, i, &thdr)) {
373*7c478bd9Sstevel@tonic-gate 			continue;
374*7c478bd9Sstevel@tonic-gate 		}
375*7c478bd9Sstevel@tonic-gate 		cc->ses_eltmap[i] = thdr.enc_maxelt;
376*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < thdr.enc_maxelt; j++) {
377*7c478bd9Sstevel@tonic-gate 			cc->ses_typidx[nobj].ses_tidx = i;
378*7c478bd9Sstevel@tonic-gate 			cc->ses_typidx[nobj].ses_oidx = j;
379*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[nobj].subenclosure = thdr.enc_subenc;
380*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[nobj++].enctype = thdr.enc_type;
381*7c478bd9Sstevel@tonic-gate 		}
382*7c478bd9Sstevel@tonic-gate 	}
383*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
384*7c478bd9Sstevel@tonic-gate 	kmem_free(sdata, SCSZ);
385*7c478bd9Sstevel@tonic-gate 	return (0);
386*7c478bd9Sstevel@tonic-gate }
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate /*
389*7c478bd9Sstevel@tonic-gate  */
390*7c478bd9Sstevel@tonic-gate int
ses_softc_init(ses_softc_t * ssc,int doinit)391*7c478bd9Sstevel@tonic-gate ses_softc_init(ses_softc_t *ssc, int doinit)
392*7c478bd9Sstevel@tonic-gate {
393*7c478bd9Sstevel@tonic-gate 	if (doinit == 0) {
394*7c478bd9Sstevel@tonic-gate 		struct sscfg *cc;
395*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ssc->ses_devp->sd_mutex);
396*7c478bd9Sstevel@tonic-gate 		if (ssc->ses_nobjects) {
397*7c478bd9Sstevel@tonic-gate 			kmem_free(ssc->ses_objmap,
398*7c478bd9Sstevel@tonic-gate 			    ssc->ses_nobjects * sizeof (encobj));
399*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap = NULL;
400*7c478bd9Sstevel@tonic-gate 		}
401*7c478bd9Sstevel@tonic-gate 		if ((cc = ssc->ses_private) != NULL) {
402*7c478bd9Sstevel@tonic-gate 			if (cc->ses_eltmap && cc->ses_ntypes) {
403*7c478bd9Sstevel@tonic-gate 				kmem_free(cc->ses_eltmap, cc->ses_ntypes);
404*7c478bd9Sstevel@tonic-gate 				cc->ses_eltmap = NULL;
405*7c478bd9Sstevel@tonic-gate 				cc->ses_ntypes = 0;
406*7c478bd9Sstevel@tonic-gate 			}
407*7c478bd9Sstevel@tonic-gate 			if (cc->ses_typidx && ssc->ses_nobjects) {
408*7c478bd9Sstevel@tonic-gate 				kmem_free(cc->ses_typidx, ssc->ses_nobjects *
409*7c478bd9Sstevel@tonic-gate 				    sizeof (struct typidx));
410*7c478bd9Sstevel@tonic-gate 				cc->ses_typidx = NULL;
411*7c478bd9Sstevel@tonic-gate 			}
412*7c478bd9Sstevel@tonic-gate 			kmem_free(cc, sizeof (struct sscfg));
413*7c478bd9Sstevel@tonic-gate 			ssc->ses_private = NULL;
414*7c478bd9Sstevel@tonic-gate 		}
415*7c478bd9Sstevel@tonic-gate 		ssc->ses_nobjects = 0;
416*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
417*7c478bd9Sstevel@tonic-gate 		return (0);
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
420*7c478bd9Sstevel@tonic-gate 	if (ssc->ses_private == NULL) {
421*7c478bd9Sstevel@tonic-gate 		ssc->ses_private = kmem_zalloc(sizeof (struct sscfg), KM_SLEEP);
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate 	if (ssc->ses_private == NULL) {
424*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
425*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	ssc->ses_nobjects = 0;
428*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat = 0;
429*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
430*7c478bd9Sstevel@tonic-gate 	return (ses_getconfig(ssc));
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate int
ses_init_enc(ses_softc_t * ssc)434*7c478bd9Sstevel@tonic-gate ses_init_enc(ses_softc_t *ssc)
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate 	UNUSED_PARAMETER(ssc);
437*7c478bd9Sstevel@tonic-gate 	return (0);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate static int
ses_getputstat(ses_softc_t * ssc,int objid,SesComStat * sp,int slp,int in)441*7c478bd9Sstevel@tonic-gate ses_getputstat(ses_softc_t *ssc, int objid, SesComStat *sp, int slp, int in)
442*7c478bd9Sstevel@tonic-gate {
443*7c478bd9Sstevel@tonic-gate 	struct sscfg *cc;
444*7c478bd9Sstevel@tonic-gate 	int err, amt, bufsiz, tidx, oidx;
445*7c478bd9Sstevel@tonic-gate 	Uscmd local, *lp = &local;
446*7c478bd9Sstevel@tonic-gate 	char rqbuf[SENSE_LENGTH], *sdata;
447*7c478bd9Sstevel@tonic-gate 	char cdb[CDB_GROUP0];
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	cc = ssc->ses_private;
450*7c478bd9Sstevel@tonic-gate 	if (cc == NULL) {
451*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	/*
455*7c478bd9Sstevel@tonic-gate 	 * If we're just getting overall enclosure status,
456*7c478bd9Sstevel@tonic-gate 	 * we only need 2 bytes of data storage.
457*7c478bd9Sstevel@tonic-gate 	 *
458*7c478bd9Sstevel@tonic-gate 	 * If we're getting anything else, we know how much
459*7c478bd9Sstevel@tonic-gate 	 * storage we need by noting that starting at offset
460*7c478bd9Sstevel@tonic-gate 	 * 8 in returned data, all object status bytes are 4
461*7c478bd9Sstevel@tonic-gate 	 * bytes long, and are stored in chunks of types(M)
462*7c478bd9Sstevel@tonic-gate 	 * and nth+1 instances of type M.
463*7c478bd9Sstevel@tonic-gate 	 */
464*7c478bd9Sstevel@tonic-gate 	if (objid == -1) {
465*7c478bd9Sstevel@tonic-gate 		bufsiz = 2;
466*7c478bd9Sstevel@tonic-gate 	} else {
467*7c478bd9Sstevel@tonic-gate 		bufsiz = (ssc->ses_nobjects * 4) + (cc->ses_ntypes * 4) + 8;
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate 	cdb[0] = SCMD_GDIAG;
470*7c478bd9Sstevel@tonic-gate 	cdb[1] = 1;
471*7c478bd9Sstevel@tonic-gate 	cdb[2] = SesStatusPage;
472*7c478bd9Sstevel@tonic-gate 	cdb[3] = bufsiz >> 8;
473*7c478bd9Sstevel@tonic-gate 	cdb[4] = bufsiz & 0xff;
474*7c478bd9Sstevel@tonic-gate 	cdb[5] = 0;
475*7c478bd9Sstevel@tonic-gate 	sdata = kmem_alloc(bufsiz, slp);
476*7c478bd9Sstevel@tonic-gate 	if (sdata == NULL)
477*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
480*7c478bd9Sstevel@tonic-gate 	lp->uscsi_timeout = ses_io_time;
481*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdb = cdb;
482*7c478bd9Sstevel@tonic-gate 	lp->uscsi_bufaddr = sdata;
483*7c478bd9Sstevel@tonic-gate 	lp->uscsi_buflen = bufsiz;
484*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdblen = sizeof (cdb);
485*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqbuf = rqbuf;
486*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqlen = sizeof (rqbuf);
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	err = ses_runcmd(ssc, lp);
489*7c478bd9Sstevel@tonic-gate 	if (err) {
490*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, bufsiz);
491*7c478bd9Sstevel@tonic-gate 		return (err);
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 	amt = lp->uscsi_buflen - lp->uscsi_resid;
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	if (objid == -1) {
496*7c478bd9Sstevel@tonic-gate 		tidx = -1;
497*7c478bd9Sstevel@tonic-gate 		oidx = -1;
498*7c478bd9Sstevel@tonic-gate 	} else {
499*7c478bd9Sstevel@tonic-gate 		tidx = cc->ses_typidx[objid].ses_tidx;
500*7c478bd9Sstevel@tonic-gate 		oidx = cc->ses_typidx[objid].ses_oidx;
501*7c478bd9Sstevel@tonic-gate 	}
502*7c478bd9Sstevel@tonic-gate 	if (in) {
503*7c478bd9Sstevel@tonic-gate 		if (ses_decode(sdata, amt, cc->ses_eltmap, tidx, oidx, sp)) {
504*7c478bd9Sstevel@tonic-gate 			err = ENODEV;
505*7c478bd9Sstevel@tonic-gate 		}
506*7c478bd9Sstevel@tonic-gate 	} else {
507*7c478bd9Sstevel@tonic-gate 		if (ses_encode(sdata, amt, cc->ses_eltmap, tidx, oidx, sp)) {
508*7c478bd9Sstevel@tonic-gate 			err = ENODEV;
509*7c478bd9Sstevel@tonic-gate 		} else {
510*7c478bd9Sstevel@tonic-gate 			cdb[0] = SCMD_SDIAG;
511*7c478bd9Sstevel@tonic-gate 			cdb[1] = 0x10;
512*7c478bd9Sstevel@tonic-gate 			cdb[2] = 0;
513*7c478bd9Sstevel@tonic-gate 			cdb[3] = bufsiz >> 8;
514*7c478bd9Sstevel@tonic-gate 			cdb[4] = bufsiz & 0xff;
515*7c478bd9Sstevel@tonic-gate 			cdb[5] = 0;
516*7c478bd9Sstevel@tonic-gate 			lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
517*7c478bd9Sstevel@tonic-gate 			lp->uscsi_timeout = ses_io_time;
518*7c478bd9Sstevel@tonic-gate 			lp->uscsi_cdb = cdb;
519*7c478bd9Sstevel@tonic-gate 			lp->uscsi_bufaddr = sdata;
520*7c478bd9Sstevel@tonic-gate 			lp->uscsi_buflen = bufsiz;
521*7c478bd9Sstevel@tonic-gate 			lp->uscsi_cdblen = sizeof (cdb);
522*7c478bd9Sstevel@tonic-gate 			lp->uscsi_rqbuf = rqbuf;
523*7c478bd9Sstevel@tonic-gate 			lp->uscsi_rqlen = sizeof (rqbuf);
524*7c478bd9Sstevel@tonic-gate 			err = ses_runcmd(ssc, lp);
525*7c478bd9Sstevel@tonic-gate 		}
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate 	kmem_free(sdata, bufsiz);
528*7c478bd9Sstevel@tonic-gate 	return (0);
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate int
ses_get_encstat(ses_softc_t * ssc,int slpflag)532*7c478bd9Sstevel@tonic-gate ses_get_encstat(ses_softc_t *ssc, int slpflag)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate 	SesComStat s;
535*7c478bd9Sstevel@tonic-gate 	int r;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	if ((r = ses_getputstat(ssc, -1, &s, slpflag, 1)) != 0) {
538*7c478bd9Sstevel@tonic-gate 		return (r);
539*7c478bd9Sstevel@tonic-gate 	}
540*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
541*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat = s.comstatus | ENCI_SVALID;
542*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
543*7c478bd9Sstevel@tonic-gate 	return (0);
544*7c478bd9Sstevel@tonic-gate }
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate int
ses_set_encstat(ses_softc_t * ssc,uchar_t encstat,int slpflag)547*7c478bd9Sstevel@tonic-gate ses_set_encstat(ses_softc_t *ssc, uchar_t encstat, int slpflag)
548*7c478bd9Sstevel@tonic-gate {
549*7c478bd9Sstevel@tonic-gate 	SesComStat s;
550*7c478bd9Sstevel@tonic-gate 	int r;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	s.comstatus = encstat & 0xf;
553*7c478bd9Sstevel@tonic-gate 	if ((r = ses_getputstat(ssc, -1, &s, slpflag, 0)) != 0) {
554*7c478bd9Sstevel@tonic-gate 		return (r);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
557*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat = encstat & 0xf;	/* note no SVALID set */
558*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
559*7c478bd9Sstevel@tonic-gate 	return (0);
560*7c478bd9Sstevel@tonic-gate }
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate int
ses_get_objstat(ses_softc_t * ssc,ses_objarg * obp,int slpflag)563*7c478bd9Sstevel@tonic-gate ses_get_objstat(ses_softc_t *ssc, ses_objarg *obp, int slpflag)
564*7c478bd9Sstevel@tonic-gate {
565*7c478bd9Sstevel@tonic-gate 	int i = (int)obp->obj_id;
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	if (ssc->ses_objmap[i].svalid == 0) {
568*7c478bd9Sstevel@tonic-gate 		SesComStat s;
569*7c478bd9Sstevel@tonic-gate 		int r = ses_getputstat(ssc, i, &s, slpflag, 1);
570*7c478bd9Sstevel@tonic-gate 		if (r)
571*7c478bd9Sstevel@tonic-gate 			return (r);
572*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ssc->ses_devp->sd_mutex);
573*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].encstat[0] = s.comstatus;
574*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].encstat[1] = s.comstat[0];
575*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].encstat[2] = s.comstat[1];
576*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].encstat[3] = s.comstat[2];
577*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].svalid = 1;
578*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
579*7c478bd9Sstevel@tonic-gate 	}
580*7c478bd9Sstevel@tonic-gate 	obp->cstat[0] = ssc->ses_objmap[i].encstat[0];
581*7c478bd9Sstevel@tonic-gate 	obp->cstat[1] = ssc->ses_objmap[i].encstat[1];
582*7c478bd9Sstevel@tonic-gate 	obp->cstat[2] = ssc->ses_objmap[i].encstat[2];
583*7c478bd9Sstevel@tonic-gate 	obp->cstat[3] = ssc->ses_objmap[i].encstat[3];
584*7c478bd9Sstevel@tonic-gate 	return (0);
585*7c478bd9Sstevel@tonic-gate }
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate int
ses_set_objstat(ses_softc_t * ssc,ses_objarg * obp,int slpflag)588*7c478bd9Sstevel@tonic-gate ses_set_objstat(ses_softc_t *ssc, ses_objarg *obp, int slpflag)
589*7c478bd9Sstevel@tonic-gate {
590*7c478bd9Sstevel@tonic-gate 	SesComStat s;
591*7c478bd9Sstevel@tonic-gate 	int r, i;
592*7c478bd9Sstevel@tonic-gate 	/*
593*7c478bd9Sstevel@tonic-gate 	 * If this is clear, we don't do diddly.
594*7c478bd9Sstevel@tonic-gate 	 */
595*7c478bd9Sstevel@tonic-gate 	if ((obp->cstat[0] & SESCTL_CSEL) == 0) {
596*7c478bd9Sstevel@tonic-gate 		return (0);
597*7c478bd9Sstevel@tonic-gate 	}
598*7c478bd9Sstevel@tonic-gate 	s.comstatus = obp->cstat[0];
599*7c478bd9Sstevel@tonic-gate 	s.comstat[0] = obp->cstat[1];
600*7c478bd9Sstevel@tonic-gate 	s.comstat[1] = obp->cstat[2];
601*7c478bd9Sstevel@tonic-gate 	s.comstat[2] = obp->cstat[3];
602*7c478bd9Sstevel@tonic-gate 	i = (int)obp->obj_id;
603*7c478bd9Sstevel@tonic-gate 	r = ses_getputstat(ssc, i, &s, slpflag, 0);
604*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
605*7c478bd9Sstevel@tonic-gate 	ssc->ses_objmap[i].svalid = 0;
606*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
607*7c478bd9Sstevel@tonic-gate 	return (r);
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate /*
611*7c478bd9Sstevel@tonic-gate  * Routines to parse returned SES data structures.
612*7c478bd9Sstevel@tonic-gate  * Architecture and compiler independent.
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate static int
ses_cfghdr(uchar_t * buffer,int buflen,SesCfgHdr * cfp)616*7c478bd9Sstevel@tonic-gate ses_cfghdr(uchar_t *buffer, int buflen, SesCfgHdr *cfp)
617*7c478bd9Sstevel@tonic-gate {
618*7c478bd9Sstevel@tonic-gate 	if (buflen < SES_CFGHDR_MINLEN)
619*7c478bd9Sstevel@tonic-gate 		return (-1);
620*7c478bd9Sstevel@tonic-gate 	gget8(buffer, 1, cfp->Nsubenc);
621*7c478bd9Sstevel@tonic-gate 	gget32(buffer, 4, cfp->GenCode);
622*7c478bd9Sstevel@tonic-gate 	return (0);
623*7c478bd9Sstevel@tonic-gate }
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate static int
ses_enchdr(uchar_t * buffer,int amt,uchar_t SubEncId,SesEncHdr * chp)626*7c478bd9Sstevel@tonic-gate ses_enchdr(uchar_t *buffer, int amt, uchar_t SubEncId, SesEncHdr *chp)
627*7c478bd9Sstevel@tonic-gate {
628*7c478bd9Sstevel@tonic-gate 	int s, off = 8;
629*7c478bd9Sstevel@tonic-gate 	for (s = 0; s < SubEncId; s++) {
630*7c478bd9Sstevel@tonic-gate 		if (off + 3 > amt)
631*7c478bd9Sstevel@tonic-gate 			return (-1);
632*7c478bd9Sstevel@tonic-gate 		off += buffer[off+3] + 4;
633*7c478bd9Sstevel@tonic-gate 	}
634*7c478bd9Sstevel@tonic-gate 	if (off + 3 > amt) {
635*7c478bd9Sstevel@tonic-gate 		return (-1);
636*7c478bd9Sstevel@tonic-gate 	}
637*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off+1, chp->Subencid);
638*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off+2, chp->Ntypes);
639*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off+3, chp->VEnclen);
640*7c478bd9Sstevel@tonic-gate 	return (0);
641*7c478bd9Sstevel@tonic-gate }
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate static int
ses_encdesc(uchar_t * buffer,int amt,uchar_t SubEncId,SesEncDesc * cdp)644*7c478bd9Sstevel@tonic-gate ses_encdesc(uchar_t *buffer, int amt, uchar_t SubEncId, SesEncDesc *cdp)
645*7c478bd9Sstevel@tonic-gate {
646*7c478bd9Sstevel@tonic-gate 	int s, e, enclen, off = 8;
647*7c478bd9Sstevel@tonic-gate 	for (s = 0; s < SubEncId; s++) {
648*7c478bd9Sstevel@tonic-gate 		if (off + 3 > amt)
649*7c478bd9Sstevel@tonic-gate 			return (-1);
650*7c478bd9Sstevel@tonic-gate 		off += buffer[off+3] + 4;
651*7c478bd9Sstevel@tonic-gate 	}
652*7c478bd9Sstevel@tonic-gate 	if (off + 3 > amt) {
653*7c478bd9Sstevel@tonic-gate 		return (-1);
654*7c478bd9Sstevel@tonic-gate 	}
655*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off+3, enclen);
656*7c478bd9Sstevel@tonic-gate 	off += 4;
657*7c478bd9Sstevel@tonic-gate 	if (off  >= amt)
658*7c478bd9Sstevel@tonic-gate 		return (-1);
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	e = off + enclen;
661*7c478bd9Sstevel@tonic-gate 	if (e > amt) {
662*7c478bd9Sstevel@tonic-gate 		e = amt;
663*7c478bd9Sstevel@tonic-gate 	}
664*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&buffer[off], (caddr_t)cdp, e - off);
665*7c478bd9Sstevel@tonic-gate 	return (0);
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate static int
ses_getthdr(uchar_t * buffer,int amt,int nth,SesThdr * thp)669*7c478bd9Sstevel@tonic-gate ses_getthdr(uchar_t *buffer, int amt, int nth, SesThdr *thp)
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate 	int s, off = 8;
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	if (amt < SES_CFGHDR_MINLEN) {
674*7c478bd9Sstevel@tonic-gate 		return (-1);
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 	for (s = 0; s < buffer[1]; s++) {
677*7c478bd9Sstevel@tonic-gate 		if (off + 3 > amt)
678*7c478bd9Sstevel@tonic-gate 			return (-1);
679*7c478bd9Sstevel@tonic-gate 		off += buffer[off+3] + 4;
680*7c478bd9Sstevel@tonic-gate 	}
681*7c478bd9Sstevel@tonic-gate 	if (off + 3 > amt) {
682*7c478bd9Sstevel@tonic-gate 		return (-1);
683*7c478bd9Sstevel@tonic-gate 	}
684*7c478bd9Sstevel@tonic-gate 	off += buffer[off+3] + 4 + (nth * 4);
685*7c478bd9Sstevel@tonic-gate 	if (amt < (off + 4))
686*7c478bd9Sstevel@tonic-gate 		return (-1);
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off++, thp->enc_type);
689*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off++, thp->enc_maxelt);
690*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off++, thp->enc_subenc);
691*7c478bd9Sstevel@tonic-gate 	gget8(buffer, off, thp->enc_tlen);
692*7c478bd9Sstevel@tonic-gate 	return (0);
693*7c478bd9Sstevel@tonic-gate }
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate /*
696*7c478bd9Sstevel@tonic-gate  * This function needs a little explanation.
697*7c478bd9Sstevel@tonic-gate  *
698*7c478bd9Sstevel@tonic-gate  * The arguments are:
699*7c478bd9Sstevel@tonic-gate  *
700*7c478bd9Sstevel@tonic-gate  *
701*7c478bd9Sstevel@tonic-gate  *	char *b, int amt
702*7c478bd9Sstevel@tonic-gate  *
703*7c478bd9Sstevel@tonic-gate  *		These describes the raw input SES status data and length.
704*7c478bd9Sstevel@tonic-gate  *
705*7c478bd9Sstevel@tonic-gate  *	uchar_t *ep
706*7c478bd9Sstevel@tonic-gate  *
707*7c478bd9Sstevel@tonic-gate  *		This is a map of the number of types for each element type
708*7c478bd9Sstevel@tonic-gate  *		in the enclosure.
709*7c478bd9Sstevel@tonic-gate  *
710*7c478bd9Sstevel@tonic-gate  *	int elt
711*7c478bd9Sstevel@tonic-gate  *
712*7c478bd9Sstevel@tonic-gate  *		This is the element type being sought. If elt is -1,
713*7c478bd9Sstevel@tonic-gate  *		then overal enclosure status is being sought.
714*7c478bd9Sstevel@tonic-gate  *
715*7c478bd9Sstevel@tonic-gate  *	int elm
716*7c478bd9Sstevel@tonic-gate  *
717*7c478bd9Sstevel@tonic-gate  *		This is the ordinal Mth element of type elt being sought.
718*7c478bd9Sstevel@tonic-gate  *
719*7c478bd9Sstevel@tonic-gate  *	SesComStat *sp
720*7c478bd9Sstevel@tonic-gate  *
721*7c478bd9Sstevel@tonic-gate  *		This is the output area to store the status for
722*7c478bd9Sstevel@tonic-gate  *		the Mth element of type Elt.
723*7c478bd9Sstevel@tonic-gate  */
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate static int
ses_decode(char * b,int amt,uchar_t * ep,int elt,int elm,SesComStat * sp)726*7c478bd9Sstevel@tonic-gate ses_decode(char *b, int amt, uchar_t *ep, int elt, int elm, SesComStat *sp)
727*7c478bd9Sstevel@tonic-gate {
728*7c478bd9Sstevel@tonic-gate 	int idx, i;
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	/*
731*7c478bd9Sstevel@tonic-gate 	 * If it's overall enclosure status being sought, get that.
732*7c478bd9Sstevel@tonic-gate 	 * We need at least 2 bytes of status data to get that.
733*7c478bd9Sstevel@tonic-gate 	 */
734*7c478bd9Sstevel@tonic-gate 	if (elt == -1) {
735*7c478bd9Sstevel@tonic-gate 		if (amt < 2)
736*7c478bd9Sstevel@tonic-gate 			return (-1);
737*7c478bd9Sstevel@tonic-gate 		gget8(b, 1, sp->comstatus);
738*7c478bd9Sstevel@tonic-gate 		sp->comstat[0] = 0;
739*7c478bd9Sstevel@tonic-gate 		sp->comstat[1] = 0;
740*7c478bd9Sstevel@tonic-gate 		sp->comstat[2] = 0;
741*7c478bd9Sstevel@tonic-gate 		return (0);
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate 	/*
745*7c478bd9Sstevel@tonic-gate 	 * Check to make sure that the Mth element is legal for type Elt.
746*7c478bd9Sstevel@tonic-gate 	 */
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	if (elm >= ep[elt])
749*7c478bd9Sstevel@tonic-gate 		return (-1);
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	/*
752*7c478bd9Sstevel@tonic-gate 	 * Starting at offset 8, start skipping over the storage
753*7c478bd9Sstevel@tonic-gate 	 * for the element types we're not interested in.
754*7c478bd9Sstevel@tonic-gate 	 */
755*7c478bd9Sstevel@tonic-gate 	for (idx = 8, i = 0; i < elt; i++) {
756*7c478bd9Sstevel@tonic-gate 		idx += ((ep[i] + 1) * 4);
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 	/*
760*7c478bd9Sstevel@tonic-gate 	 * Skip over Overall status for this element type.
761*7c478bd9Sstevel@tonic-gate 	 */
762*7c478bd9Sstevel@tonic-gate 	idx += 4;
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate 	/*
765*7c478bd9Sstevel@tonic-gate 	 * And skip to the index for the Mth element that we're going for.
766*7c478bd9Sstevel@tonic-gate 	 */
767*7c478bd9Sstevel@tonic-gate 	idx += (4 * elm);
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	/*
770*7c478bd9Sstevel@tonic-gate 	 * Make sure we haven't overflowed the buffer.
771*7c478bd9Sstevel@tonic-gate 	 */
772*7c478bd9Sstevel@tonic-gate 	if (idx+4 > amt)
773*7c478bd9Sstevel@tonic-gate 		return (-1);
774*7c478bd9Sstevel@tonic-gate 	/*
775*7c478bd9Sstevel@tonic-gate 	 * Retrieve the status.
776*7c478bd9Sstevel@tonic-gate 	 */
777*7c478bd9Sstevel@tonic-gate 	gget8(b, idx++, sp->comstatus);
778*7c478bd9Sstevel@tonic-gate 	gget8(b, idx++, sp->comstat[0]);
779*7c478bd9Sstevel@tonic-gate 	gget8(b, idx++, sp->comstat[1]);
780*7c478bd9Sstevel@tonic-gate 	gget8(b, idx++, sp->comstat[2]);
781*7c478bd9Sstevel@tonic-gate 	SES_LOG(NULL, SES_CE_DEBUG5, "Get Elt 0x%x Elm 0x%x (idx %d)",
782*7c478bd9Sstevel@tonic-gate 	    elt, elm, idx-4);
783*7c478bd9Sstevel@tonic-gate 	return (0);
784*7c478bd9Sstevel@tonic-gate }
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate /*
787*7c478bd9Sstevel@tonic-gate  * This is the mirror function to ses_decode, but we set the 'select'
788*7c478bd9Sstevel@tonic-gate  * bit for the object which we're interested in. All other objects,
789*7c478bd9Sstevel@tonic-gate  * after a status fetch, should have that bit off. Hmm. It'd be easy
790*7c478bd9Sstevel@tonic-gate  * enough to ensure this, so we will.
791*7c478bd9Sstevel@tonic-gate  */
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate static int
ses_encode(char * b,int amt,uchar_t * ep,int elt,int elm,SesComStat * sp)794*7c478bd9Sstevel@tonic-gate ses_encode(char *b, int amt, uchar_t *ep, int elt, int elm, SesComStat *sp)
795*7c478bd9Sstevel@tonic-gate {
796*7c478bd9Sstevel@tonic-gate 	int idx, i;
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 	/*
799*7c478bd9Sstevel@tonic-gate 	 * If it's overall enclosure status being sought, get that.
800*7c478bd9Sstevel@tonic-gate 	 * We need at least 2 bytes of status data to get that.
801*7c478bd9Sstevel@tonic-gate 	 */
802*7c478bd9Sstevel@tonic-gate 	if (elt == -1) {
803*7c478bd9Sstevel@tonic-gate 		if (amt < 2)
804*7c478bd9Sstevel@tonic-gate 			return (-1);
805*7c478bd9Sstevel@tonic-gate 		i = 0;
806*7c478bd9Sstevel@tonic-gate 		sset8(b, i, 0);
807*7c478bd9Sstevel@tonic-gate 		sset8(b, i, sp->comstatus & 0xf);
808*7c478bd9Sstevel@tonic-gate 		SES_LOG(NULL, SES_CE_DEBUG5, "set EncStat %x", sp->comstatus);
809*7c478bd9Sstevel@tonic-gate 		return (0);
810*7c478bd9Sstevel@tonic-gate 	}
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 	/*
813*7c478bd9Sstevel@tonic-gate 	 * Check to make sure that the Mth element is legal for type Elt.
814*7c478bd9Sstevel@tonic-gate 	 */
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 	if (elm >= ep[elt])
817*7c478bd9Sstevel@tonic-gate 		return (-1);
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	/*
820*7c478bd9Sstevel@tonic-gate 	 * Starting at offset 8, start skipping over the storage
821*7c478bd9Sstevel@tonic-gate 	 * for the element types we're not interested in.
822*7c478bd9Sstevel@tonic-gate 	 */
823*7c478bd9Sstevel@tonic-gate 	for (idx = 8, i = 0; i < elt; i++) {
824*7c478bd9Sstevel@tonic-gate 		idx += ((ep[i] + 1) * 4);
825*7c478bd9Sstevel@tonic-gate 	}
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	/*
828*7c478bd9Sstevel@tonic-gate 	 * Skip over Overall status for this element type.
829*7c478bd9Sstevel@tonic-gate 	 */
830*7c478bd9Sstevel@tonic-gate 	idx += 4;
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	/*
833*7c478bd9Sstevel@tonic-gate 	 * And skip to the index for the Mth element that we're going for.
834*7c478bd9Sstevel@tonic-gate 	 */
835*7c478bd9Sstevel@tonic-gate 	idx += (4 * elm);
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	/*
838*7c478bd9Sstevel@tonic-gate 	 * Make sure we haven't overflowed the buffer.
839*7c478bd9Sstevel@tonic-gate 	 */
840*7c478bd9Sstevel@tonic-gate 	if (idx+4 > amt)
841*7c478bd9Sstevel@tonic-gate 		return (-1);
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 	/*
844*7c478bd9Sstevel@tonic-gate 	 * Set the status.
845*7c478bd9Sstevel@tonic-gate 	 */
846*7c478bd9Sstevel@tonic-gate 	sset8(b, idx, sp->comstatus);
847*7c478bd9Sstevel@tonic-gate 	sset8(b, idx, sp->comstat[0]);
848*7c478bd9Sstevel@tonic-gate 	sset8(b, idx, sp->comstat[1]);
849*7c478bd9Sstevel@tonic-gate 	sset8(b, idx, sp->comstat[2]);
850*7c478bd9Sstevel@tonic-gate 	idx -= 4;
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate 	SES_LOG(NULL, SES_CE_DEBUG2, "Set Elt 0x%x Elm 0x%x (idx %d) with "
853*7c478bd9Sstevel@tonic-gate 	    "%x %x %x %x", elt, elm, idx, sp->comstatus, sp->comstat[0],
854*7c478bd9Sstevel@tonic-gate 	    sp->comstat[1], sp->comstat[2]);
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 	/*
857*7c478bd9Sstevel@tonic-gate 	 * Now make sure all other 'Select' bits are off.
858*7c478bd9Sstevel@tonic-gate 	 */
859*7c478bd9Sstevel@tonic-gate 	for (i = 8; i < amt; i += 4) {
860*7c478bd9Sstevel@tonic-gate 		if (i != idx)
861*7c478bd9Sstevel@tonic-gate 			b[i] &= ~0x80;
862*7c478bd9Sstevel@tonic-gate 	}
863*7c478bd9Sstevel@tonic-gate 	/*
864*7c478bd9Sstevel@tonic-gate 	 * And make sure the INVOP bit is clear.
865*7c478bd9Sstevel@tonic-gate 	 */
866*7c478bd9Sstevel@tonic-gate 	b[1] &= ~INVOP;
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 	return (0);
869*7c478bd9Sstevel@tonic-gate }
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate /*
872*7c478bd9Sstevel@tonic-gate  * mode: c
873*7c478bd9Sstevel@tonic-gate  * Local variables:
874*7c478bd9Sstevel@tonic-gate  * c-indent-level: 8
875*7c478bd9Sstevel@tonic-gate  * c-brace-imaginary-offset: 0
876*7c478bd9Sstevel@tonic-gate  * c-brace-offset: -8
877*7c478bd9Sstevel@tonic-gate  * c-argdecl-indent: 8
878*7c478bd9Sstevel@tonic-gate  * c-label-offset: -8
879*7c478bd9Sstevel@tonic-gate  * c-continued-statement-offset: 8
880*7c478bd9Sstevel@tonic-gate  * c-continued-brace-offset: 0
881*7c478bd9Sstevel@tonic-gate  * End:
882*7c478bd9Sstevel@tonic-gate  */
883