xref: /illumos-gate/usr/src/uts/common/io/scsi/targets/ses_sen.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, SEN 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 /*
38*7c478bd9Sstevel@tonic-gate  * The SEN unit is wired to support 7 disk units,
39*7c478bd9Sstevel@tonic-gate  * two power supplies, one fan module, one overtemp sensor,
40*7c478bd9Sstevel@tonic-gate  * and one alarm.
41*7c478bd9Sstevel@tonic-gate  */
42*7c478bd9Sstevel@tonic-gate #define	NOBJECTS	(7+2+1+1+1)
43*7c478bd9Sstevel@tonic-gate #define	DRVOFF	0
44*7c478bd9Sstevel@tonic-gate #define	SDRVOFF	20
45*7c478bd9Sstevel@tonic-gate #define	NDRV	7
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #define	PWROFF	NDRV
48*7c478bd9Sstevel@tonic-gate #define	SPWROFF	28
49*7c478bd9Sstevel@tonic-gate #define	NPWR	2
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #define	FANOFF	(PWROFF + NPWR)
52*7c478bd9Sstevel@tonic-gate #define	SFANOFF	30
53*7c478bd9Sstevel@tonic-gate #define	NFAN	1
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #define	THMOFF	(FANOFF + NFAN)
56*7c478bd9Sstevel@tonic-gate #define	STHMOFF	31
57*7c478bd9Sstevel@tonic-gate #define	NTHM	1
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	ALRMOFF	(THMOFF + NTHM)
60*7c478bd9Sstevel@tonic-gate #define	NALRM	1
61*7c478bd9Sstevel@tonic-gate #define	SALRMOFF	8
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #define	SENPGINSIZE	32
64*7c478bd9Sstevel@tonic-gate #define	SENPGOUTSIZE	22
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate int
sen_softc_init(ses_softc_t * ssc,int doinit)67*7c478bd9Sstevel@tonic-gate sen_softc_init(ses_softc_t *ssc, int doinit)
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	int i;
70*7c478bd9Sstevel@tonic-gate 	if (doinit == 0) {
71*7c478bd9Sstevel@tonic-gate 		mutex_enter(&ssc->ses_devp->sd_mutex);
72*7c478bd9Sstevel@tonic-gate 		if (ssc->ses_nobjects) {
73*7c478bd9Sstevel@tonic-gate 			kmem_free(ssc->ses_objmap,
74*7c478bd9Sstevel@tonic-gate 			    ssc->ses_nobjects * sizeof (encobj));
75*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap = NULL;
76*7c478bd9Sstevel@tonic-gate 			ssc->ses_nobjects = 0;
77*7c478bd9Sstevel@tonic-gate 		}
78*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
79*7c478bd9Sstevel@tonic-gate 		return (0);
80*7c478bd9Sstevel@tonic-gate 	}
81*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
82*7c478bd9Sstevel@tonic-gate 	ssc->ses_nobjects = 0;
83*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat = 0;
84*7c478bd9Sstevel@tonic-gate 	ssc->ses_objmap = (encobj *)
85*7c478bd9Sstevel@tonic-gate 	    kmem_zalloc(NOBJECTS * sizeof (encobj), KM_SLEEP);
86*7c478bd9Sstevel@tonic-gate 	if (ssc->ses_objmap == NULL) {
87*7c478bd9Sstevel@tonic-gate 		mutex_exit(&ssc->ses_devp->sd_mutex);
88*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
89*7c478bd9Sstevel@tonic-gate 	}
90*7c478bd9Sstevel@tonic-gate 	for (i = DRVOFF; i < DRVOFF + NDRV; i++) {
91*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].enctype = SESTYP_DEVICE;
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 	for (i = PWROFF; i < PWROFF + NPWR; i++) {
94*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].enctype = SESTYP_POWER;
95*7c478bd9Sstevel@tonic-gate 	}
96*7c478bd9Sstevel@tonic-gate 	for (i = FANOFF; i < FANOFF + NFAN; i++) {
97*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].enctype = SESTYP_FAN;
98*7c478bd9Sstevel@tonic-gate 	}
99*7c478bd9Sstevel@tonic-gate 	for (i = THMOFF; i < THMOFF + NTHM; i++) {
100*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].enctype = SESTYP_THERM;
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 	for (i = ALRMOFF; i < ALRMOFF + NALRM; i++) {
103*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].enctype = SESTYP_ALARM;
104*7c478bd9Sstevel@tonic-gate 	}
105*7c478bd9Sstevel@tonic-gate 	ssc->ses_nobjects = NOBJECTS;
106*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
107*7c478bd9Sstevel@tonic-gate 	return (0);
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate int
sen_init_enc(ses_softc_t * ssc)111*7c478bd9Sstevel@tonic-gate sen_init_enc(ses_softc_t *ssc)
112*7c478bd9Sstevel@tonic-gate {
113*7c478bd9Sstevel@tonic-gate 	UNUSED_PARAMETER(ssc);
114*7c478bd9Sstevel@tonic-gate 	return (0);
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static int
sen_rdstat(ses_softc_t * ssc,int slpflag)118*7c478bd9Sstevel@tonic-gate sen_rdstat(ses_softc_t *ssc, int slpflag)
119*7c478bd9Sstevel@tonic-gate {
120*7c478bd9Sstevel@tonic-gate 	int err, i, oid, baseid, tmp;
121*7c478bd9Sstevel@tonic-gate 	Uscmd local, *lp = &local;
122*7c478bd9Sstevel@tonic-gate 	char rqbuf[SENSE_LENGTH], *sdata;
123*7c478bd9Sstevel@tonic-gate 	static char cdb[CDB_GROUP0] =
124*7c478bd9Sstevel@tonic-gate 	    { SCMD_GDIAG, 0x10, 0x4, 0, SENPGINSIZE, 0 };
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	/*
127*7c478bd9Sstevel@tonic-gate 	 * Fetch current data
128*7c478bd9Sstevel@tonic-gate 	 */
129*7c478bd9Sstevel@tonic-gate 	sdata = kmem_alloc(SENPGINSIZE, slpflag);
130*7c478bd9Sstevel@tonic-gate 	if (sdata == NULL)
131*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
134*7c478bd9Sstevel@tonic-gate 	lp->uscsi_timeout = ses_io_time;
135*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdb = cdb;
136*7c478bd9Sstevel@tonic-gate 	lp->uscsi_bufaddr = sdata;
137*7c478bd9Sstevel@tonic-gate 	lp->uscsi_buflen = SENPGINSIZE;
138*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdblen = sizeof (cdb);
139*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqbuf = rqbuf;
140*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqlen = sizeof (rqbuf);
141*7c478bd9Sstevel@tonic-gate 	err = ses_runcmd(ssc, lp);
142*7c478bd9Sstevel@tonic-gate 	if (err) {
143*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SENPGINSIZE);
144*7c478bd9Sstevel@tonic-gate 		return (err);
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	if ((lp->uscsi_buflen - lp->uscsi_resid)  < SENPGINSIZE) {
148*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, CE_NOTE, "sen_rdstat: too little data (%ld)",
149*7c478bd9Sstevel@tonic-gate 		    lp->uscsi_buflen - lp->uscsi_resid);
150*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SENPGINSIZE);
151*7c478bd9Sstevel@tonic-gate 		return (EIO);
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	/*
155*7c478bd9Sstevel@tonic-gate 	 * Set base SCSI id for drives...
156*7c478bd9Sstevel@tonic-gate 	 */
157*7c478bd9Sstevel@tonic-gate 	if (sdata[10] & 0x80)
158*7c478bd9Sstevel@tonic-gate 		baseid = 8;
159*7c478bd9Sstevel@tonic-gate 	else
160*7c478bd9Sstevel@tonic-gate 		baseid = 0;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	oid = 0;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
165*7c478bd9Sstevel@tonic-gate 	/*
166*7c478bd9Sstevel@tonic-gate 	 * Invalidate all status bits.
167*7c478bd9Sstevel@tonic-gate 	 */
168*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ssc->ses_nobjects; i++)
169*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[i].svalid = 0;
170*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat = 0;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	/*
173*7c478bd9Sstevel@tonic-gate 	 * Do Drives...
174*7c478bd9Sstevel@tonic-gate 	 */
175*7c478bd9Sstevel@tonic-gate 	for (i = SDRVOFF; i < SDRVOFF + NDRV; i++) {
176*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[1] = baseid + i - SDRVOFF;
177*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[2] = 0;
178*7c478bd9Sstevel@tonic-gate 		if (sdata[i] & 0x80) {
179*7c478bd9Sstevel@tonic-gate 			/*
180*7c478bd9Sstevel@tonic-gate 			 * Drive is present
181*7c478bd9Sstevel@tonic-gate 			 */
182*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
183*7c478bd9Sstevel@tonic-gate 		} else {
184*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_NOTINSTALLED;
185*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_INFO;
186*7c478bd9Sstevel@tonic-gate 		}
187*7c478bd9Sstevel@tonic-gate 		/*
188*7c478bd9Sstevel@tonic-gate 		 * Is the fault LED lit?
189*7c478bd9Sstevel@tonic-gate 		 */
190*7c478bd9Sstevel@tonic-gate 		if (sdata[i] & 0x40) {
191*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
192*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x40;
193*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_CRITICAL;
194*7c478bd9Sstevel@tonic-gate 		} else {
195*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x0;
196*7c478bd9Sstevel@tonic-gate 		}
197*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid++].svalid = 1;
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	/*
201*7c478bd9Sstevel@tonic-gate 	 * Do Power Supplies...
202*7c478bd9Sstevel@tonic-gate 	 *
203*7c478bd9Sstevel@tonic-gate 	 * Power supply bad, or not installed cannot be distinguished.
204*7c478bd9Sstevel@tonic-gate 	 * Which one to pick? Let's say 'bad' and make it NONCRITICAL
205*7c478bd9Sstevel@tonic-gate 	 * if only one is bad but CRITICAL if both are bad.
206*7c478bd9Sstevel@tonic-gate 	 */
207*7c478bd9Sstevel@tonic-gate 	for (tmp = 0, i = SPWROFF; i < SPWROFF + NPWR; i++) {
208*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[1] = 0;
209*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[2] = 0;
210*7c478bd9Sstevel@tonic-gate 		if ((sdata[i] & 0x80) == 0) {
211*7c478bd9Sstevel@tonic-gate 			/*
212*7c478bd9Sstevel@tonic-gate 			 * Power supply 'ok'...
213*7c478bd9Sstevel@tonic-gate 			 */
214*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
215*7c478bd9Sstevel@tonic-gate 			tmp++;
216*7c478bd9Sstevel@tonic-gate 		} else {
217*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
218*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
219*7c478bd9Sstevel@tonic-gate 		}
220*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid++].svalid = 1;
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 	if (tmp == 0) {
223*7c478bd9Sstevel@tonic-gate 		ssc->ses_encstat |= ENCSTAT_CRITICAL;
224*7c478bd9Sstevel@tonic-gate 	}
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	/*
227*7c478bd9Sstevel@tonic-gate 	 *  Do the Fan(s)
228*7c478bd9Sstevel@tonic-gate 	 */
229*7c478bd9Sstevel@tonic-gate 	for (i = SFANOFF; i < SFANOFF + NFAN; i++) {
230*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[1] = 0;
231*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[2] = 0;
232*7c478bd9Sstevel@tonic-gate 		if (sdata[i] & 0x20) {	/* both fans have failed */
233*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
234*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x40;
235*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_CRITICAL;
236*7c478bd9Sstevel@tonic-gate 		} else if (sdata[i] & 0x80) {	/* one fan has failed */
237*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_NONCRIT;
238*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x41;
239*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_NONCRITICAL;
240*7c478bd9Sstevel@tonic-gate 		} else {
241*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
242*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x6;
243*7c478bd9Sstevel@tonic-gate 		}
244*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid++].svalid = 1;
245*7c478bd9Sstevel@tonic-gate 	}
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	/*
248*7c478bd9Sstevel@tonic-gate 	 * Do the temperature sensor...
249*7c478bd9Sstevel@tonic-gate 	 */
250*7c478bd9Sstevel@tonic-gate 	for (i = STHMOFF; i < STHMOFF + NTHM; i++) {
251*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[1] = 0;
252*7c478bd9Sstevel@tonic-gate 		if (sdata[i] & 0x80) {
253*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
254*7c478bd9Sstevel@tonic-gate 			/* ssc->ses_objmap[oid].encstat[2] = 0; */
255*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x8;
256*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_CRITICAL;
257*7c478bd9Sstevel@tonic-gate 		} else {
258*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
259*7c478bd9Sstevel@tonic-gate 			/* ssc->ses_objmap[oid].encstat[2] = 0; */
260*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0;
261*7c478bd9Sstevel@tonic-gate 		}
262*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid++].svalid = 1;
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	/*
266*7c478bd9Sstevel@tonic-gate 	 * and last, but not least, check the state of the alarm.
267*7c478bd9Sstevel@tonic-gate 	 */
268*7c478bd9Sstevel@tonic-gate 	for (i = SALRMOFF; i < SALRMOFF + NALRM; i++) {
269*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[1] = 0;
270*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid].encstat[2] = 0;
271*7c478bd9Sstevel@tonic-gate 		if (sdata[i]  & 0x80) {	/* Alarm is or was sounding */
272*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_CRIT;
273*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0x2;
274*7c478bd9Sstevel@tonic-gate 			if ((sdata[i] & 0xf))
275*7c478bd9Sstevel@tonic-gate 				ssc->ses_objmap[oid].encstat[3] |= 0x40;
276*7c478bd9Sstevel@tonic-gate 			ssc->ses_encstat |= ENCSTAT_CRITICAL;
277*7c478bd9Sstevel@tonic-gate 		} else {
278*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[0] = SESSTAT_OK;
279*7c478bd9Sstevel@tonic-gate 			ssc->ses_objmap[oid].encstat[3] = 0;
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 		ssc->ses_objmap[oid++].svalid = 1;
282*7c478bd9Sstevel@tonic-gate 	}
283*7c478bd9Sstevel@tonic-gate 	ssc->ses_encstat |= ENCI_SVALID;
284*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
285*7c478bd9Sstevel@tonic-gate 	kmem_free(sdata, SENPGINSIZE);
286*7c478bd9Sstevel@tonic-gate 	return (0);
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate int
sen_get_encstat(ses_softc_t * ssc,int slpflag)290*7c478bd9Sstevel@tonic-gate sen_get_encstat(ses_softc_t *ssc, int slpflag)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate 	return (sen_rdstat(ssc, slpflag));
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate int
sen_set_encstat(ses_softc_t * ssc,uchar_t encstat,int slpflag)296*7c478bd9Sstevel@tonic-gate sen_set_encstat(ses_softc_t *ssc, uchar_t encstat, int slpflag)
297*7c478bd9Sstevel@tonic-gate {
298*7c478bd9Sstevel@tonic-gate 	UNUSED_PARAMETER(ssc);
299*7c478bd9Sstevel@tonic-gate 	UNUSED_PARAMETER(encstat);
300*7c478bd9Sstevel@tonic-gate 	UNUSED_PARAMETER(slpflag);
301*7c478bd9Sstevel@tonic-gate 	return (0);
302*7c478bd9Sstevel@tonic-gate }
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate int
sen_get_objstat(ses_softc_t * ssc,ses_objarg * obp,int slpflag)305*7c478bd9Sstevel@tonic-gate sen_get_objstat(ses_softc_t *ssc, ses_objarg *obp, int slpflag)
306*7c478bd9Sstevel@tonic-gate {
307*7c478bd9Sstevel@tonic-gate 	int i = (int)obp->obj_id;
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	if ((ssc->ses_encstat & ENCI_SVALID) == 0 ||
310*7c478bd9Sstevel@tonic-gate 	    (ssc->ses_objmap[i].svalid) == 0) {
311*7c478bd9Sstevel@tonic-gate 		int r = sen_rdstat(ssc, slpflag);
312*7c478bd9Sstevel@tonic-gate 		if (r)
313*7c478bd9Sstevel@tonic-gate 			return (r);
314*7c478bd9Sstevel@tonic-gate 	}
315*7c478bd9Sstevel@tonic-gate 	obp->cstat[0] = ssc->ses_objmap[i].encstat[0];
316*7c478bd9Sstevel@tonic-gate 	obp->cstat[1] = ssc->ses_objmap[i].encstat[1];
317*7c478bd9Sstevel@tonic-gate 	obp->cstat[2] = ssc->ses_objmap[i].encstat[2];
318*7c478bd9Sstevel@tonic-gate 	obp->cstat[3] = ssc->ses_objmap[i].encstat[3];
319*7c478bd9Sstevel@tonic-gate 	return (0);
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate int
sen_set_objstat(ses_softc_t * ssc,ses_objarg * obp,int slpflag)324*7c478bd9Sstevel@tonic-gate sen_set_objstat(ses_softc_t *ssc, ses_objarg *obp, int slpflag)
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate 	encobj *ep;
327*7c478bd9Sstevel@tonic-gate 	int err, runcmd, idx;
328*7c478bd9Sstevel@tonic-gate 	Uscmd local, *lp = &local;
329*7c478bd9Sstevel@tonic-gate 	char rqbuf[SENSE_LENGTH], *sdata;
330*7c478bd9Sstevel@tonic-gate 	static char cdb[CDB_GROUP0] =
331*7c478bd9Sstevel@tonic-gate 	    { SCMD_GDIAG, 0x10, 0x4, 0, SENPGINSIZE, 0 };
332*7c478bd9Sstevel@tonic-gate 	static char cdb1[CDB_GROUP0] =
333*7c478bd9Sstevel@tonic-gate 	    { SCMD_SDIAG, 0x10, 0, 0, SENPGOUTSIZE, 0 };
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	/*
336*7c478bd9Sstevel@tonic-gate 	 * If this is clear, we don't do diddly.
337*7c478bd9Sstevel@tonic-gate 	 */
338*7c478bd9Sstevel@tonic-gate 	if ((obp->cstat[0] & SESCTL_CSEL) == 0) {
339*7c478bd9Sstevel@tonic-gate 		return (0);
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 	/*
342*7c478bd9Sstevel@tonic-gate 	 * Fetch current data
343*7c478bd9Sstevel@tonic-gate 	 */
344*7c478bd9Sstevel@tonic-gate 	sdata = kmem_alloc(SENPGINSIZE, slpflag);
345*7c478bd9Sstevel@tonic-gate 	if (sdata == NULL)
346*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
347*7c478bd9Sstevel@tonic-gate 	lp->uscsi_flags = USCSI_READ|USCSI_RQENABLE;
348*7c478bd9Sstevel@tonic-gate 	lp->uscsi_timeout = ses_io_time;
349*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdb = cdb;
350*7c478bd9Sstevel@tonic-gate 	lp->uscsi_bufaddr = sdata;
351*7c478bd9Sstevel@tonic-gate 	lp->uscsi_buflen = SENPGINSIZE;
352*7c478bd9Sstevel@tonic-gate 	lp->uscsi_cdblen = sizeof (cdb);
353*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqbuf = rqbuf;
354*7c478bd9Sstevel@tonic-gate 	lp->uscsi_rqlen = sizeof (rqbuf);
355*7c478bd9Sstevel@tonic-gate 	err = ses_runcmd(ssc, lp);
356*7c478bd9Sstevel@tonic-gate 	if (err) {
357*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SENPGINSIZE);
358*7c478bd9Sstevel@tonic-gate 		return (err);
359*7c478bd9Sstevel@tonic-gate 	}
360*7c478bd9Sstevel@tonic-gate 	if ((lp->uscsi_buflen - lp->uscsi_resid)  < SENPGINSIZE) {
361*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, CE_NOTE, "Too Little Data Returned (%ld)",
362*7c478bd9Sstevel@tonic-gate 		    lp->uscsi_buflen - lp->uscsi_resid);
363*7c478bd9Sstevel@tonic-gate 		kmem_free(sdata, SENPGINSIZE);
364*7c478bd9Sstevel@tonic-gate 		return (EIO);
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 	/*
367*7c478bd9Sstevel@tonic-gate 	 * Okay, now convert the input page to the output page.
368*7c478bd9Sstevel@tonic-gate 	 */
369*7c478bd9Sstevel@tonic-gate 	sdata[1] = 0;
370*7c478bd9Sstevel@tonic-gate 	sdata[3] = 0x12;
371*7c478bd9Sstevel@tonic-gate 	sdata[6] = 1;
372*7c478bd9Sstevel@tonic-gate 	sdata[8] &= ~0x80;
373*7c478bd9Sstevel@tonic-gate 	sdata[10] = 0;
374*7c478bd9Sstevel@tonic-gate 	sdata[14] = sdata[20] & ~0x80;
375*7c478bd9Sstevel@tonic-gate 	sdata[15] = sdata[21] & ~0x80;
376*7c478bd9Sstevel@tonic-gate 	sdata[16] = sdata[22] & ~0x80;
377*7c478bd9Sstevel@tonic-gate 	sdata[17] = sdata[23] & ~0x80;
378*7c478bd9Sstevel@tonic-gate 	sdata[18] = sdata[24] & ~0x80;
379*7c478bd9Sstevel@tonic-gate 	sdata[19] = sdata[25] & ~0x80;
380*7c478bd9Sstevel@tonic-gate 	sdata[20] = sdata[26] & ~0x80;
381*7c478bd9Sstevel@tonic-gate 	sdata[21] = 0;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	runcmd = 0;
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	idx = (int)obp->obj_id;
386*7c478bd9Sstevel@tonic-gate 	ep = &ssc->ses_objmap[idx];
387*7c478bd9Sstevel@tonic-gate 	switch (ep->enctype) {
388*7c478bd9Sstevel@tonic-gate 	case SESTYP_DEVICE:
389*7c478bd9Sstevel@tonic-gate 		if (idx < 0 || idx >= NDRV) {
390*7c478bd9Sstevel@tonic-gate 			err = EINVAL;
391*7c478bd9Sstevel@tonic-gate 		} else if ((obp->cstat[3] & SESCTL_RQSFLT) != 0) {
392*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, SES_CE_DEBUG1, "faulted %d", idx);
393*7c478bd9Sstevel@tonic-gate 			sdata[14 + idx] |= 0x40;
394*7c478bd9Sstevel@tonic-gate 			runcmd++;
395*7c478bd9Sstevel@tonic-gate 		} else {
396*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, SES_CE_DEBUG1, "clrd fault on %d", idx);
397*7c478bd9Sstevel@tonic-gate 			sdata[14 + idx] &= ~0x40;
398*7c478bd9Sstevel@tonic-gate 			runcmd++;
399*7c478bd9Sstevel@tonic-gate 		}
400*7c478bd9Sstevel@tonic-gate 		break;
401*7c478bd9Sstevel@tonic-gate 	case SESTYP_POWER:
402*7c478bd9Sstevel@tonic-gate 		if ((obp->cstat[3] & SESCTL_RQSTFAIL) ||
403*7c478bd9Sstevel@tonic-gate 		    (obp->cstat[0] & SESCTL_DISABLE)) {
404*7c478bd9Sstevel@tonic-gate 			SES_LOG(ssc, CE_WARN, "Commanding Off Power Supply!");
405*7c478bd9Sstevel@tonic-gate 			sdata[10] |= 0x40;	/* Seppuku!!!! */
406*7c478bd9Sstevel@tonic-gate 			runcmd++;
407*7c478bd9Sstevel@tonic-gate 		}
408*7c478bd9Sstevel@tonic-gate 		break;
409*7c478bd9Sstevel@tonic-gate 	case SESTYP_ALARM:
410*7c478bd9Sstevel@tonic-gate 		/*
411*7c478bd9Sstevel@tonic-gate 		 * On all nonzero but the 'muted' bit,
412*7c478bd9Sstevel@tonic-gate 		 * we turn on the alarm,
413*7c478bd9Sstevel@tonic-gate 		 */
414*7c478bd9Sstevel@tonic-gate 		obp->cstat[3] &= ~0xa;
415*7c478bd9Sstevel@tonic-gate 		if ((obp->cstat[3] & 0x40) ||
416*7c478bd9Sstevel@tonic-gate 		    (obp->cstat[0] & SESCTL_DISABLE)) {
417*7c478bd9Sstevel@tonic-gate 			sdata[8] = 0;
418*7c478bd9Sstevel@tonic-gate 		} else if (obp->cstat[3] != 0) {
419*7c478bd9Sstevel@tonic-gate 			sdata[8] = 0x40;
420*7c478bd9Sstevel@tonic-gate 		} else {
421*7c478bd9Sstevel@tonic-gate 			sdata[8] = 0;
422*7c478bd9Sstevel@tonic-gate 		}
423*7c478bd9Sstevel@tonic-gate 		runcmd++;
424*7c478bd9Sstevel@tonic-gate 		SES_LOG(ssc, SES_CE_DEBUG1, "%sabling alarm",
425*7c478bd9Sstevel@tonic-gate 		    (sdata[8] & 0x40)? "en" : "dis");
426*7c478bd9Sstevel@tonic-gate 		break;
427*7c478bd9Sstevel@tonic-gate 	default:
428*7c478bd9Sstevel@tonic-gate 		break;
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	if (runcmd) {
432*7c478bd9Sstevel@tonic-gate 		lp->uscsi_flags = USCSI_WRITE|USCSI_RQENABLE;
433*7c478bd9Sstevel@tonic-gate 		lp->uscsi_timeout = ses_io_time;
434*7c478bd9Sstevel@tonic-gate 		lp->uscsi_cdb = cdb1;
435*7c478bd9Sstevel@tonic-gate 		lp->uscsi_bufaddr = sdata;
436*7c478bd9Sstevel@tonic-gate 		lp->uscsi_buflen = SENPGOUTSIZE;
437*7c478bd9Sstevel@tonic-gate 		lp->uscsi_cdblen = sizeof (cdb);
438*7c478bd9Sstevel@tonic-gate 		lp->uscsi_rqbuf = rqbuf;
439*7c478bd9Sstevel@tonic-gate 		lp->uscsi_rqlen = sizeof (rqbuf);
440*7c478bd9Sstevel@tonic-gate 		err = ses_runcmd(ssc, lp);
441*7c478bd9Sstevel@tonic-gate 		/* preserve error across the rest of the action */
442*7c478bd9Sstevel@tonic-gate 	} else {
443*7c478bd9Sstevel@tonic-gate 		err = 0;
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	mutex_enter(&ssc->ses_devp->sd_mutex);
447*7c478bd9Sstevel@tonic-gate 	ep->svalid = 0;
448*7c478bd9Sstevel@tonic-gate 	mutex_exit(&ssc->ses_devp->sd_mutex);
449*7c478bd9Sstevel@tonic-gate 	kmem_free(sdata, SENPGINSIZE);
450*7c478bd9Sstevel@tonic-gate 	return (err);
451*7c478bd9Sstevel@tonic-gate }
452*7c478bd9Sstevel@tonic-gate /*
453*7c478bd9Sstevel@tonic-gate  * mode: c
454*7c478bd9Sstevel@tonic-gate  * Local variables:
455*7c478bd9Sstevel@tonic-gate  * c-indent-level: 8
456*7c478bd9Sstevel@tonic-gate  * c-brace-imaginary-offset: 0
457*7c478bd9Sstevel@tonic-gate  * c-brace-offset: -8
458*7c478bd9Sstevel@tonic-gate  * c-argdecl-indent: 8
459*7c478bd9Sstevel@tonic-gate  * c-label-offset: -8
460*7c478bd9Sstevel@tonic-gate  * c-continued-statement-offset: 8
461*7c478bd9Sstevel@tonic-gate  * c-continued-brace-offset: 0
462*7c478bd9Sstevel@tonic-gate  * End:
463*7c478bd9Sstevel@tonic-gate  */
464