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 * Enclosure Services Devices, SAF-TE Enclosure Routines
24*0Sstevel@tonic-gate *
25*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
26*0Sstevel@tonic-gate * Use is subject to license terms.
27*0Sstevel@tonic-gate */
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate #include <sys/modctl.h>
32*0Sstevel@tonic-gate #include <sys/file.h>
33*0Sstevel@tonic-gate #include <sys/scsi/scsi.h>
34*0Sstevel@tonic-gate #include <sys/stat.h>
35*0Sstevel@tonic-gate #include <sys/scsi/targets/sesio.h>
36*0Sstevel@tonic-gate #include <sys/scsi/targets/ses.h>
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate static int set_objstat_sel(ses_softc_t *, ses_objarg *, int);
40*0Sstevel@tonic-gate static int wrbuf16(ses_softc_t *, uchar_t, uchar_t, uchar_t, uchar_t, int);
41*0Sstevel@tonic-gate static void wrslot_stat(ses_softc_t *, int);
42*0Sstevel@tonic-gate static int perf_slotop(ses_softc_t *, uchar_t, uchar_t, int);
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate #define ALL_ENC_STAT \
45*0Sstevel@tonic-gate (ENCSTAT_CRITICAL|ENCSTAT_UNRECOV|ENCSTAT_NONCRITICAL|ENCSTAT_INFO)
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate #define SCRATCH 64
48*0Sstevel@tonic-gate #define NPSEUDO_THERM 1
49*0Sstevel@tonic-gate #define NPSEUDO_ALARM 1
50*0Sstevel@tonic-gate struct scfg {
51*0Sstevel@tonic-gate /*
52*0Sstevel@tonic-gate * Cached Configuration
53*0Sstevel@tonic-gate */
54*0Sstevel@tonic-gate uchar_t Nfans; /* Number of Fans */
55*0Sstevel@tonic-gate uchar_t Npwr; /* Number of Power Supplies */
56*0Sstevel@tonic-gate uchar_t Nslots; /* Number of Device Slots */
57*0Sstevel@tonic-gate uchar_t DoorLock; /* Door Lock Installed */
58*0Sstevel@tonic-gate uchar_t Ntherm; /* Number of Temperature Sensors */
59*0Sstevel@tonic-gate uchar_t Nspkrs; /* Number of Speakers */
60*0Sstevel@tonic-gate uchar_t Nalarm; /* Number of Alarms (at least one) */
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate * Cached Flag Bytes for Global Status
63*0Sstevel@tonic-gate */
64*0Sstevel@tonic-gate uchar_t flag1;
65*0Sstevel@tonic-gate uchar_t flag2;
66*0Sstevel@tonic-gate /*
67*0Sstevel@tonic-gate * What object index ID is where various slots start.
68*0Sstevel@tonic-gate */
69*0Sstevel@tonic-gate uchar_t pwroff;
70*0Sstevel@tonic-gate uchar_t slotoff;
71*0Sstevel@tonic-gate #define ALARM_OFFSET(cc) (cc)->slotoff - 1
72*0Sstevel@tonic-gate };
73*0Sstevel@tonic-gate #define FLG1_ALARM 0x1
74*0Sstevel@tonic-gate #define FLG1_GLOBFAIL 0x2
75*0Sstevel@tonic-gate #define FLG1_GLOBWARN 0x4
76*0Sstevel@tonic-gate #define FLG1_ENCPWROFF 0x8
77*0Sstevel@tonic-gate #define FLG1_ENCFANFAIL 0x10
78*0Sstevel@tonic-gate #define FLG1_ENCPWRFAIL 0x20
79*0Sstevel@tonic-gate #define FLG1_ENCDRVFAIL 0x40
80*0Sstevel@tonic-gate #define FLG1_ENCDRVWARN 0x80
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gate #define FLG2_LOCKDOOR 0x4
83*0Sstevel@tonic-gate #define SAFTE_PRIVATE sizeof (struct scfg)
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate #if !defined(lint)
86*0Sstevel@tonic-gate _NOTE(MUTEX_PROTECTS_DATA(scsi_device::sd_mutex, scfg))
_NOTE(DATA_READABLE_WITHOUT_LOCK (scfg::Nfans))87*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Nfans))
88*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Npwr))
89*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Nslots))
90*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::DoorLock))
91*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Ntherm))
92*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Nspkrs))
93*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::Nalarm))
94*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::flag1))
95*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::flag2))
96*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::pwroff))
97*0Sstevel@tonic-gate _NOTE(DATA_READABLE_WITHOUT_LOCK(scfg::slotoff))
98*0Sstevel@tonic-gate #endif
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate static int
101*0Sstevel@tonic-gate safte_getconfig(ses_softc_t *ssc)
102*0Sstevel@tonic-gate {
103*0Sstevel@tonic-gate struct scfg *cfg;
104*0Sstevel@tonic-gate int err;
105*0Sstevel@tonic-gate Uscmd local, *lp = &local;
106*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], *sdata;
107*0Sstevel@tonic-gate static char cdb[CDB_GROUP1] =
108*0Sstevel@tonic-gate { SCMD_READ_BUFFER, 1, SAFTE_RD_RDCFG, 0, 0, 0, 0, 0, SCRATCH, 0 };
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate cfg = ssc->ses_private;
111*0Sstevel@tonic-gate if (cfg == NULL)
112*0Sstevel@tonic-gate return (ENXIO);
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gate sdata = kmem_alloc(SCRATCH, KM_SLEEP);
115*0Sstevel@tonic-gate if (sdata == NULL)
116*0Sstevel@tonic-gate return (ENOMEM);
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
119*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
120*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
121*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
122*0Sstevel@tonic-gate lp->uscsi_buflen = SCRATCH;
123*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
124*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
125*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
128*0Sstevel@tonic-gate if (err) {
129*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
130*0Sstevel@tonic-gate return (err);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate if ((lp->uscsi_buflen - lp->uscsi_resid) < 6) {
134*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "Too little data (%ld) for configuration",
135*0Sstevel@tonic-gate lp->uscsi_buflen - lp->uscsi_resid);
136*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
137*0Sstevel@tonic-gate return (EIO);
138*0Sstevel@tonic-gate }
139*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm "
140*0Sstevel@tonic-gate "%d Nspkrs %d", sdata[0], sdata[1], sdata[2], sdata[3], sdata[4],
141*0Sstevel@tonic-gate sdata[5]);
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
144*0Sstevel@tonic-gate cfg->Nfans = sdata[0];
145*0Sstevel@tonic-gate cfg->Npwr = sdata[1];
146*0Sstevel@tonic-gate cfg->Nslots = sdata[2];
147*0Sstevel@tonic-gate cfg->DoorLock = sdata[3];
148*0Sstevel@tonic-gate cfg->Ntherm = sdata[4];
149*0Sstevel@tonic-gate cfg->Nspkrs = sdata[5];
150*0Sstevel@tonic-gate cfg->Nalarm = NPSEUDO_ALARM;
151*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
152*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
153*0Sstevel@tonic-gate return (0);
154*0Sstevel@tonic-gate }
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate int
safte_softc_init(ses_softc_t * ssc,int doinit)157*0Sstevel@tonic-gate safte_softc_init(ses_softc_t *ssc, int doinit)
158*0Sstevel@tonic-gate {
159*0Sstevel@tonic-gate int r, i;
160*0Sstevel@tonic-gate struct scfg *cc;
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gate if (doinit == 0) {
163*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
164*0Sstevel@tonic-gate if (ssc->ses_nobjects) {
165*0Sstevel@tonic-gate if (ssc->ses_objmap) {
166*0Sstevel@tonic-gate kmem_free(ssc->ses_objmap,
167*0Sstevel@tonic-gate ssc->ses_nobjects * sizeof (encobj));
168*0Sstevel@tonic-gate ssc->ses_objmap = NULL;
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate ssc->ses_nobjects = 0;
171*0Sstevel@tonic-gate }
172*0Sstevel@tonic-gate if (ssc->ses_private) {
173*0Sstevel@tonic-gate kmem_free(ssc->ses_private, SAFTE_PRIVATE);
174*0Sstevel@tonic-gate ssc->ses_private = NULL;
175*0Sstevel@tonic-gate }
176*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
177*0Sstevel@tonic-gate return (0);
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
181*0Sstevel@tonic-gate if (ssc->ses_private == NULL) {
182*0Sstevel@tonic-gate ssc->ses_private = kmem_zalloc(SAFTE_PRIVATE, KM_SLEEP);
183*0Sstevel@tonic-gate if (ssc->ses_private == NULL) {
184*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
185*0Sstevel@tonic-gate return (ENOMEM);
186*0Sstevel@tonic-gate }
187*0Sstevel@tonic-gate }
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate ssc->ses_nobjects = 0;
190*0Sstevel@tonic-gate ssc->ses_encstat = 0;
191*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gate if ((r = safte_getconfig(ssc)) != 0) {
194*0Sstevel@tonic-gate return (r);
195*0Sstevel@tonic-gate }
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate /*
198*0Sstevel@tonic-gate * The number of objects here, as well as that reported by the
199*0Sstevel@tonic-gate * READ_BUFFER/GET_CONFIG call, are the over-temperature flags (15)
200*0Sstevel@tonic-gate * that get reported during READ_BUFFER/READ_ENC_STATUS.
201*0Sstevel@tonic-gate */
202*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
203*0Sstevel@tonic-gate cc = ssc->ses_private;
204*0Sstevel@tonic-gate ssc->ses_nobjects = cc->Nfans + cc->Npwr + cc->Nslots + cc->DoorLock +
205*0Sstevel@tonic-gate cc->Ntherm + cc->Nspkrs + NPSEUDO_THERM + NPSEUDO_ALARM;
206*0Sstevel@tonic-gate ssc->ses_objmap = (encobj *)
207*0Sstevel@tonic-gate kmem_zalloc(ssc->ses_nobjects * sizeof (encobj), KM_SLEEP);
208*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
209*0Sstevel@tonic-gate if (ssc->ses_objmap == NULL)
210*0Sstevel@tonic-gate return (ENOMEM);
211*0Sstevel@tonic-gate r = 0;
212*0Sstevel@tonic-gate /*
213*0Sstevel@tonic-gate * Note that this is all arranged for the convenience
214*0Sstevel@tonic-gate * in later fetches of status.
215*0Sstevel@tonic-gate */
216*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
217*0Sstevel@tonic-gate for (i = 0; i < cc->Nfans; i++)
218*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_FAN;
219*0Sstevel@tonic-gate cc->pwroff = (uchar_t)r;
220*0Sstevel@tonic-gate for (i = 0; i < cc->Npwr; i++)
221*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_POWER;
222*0Sstevel@tonic-gate for (i = 0; i < cc->DoorLock; i++)
223*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_DOORLOCK;
224*0Sstevel@tonic-gate for (i = 0; i < cc->Nspkrs; i++)
225*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_ALARM;
226*0Sstevel@tonic-gate for (i = 0; i < cc->Ntherm; i++)
227*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_THERM;
228*0Sstevel@tonic-gate for (i = 0; i < NPSEUDO_THERM; i++)
229*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_THERM;
230*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_ALARM;
231*0Sstevel@tonic-gate cc->slotoff = (uchar_t)r;
232*0Sstevel@tonic-gate for (i = 0; i < cc->Nslots; i++)
233*0Sstevel@tonic-gate ssc->ses_objmap[r++].enctype = SESTYP_DEVICE;
234*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
235*0Sstevel@tonic-gate return (0);
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate int
safte_init_enc(ses_softc_t * ssc)239*0Sstevel@tonic-gate safte_init_enc(ses_softc_t *ssc)
240*0Sstevel@tonic-gate {
241*0Sstevel@tonic-gate int err;
242*0Sstevel@tonic-gate Uscmd local, *lp = &local;
243*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], *sdata;
244*0Sstevel@tonic-gate static char cdb0[CDB_GROUP1] = { SCMD_SDIAG };
245*0Sstevel@tonic-gate static char cdb[CDB_GROUP1] =
246*0Sstevel@tonic-gate { SCMD_WRITE_BUFFER, 1, 0, 0, 0, 0, 0, 0, SCRATCH, 0 };
247*0Sstevel@tonic-gate
248*0Sstevel@tonic-gate sdata = kmem_alloc(SCRATCH, KM_SLEEP);
249*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_RQENABLE;
250*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
251*0Sstevel@tonic-gate lp->uscsi_cdb = cdb0;
252*0Sstevel@tonic-gate lp->uscsi_bufaddr = NULL;
253*0Sstevel@tonic-gate lp->uscsi_buflen = 0;
254*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb0);
255*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
256*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
257*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
258*0Sstevel@tonic-gate if (err) {
259*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
260*0Sstevel@tonic-gate return (err);
261*0Sstevel@tonic-gate }
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
264*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
265*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
266*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
267*0Sstevel@tonic-gate lp->uscsi_buflen = SCRATCH;
268*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
269*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
270*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
271*0Sstevel@tonic-gate bzero(&sdata[1], 15);
272*0Sstevel@tonic-gate sdata[0] = SAFTE_WT_GLOBAL;
273*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
274*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
275*0Sstevel@tonic-gate return (err);
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate
279*0Sstevel@tonic-gate static char *toolittle = "Too Little Data Returned (%d) at line %d";
280*0Sstevel@tonic-gate #define BAIL(r, x, k, l, m, n) \
281*0Sstevel@tonic-gate if (r >= x) { \
282*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, toolittle, x, __LINE__); \
283*0Sstevel@tonic-gate kmem_free(k, l); \
284*0Sstevel@tonic-gate kmem_free(m, n); \
285*0Sstevel@tonic-gate return (EIO); \
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate
288*0Sstevel@tonic-gate static int
safte_rdstat(ses_softc_t * ssc,int slpflg)289*0Sstevel@tonic-gate safte_rdstat(ses_softc_t *ssc, int slpflg)
290*0Sstevel@tonic-gate {
291*0Sstevel@tonic-gate int err, oid, r, i, hiwater, nitems;
292*0Sstevel@tonic-gate ushort_t tempflags;
293*0Sstevel@tonic-gate size_t buflen;
294*0Sstevel@tonic-gate uchar_t status, oencstat;
295*0Sstevel@tonic-gate Uscmd local, *lp = &local;
296*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
297*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], *sdata;
298*0Sstevel@tonic-gate char cdb[CDB_GROUP1];
299*0Sstevel@tonic-gate int *driveids, id_size = cc->Nslots * sizeof (int);
300*0Sstevel@tonic-gate
301*0Sstevel@tonic-gate driveids = kmem_alloc(id_size, slpflg);
302*0Sstevel@tonic-gate if (driveids == NULL) {
303*0Sstevel@tonic-gate return (ENOMEM);
304*0Sstevel@tonic-gate }
305*0Sstevel@tonic-gate
306*0Sstevel@tonic-gate /*
307*0Sstevel@tonic-gate * The number of bytes of data we need to get is
308*0Sstevel@tonic-gate * Nfans + Npwr + Nslots + Nspkrs + Ntherm + nochoice
309*0Sstevel@tonic-gate * (nochoice = 1 doorlock + 1 spkr + 2 pseudo therms + 10 extra)
310*0Sstevel@tonic-gate * the extra are simply for good luck.
311*0Sstevel@tonic-gate */
312*0Sstevel@tonic-gate buflen = cc->Nfans + cc->Npwr + cc->Nslots + cc->Nspkrs;
313*0Sstevel@tonic-gate buflen += cc->Ntherm + 14;
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate /*
316*0Sstevel@tonic-gate * Towards the end of this function this buffer is reused.
317*0Sstevel@tonic-gate * Thus we need to make sure that we have allocated enough
318*0Sstevel@tonic-gate * memory retrieving buffer 1 & 4.
319*0Sstevel@tonic-gate * buffer 1 -> element status & drive id
320*0Sstevel@tonic-gate * buffer 4 -> drive status & drive command history.
321*0Sstevel@tonic-gate * buffer 4 uses 4 bytes per drive bay.
322*0Sstevel@tonic-gate */
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gate if (buflen < cc->Nslots * 4) {
325*0Sstevel@tonic-gate buflen = cc->Nslots * 4;
326*0Sstevel@tonic-gate }
327*0Sstevel@tonic-gate
328*0Sstevel@tonic-gate if (ssc->ses_nobjects > buflen)
329*0Sstevel@tonic-gate buflen = ssc->ses_nobjects;
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate if (buflen > 0xffff) {
332*0Sstevel@tonic-gate cmn_err(CE_WARN, "Illogical SCSI data");
333*0Sstevel@tonic-gate return (EIO);
334*0Sstevel@tonic-gate }
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate sdata = kmem_alloc(buflen, slpflg);
337*0Sstevel@tonic-gate if (sdata == NULL) {
338*0Sstevel@tonic-gate kmem_free(driveids, id_size);
339*0Sstevel@tonic-gate return (ENOMEM);
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate
342*0Sstevel@tonic-gate cdb[0] = SCMD_READ_BUFFER;
343*0Sstevel@tonic-gate cdb[1] = 1;
344*0Sstevel@tonic-gate cdb[2] = SAFTE_RD_RDESTS;
345*0Sstevel@tonic-gate cdb[3] = 0;
346*0Sstevel@tonic-gate cdb[4] = 0;
347*0Sstevel@tonic-gate cdb[5] = 0;
348*0Sstevel@tonic-gate cdb[6] = 0;
349*0Sstevel@tonic-gate cdb[7] = (buflen >> 8) & 0xff;
350*0Sstevel@tonic-gate cdb[8] = buflen & 0xff;
351*0Sstevel@tonic-gate cdb[9] = 0;
352*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
353*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
354*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
355*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
356*0Sstevel@tonic-gate lp->uscsi_buflen = buflen;
357*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
358*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
359*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
360*0Sstevel@tonic-gate
361*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
362*0Sstevel@tonic-gate if (err) {
363*0Sstevel@tonic-gate kmem_free(sdata, buflen);
364*0Sstevel@tonic-gate kmem_free(driveids, id_size);
365*0Sstevel@tonic-gate return (err);
366*0Sstevel@tonic-gate }
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate hiwater = lp->uscsi_buflen - lp->uscsi_resid;
369*0Sstevel@tonic-gate
370*0Sstevel@tonic-gate /*
371*0Sstevel@tonic-gate * invalidate all status bits.
372*0Sstevel@tonic-gate */
373*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
374*0Sstevel@tonic-gate for (i = 0; i < ssc->ses_nobjects; i++)
375*0Sstevel@tonic-gate ssc->ses_objmap[i].svalid = 0;
376*0Sstevel@tonic-gate oencstat = ssc->ses_encstat & ALL_ENC_STAT;
377*0Sstevel@tonic-gate ssc->ses_encstat = 0;
378*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
379*0Sstevel@tonic-gate
380*0Sstevel@tonic-gate /*
381*0Sstevel@tonic-gate * Now parse returned buffer.
382*0Sstevel@tonic-gate * If we didn't get enough data back,
383*0Sstevel@tonic-gate * that's considered a fatal error.
384*0Sstevel@tonic-gate */
385*0Sstevel@tonic-gate oid = r = 0;
386*0Sstevel@tonic-gate
387*0Sstevel@tonic-gate for (nitems = i = 0; i < cc->Nfans; i++) {
388*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
389*0Sstevel@tonic-gate /*
390*0Sstevel@tonic-gate * 0 = Fan Operational
391*0Sstevel@tonic-gate * 1 = Fan is malfunctioning
392*0Sstevel@tonic-gate * 2 = Fan is not present
393*0Sstevel@tonic-gate * 0x80 = Unknown or Not Reportable Status
394*0Sstevel@tonic-gate */
395*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
396*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0; /* resvd */
397*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0; /* resvd */
398*0Sstevel@tonic-gate switch ((uchar_t)sdata[r]) {
399*0Sstevel@tonic-gate case 0:
400*0Sstevel@tonic-gate nitems++;
401*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
402*0Sstevel@tonic-gate /*
403*0Sstevel@tonic-gate * We could get fancier and cache
404*0Sstevel@tonic-gate * fan speeds that we have set, but
405*0Sstevel@tonic-gate * that isn't done now.
406*0Sstevel@tonic-gate */
407*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 7;
408*0Sstevel@tonic-gate break;
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate case 1:
411*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
412*0Sstevel@tonic-gate /*
413*0Sstevel@tonic-gate * FAIL and FAN STOPPED synthesized
414*0Sstevel@tonic-gate */
415*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x40;
416*0Sstevel@tonic-gate /*
417*0Sstevel@tonic-gate * Enclosure marked with CRITICAL error
418*0Sstevel@tonic-gate * if only one fan or no thermometers,
419*0Sstevel@tonic-gate * else NONCRIT error set.
420*0Sstevel@tonic-gate */
421*0Sstevel@tonic-gate if (cc->Nfans == 1 || cc->Ntherm == 0)
422*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
423*0Sstevel@tonic-gate else
424*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
425*0Sstevel@tonic-gate break;
426*0Sstevel@tonic-gate case 2:
427*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_NOTINSTALLED;
428*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
429*0Sstevel@tonic-gate if (cc->Nfans == 1)
430*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
431*0Sstevel@tonic-gate else
432*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
433*0Sstevel@tonic-gate break;
434*0Sstevel@tonic-gate case 0x80:
435*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNKNOWN;
436*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
437*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_INFO;
438*0Sstevel@tonic-gate break;
439*0Sstevel@tonic-gate default:
440*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
441*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "unknown fan%d status 0x%x",
442*0Sstevel@tonic-gate i, sdata[r] & 0xff);
443*0Sstevel@tonic-gate break;
444*0Sstevel@tonic-gate }
445*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
446*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
447*0Sstevel@tonic-gate r++;
448*0Sstevel@tonic-gate }
449*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
450*0Sstevel@tonic-gate /*
451*0Sstevel@tonic-gate * No matter how you cut it, no cooling elements when there
452*0Sstevel@tonic-gate * should be some there is critical.
453*0Sstevel@tonic-gate */
454*0Sstevel@tonic-gate if (cc->Nfans && nitems == 0) {
455*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
456*0Sstevel@tonic-gate }
457*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
458*0Sstevel@tonic-gate
459*0Sstevel@tonic-gate
460*0Sstevel@tonic-gate for (i = 0; i < cc->Npwr; i++) {
461*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
462*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
463*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
464*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0; /* resvd */
465*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0; /* resvd */
466*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x20; /* requested on */
467*0Sstevel@tonic-gate switch ((uchar_t)sdata[r]) {
468*0Sstevel@tonic-gate case 0x00: /* pws operational and on */
469*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
470*0Sstevel@tonic-gate break;
471*0Sstevel@tonic-gate case 0x01: /* pws operational and off */
472*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x10;
473*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_NOTAVAIL;
474*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_INFO;
475*0Sstevel@tonic-gate break;
476*0Sstevel@tonic-gate case 0x10: /* pws is malfunctioning and commanded on */
477*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x61;
478*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
479*0Sstevel@tonic-gate if (cc->Npwr < 2)
480*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
481*0Sstevel@tonic-gate else
482*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
483*0Sstevel@tonic-gate break;
484*0Sstevel@tonic-gate
485*0Sstevel@tonic-gate case 0x11: /* pws is malfunctioning and commanded off */
486*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x51;
487*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
488*0Sstevel@tonic-gate if (cc->Npwr < 2)
489*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
490*0Sstevel@tonic-gate else
491*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
492*0Sstevel@tonic-gate break;
493*0Sstevel@tonic-gate case 0x20: /* pws is not present */
494*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_NOTINSTALLED;
495*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
496*0Sstevel@tonic-gate if (cc->Npwr < 2)
497*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
498*0Sstevel@tonic-gate else
499*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_INFO;
500*0Sstevel@tonic-gate break;
501*0Sstevel@tonic-gate case 0x21: /* pws is present */
502*0Sstevel@tonic-gate break;
503*0Sstevel@tonic-gate case 0x80: /* Unknown or Not Reportable Status */
504*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNKNOWN;
505*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
506*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_INFO;
507*0Sstevel@tonic-gate break;
508*0Sstevel@tonic-gate default:
509*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
510*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "unknown pwr%d status 0x%x",
511*0Sstevel@tonic-gate i, sdata[r] & 0xff);
512*0Sstevel@tonic-gate break;
513*0Sstevel@tonic-gate }
514*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
515*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
516*0Sstevel@tonic-gate r++;
517*0Sstevel@tonic-gate }
518*0Sstevel@tonic-gate
519*0Sstevel@tonic-gate /*
520*0Sstevel@tonic-gate * Now I am going to save the target id's for the end of
521*0Sstevel@tonic-gate * the function. (when I build the drive objects)
522*0Sstevel@tonic-gate * that is when I will be getting the drive status from buffer 4
523*0Sstevel@tonic-gate */
524*0Sstevel@tonic-gate
525*0Sstevel@tonic-gate for (i = 0; i < cc->Nslots; i++) {
526*0Sstevel@tonic-gate driveids[i] = sdata[r++];
527*0Sstevel@tonic-gate }
528*0Sstevel@tonic-gate
529*0Sstevel@tonic-gate
530*0Sstevel@tonic-gate
531*0Sstevel@tonic-gate /*
532*0Sstevel@tonic-gate * We always have doorlock status, no matter what,
533*0Sstevel@tonic-gate * but we only save the status if we have one.
534*0Sstevel@tonic-gate */
535*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
536*0Sstevel@tonic-gate if (cc->DoorLock) {
537*0Sstevel@tonic-gate /*
538*0Sstevel@tonic-gate * 0 = Door Locked
539*0Sstevel@tonic-gate * 1 = Door Unlocked, or no Lock Installed
540*0Sstevel@tonic-gate * 0x80 = Unknown or Not Reportable Status
541*0Sstevel@tonic-gate */
542*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
543*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0;
544*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0;
545*0Sstevel@tonic-gate switch ((uchar_t)sdata[r]) {
546*0Sstevel@tonic-gate case 0:
547*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
548*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
549*0Sstevel@tonic-gate break;
550*0Sstevel@tonic-gate case 1:
551*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
552*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 1;
553*0Sstevel@tonic-gate break;
554*0Sstevel@tonic-gate case 0x80:
555*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNKNOWN;
556*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
557*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_INFO;
558*0Sstevel@tonic-gate break;
559*0Sstevel@tonic-gate default:
560*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
561*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "unknown lock status 0x%x",
562*0Sstevel@tonic-gate sdata[r] & 0xff);
563*0Sstevel@tonic-gate break;
564*0Sstevel@tonic-gate }
565*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
566*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
567*0Sstevel@tonic-gate }
568*0Sstevel@tonic-gate r++;
569*0Sstevel@tonic-gate
570*0Sstevel@tonic-gate /*
571*0Sstevel@tonic-gate * We always have speaker status, no matter what,
572*0Sstevel@tonic-gate * but we only save the status if we have one.
573*0Sstevel@tonic-gate */
574*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
575*0Sstevel@tonic-gate if (cc->Nspkrs) {
576*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
577*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0;
578*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0;
579*0Sstevel@tonic-gate if (sdata[r] == 1) {
580*0Sstevel@tonic-gate /*
581*0Sstevel@tonic-gate * We need to cache tone urgency indicators.
582*0Sstevel@tonic-gate * Someday.
583*0Sstevel@tonic-gate */
584*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_NONCRIT;
585*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x8;
586*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
587*0Sstevel@tonic-gate } else if (sdata[r] == 0) {
588*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
589*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
590*0Sstevel@tonic-gate } else {
591*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
592*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
593*0Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "unknown spkr status 0x%x",
594*0Sstevel@tonic-gate sdata[r] & 0xff);
595*0Sstevel@tonic-gate }
596*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
597*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
598*0Sstevel@tonic-gate }
599*0Sstevel@tonic-gate r++;
600*0Sstevel@tonic-gate
601*0Sstevel@tonic-gate for (i = 0; i < cc->Ntherm; i++) {
602*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
603*0Sstevel@tonic-gate /*
604*0Sstevel@tonic-gate * Status is a range from -10 to 245 deg Celsius,
605*0Sstevel@tonic-gate * which we need to normalize to -20 to -235 according
606*0Sstevel@tonic-gate * to the latest SCSI spec.
607*0Sstevel@tonic-gate */
608*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
609*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0;
610*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] =
611*0Sstevel@tonic-gate ((unsigned int) sdata[r]) - 10;
612*0Sstevel@tonic-gate if (sdata[r] < 20) {
613*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
614*0Sstevel@tonic-gate /*
615*0Sstevel@tonic-gate * Set 'under temperature' failure.
616*0Sstevel@tonic-gate */
617*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 2;
618*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
619*0Sstevel@tonic-gate } else if (sdata[r] > 30) {
620*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
621*0Sstevel@tonic-gate /*
622*0Sstevel@tonic-gate * Set 'over temperature' failure.
623*0Sstevel@tonic-gate */
624*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 8;
625*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
626*0Sstevel@tonic-gate } else {
627*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
628*0Sstevel@tonic-gate }
629*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
630*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
631*0Sstevel@tonic-gate r++;
632*0Sstevel@tonic-gate }
633*0Sstevel@tonic-gate
634*0Sstevel@tonic-gate /*
635*0Sstevel@tonic-gate * Now, for "pseudo" thermometers, we have two bytes
636*0Sstevel@tonic-gate * of information in enclosure status- 16 bits. Actually,
637*0Sstevel@tonic-gate * the MSB is a single TEMP ALERT flag indicating whether
638*0Sstevel@tonic-gate * any other bits are set, but, thanks to fuzzy thinking,
639*0Sstevel@tonic-gate * in the SAF-TE spec, this can also be set even if no
640*0Sstevel@tonic-gate * other bits are set, thus making this really another
641*0Sstevel@tonic-gate * binary temperature sensor.
642*0Sstevel@tonic-gate */
643*0Sstevel@tonic-gate
644*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
645*0Sstevel@tonic-gate tempflags = sdata[r++];
646*0Sstevel@tonic-gate BAIL(r, hiwater, sdata, buflen, driveids, id_size);
647*0Sstevel@tonic-gate tempflags |= (tempflags << 8) | sdata[r++];
648*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
649*0Sstevel@tonic-gate
650*0Sstevel@tonic-gate #if NPSEUDO_THERM == 1
651*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0;
652*0Sstevel@tonic-gate if (tempflags) {
653*0Sstevel@tonic-gate /* Set 'over temperature' failure. */
654*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
655*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 8;
656*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
657*0Sstevel@tonic-gate } else {
658*0Sstevel@tonic-gate /* Set 'nominal' temperature. */
659*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
660*0Sstevel@tonic-gate }
661*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
662*0Sstevel@tonic-gate
663*0Sstevel@tonic-gate #else /* NPSEUDO_THERM == 1 */
664*0Sstevel@tonic-gate for (i = 0; i < NPSEUDO_THERM; i++) {
665*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = 0;
666*0Sstevel@tonic-gate if (tempflags & (1 << (NPSEUDO_THERM - i - 1))) {
667*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
668*0Sstevel@tonic-gate /* ssc->ses_objmap[oid].encstat[2] = 0; */
669*0Sstevel@tonic-gate
670*0Sstevel@tonic-gate /*
671*0Sstevel@tonic-gate * Set 'over temperature' failure.
672*0Sstevel@tonic-gate */
673*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 8;
674*0Sstevel@tonic-gate ssc->ses_encstat |= ENCSTAT_CRITICAL;
675*0Sstevel@tonic-gate } else {
676*0Sstevel@tonic-gate /*
677*0Sstevel@tonic-gate * Set 'nominal' temperature.
678*0Sstevel@tonic-gate */
679*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
680*0Sstevel@tonic-gate /* ssc->ses_objmap[oid].encstat[2] = 0; */
681*0Sstevel@tonic-gate }
682*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
683*0Sstevel@tonic-gate }
684*0Sstevel@tonic-gate #endif /* NPSEUDO_THERM == 1 */
685*0Sstevel@tonic-gate
686*0Sstevel@tonic-gate
687*0Sstevel@tonic-gate /*
688*0Sstevel@tonic-gate * Get alarm status.
689*0Sstevel@tonic-gate */
690*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
691*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = ssc->ses_objmap[oid].priv;
692*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
693*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
694*0Sstevel@tonic-gate
695*0Sstevel@tonic-gate /*
696*0Sstevel@tonic-gate * Now get drive slot status
697*0Sstevel@tonic-gate */
698*0Sstevel@tonic-gate cdb[2] = SAFTE_RD_RDDSTS;
699*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
700*0Sstevel@tonic-gate if (err) {
701*0Sstevel@tonic-gate kmem_free(sdata, buflen);
702*0Sstevel@tonic-gate kmem_free(driveids, id_size);
703*0Sstevel@tonic-gate return (err);
704*0Sstevel@tonic-gate }
705*0Sstevel@tonic-gate hiwater = lp->uscsi_buflen - lp->uscsi_resid;
706*0Sstevel@tonic-gate for (r = i = 0; i < cc->Nslots; i++, r += 4) {
707*0Sstevel@tonic-gate BAIL(r+3, hiwater, sdata, buflen, driveids, id_size);
708*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
709*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_UNSUPPORTED;
710*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[1] = (uchar_t)driveids[i];
711*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0;
712*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0;
713*0Sstevel@tonic-gate status = sdata[r+3];
714*0Sstevel@tonic-gate if ((status & 0x1) == 0) { /* no device */
715*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_NOTINSTALLED;
716*0Sstevel@tonic-gate } else {
717*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
718*0Sstevel@tonic-gate }
719*0Sstevel@tonic-gate if (status & 0x2) {
720*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[2] = 0x8;
721*0Sstevel@tonic-gate }
722*0Sstevel@tonic-gate if ((status & 0x4) == 0) {
723*0Sstevel@tonic-gate ssc->ses_objmap[oid].encstat[3] = 0x10;
724*0Sstevel@tonic-gate }
725*0Sstevel@tonic-gate ssc->ses_objmap[oid++].svalid = 1;
726*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
727*0Sstevel@tonic-gate }
728*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
729*0Sstevel@tonic-gate /* see comment below about sticky enclosure status */
730*0Sstevel@tonic-gate ssc->ses_encstat |= ENCI_SVALID | oencstat;
731*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
732*0Sstevel@tonic-gate kmem_free(sdata, buflen);
733*0Sstevel@tonic-gate kmem_free(driveids, id_size);
734*0Sstevel@tonic-gate return (0);
735*0Sstevel@tonic-gate }
736*0Sstevel@tonic-gate
737*0Sstevel@tonic-gate int
safte_get_encstat(ses_softc_t * ssc,int slpflg)738*0Sstevel@tonic-gate safte_get_encstat(ses_softc_t *ssc, int slpflg)
739*0Sstevel@tonic-gate {
740*0Sstevel@tonic-gate return (safte_rdstat(ssc, slpflg));
741*0Sstevel@tonic-gate }
742*0Sstevel@tonic-gate
743*0Sstevel@tonic-gate int
safte_set_encstat(ses_softc_t * ssc,uchar_t encstat,int slpflg)744*0Sstevel@tonic-gate safte_set_encstat(ses_softc_t *ssc, uchar_t encstat, int slpflg)
745*0Sstevel@tonic-gate {
746*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
747*0Sstevel@tonic-gate if (cc == NULL)
748*0Sstevel@tonic-gate return (0);
749*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
750*0Sstevel@tonic-gate /*
751*0Sstevel@tonic-gate * Since SAF-TE devices aren't necessarily sticky in terms
752*0Sstevel@tonic-gate * of state, make our soft copy of enclosure status 'sticky'-
753*0Sstevel@tonic-gate * that is, things set in enclosure status stay set (as implied
754*0Sstevel@tonic-gate * by conditions set in reading object status) until cleared.
755*0Sstevel@tonic-gate */
756*0Sstevel@tonic-gate ssc->ses_encstat &= ~ALL_ENC_STAT;
757*0Sstevel@tonic-gate ssc->ses_encstat |= (encstat & ALL_ENC_STAT);
758*0Sstevel@tonic-gate ssc->ses_encstat |= ENCI_SVALID;
759*0Sstevel@tonic-gate cc->flag1 &= ~(FLG1_ALARM|FLG1_GLOBFAIL|FLG1_GLOBWARN);
760*0Sstevel@tonic-gate if ((encstat & (ENCSTAT_CRITICAL|ENCSTAT_UNRECOV)) != 0) {
761*0Sstevel@tonic-gate cc->flag1 |= FLG1_ALARM|FLG1_GLOBFAIL;
762*0Sstevel@tonic-gate } else if ((encstat & ENCSTAT_NONCRITICAL) != 0) {
763*0Sstevel@tonic-gate cc->flag1 |= FLG1_GLOBWARN;
764*0Sstevel@tonic-gate }
765*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
766*0Sstevel@tonic-gate return (wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1, cc->flag2, 0, slpflg));
767*0Sstevel@tonic-gate }
768*0Sstevel@tonic-gate
769*0Sstevel@tonic-gate int
safte_get_objstat(ses_softc_t * ssc,ses_objarg * obp,int slpflg)770*0Sstevel@tonic-gate safte_get_objstat(ses_softc_t *ssc, ses_objarg *obp, int slpflg)
771*0Sstevel@tonic-gate {
772*0Sstevel@tonic-gate int i = (int)obp->obj_id;
773*0Sstevel@tonic-gate
774*0Sstevel@tonic-gate if ((ssc->ses_encstat & ENCI_SVALID) == 0 ||
775*0Sstevel@tonic-gate (ssc->ses_objmap[i].svalid) == 0) {
776*0Sstevel@tonic-gate int r = safte_rdstat(ssc, slpflg);
777*0Sstevel@tonic-gate if (r)
778*0Sstevel@tonic-gate return (r);
779*0Sstevel@tonic-gate }
780*0Sstevel@tonic-gate obp->cstat[0] = ssc->ses_objmap[i].encstat[0];
781*0Sstevel@tonic-gate obp->cstat[1] = ssc->ses_objmap[i].encstat[1];
782*0Sstevel@tonic-gate obp->cstat[2] = ssc->ses_objmap[i].encstat[2];
783*0Sstevel@tonic-gate obp->cstat[3] = ssc->ses_objmap[i].encstat[3];
784*0Sstevel@tonic-gate return (0);
785*0Sstevel@tonic-gate }
786*0Sstevel@tonic-gate
787*0Sstevel@tonic-gate
788*0Sstevel@tonic-gate int
safte_set_objstat(ses_softc_t * ssc,ses_objarg * obp,int slp)789*0Sstevel@tonic-gate safte_set_objstat(ses_softc_t *ssc, ses_objarg *obp, int slp)
790*0Sstevel@tonic-gate {
791*0Sstevel@tonic-gate int idx, err;
792*0Sstevel@tonic-gate encobj *ep;
793*0Sstevel@tonic-gate struct scfg *cc;
794*0Sstevel@tonic-gate
795*0Sstevel@tonic-gate
796*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "safte_set_objstat(%d): %x %x %x %x",
797*0Sstevel@tonic-gate (int)obp->obj_id, obp->cstat[0], obp->cstat[1], obp->cstat[2],
798*0Sstevel@tonic-gate obp->cstat[3]);
799*0Sstevel@tonic-gate
800*0Sstevel@tonic-gate /*
801*0Sstevel@tonic-gate * If this is clear, we don't do diddly.
802*0Sstevel@tonic-gate */
803*0Sstevel@tonic-gate if ((obp->cstat[0] & SESCTL_CSEL) == 0) {
804*0Sstevel@tonic-gate return (0);
805*0Sstevel@tonic-gate }
806*0Sstevel@tonic-gate
807*0Sstevel@tonic-gate err = 0;
808*0Sstevel@tonic-gate /*
809*0Sstevel@tonic-gate * Check to see if the common bits are set and do them first.
810*0Sstevel@tonic-gate */
811*0Sstevel@tonic-gate if (obp->cstat[0] & ~SESCTL_CSEL) {
812*0Sstevel@tonic-gate err = set_objstat_sel(ssc, obp, slp);
813*0Sstevel@tonic-gate if (err)
814*0Sstevel@tonic-gate return (err);
815*0Sstevel@tonic-gate }
816*0Sstevel@tonic-gate
817*0Sstevel@tonic-gate cc = ssc->ses_private;
818*0Sstevel@tonic-gate if (cc == NULL)
819*0Sstevel@tonic-gate return (0);
820*0Sstevel@tonic-gate
821*0Sstevel@tonic-gate idx = (int)obp->obj_id;
822*0Sstevel@tonic-gate ep = &ssc->ses_objmap[idx];
823*0Sstevel@tonic-gate
824*0Sstevel@tonic-gate switch (ep->enctype) {
825*0Sstevel@tonic-gate case SESTYP_DEVICE:
826*0Sstevel@tonic-gate {
827*0Sstevel@tonic-gate uchar_t slotop = 0;
828*0Sstevel@tonic-gate /*
829*0Sstevel@tonic-gate * XXX: I should probably cache the previous state
830*0Sstevel@tonic-gate * XXX: of SESCTL_DEVOFF so that when it goes from
831*0Sstevel@tonic-gate * XXX: true to false I can then set PREPARE FOR OPERATION
832*0Sstevel@tonic-gate * XXX: flag in PERFORM SLOT OPERATION write buffer command.
833*0Sstevel@tonic-gate */
834*0Sstevel@tonic-gate if (obp->cstat[2] & (SESCTL_RQSINS|SESCTL_RQSRMV)) {
835*0Sstevel@tonic-gate slotop |= 0x2;
836*0Sstevel@tonic-gate }
837*0Sstevel@tonic-gate if (obp->cstat[2] & SESCTL_RQSID) {
838*0Sstevel@tonic-gate slotop |= 0x4;
839*0Sstevel@tonic-gate }
840*0Sstevel@tonic-gate err = perf_slotop(ssc, (uchar_t)idx - (uchar_t)cc->slotoff,
841*0Sstevel@tonic-gate slotop, slp);
842*0Sstevel@tonic-gate if (err)
843*0Sstevel@tonic-gate return (err);
844*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
845*0Sstevel@tonic-gate if (obp->cstat[3] & SESCTL_RQSFLT) {
846*0Sstevel@tonic-gate ep->priv |= 0x2;
847*0Sstevel@tonic-gate } else {
848*0Sstevel@tonic-gate ep->priv &= ~0x2;
849*0Sstevel@tonic-gate }
850*0Sstevel@tonic-gate if (ep->priv & 0xc6) {
851*0Sstevel@tonic-gate ep->priv &= ~0x1;
852*0Sstevel@tonic-gate } else {
853*0Sstevel@tonic-gate ep->priv |= 0x1; /* no errors */
854*0Sstevel@tonic-gate }
855*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
856*0Sstevel@tonic-gate wrslot_stat(ssc, slp);
857*0Sstevel@tonic-gate break;
858*0Sstevel@tonic-gate }
859*0Sstevel@tonic-gate case SESTYP_POWER:
860*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
861*0Sstevel@tonic-gate if (obp->cstat[3] & SESCTL_RQSTFAIL) {
862*0Sstevel@tonic-gate cc->flag1 |= FLG1_ENCPWRFAIL;
863*0Sstevel@tonic-gate } else {
864*0Sstevel@tonic-gate cc->flag1 &= ~FLG1_ENCPWRFAIL;
865*0Sstevel@tonic-gate }
866*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
867*0Sstevel@tonic-gate err = wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
868*0Sstevel@tonic-gate cc->flag2, 0, slp);
869*0Sstevel@tonic-gate if (err)
870*0Sstevel@tonic-gate return (err);
871*0Sstevel@tonic-gate if (obp->cstat[3] & SESCTL_RQSTON) {
872*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
873*0Sstevel@tonic-gate idx - cc->pwroff, 0, 0, slp);
874*0Sstevel@tonic-gate } else {
875*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
876*0Sstevel@tonic-gate idx - cc->pwroff, 0, 1, slp);
877*0Sstevel@tonic-gate }
878*0Sstevel@tonic-gate break;
879*0Sstevel@tonic-gate case SESTYP_FAN:
880*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
881*0Sstevel@tonic-gate if (obp->cstat[3] & SESCTL_RQSTFAIL) {
882*0Sstevel@tonic-gate cc->flag1 |= FLG1_ENCFANFAIL;
883*0Sstevel@tonic-gate } else {
884*0Sstevel@tonic-gate cc->flag1 &= ~FLG1_ENCFANFAIL;
885*0Sstevel@tonic-gate }
886*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
887*0Sstevel@tonic-gate err = wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
888*0Sstevel@tonic-gate cc->flag2, 0, slp);
889*0Sstevel@tonic-gate if (err)
890*0Sstevel@tonic-gate return (err);
891*0Sstevel@tonic-gate if (obp->cstat[3] & SESCTL_RQSTON) {
892*0Sstevel@tonic-gate uchar_t fsp;
893*0Sstevel@tonic-gate if ((obp->cstat[3] & 0x7) == 7) {
894*0Sstevel@tonic-gate fsp = 4;
895*0Sstevel@tonic-gate } else if ((obp->cstat[3] & 0x7) == 6) {
896*0Sstevel@tonic-gate fsp = 3;
897*0Sstevel@tonic-gate } else if ((obp->cstat[3] & 0x7) == 4) {
898*0Sstevel@tonic-gate fsp = 2;
899*0Sstevel@tonic-gate } else {
900*0Sstevel@tonic-gate fsp = 1;
901*0Sstevel@tonic-gate }
902*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, fsp, 0, slp);
903*0Sstevel@tonic-gate } else {
904*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, 0, 0, slp);
905*0Sstevel@tonic-gate }
906*0Sstevel@tonic-gate break;
907*0Sstevel@tonic-gate case SESTYP_DOORLOCK:
908*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
909*0Sstevel@tonic-gate if (obp->cstat[3] & 0x1) {
910*0Sstevel@tonic-gate cc->flag2 &= ~FLG2_LOCKDOOR;
911*0Sstevel@tonic-gate } else {
912*0Sstevel@tonic-gate cc->flag2 |= FLG2_LOCKDOOR;
913*0Sstevel@tonic-gate }
914*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
915*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
916*0Sstevel@tonic-gate cc->flag2, 0, slp);
917*0Sstevel@tonic-gate break;
918*0Sstevel@tonic-gate case SESTYP_ALARM:
919*0Sstevel@tonic-gate /*
920*0Sstevel@tonic-gate * On all nonzero but the 'muted' bit, we turn on the alarm,
921*0Sstevel@tonic-gate */
922*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
923*0Sstevel@tonic-gate obp->cstat[3] &= ~0xa;
924*0Sstevel@tonic-gate if (obp->cstat[3] & 0x40) {
925*0Sstevel@tonic-gate cc->flag2 &= ~FLG1_ALARM;
926*0Sstevel@tonic-gate } else if (obp->cstat[3] != 0) {
927*0Sstevel@tonic-gate cc->flag2 |= FLG1_ALARM;
928*0Sstevel@tonic-gate } else {
929*0Sstevel@tonic-gate cc->flag2 &= ~FLG1_ALARM;
930*0Sstevel@tonic-gate }
931*0Sstevel@tonic-gate ep->priv = obp->cstat[3];
932*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
933*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
934*0Sstevel@tonic-gate cc->flag2, 0, slp);
935*0Sstevel@tonic-gate break;
936*0Sstevel@tonic-gate default:
937*0Sstevel@tonic-gate break;
938*0Sstevel@tonic-gate }
939*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
940*0Sstevel@tonic-gate ep->svalid = 0;
941*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
942*0Sstevel@tonic-gate return (0);
943*0Sstevel@tonic-gate }
944*0Sstevel@tonic-gate
945*0Sstevel@tonic-gate static int
set_objstat_sel(ses_softc_t * ssc,ses_objarg * obp,int slp)946*0Sstevel@tonic-gate set_objstat_sel(ses_softc_t *ssc, ses_objarg *obp, int slp)
947*0Sstevel@tonic-gate {
948*0Sstevel@tonic-gate int idx;
949*0Sstevel@tonic-gate encobj *ep;
950*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
951*0Sstevel@tonic-gate
952*0Sstevel@tonic-gate if (cc == NULL)
953*0Sstevel@tonic-gate return (0);
954*0Sstevel@tonic-gate
955*0Sstevel@tonic-gate idx = (int)obp->obj_id;
956*0Sstevel@tonic-gate ep = &ssc->ses_objmap[idx];
957*0Sstevel@tonic-gate
958*0Sstevel@tonic-gate switch (ep->enctype) {
959*0Sstevel@tonic-gate case SESTYP_DEVICE:
960*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
961*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_PRDFAIL) {
962*0Sstevel@tonic-gate ep->priv |= 0x40;
963*0Sstevel@tonic-gate }
964*0Sstevel@tonic-gate /* SESCTL_RSTSWAP has no correspondence in SAF-TE */
965*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_DISABLE) {
966*0Sstevel@tonic-gate ep->priv |= 0x80;
967*0Sstevel@tonic-gate /*
968*0Sstevel@tonic-gate * Hmm. Try to set the 'No Drive' flag.
969*0Sstevel@tonic-gate * Maybe that will count as a 'disable'.
970*0Sstevel@tonic-gate */
971*0Sstevel@tonic-gate }
972*0Sstevel@tonic-gate if (ep->priv & 0xc6) {
973*0Sstevel@tonic-gate ep->priv &= ~0x1;
974*0Sstevel@tonic-gate } else {
975*0Sstevel@tonic-gate ep->priv |= 0x1; /* no errors */
976*0Sstevel@tonic-gate }
977*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
978*0Sstevel@tonic-gate wrslot_stat(ssc, slp);
979*0Sstevel@tonic-gate break;
980*0Sstevel@tonic-gate case SESTYP_POWER:
981*0Sstevel@tonic-gate /*
982*0Sstevel@tonic-gate * Okay- the only one that makes sense here is to
983*0Sstevel@tonic-gate * do the 'disable' for a power supply.
984*0Sstevel@tonic-gate */
985*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_DISABLE) {
986*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
987*0Sstevel@tonic-gate idx - cc->pwroff, 0, 0, slp);
988*0Sstevel@tonic-gate }
989*0Sstevel@tonic-gate break;
990*0Sstevel@tonic-gate case SESTYP_FAN:
991*0Sstevel@tonic-gate /*
992*0Sstevel@tonic-gate * Okay- the only one that makes sense here is to
993*0Sstevel@tonic-gate * set fan speed to zero on disable.
994*0Sstevel@tonic-gate */
995*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_DISABLE) {
996*0Sstevel@tonic-gate /* remember- fans are the first items, so idx works */
997*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, 0, 0, slp);
998*0Sstevel@tonic-gate }
999*0Sstevel@tonic-gate break;
1000*0Sstevel@tonic-gate case SESTYP_DOORLOCK:
1001*0Sstevel@tonic-gate /*
1002*0Sstevel@tonic-gate * Well, we can 'disable' the lock.
1003*0Sstevel@tonic-gate */
1004*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_DISABLE) {
1005*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
1006*0Sstevel@tonic-gate cc->flag2 &= ~FLG2_LOCKDOOR;
1007*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
1008*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
1009*0Sstevel@tonic-gate cc->flag2, 0, slp);
1010*0Sstevel@tonic-gate }
1011*0Sstevel@tonic-gate break;
1012*0Sstevel@tonic-gate case SESTYP_ALARM:
1013*0Sstevel@tonic-gate /*
1014*0Sstevel@tonic-gate * Well, we can 'disable' the alarm.
1015*0Sstevel@tonic-gate */
1016*0Sstevel@tonic-gate if (obp->cstat[0] & SESCTL_DISABLE) {
1017*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
1018*0Sstevel@tonic-gate cc->flag2 &= ~FLG1_ALARM;
1019*0Sstevel@tonic-gate ep->priv |= 0x40; /* Muted */
1020*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
1021*0Sstevel@tonic-gate (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
1022*0Sstevel@tonic-gate cc->flag2, 0, slp);
1023*0Sstevel@tonic-gate }
1024*0Sstevel@tonic-gate break;
1025*0Sstevel@tonic-gate default:
1026*0Sstevel@tonic-gate break;
1027*0Sstevel@tonic-gate }
1028*0Sstevel@tonic-gate mutex_enter(&ssc->ses_devp->sd_mutex);
1029*0Sstevel@tonic-gate ep->svalid = 0;
1030*0Sstevel@tonic-gate mutex_exit(&ssc->ses_devp->sd_mutex);
1031*0Sstevel@tonic-gate return (0);
1032*0Sstevel@tonic-gate }
1033*0Sstevel@tonic-gate
1034*0Sstevel@tonic-gate /*
1035*0Sstevel@tonic-gate * This function handles all of the 16 byte WRITE BUFFER commands.
1036*0Sstevel@tonic-gate */
1037*0Sstevel@tonic-gate static int
wrbuf16(ses_softc_t * ssc,uchar_t op,uchar_t b1,uchar_t b2,uchar_t b3,int slp)1038*0Sstevel@tonic-gate wrbuf16(ses_softc_t *ssc, uchar_t op, uchar_t b1, uchar_t b2,
1039*0Sstevel@tonic-gate uchar_t b3, int slp)
1040*0Sstevel@tonic-gate {
1041*0Sstevel@tonic-gate int err;
1042*0Sstevel@tonic-gate Uscmd local, *lp = &local;
1043*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], *sdata;
1044*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
1045*0Sstevel@tonic-gate static char cdb[CDB_GROUP1] =
1046*0Sstevel@tonic-gate { SCMD_WRITE_BUFFER, 1, 0, 0, 0, 0, 0, 0, 16, 0 };
1047*0Sstevel@tonic-gate
1048*0Sstevel@tonic-gate if (cc == NULL)
1049*0Sstevel@tonic-gate return (0);
1050*0Sstevel@tonic-gate
1051*0Sstevel@tonic-gate sdata = kmem_alloc(16, slp);
1052*0Sstevel@tonic-gate if (sdata == NULL)
1053*0Sstevel@tonic-gate return (ENOMEM);
1054*0Sstevel@tonic-gate
1055*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
1056*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
1057*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
1058*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
1059*0Sstevel@tonic-gate lp->uscsi_buflen = SCRATCH;
1060*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
1061*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
1062*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
1063*0Sstevel@tonic-gate
1064*0Sstevel@tonic-gate sdata[0] = op;
1065*0Sstevel@tonic-gate sdata[1] = b1;
1066*0Sstevel@tonic-gate sdata[2] = b2;
1067*0Sstevel@tonic-gate sdata[3] = b3;
1068*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "saf_wrbuf16 %x %x %x %x", op, b1, b2, b3);
1069*0Sstevel@tonic-gate bzero(&sdata[4], 12);
1070*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
1071*0Sstevel@tonic-gate kmem_free(sdata, 16);
1072*0Sstevel@tonic-gate return (err);
1073*0Sstevel@tonic-gate }
1074*0Sstevel@tonic-gate
1075*0Sstevel@tonic-gate /*
1076*0Sstevel@tonic-gate * This function updates the status byte for the device slot described.
1077*0Sstevel@tonic-gate *
1078*0Sstevel@tonic-gate * Since this is an optional SAF-TE command, there's no point in
1079*0Sstevel@tonic-gate * returning an error.
1080*0Sstevel@tonic-gate */
1081*0Sstevel@tonic-gate static void
wrslot_stat(ses_softc_t * ssc,int slp)1082*0Sstevel@tonic-gate wrslot_stat(ses_softc_t *ssc, int slp)
1083*0Sstevel@tonic-gate {
1084*0Sstevel@tonic-gate int i;
1085*0Sstevel@tonic-gate encobj *ep;
1086*0Sstevel@tonic-gate Uscmd local, *lp = &local;
1087*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], cdb[CDB_GROUP1], *sdata;
1088*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
1089*0Sstevel@tonic-gate
1090*0Sstevel@tonic-gate if (cc == NULL)
1091*0Sstevel@tonic-gate return;
1092*0Sstevel@tonic-gate
1093*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "saf_wrslot");
1094*0Sstevel@tonic-gate cdb[0] = SCMD_WRITE_BUFFER;
1095*0Sstevel@tonic-gate cdb[1] = 1;
1096*0Sstevel@tonic-gate cdb[2] = 0;
1097*0Sstevel@tonic-gate cdb[3] = 0;
1098*0Sstevel@tonic-gate cdb[4] = 0;
1099*0Sstevel@tonic-gate cdb[5] = 0;
1100*0Sstevel@tonic-gate cdb[6] = 0;
1101*0Sstevel@tonic-gate cdb[7] = 0;
1102*0Sstevel@tonic-gate cdb[8] = cc->Nslots * 3 + 1;
1103*0Sstevel@tonic-gate cdb[9] = 0;
1104*0Sstevel@tonic-gate
1105*0Sstevel@tonic-gate sdata = kmem_zalloc(cc->Nslots * 3 + 1, slp);
1106*0Sstevel@tonic-gate if (sdata == NULL)
1107*0Sstevel@tonic-gate return;
1108*0Sstevel@tonic-gate
1109*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
1110*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
1111*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
1112*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
1113*0Sstevel@tonic-gate lp->uscsi_buflen = cc->Nslots * 3 + 1;
1114*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
1115*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
1116*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
1117*0Sstevel@tonic-gate
1118*0Sstevel@tonic-gate sdata[0] = SAFTE_WT_DSTAT;
1119*0Sstevel@tonic-gate for (i = 0; i < cc->Nslots; i++) {
1120*0Sstevel@tonic-gate ep = &ssc->ses_objmap[cc->slotoff + i];
1121*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "saf_wrslot %d <- %x", i,
1122*0Sstevel@tonic-gate ep->priv & 0xff);
1123*0Sstevel@tonic-gate sdata[1 + (3 * i)] = ep->priv & 0xff;
1124*0Sstevel@tonic-gate }
1125*0Sstevel@tonic-gate (void) ses_runcmd(ssc, lp);
1126*0Sstevel@tonic-gate kmem_free(sdata, cc->Nslots * 3 + 1);
1127*0Sstevel@tonic-gate }
1128*0Sstevel@tonic-gate
1129*0Sstevel@tonic-gate /*
1130*0Sstevel@tonic-gate * This function issues the "PERFORM SLOT OPERATION" command.
1131*0Sstevel@tonic-gate */
1132*0Sstevel@tonic-gate static int
perf_slotop(ses_softc_t * ssc,uchar_t slot,uchar_t opflag,int slp)1133*0Sstevel@tonic-gate perf_slotop(ses_softc_t *ssc, uchar_t slot, uchar_t opflag, int slp)
1134*0Sstevel@tonic-gate {
1135*0Sstevel@tonic-gate int err;
1136*0Sstevel@tonic-gate Uscmd local, *lp = &local;
1137*0Sstevel@tonic-gate char rqbuf[SENSE_LENGTH], *sdata;
1138*0Sstevel@tonic-gate struct scfg *cc = ssc->ses_private;
1139*0Sstevel@tonic-gate static char cdb[CDB_GROUP1] =
1140*0Sstevel@tonic-gate { SCMD_WRITE_BUFFER, 1, 0, 0, 0, 0, 0, 0, SCRATCH, 0 };
1141*0Sstevel@tonic-gate
1142*0Sstevel@tonic-gate if (cc == NULL)
1143*0Sstevel@tonic-gate return (0);
1144*0Sstevel@tonic-gate
1145*0Sstevel@tonic-gate sdata = kmem_zalloc(SCRATCH, slp);
1146*0Sstevel@tonic-gate if (sdata == NULL)
1147*0Sstevel@tonic-gate return (ENOMEM);
1148*0Sstevel@tonic-gate
1149*0Sstevel@tonic-gate lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
1150*0Sstevel@tonic-gate lp->uscsi_timeout = ses_io_time;
1151*0Sstevel@tonic-gate lp->uscsi_cdb = cdb;
1152*0Sstevel@tonic-gate lp->uscsi_bufaddr = sdata;
1153*0Sstevel@tonic-gate lp->uscsi_buflen = SCRATCH;
1154*0Sstevel@tonic-gate lp->uscsi_cdblen = sizeof (cdb);
1155*0Sstevel@tonic-gate lp->uscsi_rqbuf = rqbuf;
1156*0Sstevel@tonic-gate lp->uscsi_rqlen = sizeof (rqbuf);
1157*0Sstevel@tonic-gate
1158*0Sstevel@tonic-gate sdata[0] = SAFTE_WT_SLTOP;
1159*0Sstevel@tonic-gate sdata[1] = slot;
1160*0Sstevel@tonic-gate sdata[2] = opflag;
1161*0Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "saf_slotop slot %d op %x", slot, opflag);
1162*0Sstevel@tonic-gate err = ses_runcmd(ssc, lp);
1163*0Sstevel@tonic-gate kmem_free(sdata, SCRATCH);
1164*0Sstevel@tonic-gate return (err);
1165*0Sstevel@tonic-gate }
1166*0Sstevel@tonic-gate
1167*0Sstevel@tonic-gate /*
1168*0Sstevel@tonic-gate * mode: c
1169*0Sstevel@tonic-gate * Local variables:
1170*0Sstevel@tonic-gate * c-indent-level: 8
1171*0Sstevel@tonic-gate * c-brace-imaginary-offset: 0
1172*0Sstevel@tonic-gate * c-brace-offset: -8
1173*0Sstevel@tonic-gate * c-argdecl-indent: 8
1174*0Sstevel@tonic-gate * c-label-offset: -8
1175*0Sstevel@tonic-gate * c-continued-statement-offset: 8
1176*0Sstevel@tonic-gate * c-continued-brace-offset: 0
1177*0Sstevel@tonic-gate * End:
1178*0Sstevel@tonic-gate */
1179