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