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