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