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