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