xref: /freebsd/sys/cam/scsi/scsi_enc_safte.c (revision fed1ca4b719c56c930f2259d80663cd34be812bb)
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_RWTUN,
230            &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
231 
232 static int
233 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
234 		       union ccb *ccb, uint8_t *buf)
235 {
236 
237 	if (state->page_code != SAFTE_RD_RDCFG &&
238 	    enc->enc_cache.nelms == 0) {
239 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
240 		return (-1);
241 	}
242 
243 	if (enc->enc_type == ENC_SEMB_SAFT) {
244 		semb_read_buffer(&ccb->ataio, /*retries*/5,
245 				NULL, MSG_SIMPLE_Q_TAG,
246 				state->page_code, buf, state->buf_size,
247 				state->timeout);
248 	} else {
249 		scsi_read_buffer(&ccb->csio, /*retries*/5,
250 				NULL, MSG_SIMPLE_Q_TAG, 1,
251 				state->page_code, 0, buf, state->buf_size,
252 				SSD_FULL_SIZE, state->timeout);
253 	}
254 	return (0);
255 }
256 
257 static int
258 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
259     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
260 {
261 	struct scfg *cfg;
262 	uint8_t *buf = *bufp;
263 	int i, r;
264 
265 	cfg = enc->enc_private;
266 	if (cfg == NULL)
267 		return (ENXIO);
268 	if (error != 0)
269 		return (error);
270 	if (xfer_len < 6) {
271 		ENC_VLOG(enc, "too little data (%d) for configuration\n",
272 		    xfer_len);
273 		return (EIO);
274 	}
275 	cfg->Nfans = buf[0];
276 	cfg->Npwr = buf[1];
277 	cfg->Nslots = buf[2];
278 	cfg->DoorLock = buf[3];
279 	cfg->Ntherm = buf[4];
280 	cfg->Nspkrs = buf[5];
281 	if (xfer_len >= 7)
282 		cfg->Ntstats = buf[6] & 0x0f;
283 	else
284 		cfg->Ntstats = 0;
285 	ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
286 	    "Ntstats %d\n",
287 	    cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
288 	    cfg->Nspkrs, cfg->Ntstats);
289 
290 	enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
291 	    cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
292 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
293 	enc->enc_cache.elm_map =
294 	    malloc(enc->enc_cache.nelms * sizeof(enc_element_t),
295 	    M_SCSIENC, M_WAITOK|M_ZERO);
296 
297 	r = 0;
298 	/*
299 	 * Note that this is all arranged for the convenience
300 	 * in later fetches of status.
301 	 */
302 	for (i = 0; i < cfg->Nfans; i++)
303 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
304 	cfg->pwroff = (uint8_t) r;
305 	for (i = 0; i < cfg->Npwr; i++)
306 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
307 	for (i = 0; i < cfg->DoorLock; i++)
308 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
309 	if (cfg->Nspkrs > 0)
310 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
311 	for (i = 0; i < cfg->Ntherm; i++)
312 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
313 	for (i = 0; i <= cfg->Ntstats; i++)
314 		enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
315 	cfg->slotoff = (uint8_t) r;
316 	for (i = 0; i < cfg->Nslots; i++)
317 		enc->enc_cache.elm_map[r++].enctype =
318 		    emulate_array_devices ? ELMTYP_ARRAY_DEV :
319 		     ELMTYP_DEVICE;
320 
321 	enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
322 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
323 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
324 
325 	return (0);
326 }
327 
328 static int
329 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
330     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
331 {
332 	struct scfg *cfg;
333 	uint8_t *buf = *bufp;
334 
335 	cfg = enc->enc_private;
336 	if (cfg == NULL)
337 		return (ENXIO);
338 	if (error != 0)
339 		return (error);
340 	SAFT_BAIL(3, xfer_len);
341 	cfg->flag1 = buf[1];
342 	cfg->flag2 = buf[2];
343 
344 	cfg->adm_status = 0;
345 	if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
346 		cfg->adm_status |= SES_ENCSTAT_CRITICAL;
347 	else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
348 		cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
349 
350 	return (0);
351 }
352 
353 static int
354 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
355     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
356 {
357 	struct scfg *cfg;
358 	uint8_t *buf = *bufp;
359 	int oid, r, i, nitems;
360 	uint16_t tempflags;
361 	enc_cache_t *cache = &enc->enc_cache;
362 
363 	cfg = enc->enc_private;
364 	if (cfg == NULL)
365 		return (ENXIO);
366 	if (error != 0)
367 		return (error);
368 
369 	oid = r = 0;
370 	cfg->enc_status = 0;
371 
372 	for (nitems = i = 0; i < cfg->Nfans; i++) {
373 		SAFT_BAIL(r, xfer_len);
374 		/*
375 		 * 0 = Fan Operational
376 		 * 1 = Fan is malfunctioning
377 		 * 2 = Fan is not present
378 		 * 0x80 = Unknown or Not Reportable Status
379 		 */
380 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
381 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
382 		if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
383 			cache->elm_map[oid].encstat[3] |= 0x40;
384 		else
385 			cache->elm_map[oid].encstat[3] &= ~0x40;
386 		switch ((int)buf[r]) {
387 		case 0:
388 			nitems++;
389 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
390 			if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
391 				cache->elm_map[oid].encstat[3] |= 0x27;
392 			break;
393 
394 		case 1:
395 			cache->elm_map[oid].encstat[0] =
396 			    SES_OBJSTAT_CRIT;
397 			/*
398 			 * FAIL and FAN STOPPED synthesized
399 			 */
400 			cache->elm_map[oid].encstat[3] |= 0x10;
401 			cache->elm_map[oid].encstat[3] &= ~0x07;
402 			/*
403 			 * Enclosure marked with CRITICAL error
404 			 * if only one fan or no thermometers,
405 			 * else the NONCRITICAL error is set.
406 			 */
407 			if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
408 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
409 			else
410 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
411 			break;
412 		case 2:
413 			cache->elm_map[oid].encstat[0] =
414 			    SES_OBJSTAT_NOTINSTALLED;
415 			cache->elm_map[oid].encstat[3] |= 0x10;
416 			cache->elm_map[oid].encstat[3] &= ~0x07;
417 			/*
418 			 * Enclosure marked with CRITICAL error
419 			 * if only one fan or no thermometers,
420 			 * else the NONCRITICAL error is set.
421 			 */
422 			if (cfg->Nfans == 1)
423 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
424 			else
425 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
426 			break;
427 		case 0x80:
428 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
429 			cache->elm_map[oid].encstat[3] = 0;
430 			cfg->enc_status |= SES_ENCSTAT_INFO;
431 			break;
432 		default:
433 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
434 			ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
435 			    buf[r] & 0xff);
436 			break;
437 		}
438 		cache->elm_map[oid++].svalid = 1;
439 		r++;
440 	}
441 
442 	/*
443 	 * No matter how you cut it, no cooling elements when there
444 	 * should be some there is critical.
445 	 */
446 	if (cfg->Nfans && nitems == 0)
447 		cfg->enc_status |= SES_ENCSTAT_CRITICAL;
448 
449 	for (i = 0; i < cfg->Npwr; i++) {
450 		SAFT_BAIL(r, xfer_len);
451 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
452 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
453 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
454 		cache->elm_map[oid].encstat[3] = 0x20;	/* requested on */
455 		switch (buf[r]) {
456 		case 0x00:	/* pws operational and on */
457 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
458 			break;
459 		case 0x01:	/* pws operational and off */
460 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
461 			cache->elm_map[oid].encstat[3] = 0x10;
462 			cfg->enc_status |= SES_ENCSTAT_INFO;
463 			break;
464 		case 0x10:	/* pws is malfunctioning and commanded on */
465 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
466 			cache->elm_map[oid].encstat[3] = 0x61;
467 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
468 			break;
469 
470 		case 0x11:	/* pws is malfunctioning and commanded off */
471 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
472 			cache->elm_map[oid].encstat[3] = 0x51;
473 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
474 			break;
475 		case 0x20:	/* pws is not present */
476 			cache->elm_map[oid].encstat[0] =
477 			    SES_OBJSTAT_NOTINSTALLED;
478 			cache->elm_map[oid].encstat[3] = 0;
479 			cfg->enc_status |= SES_ENCSTAT_INFO;
480 			break;
481 		case 0x21:	/* pws is present */
482 			/*
483 			 * This is for enclosures that cannot tell whether the
484 			 * device is on or malfunctioning, but know that it is
485 			 * present. Just fall through.
486 			 */
487 			/* FALLTHROUGH */
488 		case 0x80:	/* Unknown or Not Reportable Status */
489 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
490 			cache->elm_map[oid].encstat[3] = 0;
491 			cfg->enc_status |= SES_ENCSTAT_INFO;
492 			break;
493 		default:
494 			ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
495 			    i, buf[r] & 0xff);
496 			break;
497 		}
498 		enc->enc_cache.elm_map[oid++].svalid = 1;
499 		r++;
500 	}
501 
502 	/*
503 	 * Copy Slot SCSI IDs
504 	 */
505 	for (i = 0; i < cfg->Nslots; i++) {
506 		SAFT_BAIL(r, xfer_len);
507 		if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
508 			cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
509 		r++;
510 	}
511 
512 	/*
513 	 * We always have doorlock status, no matter what,
514 	 * but we only save the status if we have one.
515 	 */
516 	SAFT_BAIL(r, xfer_len);
517 	if (cfg->DoorLock) {
518 		/*
519 		 * 0 = Door Locked
520 		 * 1 = Door Unlocked, or no Lock Installed
521 		 * 0x80 = Unknown or Not Reportable Status
522 		 */
523 		cache->elm_map[oid].encstat[1] = 0;
524 		cache->elm_map[oid].encstat[2] = 0;
525 		switch (buf[r]) {
526 		case 0:
527 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
528 			cache->elm_map[oid].encstat[3] = 0;
529 			break;
530 		case 1:
531 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
532 			cache->elm_map[oid].encstat[3] = 1;
533 			break;
534 		case 0x80:
535 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
536 			cache->elm_map[oid].encstat[3] = 0;
537 			cfg->enc_status |= SES_ENCSTAT_INFO;
538 			break;
539 		default:
540 			cache->elm_map[oid].encstat[0] =
541 			    SES_OBJSTAT_UNSUPPORTED;
542 			ENC_VLOG(enc, "unknown lock status 0x%x\n",
543 			    buf[r] & 0xff);
544 			break;
545 		}
546 		cache->elm_map[oid++].svalid = 1;
547 	}
548 	r++;
549 
550 	/*
551 	 * We always have speaker status, no matter what,
552 	 * but we only save the status if we have one.
553 	 */
554 	SAFT_BAIL(r, xfer_len);
555 	if (cfg->Nspkrs) {
556 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
557 		cache->elm_map[oid].encstat[1] = 0;
558 		cache->elm_map[oid].encstat[2] = 0;
559 		if (buf[r] == 0) {
560 			cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
561 			cache->elm_map[oid].encstat[3] |= 0x40;
562 		}
563 		cache->elm_map[oid++].svalid = 1;
564 	}
565 	r++;
566 
567 	/*
568 	 * Now, for "pseudo" thermometers, we have two bytes
569 	 * of information in enclosure status- 16 bits. Actually,
570 	 * the MSB is a single TEMP ALERT flag indicating whether
571 	 * any other bits are set, but, thanks to fuzzy thinking,
572 	 * in the SAF-TE spec, this can also be set even if no
573 	 * other bits are set, thus making this really another
574 	 * binary temperature sensor.
575 	 */
576 
577 	SAFT_BAIL(r + cfg->Ntherm, xfer_len);
578 	tempflags = buf[r + cfg->Ntherm];
579 	SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
580 	tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
581 
582 	for (i = 0; i < cfg->Ntherm; i++) {
583 		SAFT_BAIL(r, xfer_len);
584 		/*
585 		 * Status is a range from -10 to 245 deg Celsius,
586 		 * which we need to normalize to -20 to -245 according
587 		 * to the latest SCSI spec, which makes little
588 		 * sense since this would overflow an 8bit value.
589 		 * Well, still, the base normalization is -20,
590 		 * not -10, so we have to adjust.
591 		 *
592 		 * So what's over and under temperature?
593 		 * Hmm- we'll state that 'normal' operating
594 		 * is 10 to 40 deg Celsius.
595 		 */
596 
597 		/*
598 		 * Actually.... All of the units that people out in the world
599 		 * seem to have do not come even close to setting a value that
600 		 * complies with this spec.
601 		 *
602 		 * The closest explanation I could find was in an
603 		 * LSI-Logic manual, which seemed to indicate that
604 		 * this value would be set by whatever the I2C code
605 		 * would interpolate from the output of an LM75
606 		 * temperature sensor.
607 		 *
608 		 * This means that it is impossible to use the actual
609 		 * numeric value to predict anything. But we don't want
610 		 * to lose the value. So, we'll propagate the *uncorrected*
611 		 * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
612 		 * temperature flags for warnings.
613 		 */
614 		if (tempflags & (1 << i)) {
615 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
616 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
617 		} else
618 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
619 		cache->elm_map[oid].encstat[1] = 0;
620 		cache->elm_map[oid].encstat[2] = buf[r];
621 		cache->elm_map[oid].encstat[3] = 0;
622 		cache->elm_map[oid++].svalid = 1;
623 		r++;
624 	}
625 
626 	for (i = 0; i <= cfg->Ntstats; i++) {
627 		cache->elm_map[oid].encstat[1] = 0;
628 		if (tempflags & (1 <<
629 		    ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
630 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
631 			cache->elm_map[4].encstat[2] = 0xff;
632 			/*
633 			 * Set 'over temperature' failure.
634 			 */
635 			cache->elm_map[oid].encstat[3] = 8;
636 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
637 		} else {
638 			/*
639 			 * We used to say 'not available' and synthesize a
640 			 * nominal 30 deg (C)- that was wrong. Actually,
641 			 * Just say 'OK', and use the reserved value of
642 			 * zero.
643 			 */
644 			if ((cfg->Ntherm + cfg->Ntstats) == 0)
645 				cache->elm_map[oid].encstat[0] =
646 				    SES_OBJSTAT_NOTAVAIL;
647 			else
648 				cache->elm_map[oid].encstat[0] =
649 				    SES_OBJSTAT_OK;
650 			cache->elm_map[oid].encstat[2] = 0;
651 			cache->elm_map[oid].encstat[3] = 0;
652 		}
653 		cache->elm_map[oid++].svalid = 1;
654 	}
655 	r += 2;
656 
657 	cache->enc_status =
658 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
659 	return (0);
660 }
661 
662 static int
663 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
664     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
665 {
666 	struct scfg *cfg;
667 	uint8_t *buf = *bufp;
668 	enc_cache_t *cache = &enc->enc_cache;
669 	int oid, r, i;
670 
671 	cfg = enc->enc_private;
672 	if (cfg == NULL)
673 		return (ENXIO);
674 	if (error != 0)
675 		return (error);
676 	cfg->slot_status = 0;
677 	oid = cfg->slotoff;
678 	for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
679 		SAFT_BAIL(r+3, xfer_len);
680 		if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
681 			cache->elm_map[oid].encstat[1] = 0;
682 		cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
683 		cache->elm_map[oid].encstat[3] = 0;
684 		if ((buf[r+3] & 0x01) == 0) {	/* no device */
685 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
686 		} else if (buf[r+0] & 0x02) {
687 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
688 			cfg->slot_status |= SES_ENCSTAT_CRITICAL;
689 		} else if (buf[r+0] & 0x40) {
690 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
691 			cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
692 		} else {
693 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
694 		}
695 		if (buf[r+3] & 0x2) {
696 			if (buf[r+3] & 0x01)
697 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
698 			else
699 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
700 		}
701 		if ((buf[r+3] & 0x04) == 0)
702 			cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
703 		if (buf[r+0] & 0x02)
704 			cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
705 		if (buf[r+0] & 0x40)
706 			cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
707 		if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
708 			if (buf[r+0] & 0x01)
709 				cache->elm_map[oid].encstat[1] |= 0x80;
710 			if (buf[r+0] & 0x04)
711 				cache->elm_map[oid].encstat[1] |= 0x02;
712 			if (buf[r+0] & 0x08)
713 				cache->elm_map[oid].encstat[1] |= 0x04;
714 			if (buf[r+0] & 0x10)
715 				cache->elm_map[oid].encstat[1] |= 0x08;
716 			if (buf[r+0] & 0x20)
717 				cache->elm_map[oid].encstat[1] |= 0x10;
718 			if (buf[r+1] & 0x01)
719 				cache->elm_map[oid].encstat[1] |= 0x20;
720 			if (buf[r+1] & 0x02)
721 				cache->elm_map[oid].encstat[1] |= 0x01;
722 		}
723 		cache->elm_map[oid++].svalid = 1;
724 	}
725 
726 	cache->enc_status =
727 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
728 	return (0);
729 }
730 
731 static int
732 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
733 		       union ccb *ccb, uint8_t *buf)
734 {
735 	struct scfg *cfg;
736 	enc_element_t *ep, *ep1;
737 	safte_control_request_t *req;
738 	int i, idx, xfer_len;
739 
740 	cfg = enc->enc_private;
741 	if (cfg == NULL)
742 		return (ENXIO);
743 
744 	if (enc->enc_cache.nelms == 0) {
745 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
746 		return (-1);
747 	}
748 
749 	if (cfg->current_request == NULL) {
750 		cfg->current_request = TAILQ_FIRST(&cfg->requests);
751 		TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
752 		cfg->current_request_stage = 0;
753 		cfg->current_request_stages = 1;
754 	}
755 	req = cfg->current_request;
756 
757 	idx = (int)req->elm_idx;
758 	if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
759 		cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
760 		cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
761 		if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
762 			cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
763 		else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
764 			cfg->flag1 |= SAFT_FLG1_GLOBWARN;
765 		buf[0] = SAFTE_WT_GLOBAL;
766 		buf[1] = cfg->flag1;
767 		buf[2] = cfg->flag2;
768 		buf[3] = 0;
769 		xfer_len = 16;
770 	} else {
771 		ep = &enc->enc_cache.elm_map[idx];
772 
773 		switch (ep->enctype) {
774 		case ELMTYP_DEVICE:
775 		case ELMTYP_ARRAY_DEV:
776 			switch (cfg->current_request_stage) {
777 			case 0:
778 				ep->priv = 0;
779 				if (req->elm_stat[0] & SESCTL_PRDFAIL)
780 					ep->priv |= 0x40;
781 				if (req->elm_stat[3] & SESCTL_RQSFLT)
782 					ep->priv |= 0x02;
783 				if (ep->enctype == ELMTYP_ARRAY_DEV) {
784 					if (req->elm_stat[1] & 0x01)
785 						ep->priv |= 0x200;
786 					if (req->elm_stat[1] & 0x02)
787 						ep->priv |= 0x04;
788 					if (req->elm_stat[1] & 0x04)
789 						ep->priv |= 0x08;
790 					if (req->elm_stat[1] & 0x08)
791 						ep->priv |= 0x10;
792 					if (req->elm_stat[1] & 0x10)
793 						ep->priv |= 0x20;
794 					if (req->elm_stat[1] & 0x20)
795 						ep->priv |= 0x100;
796 					if (req->elm_stat[1] & 0x80)
797 						ep->priv |= 0x01;
798 				}
799 				if (ep->priv == 0)
800 					ep->priv |= 0x01;	/* no errors */
801 
802 				buf[0] = SAFTE_WT_DSTAT;
803 				for (i = 0; i < cfg->Nslots; i++) {
804 					ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
805 					buf[1 + (3 * i)] = ep1->priv;
806 					buf[2 + (3 * i)] = ep1->priv >> 8;
807 				}
808 				xfer_len = cfg->Nslots * 3 + 1;
809 #define DEVON(x)	(!(((x)[2] & SESCTL_RQSINS) |	\
810 			   ((x)[2] & SESCTL_RQSRMV) |	\
811 			   ((x)[3] & SESCTL_DEVOFF)))
812 				if (DEVON(req->elm_stat) != DEVON(ep->encstat))
813 					cfg->current_request_stages++;
814 #define IDON(x)		(!!((x)[2] & SESCTL_RQSID))
815 				if (IDON(req->elm_stat) != IDON(ep->encstat))
816 					cfg->current_request_stages++;
817 				break;
818 			case 1:
819 			case 2:
820 				buf[0] = SAFTE_WT_SLTOP;
821 				buf[1] = idx - cfg->slotoff;
822 				if (cfg->current_request_stage == 1 &&
823 				    DEVON(req->elm_stat) != DEVON(ep->encstat)) {
824 					if (DEVON(req->elm_stat))
825 						buf[2] = 0x01;
826 					else
827 						buf[2] = 0x02;
828 				} else {
829 					if (IDON(req->elm_stat))
830 						buf[2] = 0x04;
831 					else
832 						buf[2] = 0x00;
833 					ep->encstat[2] &= ~SESCTL_RQSID;
834 					ep->encstat[2] |= req->elm_stat[2] &
835 					    SESCTL_RQSID;
836 				}
837 				xfer_len = 64;
838 				break;
839 			default:
840 				return (EINVAL);
841 			}
842 			break;
843 		case ELMTYP_POWER:
844 			cfg->current_request_stages = 2;
845 			switch (cfg->current_request_stage) {
846 			case 0:
847 				if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
848 					cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
849 				} else {
850 					cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
851 				}
852 				buf[0] = SAFTE_WT_GLOBAL;
853 				buf[1] = cfg->flag1;
854 				buf[2] = cfg->flag2;
855 				buf[3] = 0;
856 				xfer_len = 16;
857 				break;
858 			case 1:
859 				buf[0] = SAFTE_WT_ACTPWS;
860 				buf[1] = idx - cfg->pwroff;
861 				if (req->elm_stat[3] & SESCTL_RQSTON)
862 					buf[2] = 0x01;
863 				else
864 					buf[2] = 0x00;
865 				buf[3] = 0;
866 				xfer_len = 16;
867 			default:
868 				return (EINVAL);
869 			}
870 			break;
871 		case ELMTYP_FAN:
872 			if ((req->elm_stat[3] & 0x7) != 0)
873 				cfg->current_request_stages = 2;
874 			switch (cfg->current_request_stage) {
875 			case 0:
876 				if (req->elm_stat[3] & SESCTL_RQSTFAIL)
877 					cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
878 				else
879 					cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
880 				buf[0] = SAFTE_WT_GLOBAL;
881 				buf[1] = cfg->flag1;
882 				buf[2] = cfg->flag2;
883 				buf[3] = 0;
884 				xfer_len = 16;
885 				break;
886 			case 1:
887 				buf[0] = SAFTE_WT_FANSPD;
888 				buf[1] = idx;
889 				if (req->elm_stat[3] & SESCTL_RQSTON) {
890 					if ((req->elm_stat[3] & 0x7) == 7)
891 						buf[2] = 4;
892 					else if ((req->elm_stat[3] & 0x7) >= 5)
893 						buf[2] = 3;
894 					else if ((req->elm_stat[3] & 0x7) >= 3)
895 						buf[2] = 2;
896 					else
897 						buf[2] = 1;
898 				} else
899 					buf[2] = 0;
900 				buf[3] = 0;
901 				xfer_len = 16;
902 				ep->encstat[3] = req->elm_stat[3] & 0x67;
903 			default:
904 				return (EINVAL);
905 			}
906 			break;
907 		case ELMTYP_DOORLOCK:
908 			if (req->elm_stat[3] & 0x1)
909 				cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
910 			else
911 				cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
912 			buf[0] = SAFTE_WT_GLOBAL;
913 			buf[1] = cfg->flag1;
914 			buf[2] = cfg->flag2;
915 			buf[3] = 0;
916 			xfer_len = 16;
917 			break;
918 		case ELMTYP_ALARM:
919 			if ((req->elm_stat[0] & SESCTL_DISABLE) ||
920 			    (req->elm_stat[3] & 0x40)) {
921 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
922 			} else if ((req->elm_stat[3] & 0x0f) != 0) {
923 				cfg->flag2 |= SAFT_FLG1_ALARM;
924 			} else {
925 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
926 			}
927 			buf[0] = SAFTE_WT_GLOBAL;
928 			buf[1] = cfg->flag1;
929 			buf[2] = cfg->flag2;
930 			buf[3] = 0;
931 			xfer_len = 16;
932 			ep->encstat[3] = req->elm_stat[3];
933 			break;
934 		default:
935 			return (EINVAL);
936 		}
937 	}
938 
939 	if (enc->enc_type == ENC_SEMB_SAFT) {
940 		semb_write_buffer(&ccb->ataio, /*retries*/5,
941 				NULL, MSG_SIMPLE_Q_TAG,
942 				buf, xfer_len, state->timeout);
943 	} else {
944 		scsi_write_buffer(&ccb->csio, /*retries*/5,
945 				NULL, MSG_SIMPLE_Q_TAG, 1,
946 				0, 0, buf, xfer_len,
947 				SSD_FULL_SIZE, state->timeout);
948 	}
949 	return (0);
950 }
951 
952 static int
953 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
954     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
955 {
956 	struct scfg *cfg;
957 	safte_control_request_t *req;
958 	int idx, type;
959 
960 	cfg = enc->enc_private;
961 	if (cfg == NULL)
962 		return (ENXIO);
963 
964 	req = cfg->current_request;
965 	if (req->result == 0)
966 		req->result = error;
967 	if (++cfg->current_request_stage >= cfg->current_request_stages) {
968 		idx = req->elm_idx;
969 		if (idx == SES_SETSTATUS_ENC_IDX)
970 			type = -1;
971 		else
972 			type = enc->enc_cache.elm_map[idx].enctype;
973 		if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
974 			enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
975 		else
976 			enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
977 		cfg->current_request = NULL;
978 		wakeup(req);
979 	} else {
980 		enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
981 	}
982 	return (0);
983 }
984 
985 static void
986 safte_softc_invalidate(enc_softc_t *enc)
987 {
988 	struct scfg *cfg;
989 
990 	cfg = enc->enc_private;
991 	safte_terminate_control_requests(&cfg->requests, ENXIO);
992 }
993 
994 static void
995 safte_softc_cleanup(enc_softc_t *enc)
996 {
997 
998 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
999 	ENC_FREE_AND_NULL(enc->enc_private);
1000 	enc->enc_cache.nelms = 0;
1001 }
1002 
1003 static int
1004 safte_init_enc(enc_softc_t *enc)
1005 {
1006 	struct scfg *cfg;
1007 	int err;
1008 	static char cdb0[6] = { SEND_DIAGNOSTIC };
1009 
1010 	cfg = enc->enc_private;
1011 	if (cfg == NULL)
1012 		return (ENXIO);
1013 
1014 	err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1015 	if (err) {
1016 		return (err);
1017 	}
1018 	DELAY(5000);
1019 	cfg->flag1 = 0;
1020 	cfg->flag2 = 0;
1021 	err = safte_set_enc_status(enc, 0, 1);
1022 	return (err);
1023 }
1024 
1025 static int
1026 safte_get_enc_status(enc_softc_t *enc, int slpflg)
1027 {
1028 
1029 	return (0);
1030 }
1031 
1032 static int
1033 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1034 {
1035 	struct scfg *cfg;
1036 	safte_control_request_t req;
1037 
1038 	cfg = enc->enc_private;
1039 	if (cfg == NULL)
1040 		return (ENXIO);
1041 
1042 	req.elm_idx = SES_SETSTATUS_ENC_IDX;
1043 	req.elm_stat[0] = encstat & 0xf;
1044 	req.result = 0;
1045 
1046 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1047 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1048 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1049 
1050 	return (req.result);
1051 }
1052 
1053 static int
1054 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1055 {
1056 	int i = (int)elms->elm_idx;
1057 
1058 	elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1059 	elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1060 	elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1061 	elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1062 	return (0);
1063 }
1064 
1065 static int
1066 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1067 {
1068 	struct scfg *cfg;
1069 	safte_control_request_t req;
1070 
1071 	cfg = enc->enc_private;
1072 	if (cfg == NULL)
1073 		return (ENXIO);
1074 
1075 	/* If this is clear, we don't do diddly.  */
1076 	if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1077 		return (0);
1078 
1079 	req.elm_idx = elms->elm_idx;
1080 	memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1081 	req.result = 0;
1082 
1083 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1084 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1085 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1086 
1087 	return (req.result);
1088 }
1089 
1090 static void
1091 safte_poll_status(enc_softc_t *enc)
1092 {
1093 
1094 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1095 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1096 }
1097 
1098 static struct enc_vec safte_enc_vec =
1099 {
1100 	.softc_invalidate	= safte_softc_invalidate,
1101 	.softc_cleanup	= safte_softc_cleanup,
1102 	.init_enc	= safte_init_enc,
1103 	.get_enc_status	= safte_get_enc_status,
1104 	.set_enc_status	= safte_set_enc_status,
1105 	.get_elm_status	= safte_get_elm_status,
1106 	.set_elm_status	= safte_set_elm_status,
1107 	.poll_status	= safte_poll_status
1108 };
1109 
1110 int
1111 safte_softc_init(enc_softc_t *enc)
1112 {
1113 	struct scfg *cfg;
1114 
1115 	enc->enc_vec = safte_enc_vec;
1116 	enc->enc_fsm_states = enc_fsm_states;
1117 
1118 	if (enc->enc_private == NULL) {
1119 		enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1120 		if (enc->enc_private == NULL)
1121 			return (ENOMEM);
1122 	}
1123 	cfg = enc->enc_private;
1124 
1125 	enc->enc_cache.nelms = 0;
1126 	enc->enc_cache.enc_status = 0;
1127 
1128 	TAILQ_INIT(&cfg->requests);
1129 	return (0);
1130 }
1131 
1132