xref: /freebsd/sys/cam/scsi/scsi_enc_safte.c (revision f05cddf9)
1 /*-
2  * Copyright (c) 2000 Matthew Jacob
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. The name of the author may not be used to endorse or promote products
12  *    derived from this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 
32 #include <sys/conf.h>
33 #include <sys/errno.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/mutex.h>
37 #include <sys/queue.h>
38 #include <sys/sx.h>
39 #include <sys/systm.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
42 
43 #include <cam/cam.h>
44 #include <cam/cam_ccb.h>
45 #include <cam/cam_periph.h>
46 
47 #include <cam/scsi/scsi_enc.h>
48 #include <cam/scsi/scsi_enc_internal.h>
49 #include <cam/scsi/scsi_message.h>
50 
51 /*
52  * SAF-TE Type Device Emulation
53  */
54 
55 static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
56 
57 #define	ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
58 	SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
59 /*
60  * SAF-TE specific defines- Mandatory ones only...
61  */
62 
63 /*
64  * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
65  */
66 #define	SAFTE_RD_RDCFG	0x00	/* read enclosure configuration */
67 #define	SAFTE_RD_RDESTS	0x01	/* read enclosure status */
68 #define	SAFTE_RD_RDDSTS	0x04	/* read drive slot status */
69 #define	SAFTE_RD_RDGFLG	0x05	/* read global flags */
70 
71 /*
72  * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
73  */
74 #define	SAFTE_WT_DSTAT	0x10	/* write device slot status */
75 #define	SAFTE_WT_SLTOP	0x12	/* perform slot operation */
76 #define	SAFTE_WT_FANSPD	0x13	/* set fan speed */
77 #define	SAFTE_WT_ACTPWS	0x14	/* turn on/off power supply */
78 #define	SAFTE_WT_GLOBAL	0x15	/* send global command */
79 
80 #define	SAFT_SCRATCH	64
81 #define	SCSZ		0x8000
82 
83 typedef enum {
84 	SAFTE_UPDATE_NONE,
85 	SAFTE_UPDATE_READCONFIG,
86 	SAFTE_UPDATE_READGFLAGS,
87 	SAFTE_UPDATE_READENCSTATUS,
88 	SAFTE_UPDATE_READSLOTSTATUS,
89 	SAFTE_PROCESS_CONTROL_REQS,
90 	SAFTE_NUM_UPDATE_STATES
91 } safte_update_action;
92 
93 static fsm_fill_handler_t safte_fill_read_buf_io;
94 static fsm_fill_handler_t safte_fill_control_request;
95 static fsm_done_handler_t safte_process_config;
96 static fsm_done_handler_t safte_process_gflags;
97 static fsm_done_handler_t safte_process_status;
98 static fsm_done_handler_t safte_process_slotstatus;
99 static fsm_done_handler_t safte_process_control_request;
100 
101 static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
102 {
103 	{ "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
104 	{
105 		"SAFTE_UPDATE_READCONFIG",
106 		SAFTE_RD_RDCFG,
107 		SAFT_SCRATCH,
108 		60 * 1000,
109 		safte_fill_read_buf_io,
110 		safte_process_config,
111 		enc_error
112 	},
113 	{
114 		"SAFTE_UPDATE_READGFLAGS",
115 		SAFTE_RD_RDGFLG,
116 		16,
117 		60 * 1000,
118 		safte_fill_read_buf_io,
119 		safte_process_gflags,
120 		enc_error
121 	},
122 	{
123 		"SAFTE_UPDATE_READENCSTATUS",
124 		SAFTE_RD_RDESTS,
125 		SCSZ,
126 		60 * 1000,
127 		safte_fill_read_buf_io,
128 		safte_process_status,
129 		enc_error
130 	},
131 	{
132 		"SAFTE_UPDATE_READSLOTSTATUS",
133 		SAFTE_RD_RDDSTS,
134 		SCSZ,
135 		60 * 1000,
136 		safte_fill_read_buf_io,
137 		safte_process_slotstatus,
138 		enc_error
139 	},
140 	{
141 		"SAFTE_PROCESS_CONTROL_REQS",
142 		0,
143 		SCSZ,
144 		60 * 1000,
145 		safte_fill_control_request,
146 		safte_process_control_request,
147 		enc_error
148 	}
149 };
150 
151 typedef struct safte_control_request {
152 	int	elm_idx;
153 	uint8_t	elm_stat[4];
154 	int	result;
155 	TAILQ_ENTRY(safte_control_request) links;
156 } safte_control_request_t;
157 TAILQ_HEAD(safte_control_reqlist, safte_control_request);
158 typedef struct safte_control_reqlist safte_control_reqlist_t;
159 enum {
160 	SES_SETSTATUS_ENC_IDX = -1
161 };
162 
163 static void
164 safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
165 {
166 	safte_control_request_t *req;
167 
168 	while ((req = TAILQ_FIRST(reqlist)) != NULL) {
169 		TAILQ_REMOVE(reqlist, req, links);
170 		req->result = result;
171 		wakeup(req);
172 	}
173 }
174 
175 struct scfg {
176 	/*
177 	 * Cached Configuration
178 	 */
179 	uint8_t	Nfans;		/* Number of Fans */
180 	uint8_t	Npwr;		/* Number of Power Supplies */
181 	uint8_t	Nslots;		/* Number of Device Slots */
182 	uint8_t	DoorLock;	/* Door Lock Installed */
183 	uint8_t	Ntherm;		/* Number of Temperature Sensors */
184 	uint8_t	Nspkrs;		/* Number of Speakers */
185 	uint8_t	Ntstats;	/* Number of Thermostats */
186 	/*
187 	 * Cached Flag Bytes for Global Status
188 	 */
189 	uint8_t	flag1;
190 	uint8_t	flag2;
191 	/*
192 	 * What object index ID is where various slots start.
193 	 */
194 	uint8_t	pwroff;
195 	uint8_t	slotoff;
196 #define	SAFT_ALARM_OFFSET(cc)	(cc)->slotoff - 1
197 
198 	encioc_enc_status_t	adm_status;
199 	encioc_enc_status_t	enc_status;
200 	encioc_enc_status_t	slot_status;
201 
202 	safte_control_reqlist_t	requests;
203 	safte_control_request_t	*current_request;
204 	int			current_request_stage;
205 	int			current_request_stages;
206 };
207 
208 #define	SAFT_FLG1_ALARM		0x1
209 #define	SAFT_FLG1_GLOBFAIL	0x2
210 #define	SAFT_FLG1_GLOBWARN	0x4
211 #define	SAFT_FLG1_ENCPWROFF	0x8
212 #define	SAFT_FLG1_ENCFANFAIL	0x10
213 #define	SAFT_FLG1_ENCPWRFAIL	0x20
214 #define	SAFT_FLG1_ENCDRVFAIL	0x40
215 #define	SAFT_FLG1_ENCDRVWARN	0x80
216 
217 #define	SAFT_FLG2_LOCKDOOR	0x4
218 #define	SAFT_PRIVATE		sizeof (struct scfg)
219 
220 static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
221 #define	SAFT_BAIL(r, x)	\
222 	if ((r) >= (x)) { \
223 		ENC_VLOG(enc, safte_2little, x, __LINE__);\
224 		return (EIO); \
225 	}
226 
227 int emulate_array_devices = 1;
228 SYSCTL_DECL(_kern_cam_enc);
229 SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RW,
230            &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
231 TUNABLE_INT("kern.cam.enc.emulate_array_devices", &emulate_array_devices);
232 
233 static int
234 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
235 		       union ccb *ccb, uint8_t *buf)
236 {
237 
238 	if (state->page_code != SAFTE_RD_RDCFG &&
239 	    enc->enc_cache.nelms == 0) {
240 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
241 		return (-1);
242 	}
243 
244 	if (enc->enc_type == ENC_SEMB_SAFT) {
245 		semb_read_buffer(&ccb->ataio, /*retries*/5,
246 				enc_done, MSG_SIMPLE_Q_TAG,
247 				state->page_code, buf, state->buf_size,
248 				state->timeout);
249 	} else {
250 		scsi_read_buffer(&ccb->csio, /*retries*/5,
251 				enc_done, MSG_SIMPLE_Q_TAG, 1,
252 				state->page_code, 0, buf, state->buf_size,
253 				SSD_FULL_SIZE, state->timeout);
254 	}
255 	return (0);
256 }
257 
258 static int
259 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
260     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
261 {
262 	struct scfg *cfg;
263 	uint8_t *buf = *bufp;
264 	int i, r;
265 
266 	cfg = enc->enc_private;
267 	if (cfg == NULL)
268 		return (ENXIO);
269 	if (error != 0)
270 		return (error);
271 	if (xfer_len < 6) {
272 		ENC_VLOG(enc, "too little data (%d) for configuration\n",
273 		    xfer_len);
274 		return (EIO);
275 	}
276 	cfg->Nfans = buf[0];
277 	cfg->Npwr = buf[1];
278 	cfg->Nslots = buf[2];
279 	cfg->DoorLock = buf[3];
280 	cfg->Ntherm = buf[4];
281 	cfg->Nspkrs = buf[5];
282 	if (xfer_len >= 7)
283 		cfg->Ntstats = buf[6] & 0x0f;
284 	else
285 		cfg->Ntstats = 0;
286 	ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
287 	    "Ntstats %d\n",
288 	    cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
289 	    cfg->Nspkrs, cfg->Ntstats);
290 
291 	enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
292 	    cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
293 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
294 	enc->enc_cache.elm_map =
295 	    ENC_MALLOCZ(enc->enc_cache.nelms * sizeof(enc_element_t));
296 	if (enc->enc_cache.elm_map == NULL) {
297 		enc->enc_cache.nelms = 0;
298 		return (ENOMEM);
299 	}
300 
301 	r = 0;
302 	/*
303 	 * Note that this is all arranged for the convenience
304 	 * in later fetches of status.
305 	 */
306 	for (i = 0; i < cfg->Nfans; i++)
307 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
308 	cfg->pwroff = (uint8_t) r;
309 	for (i = 0; i < cfg->Npwr; i++)
310 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
311 	for (i = 0; i < cfg->DoorLock; i++)
312 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
313 	if (cfg->Nspkrs > 0)
314 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
315 	for (i = 0; i < cfg->Ntherm; i++)
316 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
317 	for (i = 0; i <= cfg->Ntstats; i++)
318 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
319 	cfg->slotoff = (uint8_t) r;
320 	for (i = 0; i < cfg->Nslots; i++)
321 		enc->enc_cache.elm_map[r++].enctype =
322 		    emulate_array_devices ? ELMTYP_ARRAY_DEV :
323 		     ELMTYP_DEVICE;
324 
325 	enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
326 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
327 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
328 
329 	return (0);
330 }
331 
332 static int
333 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
334     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
335 {
336 	struct scfg *cfg;
337 	uint8_t *buf = *bufp;
338 
339 	cfg = enc->enc_private;
340 	if (cfg == NULL)
341 		return (ENXIO);
342 	if (error != 0)
343 		return (error);
344 	SAFT_BAIL(3, xfer_len);
345 	cfg->flag1 = buf[1];
346 	cfg->flag2 = buf[2];
347 
348 	cfg->adm_status = 0;
349 	if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
350 		cfg->adm_status |= SES_ENCSTAT_CRITICAL;
351 	else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
352 		cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
353 
354 	return (0);
355 }
356 
357 static int
358 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
359     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
360 {
361 	struct scfg *cfg;
362 	uint8_t *buf = *bufp;
363 	int oid, r, i, nitems;
364 	uint16_t tempflags;
365 	enc_cache_t *cache = &enc->enc_cache;
366 
367 	cfg = enc->enc_private;
368 	if (cfg == NULL)
369 		return (ENXIO);
370 	if (error != 0)
371 		return (error);
372 
373 	oid = r = 0;
374 	cfg->enc_status = 0;
375 
376 	for (nitems = i = 0; i < cfg->Nfans; i++) {
377 		SAFT_BAIL(r, xfer_len);
378 		/*
379 		 * 0 = Fan Operational
380 		 * 1 = Fan is malfunctioning
381 		 * 2 = Fan is not present
382 		 * 0x80 = Unknown or Not Reportable Status
383 		 */
384 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
385 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
386 		if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
387 			cache->elm_map[oid].encstat[3] |= 0x40;
388 		else
389 			cache->elm_map[oid].encstat[3] &= ~0x40;
390 		switch ((int)buf[r]) {
391 		case 0:
392 			nitems++;
393 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
394 			if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
395 				cache->elm_map[oid].encstat[3] |= 0x27;
396 			break;
397 
398 		case 1:
399 			cache->elm_map[oid].encstat[0] =
400 			    SES_OBJSTAT_CRIT;
401 			/*
402 			 * FAIL and FAN STOPPED synthesized
403 			 */
404 			cache->elm_map[oid].encstat[3] |= 0x10;
405 			cache->elm_map[oid].encstat[3] &= ~0x07;
406 			/*
407 			 * Enclosure marked with CRITICAL error
408 			 * if only one fan or no thermometers,
409 			 * else the NONCRITICAL error is set.
410 			 */
411 			if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
412 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
413 			else
414 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
415 			break;
416 		case 2:
417 			cache->elm_map[oid].encstat[0] =
418 			    SES_OBJSTAT_NOTINSTALLED;
419 			cache->elm_map[oid].encstat[3] |= 0x10;
420 			cache->elm_map[oid].encstat[3] &= ~0x07;
421 			/*
422 			 * Enclosure marked with CRITICAL error
423 			 * if only one fan or no thermometers,
424 			 * else the NONCRITICAL error is set.
425 			 */
426 			if (cfg->Nfans == 1)
427 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
428 			else
429 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
430 			break;
431 		case 0x80:
432 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
433 			cache->elm_map[oid].encstat[3] = 0;
434 			cfg->enc_status |= SES_ENCSTAT_INFO;
435 			break;
436 		default:
437 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
438 			ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
439 			    buf[r] & 0xff);
440 			break;
441 		}
442 		cache->elm_map[oid++].svalid = 1;
443 		r++;
444 	}
445 
446 	/*
447 	 * No matter how you cut it, no cooling elements when there
448 	 * should be some there is critical.
449 	 */
450 	if (cfg->Nfans && nitems == 0)
451 		cfg->enc_status |= SES_ENCSTAT_CRITICAL;
452 
453 	for (i = 0; i < cfg->Npwr; i++) {
454 		SAFT_BAIL(r, xfer_len);
455 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
456 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
457 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
458 		cache->elm_map[oid].encstat[3] = 0x20;	/* requested on */
459 		switch (buf[r]) {
460 		case 0x00:	/* pws operational and on */
461 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
462 			break;
463 		case 0x01:	/* pws operational and off */
464 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
465 			cache->elm_map[oid].encstat[3] = 0x10;
466 			cfg->enc_status |= SES_ENCSTAT_INFO;
467 			break;
468 		case 0x10:	/* pws is malfunctioning and commanded on */
469 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
470 			cache->elm_map[oid].encstat[3] = 0x61;
471 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
472 			break;
473 
474 		case 0x11:	/* pws is malfunctioning and commanded off */
475 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
476 			cache->elm_map[oid].encstat[3] = 0x51;
477 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
478 			break;
479 		case 0x20:	/* pws is not present */
480 			cache->elm_map[oid].encstat[0] =
481 			    SES_OBJSTAT_NOTINSTALLED;
482 			cache->elm_map[oid].encstat[3] = 0;
483 			cfg->enc_status |= SES_ENCSTAT_INFO;
484 			break;
485 		case 0x21:	/* pws is present */
486 			/*
487 			 * This is for enclosures that cannot tell whether the
488 			 * device is on or malfunctioning, but know that it is
489 			 * present. Just fall through.
490 			 */
491 			/* FALLTHROUGH */
492 		case 0x80:	/* Unknown or Not Reportable Status */
493 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
494 			cache->elm_map[oid].encstat[3] = 0;
495 			cfg->enc_status |= SES_ENCSTAT_INFO;
496 			break;
497 		default:
498 			ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
499 			    i, buf[r] & 0xff);
500 			break;
501 		}
502 		enc->enc_cache.elm_map[oid++].svalid = 1;
503 		r++;
504 	}
505 
506 	/*
507 	 * Copy Slot SCSI IDs
508 	 */
509 	for (i = 0; i < cfg->Nslots; i++) {
510 		SAFT_BAIL(r, xfer_len);
511 		if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
512 			cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
513 		r++;
514 	}
515 
516 	/*
517 	 * We always have doorlock status, no matter what,
518 	 * but we only save the status if we have one.
519 	 */
520 	SAFT_BAIL(r, xfer_len);
521 	if (cfg->DoorLock) {
522 		/*
523 		 * 0 = Door Locked
524 		 * 1 = Door Unlocked, or no Lock Installed
525 		 * 0x80 = Unknown or Not Reportable Status
526 		 */
527 		cache->elm_map[oid].encstat[1] = 0;
528 		cache->elm_map[oid].encstat[2] = 0;
529 		switch (buf[r]) {
530 		case 0:
531 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
532 			cache->elm_map[oid].encstat[3] = 0;
533 			break;
534 		case 1:
535 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
536 			cache->elm_map[oid].encstat[3] = 1;
537 			break;
538 		case 0x80:
539 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
540 			cache->elm_map[oid].encstat[3] = 0;
541 			cfg->enc_status |= SES_ENCSTAT_INFO;
542 			break;
543 		default:
544 			cache->elm_map[oid].encstat[0] =
545 			    SES_OBJSTAT_UNSUPPORTED;
546 			ENC_VLOG(enc, "unknown lock status 0x%x\n",
547 			    buf[r] & 0xff);
548 			break;
549 		}
550 		cache->elm_map[oid++].svalid = 1;
551 	}
552 	r++;
553 
554 	/*
555 	 * We always have speaker status, no matter what,
556 	 * but we only save the status if we have one.
557 	 */
558 	SAFT_BAIL(r, xfer_len);
559 	if (cfg->Nspkrs) {
560 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
561 		cache->elm_map[oid].encstat[1] = 0;
562 		cache->elm_map[oid].encstat[2] = 0;
563 		if (buf[r] == 0) {
564 			cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
565 			cache->elm_map[oid].encstat[3] |= 0x40;
566 		}
567 		cache->elm_map[oid++].svalid = 1;
568 	}
569 	r++;
570 
571 	/*
572 	 * Now, for "pseudo" thermometers, we have two bytes
573 	 * of information in enclosure status- 16 bits. Actually,
574 	 * the MSB is a single TEMP ALERT flag indicating whether
575 	 * any other bits are set, but, thanks to fuzzy thinking,
576 	 * in the SAF-TE spec, this can also be set even if no
577 	 * other bits are set, thus making this really another
578 	 * binary temperature sensor.
579 	 */
580 
581 	SAFT_BAIL(r + cfg->Ntherm, xfer_len);
582 	tempflags = buf[r + cfg->Ntherm];
583 	SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
584 	tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
585 
586 	for (i = 0; i < cfg->Ntherm; i++) {
587 		SAFT_BAIL(r, xfer_len);
588 		/*
589 		 * Status is a range from -10 to 245 deg Celsius,
590 		 * which we need to normalize to -20 to -245 according
591 		 * to the latest SCSI spec, which makes little
592 		 * sense since this would overflow an 8bit value.
593 		 * Well, still, the base normalization is -20,
594 		 * not -10, so we have to adjust.
595 		 *
596 		 * So what's over and under temperature?
597 		 * Hmm- we'll state that 'normal' operating
598 		 * is 10 to 40 deg Celsius.
599 		 */
600 
601 		/*
602 		 * Actually.... All of the units that people out in the world
603 		 * seem to have do not come even close to setting a value that
604 		 * complies with this spec.
605 		 *
606 		 * The closest explanation I could find was in an
607 		 * LSI-Logic manual, which seemed to indicate that
608 		 * this value would be set by whatever the I2C code
609 		 * would interpolate from the output of an LM75
610 		 * temperature sensor.
611 		 *
612 		 * This means that it is impossible to use the actual
613 		 * numeric value to predict anything. But we don't want
614 		 * to lose the value. So, we'll propagate the *uncorrected*
615 		 * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
616 		 * temperature flags for warnings.
617 		 */
618 		if (tempflags & (1 << i)) {
619 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
620 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
621 		} else
622 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
623 		cache->elm_map[oid].encstat[1] = 0;
624 		cache->elm_map[oid].encstat[2] = buf[r];
625 		cache->elm_map[oid].encstat[3] = 0;
626 		cache->elm_map[oid++].svalid = 1;
627 		r++;
628 	}
629 
630 	for (i = 0; i <= cfg->Ntstats; i++) {
631 		cache->elm_map[oid].encstat[1] = 0;
632 		if (tempflags & (1 <<
633 		    ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
634 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
635 			cache->elm_map[4].encstat[2] = 0xff;
636 			/*
637 			 * Set 'over temperature' failure.
638 			 */
639 			cache->elm_map[oid].encstat[3] = 8;
640 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
641 		} else {
642 			/*
643 			 * We used to say 'not available' and synthesize a
644 			 * nominal 30 deg (C)- that was wrong. Actually,
645 			 * Just say 'OK', and use the reserved value of
646 			 * zero.
647 			 */
648 			if ((cfg->Ntherm + cfg->Ntstats) == 0)
649 				cache->elm_map[oid].encstat[0] =
650 				    SES_OBJSTAT_NOTAVAIL;
651 			else
652 				cache->elm_map[oid].encstat[0] =
653 				    SES_OBJSTAT_OK;
654 			cache->elm_map[oid].encstat[2] = 0;
655 			cache->elm_map[oid].encstat[3] = 0;
656 		}
657 		cache->elm_map[oid++].svalid = 1;
658 	}
659 	r += 2;
660 
661 	cache->enc_status =
662 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
663 	return (0);
664 }
665 
666 static int
667 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
668     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
669 {
670 	struct scfg *cfg;
671 	uint8_t *buf = *bufp;
672 	enc_cache_t *cache = &enc->enc_cache;
673 	int oid, r, i;
674 
675 	cfg = enc->enc_private;
676 	if (cfg == NULL)
677 		return (ENXIO);
678 	if (error != 0)
679 		return (error);
680 	cfg->slot_status = 0;
681 	oid = cfg->slotoff;
682 	for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
683 		SAFT_BAIL(r+3, xfer_len);
684 		if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
685 			cache->elm_map[oid].encstat[1] = 0;
686 		cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
687 		cache->elm_map[oid].encstat[3] = 0;
688 		if ((buf[r+3] & 0x01) == 0) {	/* no device */
689 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
690 		} else if (buf[r+0] & 0x02) {
691 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
692 			cfg->slot_status |= SES_ENCSTAT_CRITICAL;
693 		} else if (buf[r+0] & 0x40) {
694 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
695 			cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
696 		} else {
697 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
698 		}
699 		if (buf[r+3] & 0x2) {
700 			if (buf[r+3] & 0x01)
701 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
702 			else
703 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
704 		}
705 		if ((buf[r+3] & 0x04) == 0)
706 			cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
707 		if (buf[r+0] & 0x02)
708 			cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
709 		if (buf[r+0] & 0x40)
710 			cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
711 		if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
712 			if (buf[r+0] & 0x01)
713 				cache->elm_map[oid].encstat[1] |= 0x80;
714 			if (buf[r+0] & 0x04)
715 				cache->elm_map[oid].encstat[1] |= 0x02;
716 			if (buf[r+0] & 0x08)
717 				cache->elm_map[oid].encstat[1] |= 0x04;
718 			if (buf[r+0] & 0x10)
719 				cache->elm_map[oid].encstat[1] |= 0x08;
720 			if (buf[r+0] & 0x20)
721 				cache->elm_map[oid].encstat[1] |= 0x10;
722 			if (buf[r+1] & 0x01)
723 				cache->elm_map[oid].encstat[1] |= 0x20;
724 			if (buf[r+1] & 0x02)
725 				cache->elm_map[oid].encstat[1] |= 0x01;
726 		}
727 		cache->elm_map[oid++].svalid = 1;
728 	}
729 
730 	cache->enc_status =
731 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
732 	return (0);
733 }
734 
735 static int
736 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
737 		       union ccb *ccb, uint8_t *buf)
738 {
739 	struct scfg *cfg;
740 	enc_element_t *ep, *ep1;
741 	safte_control_request_t *req;
742 	int i, idx, xfer_len;
743 
744 	cfg = enc->enc_private;
745 	if (cfg == NULL)
746 		return (ENXIO);
747 
748 	if (enc->enc_cache.nelms == 0) {
749 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
750 		return (-1);
751 	}
752 
753 	if (cfg->current_request == NULL) {
754 		cfg->current_request = TAILQ_FIRST(&cfg->requests);
755 		TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
756 		cfg->current_request_stage = 0;
757 		cfg->current_request_stages = 1;
758 	}
759 	req = cfg->current_request;
760 
761 	idx = (int)req->elm_idx;
762 	if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
763 		cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
764 		cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
765 		if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
766 			cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
767 		else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
768 			cfg->flag1 |= SAFT_FLG1_GLOBWARN;
769 		buf[0] = SAFTE_WT_GLOBAL;
770 		buf[1] = cfg->flag1;
771 		buf[2] = cfg->flag2;
772 		buf[3] = 0;
773 		xfer_len = 16;
774 	} else {
775 		ep = &enc->enc_cache.elm_map[idx];
776 
777 		switch (ep->enctype) {
778 		case ELMTYP_DEVICE:
779 		case ELMTYP_ARRAY_DEV:
780 			switch (cfg->current_request_stage) {
781 			case 0:
782 				ep->priv = 0;
783 				if (req->elm_stat[0] & SESCTL_PRDFAIL)
784 					ep->priv |= 0x40;
785 				if (req->elm_stat[3] & SESCTL_RQSFLT)
786 					ep->priv |= 0x02;
787 				if (ep->enctype == ELMTYP_ARRAY_DEV) {
788 					if (req->elm_stat[1] & 0x01)
789 						ep->priv |= 0x200;
790 					if (req->elm_stat[1] & 0x02)
791 						ep->priv |= 0x04;
792 					if (req->elm_stat[1] & 0x04)
793 						ep->priv |= 0x08;
794 					if (req->elm_stat[1] & 0x08)
795 						ep->priv |= 0x10;
796 					if (req->elm_stat[1] & 0x10)
797 						ep->priv |= 0x20;
798 					if (req->elm_stat[1] & 0x20)
799 						ep->priv |= 0x100;
800 					if (req->elm_stat[1] & 0x80)
801 						ep->priv |= 0x01;
802 				}
803 				if (ep->priv == 0)
804 					ep->priv |= 0x01;	/* no errors */
805 
806 				buf[0] = SAFTE_WT_DSTAT;
807 				for (i = 0; i < cfg->Nslots; i++) {
808 					ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
809 					buf[1 + (3 * i)] = ep1->priv;
810 					buf[2 + (3 * i)] = ep1->priv >> 8;
811 				}
812 				xfer_len = cfg->Nslots * 3 + 1;
813 #define DEVON(x)	(!(((x)[2] & SESCTL_RQSINS) |	\
814 			   ((x)[2] & SESCTL_RQSRMV) |	\
815 			   ((x)[3] & SESCTL_DEVOFF)))
816 				if (DEVON(req->elm_stat) != DEVON(ep->encstat))
817 					cfg->current_request_stages++;
818 #define IDON(x)		(!!((x)[2] & SESCTL_RQSID))
819 				if (IDON(req->elm_stat) != IDON(ep->encstat))
820 					cfg->current_request_stages++;
821 				break;
822 			case 1:
823 			case 2:
824 				buf[0] = SAFTE_WT_SLTOP;
825 				buf[1] = idx - cfg->slotoff;
826 				if (cfg->current_request_stage == 1 &&
827 				    DEVON(req->elm_stat) != DEVON(ep->encstat)) {
828 					if (DEVON(req->elm_stat))
829 						buf[2] = 0x01;
830 					else
831 						buf[2] = 0x02;
832 				} else {
833 					if (IDON(req->elm_stat))
834 						buf[2] = 0x04;
835 					else
836 						buf[2] = 0x00;
837 					ep->encstat[2] &= ~SESCTL_RQSID;
838 					ep->encstat[2] |= req->elm_stat[2] &
839 					    SESCTL_RQSID;
840 				}
841 				xfer_len = 64;
842 				break;
843 			default:
844 				return (EINVAL);
845 			}
846 			break;
847 		case ELMTYP_POWER:
848 			cfg->current_request_stages = 2;
849 			switch (cfg->current_request_stage) {
850 			case 0:
851 				if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
852 					cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
853 				} else {
854 					cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
855 				}
856 				buf[0] = SAFTE_WT_GLOBAL;
857 				buf[1] = cfg->flag1;
858 				buf[2] = cfg->flag2;
859 				buf[3] = 0;
860 				xfer_len = 16;
861 				break;
862 			case 1:
863 				buf[0] = SAFTE_WT_ACTPWS;
864 				buf[1] = idx - cfg->pwroff;
865 				if (req->elm_stat[3] & SESCTL_RQSTON)
866 					buf[2] = 0x01;
867 				else
868 					buf[2] = 0x00;
869 				buf[3] = 0;
870 				xfer_len = 16;
871 			default:
872 				return (EINVAL);
873 			}
874 			break;
875 		case ELMTYP_FAN:
876 			if ((req->elm_stat[3] & 0x7) != 0)
877 				cfg->current_request_stages = 2;
878 			switch (cfg->current_request_stage) {
879 			case 0:
880 				if (req->elm_stat[3] & SESCTL_RQSTFAIL)
881 					cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
882 				else
883 					cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
884 				buf[0] = SAFTE_WT_GLOBAL;
885 				buf[1] = cfg->flag1;
886 				buf[2] = cfg->flag2;
887 				buf[3] = 0;
888 				xfer_len = 16;
889 				break;
890 			case 1:
891 				buf[0] = SAFTE_WT_FANSPD;
892 				buf[1] = idx;
893 				if (req->elm_stat[3] & SESCTL_RQSTON) {
894 					if ((req->elm_stat[3] & 0x7) == 7)
895 						buf[2] = 4;
896 					else if ((req->elm_stat[3] & 0x7) >= 5)
897 						buf[2] = 3;
898 					else if ((req->elm_stat[3] & 0x7) >= 3)
899 						buf[2] = 2;
900 					else
901 						buf[2] = 1;
902 				} else
903 					buf[2] = 0;
904 				buf[3] = 0;
905 				xfer_len = 16;
906 				ep->encstat[3] = req->elm_stat[3] & 0x67;
907 			default:
908 				return (EINVAL);
909 			}
910 			break;
911 		case ELMTYP_DOORLOCK:
912 			if (req->elm_stat[3] & 0x1)
913 				cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
914 			else
915 				cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
916 			buf[0] = SAFTE_WT_GLOBAL;
917 			buf[1] = cfg->flag1;
918 			buf[2] = cfg->flag2;
919 			buf[3] = 0;
920 			xfer_len = 16;
921 			break;
922 		case ELMTYP_ALARM:
923 			if ((req->elm_stat[0] & SESCTL_DISABLE) ||
924 			    (req->elm_stat[3] & 0x40)) {
925 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
926 			} else if ((req->elm_stat[3] & 0x0f) != 0) {
927 				cfg->flag2 |= SAFT_FLG1_ALARM;
928 			} else {
929 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
930 			}
931 			buf[0] = SAFTE_WT_GLOBAL;
932 			buf[1] = cfg->flag1;
933 			buf[2] = cfg->flag2;
934 			buf[3] = 0;
935 			xfer_len = 16;
936 			ep->encstat[3] = req->elm_stat[3];
937 			break;
938 		default:
939 			return (EINVAL);
940 		}
941 	}
942 
943 	if (enc->enc_type == ENC_SEMB_SAFT) {
944 		semb_write_buffer(&ccb->ataio, /*retries*/5,
945 				enc_done, MSG_SIMPLE_Q_TAG,
946 				buf, xfer_len, state->timeout);
947 	} else {
948 		scsi_write_buffer(&ccb->csio, /*retries*/5,
949 				enc_done, MSG_SIMPLE_Q_TAG, 1,
950 				0, 0, buf, xfer_len,
951 				SSD_FULL_SIZE, state->timeout);
952 	}
953 	return (0);
954 }
955 
956 static int
957 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
958     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
959 {
960 	struct scfg *cfg;
961 	safte_control_request_t *req;
962 	int idx, type;
963 
964 	cfg = enc->enc_private;
965 	if (cfg == NULL)
966 		return (ENXIO);
967 
968 	req = cfg->current_request;
969 	if (req->result == 0)
970 		req->result = error;
971 	if (++cfg->current_request_stage >= cfg->current_request_stages) {
972 		idx = req->elm_idx;
973 		if (idx == SES_SETSTATUS_ENC_IDX)
974 			type = -1;
975 		else
976 			type = enc->enc_cache.elm_map[idx].enctype;
977 		if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
978 			enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
979 		else
980 			enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
981 		cfg->current_request = NULL;
982 		wakeup(req);
983 	} else {
984 		enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
985 	}
986 	return (0);
987 }
988 
989 static void
990 safte_softc_invalidate(enc_softc_t *enc)
991 {
992 	struct scfg *cfg;
993 
994 	cfg = enc->enc_private;
995 	safte_terminate_control_requests(&cfg->requests, ENXIO);
996 }
997 
998 static void
999 safte_softc_cleanup(enc_softc_t *enc)
1000 {
1001 
1002 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
1003 	ENC_FREE_AND_NULL(enc->enc_private);
1004 	enc->enc_cache.nelms = 0;
1005 }
1006 
1007 static int
1008 safte_init_enc(enc_softc_t *enc)
1009 {
1010 	struct scfg *cfg;
1011 	int err;
1012 	static char cdb0[6] = { SEND_DIAGNOSTIC };
1013 
1014 	cfg = enc->enc_private;
1015 	if (cfg == NULL)
1016 		return (ENXIO);
1017 
1018 	err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1019 	if (err) {
1020 		return (err);
1021 	}
1022 	DELAY(5000);
1023 	cfg->flag1 = 0;
1024 	cfg->flag2 = 0;
1025 	err = safte_set_enc_status(enc, 0, 1);
1026 	return (err);
1027 }
1028 
1029 static int
1030 safte_get_enc_status(enc_softc_t *enc, int slpflg)
1031 {
1032 
1033 	return (0);
1034 }
1035 
1036 static int
1037 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1038 {
1039 	struct scfg *cfg;
1040 	safte_control_request_t req;
1041 
1042 	cfg = enc->enc_private;
1043 	if (cfg == NULL)
1044 		return (ENXIO);
1045 
1046 	req.elm_idx = SES_SETSTATUS_ENC_IDX;
1047 	req.elm_stat[0] = encstat & 0xf;
1048 	req.result = 0;
1049 
1050 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1051 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1052 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1053 
1054 	return (req.result);
1055 }
1056 
1057 static int
1058 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1059 {
1060 	int i = (int)elms->elm_idx;
1061 
1062 	elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1063 	elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1064 	elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1065 	elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1066 	return (0);
1067 }
1068 
1069 static int
1070 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1071 {
1072 	struct scfg *cfg;
1073 	safte_control_request_t req;
1074 
1075 	cfg = enc->enc_private;
1076 	if (cfg == NULL)
1077 		return (ENXIO);
1078 
1079 	/* If this is clear, we don't do diddly.  */
1080 	if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1081 		return (0);
1082 
1083 	req.elm_idx = elms->elm_idx;
1084 	memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1085 	req.result = 0;
1086 
1087 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1088 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1089 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1090 
1091 	return (req.result);
1092 }
1093 
1094 static void
1095 safte_poll_status(enc_softc_t *enc)
1096 {
1097 
1098 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1099 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1100 }
1101 
1102 static struct enc_vec safte_enc_vec =
1103 {
1104 	.softc_invalidate	= safte_softc_invalidate,
1105 	.softc_cleanup	= safte_softc_cleanup,
1106 	.init_enc	= safte_init_enc,
1107 	.get_enc_status	= safte_get_enc_status,
1108 	.set_enc_status	= safte_set_enc_status,
1109 	.get_elm_status	= safte_get_elm_status,
1110 	.set_elm_status	= safte_set_elm_status,
1111 	.poll_status	= safte_poll_status
1112 };
1113 
1114 int
1115 safte_softc_init(enc_softc_t *enc)
1116 {
1117 	struct scfg *cfg;
1118 
1119 	enc->enc_vec = safte_enc_vec;
1120 	enc->enc_fsm_states = enc_fsm_states;
1121 
1122 	if (enc->enc_private == NULL) {
1123 		enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1124 		if (enc->enc_private == NULL)
1125 			return (ENOMEM);
1126 	}
1127 	cfg = enc->enc_private;
1128 
1129 	enc->enc_cache.nelms = 0;
1130 	enc->enc_cache.enc_status = 0;
1131 
1132 	TAILQ_INIT(&cfg->requests);
1133 	return (0);
1134 }
1135 
1136