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