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